Module: Spree::Order::GiftCard
- Extended by:
- ActiveSupport::Concern
- Included in:
- Spree::Order
- Defined in:
- app/models/spree/order/gift_card.rb
Instance Method Summary collapse
-
#apply_gift_card(gift_card) ⇒ Spree::Order
Applies a gift card to the order.
-
#gift_card_total ⇒ Decimal
Returns the total amount of the gift card applied to the order.
-
#recalculate_gift_card ⇒ Object
Recalculates the gift card payment amount based on the current order total.
- #redeem_gift_card ⇒ Object
-
#remove_gift_card ⇒ Spree::Order
Removes a gift card from the order.
Instance Method Details
#apply_gift_card(gift_card) ⇒ Spree::Order
Applies a gift card to the order
27 28 29 |
# File 'app/models/spree/order/gift_card.rb', line 27 def apply_gift_card(gift_card) Spree.gift_card_apply_service.call(gift_card: gift_card, order: self) end |
#gift_card_total ⇒ Decimal
Returns the total amount of the gift card applied to the order
15 16 17 18 19 20 21 22 |
# File 'app/models/spree/order/gift_card.rb', line 15 def gift_card_total return 0.to_d unless gift_card.present? store_credit_ids = payments.store_credits.valid.pluck(:source_id) store_credits = Spree::StoreCredit.where(id: store_credit_ids, originator: gift_card) store_credits.sum(:amount) end |
#recalculate_gift_card ⇒ Object
Recalculates the gift card payment amount based on the current order total. Updates the existing payment in place instead of remove + re-apply to avoid creating unnecessary invalid payment records.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'app/models/spree/order/gift_card.rb', line 40 def recalculate_gift_card return unless gift_card.present? payment = payments.checkout.store_credits.where(source: gift_card.store_credits).first return unless payment # with_lock acquires a row lock and wraps in a transaction. # The entire read-compute-write must be inside the lock to prevent # stale amount_remaining from concurrent requests. gift_card.with_lock do new_amount = [gift_card.amount_remaining + payment.amount, total].min next if payment.amount == new_amount difference = new_amount - payment.amount # Uses update_column to bypass Payment#max_amount validation which # can fail during recalculation due to stale in-memory order state. # Bounds are enforced via min() above. payment.update_column(:amount, new_amount) payment.source.update_column(:amount, new_amount) gift_card.amount_used += difference gift_card.save! end end |
#redeem_gift_card ⇒ Object
64 65 66 67 68 |
# File 'app/models/spree/order/gift_card.rb', line 64 def redeem_gift_card return unless gift_card.present? Spree.gift_card_redeem_service.call(gift_card: gift_card) end |
#remove_gift_card ⇒ Spree::Order
Removes a gift card from the order
33 34 35 |
# File 'app/models/spree/order/gift_card.rb', line 33 def remove_gift_card Spree.gift_card_remove_service.call(order: self) end |