diff --git a/core/app/services/spree/cart/change_currency.rb b/core/app/services/spree/cart/change_currency.rb index 1bda19dfd93..ebe2da3cdde 100644 --- a/core/app/services/spree/cart/change_currency.rb +++ b/core/app/services/spree/cart/change_currency.rb @@ -6,6 +6,9 @@ class ChangeCurrency def call(order:, new_currency:) return failure('Currency not supported') unless supported_currency?(order, new_currency) + order.ensure_updated_shipments + order.update_column(:total, order.item_total) + result = order.update!(currency: new_currency) rescue false if result diff --git a/core/spec/services/spree/cart/change_currency_spec.rb b/core/spec/services/spree/cart/change_currency_spec.rb index 57e920479b0..36bbf14fab6 100644 --- a/core/spec/services/spree/cart/change_currency_spec.rb +++ b/core/spec/services/spree/cart/change_currency_spec.rb @@ -2,26 +2,86 @@ module Spree describe Cart::ChangeCurrency do - subject { described_class.call(order: order, new_currency: new_currency) } + context 'when shipment is already choosen' do + let(:country) { create(:country) } + let(:store) { create(:store, checkout_zone: zone, supported_currencies: 'USD,EUR') } + let(:order2) { create(:order_with_line_items, store: store, ship_address: create(:address, country: country)) } + let(:zone) { create(:zone_with_country) } - let(:order) { create(:order_with_line_items, store: store, currency: 'USD') } - let(:store) { create(:store, supported_currencies: 'USD,EUR,GBP') } + let!(:price) { create(:price, currency: 'EUR', variant: order2.line_items.first.variant, amount: 25.00) } - context 'when switching to a supported currency' do - let(:new_currency) { 'EUR' } + before do + zone.countries << country + end - context 'when product has a price in given currency' do - let!(:price) { create(:price, currency: 'EUR', variant: order.line_items.first.variant)} + context 'when in address state' do + it 'resets the checkout process when in address state' do + expect(described_class.call(order: order2, new_currency: 'EUR')).to be_success + order2.reload + expect(order2.currency).to eq('EUR') + expect(order2.total).to eq(25.00) + expect(order2.shipments.to_a).to eq([]) + end + end - it 'changes order and line items currency' do - expect(subject).to be_success - order.reload - expect(order.currency).to eq('EUR') - expect(order.line_items.first.currency).to eq('EUR') + context 'when in payment state' do + it 'resets the checkout process when in payment state' do + Checkout::Advance.call(order: order2) + order2.item_total = 10 + expect(described_class.call(order: order2, new_currency: 'EUR')).to be_success + order2.reload + expect(order2.state).to eq('address') + expect(order2.currency).to eq('EUR') + expect(order2.total).to eq(25.00) + expect(order2.shipments.to_a).to eq([]) + end + end + + context 'when user requests shipping methods after changing currency' do + it 'gets the new shipping method' do + shipment_id = order2.shipments.first.id + expect(described_class.call(order: order2, new_currency: 'EUR')).to be_success + order2.reload + Checkout::GetShippingRates.call(order: order2) + expect(order2.currency).to eq('EUR') + expect(order2.shipments.first.id).not_to eq(shipment_id) + end + end + end + + context 'change currency' do + subject { described_class.call(order: order, new_currency: new_currency) } + + let(:order) { create(:order_with_line_items, store: store, currency: 'USD') } + let(:store) { create(:store, supported_currencies: 'USD,EUR,GBP') } + + context 'when switching to a supported currency' do + let(:new_currency) { 'EUR' } + + context 'when product has a price in given currency' do + let!(:price) { create(:price, currency: 'EUR', variant: order.line_items.first.variant) } + + it 'changes order and line items currency' do + expect(subject).to be_success + order.reload + expect(order.currency).to eq('EUR') + expect(order.line_items.first.currency).to eq('EUR') + end + end + + context 'when product does not have a price in given currency' do + it 'returns failure' do + expect(subject).to be_failure + order.reload + expect(order.currency).to eq('USD') + expect(order.line_items.first.currency).to eq('USD') + end end end - context 'when product does not have a price in given currency' do + context 'when switching to an unsupported currency' do + let(:new_currency) { 'XOF' } + it 'returns failure' do expect(subject).to be_failure order.reload @@ -30,16 +90,5 @@ module Spree end end end - - context 'when switching to an unsupported currency' do - let(:new_currency) { 'XOF' } - - it 'returns failure' do - expect(subject).to be_failure - order.reload - expect(order.currency).to eq('USD') - expect(order.line_items.first.currency).to eq('USD') - end - end end end