From 7c4c7cd9b4e875ddd4e50a41d7b58003ebc3f107 Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Mon, 30 May 2022 21:38:10 +0200 Subject: [PATCH] Fix creating store credit with amount in foreign format The numericality validation in rails cannot handle prices in non-float based amounts (Ie. 100,00 EUR). Using `Spree::LocalizedNumber` to convert the amount before validation. --- core/app/models/spree/store_credit.rb | 8 ++++++ core/spec/models/spree/store_credit_spec.rb | 32 +++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/core/app/models/spree/store_credit.rb b/core/app/models/spree/store_credit.rb index b13fee90dbe..1e2bc0bdd09 100644 --- a/core/app/models/spree/store_credit.rb +++ b/core/app/models/spree/store_credit.rb @@ -40,6 +40,14 @@ class Spree::StoreCredit < Spree::PaymentSource extend Spree::DisplayMoney money_methods :amount, :amount_used, :amount_authorized + # Sets this store credit's amount to a new value, + # parsing it as a localized number if the new value is a string. + # + # @param number [String, #to_d] a new amount + def amount=(number) + self[:amount] = Spree::LocalizedNumber.parse(number) + end + def amount_remaining return 0.0.to_d if invalidated? amount - amount_used - amount_authorized diff --git a/core/spec/models/spree/store_credit_spec.rb b/core/spec/models/spree/store_credit_spec.rb index 52b35b43ef3..93670055147 100644 --- a/core/spec/models/spree/store_credit_spec.rb +++ b/core/spec/models/spree/store_credit_spec.rb @@ -155,6 +155,38 @@ end end + describe "#amount=" do + let(:store_credit) { described_class.new(amount: amount) } + + context "with an imperial price format" do + let(:amount) { "1,000.50" } + + before do + expect(I18n).to receive(:t).with(:'number.currency.format.separator') do + "." + end + end + + it "sets the correct amount" do + expect(store_credit.amount).to eq(1000.5) + end + end + + context "with an european price format" do + let(:amount) { "1.000,50" } + + before do + expect(I18n).to receive(:t).with(:'number.currency.format.separator') do + "," + end + end + + it "sets the correct amount" do + expect(store_credit.amount).to eq(1000.5) + end + end + end + describe "#amount_remaining" do context "invalidated" do before { allow(store_credit).to receive(:invalidated?) { true } }