From 32e77ebd0998552956189d17f54ec5b3a253d1ce 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 d85946a8d46..682bf02eb56 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 badc26750b6..16e9ba31692 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 } }