diff --git a/Gemfile b/Gemfile index 32448123..5201e2ae 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,7 @@ gem "rails-settings-cached", "0.3.1" gem 'resque' gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb gem 'protected_attributes' +gem 'ruby-units' # we use the git version of acts_as_versioned, and need to include it in this Gemfile gem 'acts_as_versioned', git: 'git://github.com/technoweenie/acts_as_versioned.git' diff --git a/Gemfile.lock b/Gemfile.lock index a5a00b98..e185bc1f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -281,6 +281,7 @@ GEM rspec-rerun (0.1.3) rspec (>= 2.11.0) ruby-prof (0.14.2) + ruby-units (1.4.4) rubyzip (1.1.0) sass (3.2.14) sass-rails (4.0.1) @@ -421,6 +422,7 @@ DEPENDENCIES rspec-rails rspec-rerun ruby-prof + ruby-units sass-rails (~> 4.0.0) select2-rails selenium-webdriver diff --git a/app/models/article.rb b/app/models/article.rb index 7fd6fa32..34b346ed 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -117,6 +117,7 @@ class Article < ActiveRecord::Base # returns nil if units are eqal def convert_units if unit != shared_article.unit + # legacy, used by foodcoops in Germany if shared_article.unit == "KI" and unit == "ST" # 'KI' means a box, with a different amount of items in it # try to match the size out of its name, e.g. "banana 10-12 St" => 10 new_unit_quantity = /[0-9\-\s]+(St)/.match(shared_article.name).to_s.to_i @@ -126,13 +127,13 @@ class Article < ActiveRecord::Base else false end - else # get factors for fc and supplier - fc_unit_factor = FoodsoftConfig[:units][self.unit] - supplier_unit_factor = FoodsoftConfig[:units][self.shared_article.unit] - if fc_unit_factor and supplier_unit_factor - convertion_factor = fc_unit_factor / supplier_unit_factor - new_price = BigDecimal((convertion_factor * shared_article.price).to_s).round(2) - new_unit_quantity = ( 1 / convertion_factor) * shared_article.unit_quantity + else # use ruby-units to convert + fc_unit = (::Unit.new(unit) rescue nil) + supplier_unit = (::Unit.new(shared_article.unit) rescue nil) + if fc_unit and supplier_unit and fc_unit =~ supplier_unit + conversion_factor = (fc_unit.convert_to(supplier_unit.units) / supplier_unit).scalar + new_price = shared_article.price * conversion_factor + new_unit_quantity = shared_article.unit_quantity / conversion_factor [new_price, new_unit_quantity] else false diff --git a/config/app_config.yml.SAMPLE b/config/app_config.yml.SAMPLE index dc7c74be..f23aede7 100644 --- a/config/app_config.yml.SAMPLE +++ b/config/app_config.yml.SAMPLE @@ -91,22 +91,6 @@ default: &defaults encoding: utf8 socket: /opt/lampp/var/mysql/mysql.sock - # auto-units-conversion - # this is used for automatic article-synchronization to handle different units - # e.g. when foodcoop-unit should be 500g and supplier-unit is 1kg - units: - KG: 1 - 1kg: 1 - 500g: 0.5 - 400g: 0.4 - 300g: 0.3 - 250g: 0.25 - 200g: 0.2 - 150g: 0.15 - 125g: 0.125 - 100g: 0.1 - 50g: 0.05 - development: <<: *defaults diff --git a/config/initializers/ruby_units.rb b/config/initializers/ruby_units.rb new file mode 100644 index 00000000..74535948 --- /dev/null +++ b/config/initializers/ruby_units.rb @@ -0,0 +1,37 @@ +# add some more units + +if defined? RubyUnits + RubyUnits::Unit.redefine!('liter') do |unit| + unit.aliases += %w{ltr} + end + + RubyUnits::Unit.redefine!('kilogram') do |unit| + unit.aliases += %w{KG} + end + + RubyUnits::Unit.redefine!('gram') do |unit| + unit.aliases += %w{gr} + end + + RubyUnits::Unit.define('piece') do |unit| + unit.definition = RubyUnits::Unit.new('1 each') + unit.aliases = %w{pc pcs piece pieces} # locale: en + unit.aliases += %w{st stuk stuks} # locale: nl + unit.kind = :counting + end + + # we use pc for piece, not parsec + RubyUnits::Unit.redefine!('parsec') do |unit| + unit.aliases = unit.aliases.reject {|u| u=='pc'} + unit.display_name = 'parsec' + end + + # workaround for ruby-units' require mathn warning: "zero and implicit precision is deprecated." + # default precision of 8 which same as all database definitions in db/migrate/20131213002332_*.rb + class Rational + alias orig_to_d to_d + def to_d(precision=8) + orig_to_d(precision) + end + end +end