diff --git a/config/initializers/money.rb b/config/initializers/money.rb new file mode 100644 index 0000000000..1dea6e473b --- /dev/null +++ b/config/initializers/money.rb @@ -0,0 +1,2 @@ +Money.rounding_mode = BigDecimal::ROUND_HALF_EVEN +Money.default_currency = Money::Currency.new(Spree::Config[:currency]) diff --git a/lib/spree/money.rb b/lib/spree/money.rb index 8ff14ce203..994aceabb7 100644 --- a/lib/spree/money.rb +++ b/lib/spree/money.rb @@ -10,15 +10,12 @@ module Spree def initialize(amount, options = {}) @money = ::Monetize.parse([amount, (options[:currency] || Spree::Config[:currency])].join) - @options = {} - @options[:with_currency] = Spree::Config[:display_currency] - @options[:symbol_position] = Spree::Config[:currency_symbol_position].to_sym - @options[:no_cents] = Spree::Config[:hide_cents] - @options[:decimal_mark] = Spree::Config[:currency_decimal_mark] - @options[:thousands_separator] = Spree::Config[:currency_thousands_separator] - @options.merge!(options) - # Must be a symbol because the Money gem doesn't do the conversion - @options[:symbol_position] = @options[:symbol_position].to_sym + + if options.key?(:symbol_position) + options[:format] = position_to_format(options.delete(:symbol_position)) + end + + @options = defaults.merge(options) end # Return the currency symbol (on its own) for the current default currency @@ -30,14 +27,8 @@ module Spree @money.format(@options) end - def to_html(options = { html: true }) - output = @money.format(@options.merge(options)) - if options[:html] - # 1) prevent blank, breaking spaces - # 2) prevent escaping of HTML character entities - output = output.sub(" ", " ").html_safe - end - output + def to_html(options = { html_wrap: true }) + @money.format(@options.merge(options)).html_safe end def format(options = {}) @@ -47,5 +38,30 @@ module Spree def ==(other) @money == other.money end + + private + + def defaults + { + with_currency: Spree::Config[:display_currency], + no_cents: Spree::Config[:hide_cents], + decimal_mark: Spree::Config[:currency_decimal_mark], + thousands_separator: Spree::Config[:currency_thousands_separator], + format: position_to_format(Spree::Config[:currency_symbol_position]) + } + end + + def position_to_format(position) + return if position.nil? + + case position.to_sym + when :before + '%u%n' + when :after + '%n %u' + else + raise 'Invalid symbol position' + end + end end end diff --git a/spec/features/admin/configuration/general_settings_spec.rb b/spec/features/admin/configuration/general_settings_spec.rb index 6c5b70a4ba..ecb6d61c91 100644 --- a/spec/features/admin/configuration/general_settings_spec.rb +++ b/spec/features/admin/configuration/general_settings_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' describe "General Settings" do include AuthenticationHelper - before(:each) do + before do login_as_admin_and_visit spree.admin_dashboard_path click_link "Configuration" click_link "General Settings" @@ -24,16 +24,25 @@ describe "General Settings" do fill_in "site_name", with: "OFN Demo Site99" click_button "Update" - assert_successful_update_message(:general_settings) - + within("[class='flash success']") do + expect(page).to have_content(Spree.t(:successfully_updated, resource: Spree.t(:general_settings))) + end expect(find("#site_name").value).to eq("OFN Demo Site99") end + end - def assert_successful_update_message(resource) - flash = Spree.t(:successfully_updated, resource: Spree.t(resource)) - within("[class='flash success']") do - expect(page).to have_content(flash) + context 'editing currency symbol position' do + it 'updates its position' do + expect(page).to have_content('Currency Settings') + + within('.currency') do + find("[for='currency_symbol_position_after']").click end + + click_button 'Update' + + expect(page).to have_content(Spree.t(:successfully_updated, resource: Spree.t(:general_settings))) + expect(page).to have_checked_field('10.00 $') end end end diff --git a/spec/lib/spree/money_spec.rb b/spec/lib/spree/money_spec.rb index 12b1d975b8..676572eff6 100644 --- a/spec/lib/spree/money_spec.rb +++ b/spec/lib/spree/money_spec.rb @@ -25,13 +25,13 @@ describe Spree::Money do context "with currency" do it "passed in option" do - money = Spree::Money.new(10, with_currency: true, html: false) + money = Spree::Money.new(10, with_currency: true, html_wrap: false) expect(money.to_s).to eq("$10.00 USD") end it "config option" do Spree::Config[:display_currency] = true - money = Spree::Money.new(10, html: false) + money = Spree::Money.new(10, html_wrap: false) expect(money.to_s).to eq("$10.00 USD") end end @@ -53,14 +53,14 @@ describe Spree::Money do context "currency parameter" do context "when currency is specified in Canadian Dollars" do it "uses the currency param over the global configuration" do - money = Spree::Money.new(10, currency: 'CAD', with_currency: true, html: false) + money = Spree::Money.new(10, currency: 'CAD', with_currency: true, html_wrap: false) expect(money.to_s).to eq("$10.00 CAD") end end context "when currency is specified in Japanese Yen" do it "uses the currency param over the global configuration" do - money = Spree::Money.new(100, currency: 'JPY', html: false) + money = Spree::Money.new(100, currency: 'JPY', html_wrap: false) expect(money.to_s).to eq("¥100") end end @@ -68,34 +68,24 @@ describe Spree::Money do context "symbol positioning" do it "passed in option" do - money = Spree::Money.new(10, symbol_position: :after, html: false) + money = Spree::Money.new(10, symbol_position: :after, html_wrap: false) expect(money.to_s).to eq("10.00 $") end it "passed in option string" do - money = Spree::Money.new(10, symbol_position: "after", html: false) + money = Spree::Money.new(10, symbol_position: "after", html_wrap: false) expect(money.to_s).to eq("10.00 $") end it "config option" do Spree::Config[:currency_symbol_position] = :after - money = Spree::Money.new(10, html: false) + money = Spree::Money.new(10, html_wrap: false) expect(money.to_s).to eq("10.00 $") end - end - context "JPY" do - before do - configure_spree_preferences do |config| - config.currency = "JPY" - config.currency_symbol_position = :before - config.display_currency = false - end - end - - it "formats correctly" do - money = Spree::Money.new(1000, html: false) - expect(money.to_s).to eq("¥1,000") + it 'raises with invalid position' do + expect { Spree::Money.new(10, symbol_position: 'invalid') } + .to raise_error('Invalid symbol position') end end @@ -128,10 +118,14 @@ describe Spree::Money do expect(money.to_s).to eq("1.000.00 €") end + # rubocop:disable Layout/LineLength it "formats as HTML if asked (nicely) to" do money = Spree::Money.new(10) # The HTMLified version of the euro sign - expect(money.to_html).to eq("10.00 €") + expect(money.to_html).to eq( + "10.00 " + ) end + # rubocop:enable Layout/LineLength end end