diff --git a/core/app/models/spree/order.rb b/core/app/models/spree/order.rb index 4f7c88ceec6..dbd9bbaa76b 100644 --- a/core/app/models/spree/order.rb +++ b/core/app/models/spree/order.rb @@ -914,9 +914,8 @@ def ensure_available_shipping_rates end def after_cancel - shipments.each(&:cancel!) - payments.completed.each { |payment| payment.cancel! unless payment.fully_refunded? } - payments.store_credits.pending.each(&:void_transaction!) + cancel_shipments! + cancel_payments! send_cancel_email # rubocop:disable Rails/SkipsModelValidations @@ -925,6 +924,19 @@ def after_cancel recalculate end + def cancel_shipments! + shipments.each(&:cancel!) + end + + def cancel_payments! + payments.each do |payment| + next if payment.fully_refunded? + next unless payment.pending? || payment.completed? + + payment.cancel! + end + end + def send_cancel_email Spree::Config.order_mailer_class.cancel_email(self).deliver_later end diff --git a/core/spec/models/spree/order_spec.rb b/core/spec/models/spree/order_spec.rb index 794d2f1d53c..494f52c3fa0 100644 --- a/core/spec/models/spree/order_spec.rb +++ b/core/spec/models/spree/order_spec.rb @@ -90,16 +90,12 @@ describe "#cancel!" do subject { order.cancel! } - context "with captured store credit" do - let!(:store_credit_payment_method) { create(:store_credit_payment_method) } - let(:order_total) { 500.00 } - let(:store_credit) { create(:store_credit, amount: order_total) } - let(:order) { create(:order_with_line_items, user: store_credit.user, line_items_price: order_total) } + context 'when the payment is completed' do + let(:order) { create(:order_ready_to_ship) } + let(:payment) { order.payments.first } - before do - order.add_store_credit_payments - order.finalize! - order.capture_payments! + it 'voids the payment' do + expect { subject }.to change { payment.reload.state }.from('completed').to('void') end it "cancels the order" do @@ -107,7 +103,7 @@ expect(order).to be_canceled end - it 'should save canceled_at' do + it 'saves canceled_at' do subject expect(order.reload.canceled_at).to_not be_nil end @@ -121,20 +117,58 @@ end end - context "with fully refunded payment" do + context "when the payment is fully refunded" do let(:order) { create(:completed_order_with_totals) } let(:payment_amount) { 50 } let(:payment) { create(:payment, order: order, amount: payment_amount, state: 'completed') } - before do - create(:refund, payment: payment, amount: payment_amount).perform! - end - it "cancels the order" do + create(:refund, payment: payment, amount: payment_amount) + expect{ subject }.to change{ order.can_cancel? }.from(true).to(false) expect(order).to be_canceled end end + + context 'when the payment is pending' do + let(:order) { create(:completed_order_with_pending_payment) } + let(:payment) { order.payments.first } + + it 'voids the pending payment' do + expect { subject }.to change { payment.reload.state }.from('pending').to('void') + end + end + + context 'with a store credit payment' do + let(:order) { create(:completed_order_with_totals) } + let(:payment) { create(:store_credit_payment, amount: order.total, order: order) } + + context 'when the payment is pending' do + let(:store_credit) { payment.source } + + before do + payment.authorize! + end + + it 'voids the payment' do + expect { subject }.to change { payment.reload.state }.from('pending').to('void') + end + + it 'releases the pending store credit authorization' do + expect { subject }.to change { store_credit.reload.amount_authorized }.from(110).to(0) + end + end + + context 'when the payment is completed' do + before do + payment.purchase! + end + + it 'refunds the payment' do + expect { subject }.to change { Spree::Refund.count }.by(1) + end + end + end end context "#canceled_by" do @@ -1604,47 +1638,6 @@ def generate expect(subject.display_store_credit_remaining_after_capture.money.cents).to eq(amount_remaining * 100.0) end end - - context 'when not capturing at order completion' do - let!(:store_credit_payment_method) do - create( - :store_credit_payment_method, - auto_capture: false, # not capturing at completion time - ) - end - - describe '#after_cancel' do - let(:user) { create(:user) } - let!(:store_credit) do - create(:store_credit, amount: 100, user: user) - end - let(:order) do - create( - :order_with_line_items, - user: user, - line_items_count: 1, - # order will be $20 total: - line_items_price: 10, - shipment_cost: 10 - ) - end - - before do - order.contents.advance - order.complete! - end - - it 'releases the pending store credit authorization' do - expect { - order.cancel! - }.to change { - store_credit.reload.amount_authorized - }.from(20).to(0) - - expect(store_credit.amount_remaining).to eq 100 - end - end - end end context 'update_params_payment_source' do