Skip to content

Commit d605b62

Browse files
dadachiclaude
andcommitted
Wire ItemTagNotifier to AASM complete event
On idled → completed transition, ItemTag#after_commit fires ItemTagNotifier to all shopkeepers in the shop's account except the completer (completed_by). idle! does not fire. Closes the AASM-trigger half of issue #58 PR #2 scope. APNs/FCM provider credentials still need provisioning (bin/rails credentials:edit) before delivery is enabled in production. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 88e1e4d commit d605b62

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Wire `ItemTagNotifier` to the `ItemTag` AASM `complete` event via `after_commit`. On state transition `idled → completed`, the notifier fires to all shopkeepers in the shop's account except the completer (`completed_by`). Only the AASM trigger — APNs/FCM provider credentials still pending (`bin/rails credentials:edit` once the keys are provisioned).
56
- Drop the standalone `Device` model and consolidate push-token registration onto `ApplicationPushDevice` (subclass of `ActionPushNative::Device`) so `deliver_by :action_push_native` actually fires for tokens registered via `POST /api/v1/shopkeeper/devices`. The custom `devices` table is dropped; `action_push_native_devices` is rebuilt with UUID primary key + UUID polymorphic owner + `bundle_id` / `last_active_at` columns + unique `(platform, token)` index.
67
- API contract change (still pre-mobile-client): `device.platform` enum is now `[apple, google]` (matches Action Push Native's APNs/FCM service convention) instead of `[ios, android]`. Mobile substrate clients (PRs #3-5) will register with `apple` or `google`.
78
- Renames: `Device``ApplicationPushDevice`, `Api::Shopkeeper::DevicePolicy``Api::Shopkeeper::ApplicationPushDevicePolicy`, `DeviceSerializer``ApplicationPushDeviceSerializer` (JSONAPI `type` stays `device`); `Shopkeeper has_many :devices``has_many :application_push_devices, as: :owner`.

app/models/item_tag.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,20 @@ class ItemTag < ApplicationRecord
2424

2525
event :complete do
2626
transitions from: [:idled], to: :completed
27+
after_commit :notify_completed
2728
end
2829
end
2930

3031
private
3132

33+
def notify_completed
34+
recipients = shop.account.shopkeepers
35+
recipients = recipients.where.not(id: completed_by_id) if completed_by_id.present?
36+
return if recipients.empty?
37+
38+
ItemTagNotifier.with(record: self).deliver(recipients)
39+
end
40+
3241
def set_default_position
3342
return if position.present?
3443

test/models/item_tag_test.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,61 @@ def setup
119119
assert item_tag.idled?
120120
end
121121
end
122+
123+
test "complete! fires ItemTagNotifier to all account shopkeepers except completer" do
124+
ActsAsTenant.with_tenant(@account) do
125+
other = shopkeepers(:two)
126+
AccountsShopkeeper.create!(account: @account, shopkeeper: other, roles: {member: true})
127+
128+
item_tag = @shop.item_tags.first
129+
item_tag.completed_by = @shopkeeper
130+
131+
assert_difference -> { Noticed::Event.count }, 1 do
132+
assert_difference -> { Noticed::Notification.count }, 1 do
133+
item_tag.complete!
134+
end
135+
end
136+
137+
notification = Noticed::Notification.last
138+
assert_equal other, notification.recipient
139+
assert_equal item_tag, notification.record
140+
end
141+
end
142+
143+
test "complete! fires notifier to all shopkeepers when completed_by is unset" do
144+
ActsAsTenant.with_tenant(@account) do
145+
other = shopkeepers(:two)
146+
AccountsShopkeeper.create!(account: @account, shopkeeper: other, roles: {member: true})
147+
148+
item_tag = @shop.item_tags.first
149+
150+
assert_difference -> { Noticed::Notification.count }, 2 do
151+
item_tag.complete!
152+
end
153+
end
154+
end
155+
156+
test "complete! is a no-op for the notifier when account has only the completer" do
157+
ActsAsTenant.with_tenant(@account) do
158+
item_tag = @shop.item_tags.first
159+
item_tag.completed_by = @shopkeeper
160+
161+
assert_no_difference -> { Noticed::Event.count } do
162+
assert_no_difference -> { Noticed::Notification.count } do
163+
item_tag.complete!
164+
end
165+
end
166+
end
167+
end
168+
169+
test "idle! does not fire ItemTagNotifier" do
170+
ActsAsTenant.with_tenant(@account) do
171+
item_tag = @shop.item_tags.first
172+
item_tag.complete!
173+
174+
assert_no_difference -> { Noticed::Event.count } do
175+
item_tag.idle!
176+
end
177+
end
178+
end
122179
end

0 commit comments

Comments
 (0)