Class: Order::AuthorizationSplitter
- Inherits:
-
Object
- Object
- Order::AuthorizationSplitter
- Defined in:
- app/services/order/authorization_splitter.rb
Overview
Allocates a parent order's existing authorization across a split-off child
order, once the child has committed delivery(ies) to attach payment to.
This is the payment half of Splitter, extracted so it can run in
two places:
- Synchronously inside Splitter when the child already has a
delivery at split time (the in-stock case). - Deferred, via AuthorizationSplitWorker, when the child's
delivery is committed after the split finished (back-order / shipping
quoted later) — the case where the authorization previously never
followed the order.
@order is the parent (which holds the un-split authorization) and
@new_order is the child. The credit-card / PayPal / PO logic is unchanged
from the original splitter.
Defined Under Namespace
Classes: Result
Class Method Summary collapse
-
.topup(order, logger: Rails.logger) ⇒ Result
Reconcile a single order whose shared-PI authorization no longer covers its total after the split's coupon reallocation / shipping re-quote settled.
Instance Method Summary collapse
-
#call ⇒ Boolean, Result
Splits the parent's authorization onto the child's deliveries.
-
#initialize(parent, new_order, logger: Rails.logger) ⇒ AuthorizationSplitter
constructor
A new instance of AuthorizationSplitter.
-
#topup_shared_pi_authorization(order) ⇒ Result
Create supplemental shared-PI payment(s) covering
order's uncovered balance and raise the PI to match (incremental auth, falling back to a fresh authorization when the PI can't be incremented).
Constructor Details
#initialize(parent, new_order, logger: Rails.logger) ⇒ AuthorizationSplitter
Returns a new instance of AuthorizationSplitter.
42 43 44 45 46 |
# File 'app/services/order/authorization_splitter.rb', line 42 def initialize(parent, new_order, logger: Rails.logger) @order = parent @new_order = new_order @logger = logger end |
Class Method Details
.topup(order, logger: Rails.logger) ⇒ Result
Reconcile a single order whose shared-PI authorization no longer covers
its total after the split's coupon reallocation / shipping re-quote
settled. Unlike #call, this runs for the PARENT too — the deferred
child-only worker never re-funds the parent.
56 57 58 |
# File 'app/services/order/authorization_splitter.rb', line 56 def self.topup(order, logger: Rails.logger) new(order, order, logger:).(order) end |
Instance Method Details
#call ⇒ Boolean, Result
Splits the parent's authorization onto the child's deliveries.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'app/services/order/authorization_splitter.rb', line 108 def call return Result.noop if @new_order.deliveries.blank? po_payment = @order.payments..where(category: [Payment::PO, Payment::VPO, Payment::CHECK, Payment::CASH]).first cc_payment = @order.payments..where(category: Payment::CREDIT_CARD).first paypal_payment = @order.payments..where(category: Payment::PAYPAL).first if po_payment attrs = { currency: po_payment.currency, category: po_payment.category, po_number: po_payment.po_number, amount: @new_order.total } Payment::OrderProcessor.new(@new_order, attrs).process elsif cc_payment && cc_payment.credit_card_vault.present? split_cc_payment(cc_payment) elsif paypal_payment split_paypal_payment(paypal_payment) else return Result.noop end # A path ran; report whether the child is actually covered now. (The # individual gateway paths swallow their own failures, so balance is the # reliable post-condition.) @new_order.reload @new_order.balance <= 0 ? Result.split : Result.failed end |
#topup_shared_pi_authorization(order) ⇒ Result
Create supplemental shared-PI payment(s) covering order's uncovered
balance and raise the PI to match (incremental auth, falling back to a
fresh authorization when the PI can't be incremented). Reuses the same
allocation + shortfall primitives as the initial split, so it is safe to
call repeatedly — a fully-funded order is a :noop.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'app/services/order/authorization_splitter.rb', line 69 def (order) order.reload return Result.noop unless order.balance.positive? source = order.payments.credit_cards. .where.not(stripe_payment_intent_id: nil) .detect(&:supports_multicapture?) unless source @logger.warn("#{Time.current}: Auth top-up skipped for order #{order.id} — no multicapture-capable shared-PI CC payment to top up") return Result.noop end vault = source.credit_card_vault unless vault @logger.warn("#{Time.current}: Auth top-up skipped for order #{order.id} — source payment #{source.id} has no vault on file") return Result.noop end begin pi = Payment::Apis::Stripe.retrieve_payment_intent(source.stripe_payment_intent_id, currency: source.currency) rescue ::Stripe::StripeError => e @logger.error("#{Time.current}: Auth top-up could not retrieve PI #{source.stripe_payment_intent_id} for order #{order.id}: #{e.}") return Result.failed end create_shared_pi_payments_for_order(order, source, vault, pi, source.stripe_capabilities, source.capture_before) resolve_shared_pi_shortfall(pi.id, pi.amount_capturable.to_i, vault, source) order.reload order.balance <= 0 ? Result.split : Result.failed end |