Class: Insika::Commands::CancelFollowup
- Inherits:
-
Object
- Object
- Insika::Commands::CancelFollowup
- Defined in:
- lib/insika/commands/cancel_followup.rb
Overview
the operator cancels ONE pending follow-up record (the Studio's Cancel button dispatches this). Synchronous control command (no task, like RecordOutcome); idempotent — an already-cancelled record returns as-is (a repeat of the same call is not an error). Tenant-scoped (WS1): a tenant principal can only cancel its own tenant's records.
Instance Method Summary collapse
-
#call(command) ⇒ Object
-> Record.
-
#initialize(followup_store:, event_stream:) ⇒ CancelFollowup
constructor
A new instance of CancelFollowup.
Constructor Details
#initialize(followup_store:, event_stream:) ⇒ CancelFollowup
Returns a new instance of CancelFollowup.
13 14 15 16 |
# File 'lib/insika/commands/cancel_followup.rb', line 13 def initialize(followup_store:, event_stream:) @followup_store = followup_store @event_stream = event_stream end |
Instance Method Details
#call(command) ⇒ Object
-> Record. Emits :followup_cancelled { id:, cancelled_by: }.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/insika/commands/cancel_followup.rb', line 19 def call(command) id = Coercion.presence(command.payload[:followup_id] || command.payload["followup_id"]) raise ValidationError, "followup_id is required" if id.nil? record = @followup_store.find(id) raise NotFoundError, "follow-up not found: #{id}" if record.nil? # WS1: the principal's tenant is the scope — a tenant token cannot # cancel another tenant's record by id. tenant = command.[:tenant] unless record.tenant == (tenant.to_s.empty? ? "platform" : tenant.to_s) raise ValidationError, "follow-up #{id} belongs to another tenant" end # A non-pending record (the tick fired it between the render and the # click) is a domain error the Studio can flash — never a 500. cancelled = begin @followup_store.cancel(id: id) rescue ArgumentError => e raise ValidationError, e. end @event_stream.emit(Insika::Event.new( type: :followup_cancelled, data: { id: cancelled.id, cancelled_by: "operator" }, meta: { tenant: command.[:tenant], at: Time.now.utc.iso8601 } )) cancelled end |