I'm building a site for SpreeCommerce 2.1.3, and I'm stuck trying to figure out how to format the prices correctly.
The currency is DKK (Danish Kroner) and I'm looking for the following:
1000 => kr. 1.000,-
1000.50 => kr. 1.000,50
Spree formats my prices like this:
1000 => kr.1.000,00
1000.50 => kr.1.000,50
So there are two problems:
I need a space between kr. and the price.
When there arent any decimals, I would like the decimals rendered as ,- (example: 1.000,-)
How do I accomplish that?
Here's my configuration from config/initializers/spree.rb:
Spree.config do |config|
# [...]
config.currency = "DKK"
config.currency_symbol_position = "before"
config.currency_decimal_mark = ","
config.currency_thousands_separator = "."
end
Solution:
1) I added this decorator to Spree::Money (to replace ,00 with ,-):
Spree::Money.class_eval do
def to_s
formatted = #money.format(#options)
formatted.gsub(/,00$/, ",-")
end
def to_html(options = { :html => true })
to_s
end
end
2) I configured danish currency in my initializer (to add the space after kr.):
Money::Currency.register({
:priority => 1,
:iso_code => "DKK",
:iso_numeric => "208",
:name => "Danish krone",
:symbol => "kr. ",
:subunit => "Øre",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
You can customize https://github.com/spree/spree/blob/master/core/lib/spree/money.rb as you want by overriding it.
Related
I am simply trying to plot a map for the distance_matrix Google API that shows the current location of one object and the distance between the other. (Simple GPS) using lon and lat -- Currently, both objects are configured correctly to support the Distance Matrix Map, but I cannot get the map to show in the view. I don't know if I am coding the parameters correctly. How can I setup my Distance Matrix helper method to show the map in the view with the current_location and time that it takes to reach the destination?
trucks_helper.rb
distance_matrix_map [Doesn't work]
def distance_matrix_map_for(location, options={})
params = {
:origins => [location.lat, location.lon].join(", "),
:zoom => 15,
:size => "500x500",
:destinations => [location.delivery.delivery_order.order.lat, location.delivery.delivery_order.order.lon].join(","),
:sensor => true
}.merge(options)
query_string = params.map{|k, v| "#{k}=#{v}"}.join("&")
image_tag "http://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&#{query_string}", :alt => location.current_location_title, class: 'img-fluid img-rounded'
end
static_map_for builder [Works]
def static_map_for(location, options = {})
params = {
:center => [location.lat, location.lon].join(","),
:zoom => 15,
:size => "300x300",
:markers => [location.lat, location.lon].join(","),
:sensor => true
}.merge(options)
query_string = params.map {|k, v| "#{k}=#{v}"}.join("&")
image_tag "http://maps.googleapis.com/maps/api/staticmap?#{query_string}", :alt => location.current_location_title, class: 'img-fluid img-rounded'
end
I'm trying use the gem money-rails but with no success.
I live in Brazil and here the decimal mark is "," and the thousand separator is "."
So, I add the follow code in a money.rb initializer:
MoneyRails.configure do |config|
config.default_currency = :brl
config.register_currency = {
:id => :brl,
:priority => 1,
:iso_code => "BRL",
:name => "Real",
:symbol => "R$",
:symbol_first => true,
:subunit => "Cent",
:subunit_to_unit => 100,
:thousands_separator => ".",
:decimal_mark => ","
}
end
And in my model class "Produto":
class Produto < ApplicationRecord
attr_accessor :nome, :preco
monetize :preco_centavos
end
But when I try use this in Rails console I get a different behavior:
irb(main):001:0> p = Produto.new
=> #<Produto id: nil, nome: nil, preco_centavos: 0, preco_currency: "BRL", created_at: nil, updated_at: nil>
irb(main):002:0> p.preco = 1000.to_money
=> #<Money fractional:100 currency:BRL>
irb(main):003:0> p.preco.format
=> "R$1,000.00"
The format method return "R$1,000.00" when I expect "R$1.000,00".
Someone already passed for this?
PS: Sorry for my bad English
This is a bug (or at least a misleading feature) in the money-rails gem code. Set Money.use_i18n = false. Once you do this, then you won't need to do config.register_currency for the commas/decimals, at least. 1000.to_money('BRL').format yields "R$1.000,00".
See https://github.com/RubyMoney/money-rails/blob/4a35ae823843fba80c036e2332e80d6b9e06dcb5/lib/money-rails/active_model/validator.rb#L58 for why this is the case.
I'm currently using Spree 3.0 and changed my currency to Colombian Peso (COP). Right now prices are shown like this: ₱80.000,00. I want them to look like this: $ 80.000. I have an idea on how to remove the two 0 after the comma but haven't been able to change the currency symbol for $. This is what I have so far:
in /config/initializers/spree.rb
Spree.config do |config|
config.logo = 'templo samadhi logo.png'
config.admin_interface_logo = 'templo samadhi logo.png'
country = Spree::Country.find_by_name('Colombia')
config.default_country_id = country.id if country.present?
config.checkout_zone = country.id
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Colombia",
:symbol => "$ ",
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
end
This is somehow working because the ₱ symbol is getting removed but the $ is not showing up.
I appreciate if someone can help me with this.
UPDATE
I added the following and now I'm removing the two 0 after the comma but I'm also getting a $ after the price like this: 80.000 $.
So right now I don't know how to move the $ symbol before the price.
Spree::Money.class_eval do
def to_s
formatted = #money.format(#options)
formatted.gsub(/,00/, "")
formatted.symbol_position == :before
end
def to_html(options = { :html => true })
to_s
end
end
I was using this solution but found an issue when I try to process the payment through the stripe gateway, it actually needs the amount subunit to be "Cents" in order to make the currency conversion.
With the #luisjar answer you actually don't use subunits in the COP currency but they may be needed for some payment gateways like stripe. In order to use the COP currency (or any other currency) with a subunit but without showing it, you need to set the format property no_cents true. This is the way I show the amount in Colombian Peso currency like $ 10,000 COP.
Spree.config do |config|
#Change currency symbol for Colombia
country = Spree::Country.find_by_name('Colombia')
config.default_country_id = country.id if country.present?
config.checkout_zone = country.id
Spree::Money.class_eval do
def to_s
#money.format.gsub(/,00/, "")
#money.format(:symbol_position => :before, :with_currency => true, :no_cents => true)
end
def to_html(options = { :html => true })
to_s
end
end
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Colombia",
:symbol => "$ ",
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
Spree::Price.update_all(currency: 'COP')
end
I hope this help to any other confused (like me) with the currencies in Spree.
You can read more about currency format in: https://github.com/RubyMoney/money/blob/master/lib/money/money/formatting.rb
With the code, you merely register another currency. Each product(-variant) has many prices, one per currency. You should make sure, probably in a migration, that all your prices on all your variants are updated to use the correct currency.
Spree::Price.update_all(currency: 'COP')
If you don't want to loose the Dollar prices, but instead want to add an additional price, you need to edit each one manually, or on a migration.
Spree::Price.find_each do |price|
Spree::Price.create(variant: price.variant, amount: price.amount * 1.337, currency: 'COP')
end
Where 1.337 is a conversion factor.
I finally found how to remove the two ceros after the comma, use the $ symbol but still use the Colombian peso Currency. This is the way I did it.
Spree.config do |config|
config.logo = 'templo samadhi logo.png'
config.admin_interface_logo = 'templo samadhi logo.png'
country = Spree::Country.find_by_name('Colombia')
config.default_country_id = country.id if country.present?
config.checkout_zone = country.id
Spree::Money.class_eval do
def to_s
#money.format.gsub(/,00/, "")
#money.format(:symbol_position => :before)
end
def to_html(options = { :html => true })
to_s
end
end
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Colombia",
:symbol => "$ ",
:subunit => "Peso",
:subunit_to_unit => 1,
:separator => ".",
:delimiter => ","
})
end
Looking at documentation of class Currency (in gems/money_6.9.0/lib/money/currency.rb) I found better the following settings:
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Peso",
:symbol => "$",
:html_entity => "$ ",
:symbol_first => true,
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
The "name" attribute is the name of the currency, not the name of the country. The space between the $ and the number goes inside the "html_entity" and not in the symbol. Finally, the "symbol_first" attribute controls where to place the symbol.
I am in a rails 3.2.6 app using the gems money and money-rails.
For money-rails I have set-up an initializer with this data:
MoneyRails.configure do |config|
config.default_currency = :eur
config.register_currency = {
:id => :euc,
:priority => 1,
:iso_code => "EUR",
:name => "Euro with Comma decimal mark",
:symbol => "€",
:symbol_first => true,
:subunit => "Cent",
:subunit_to_unit => 100,
:thousands_separator => ".",
:decimal_mark => ","
}
end
Note I have created a new currency :euc, because I want to display the euro currency with the comma decimal separator,
but the problem is the money object doesn't display yet the comma, for example:
amount = Money.new(100, 'EUR')
amount.to_s
or in a view:
<%= humanized_money amount %>
it display "1.00 instead of "1,00"
where am I doing wrong?
Try using amount.format(decimal_mark: ",") for now. It seems like a bug.
Try
100.to_money('EUR')
Money.new(100) considers 100 to be in cents.
I would like to turn a string with opening hours like this:
"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
Into this:
[ {:period => "Monday-Friday", :hours => "10:00-18:00"}, {:period => "Saturday", :hours => "12:00-17:00"}, {:period => "Sunday", :hours => "12:00-15:00"} ]
I'm trying it with the String.scan() method but can't figure out the Regexp.
Also if you have any suggestions of how to do it in reverse the best way (i.e. when getting the opening hours from a form.)
Update - Thank you all found perfect solutions! Right now I'm using (thanks kejadlen):
str.scan(/([\w-]+)>([\d:-]+)-([\d:]+)/).map { |(p,o,c)| {:period => p, :opens => o, :closes => c} }
But now how about reversing it =) So given:
[ {:opens=>"10:00", :closes=>"18:00", :period=>"Monday-Friday"},
{:opens=>"12:00", :closes=>"17:00", :period=>"Saturday"},
{:opens=>"12:00", :closes=>"15:00", :period=>"Sunday"} ]
I want to merge it to:
"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
If you prefer one-liners:
s = "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
s.split(/;/).map{|i| Hash[[[:period, :hours], i.split(/>/)].transpose]}
# or
s.split(/;/).map{|i| p, h = i.split(/>/); {:period => p, :hours => h}}
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]
Edit:
Regarding the reverse, this should do the job:
a.map{|i| "#{i[:period]}>#{i[:opens]}-#{i[:closes]}"}.join(';')
=> "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
this is how I would do it
str="Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
periods = str.split(';')
#=> ["Monday-Friday>10:00-18:00", "Saturday>12:00-17:00", "Sunday>12:00-15:00"]
period_array=[]
periods.each do |period|
period_with_hours = period.split('>')
period_array << {:period => period_with_hours.first, :hours => period_with_hours.last}
end
period_array
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]
Try this:
String S = ([^\>]*)\>([^\;]*)\;
String T = " {:period => $1, :hours => $2}, "
originalString.replaceAll(S,T);
Might have to play with the regexp a little more but that should about do it.
Edit - Well, you asked for the answer in the context of ruby and I gave you the Java answer but the regular expression should work anyway...
This looks like it works
the_input.split(';').collect{|pair|
period, hours = pair.split('>')
{:period => period, :hours => hours}
}
=> [{:hours=>"10:00-18:00", :period=>"Monday-Friday"}, {:hours=>"12:00-17:00", :
period=>"Saturday"}, {:hours=>"12:00-15:00", :period=>"Sunday"}]
str.scan(/([\w-]+)>([\d:-]+)/).map {|(p,h)| {:period => p, :hours => h }}