Module: SpreeCmCommissioner::OrderHoldable
- Extended by:
- ActiveSupport::Concern
- Defined in:
- app/models/concerns/spree_cm_commissioner/order_holdable.rb
Instance Method Summary collapse
-
#hold_order_holds ⇒ Object
Called before transitioning to :address state.
-
#lock_order_holds_for_payment ⇒ Object
Called via PaymentDecorator#after_commit when a payment is created.
-
#release_order_holds(reason: :user_canceled) ⇒ Object
Non-raising variant.
-
#release_order_holds!(reason: :user_canceled) ⇒ Object
Releases all holds (seats + inventory) for the order.
-
#reserve_order_holds! ⇒ Object
Converts all holds to reserved/complete state on order completion.
- #should_hold_inventory? ⇒ Boolean
- #should_manage_blocks? ⇒ Boolean
-
#validate_inventory_hold_before_complete ⇒ Object
Called before transitioning to :complete.
Instance Method Details
#hold_order_holds ⇒ Object
Called before transitioning to :address state. Acquires seat holds (if applicable) + inventory holds for the order.
37 38 39 40 41 42 43 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 37 def hold_order_holds result = SpreeCmCommissioner::OrderHolds::Hold.call(order: self) return true if result.success? errors.add(:holds, result.error.value[:message]) false end |
#lock_order_holds_for_payment ⇒ Object
Called via PaymentDecorator#after_commit when a payment is created. Idempotent: skips if holds are already locked (payment_locked_at is set). On first call, ensures all active holds have at least 5 minutes remaining, transitions the inventory hold to :payment_locked, stamps payment_locked_at on both inventory hold and seat blocks, and resyncs order.hold_expires_at.
50 51 52 53 54 55 56 57 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 50 def lock_order_holds_for_payment return true unless should_manage_blocks? || should_hold_inventory? result = SpreeCmCommissioner::OrderHolds::LockForPayment.call(order: self) return true if result.success? false end |
#release_order_holds(reason: :user_canceled) ⇒ Object
Non-raising variant. OrderHolds::Release rescues internally and returns a failure
result, so callers can guard on .success? instead of handling exceptions.
67 68 69 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 67 def release_order_holds(reason: :user_canceled) SpreeCmCommissioner::OrderHolds::Release.call(order: self, reason: reason) end |
#release_order_holds!(reason: :user_canceled) ⇒ Object
Releases all holds (seats + inventory) for the order. Raises on failure so the surrounding transaction rolls back.
61 62 63 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 61 def release_order_holds!(reason: :user_canceled) SpreeCmCommissioner::OrderHolds::Release.call!(order: self, reason: reason) end |
#reserve_order_holds! ⇒ Object
Converts all holds to reserved/complete state on order completion. Raises on failure so the surrounding transaction rolls back.
73 74 75 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 73 def reserve_order_holds! SpreeCmCommissioner::OrderHolds::Reserve.call!(order: self) end |
#should_hold_inventory? ⇒ Boolean
29 30 31 32 33 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 29 def should_hold_inventory? return true if line_items.any?(&:should_hold_inventory?) false end |
#should_manage_blocks? ⇒ Boolean
25 26 27 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 25 def should_manage_blocks? preload_block_ids.any? end |
#validate_inventory_hold_before_complete ⇒ Object
Called before transitioning to :complete. Blocks on ANY finalized hold, not just
released — a converted? hold reaching this point (while the order itself is still
short of :complete) can only mean an earlier completion attempt already decremented real
stock and then failed for some unrelated reason before the order's own state committed to
match. InventoryHolds::Convert treats re-hitting a converted hold as a safe no-op for its
own callers, but that's a different contract than this guard's: silently letting the state
machine "reprocess" here would still re-run the rest of unstock_inventory! (external-system
calls, notifications, ...) for what is actually an inconsistent state, not a normal retry.
Failing loudly forces that inconsistency to be looked at rather than auto-healed blind.
Halting here (returning false), the same way hold_order_holds halts :address, keeps this a normal order.errors response instead of an exception, and skips straight past the external-system/Redis work in unstock_inventory! that would otherwise run first only to be rolled back once InventoryHolds::Convert makes this same finalized? check again.
91 92 93 94 95 96 97 |
# File 'app/models/concerns/spree_cm_commissioner/order_holdable.rb', line 91 def validate_inventory_hold_before_complete return true if inventory_hold.nil? return true unless inventory_hold.finalized? errors.add(:holds, I18n.t('inventory_hold.convert.hold_expired')) false end |