diff --git a/app/models/article_version.rb b/app/models/article_version.rb index c447bd55..9bed9aa3 100644 --- a/app/models/article_version.rb +++ b/app/models/article_version.rb @@ -40,14 +40,13 @@ class ArticleVersion < ApplicationRecord validates :price, numericality: { greater_than_or_equal_to: 0 } validates :group_order_granularity, numericality: { greater_than_or_equal_to: 0 } validates :deposit, :tax, numericality: true - validates :minimum_order_quantity, - numericality: { allow_nil: true, only_integer: false, if: :supplier_order_unit_is_si_convertible } - validates :minimum_order_quantity, - numericality: { allow_nil: true, only_integer: true, unless: :supplier_order_unit_is_si_convertible } + validates :minimum_order_quantity, numericality: { allow_nil: true } + # validates_uniqueness_of :name, :scope => [:supplier_id, :deleted_at, :type], if: Proc.new {|a| a.supplier.shared_sync_method.blank? or a.supplier.shared_sync_method == 'import' } # validates_uniqueness_of :name, :scope => [:supplier_id, :deleted_at, :type, :unit, :unit_quantity] validate :uniqueness_of_name validate :only_one_unit_type + validate :minimum_order_quantity_as_integer, unless: :supplier_order_unit_is_si_convertible # Replace numeric seperator with database format localize_input_of :price, :tax, :deposit @@ -117,13 +116,7 @@ def minimum_order_quantity=(value) if value.blank? self[:minimum_order_quantity] = nil else - value = value.gsub(I18n.t('number.format.separator'), '.') if value.is_a?(String) - begin - value = value.to_i if Float(value) % 1 == 0 - rescue ArgumentError - # not any number -> let validation handle this - end - super(value) + super end end @@ -190,6 +183,17 @@ def uniqueness_of_name end end + def minimum_order_quantity_as_integer + begin + return if Float(minimum_order_quantity) % 1 == 0 + rescue ArgumentError, TypeError + # not any number -> let numericality validation handle this + return + end + + errors.add(:minimum_order_quantity, :only_integer) + end + def only_one_unit_type return if unit.blank? || supplier_order_unit.blank? diff --git a/app/models/order_article.rb b/app/models/order_article.rb index 0b29c4d4..a176675f 100644 --- a/app/models/order_article.rb +++ b/app/models/order_article.rb @@ -81,6 +81,7 @@ def update_results! # 4 | 5 | 4 | 2 # def calculate_units_to_order(quantity, tolerance = 0) + return 0 if !price.minimum_order_quantity.nil? && quantity + tolerance < price.minimum_order_quantity return price.minimum_order_quantity if quantity > 0 && !price.minimum_order_quantity.nil? && quantity < price.minimum_order_quantity && quantity + tolerance >= price.minimum_order_quantity unit_size = price.convert_quantity(1, price.supplier_order_unit, price.group_order_unit) diff --git a/config/locales/de.yml b/config/locales/de.yml index bf0cdd7c..6a699ea6 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -272,6 +272,8 @@ de: name: taken: Name ist bereits vergeben taken_with_unit: Name und Einheit sind bereits vergeben + minimum_order_quantity: + only_integer: Muss eine Ganzzahl sein, wenn die Liefereinheit eine Stückeinheit ist. supplier: attributes: shared_sync_method: diff --git a/config/locales/en.yml b/config/locales/en.yml index 480243cb..6129e6dc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -274,6 +274,8 @@ en: name: taken: name is already taken taken_with_unit: name and unit are already taken + minimum_order_quantity: + only_integer: Must be an integer if supplier order unit is a piece unit supplier: attributes: shared_sync_method: diff --git a/spec/factories/article.rb b/spec/factories/article.rb index f64cfab1..ce6e6b39 100644 --- a/spec/factories/article.rb +++ b/spec/factories/article.rb @@ -10,6 +10,7 @@ order_number { nil } unit_quantity { nil } unit { nil } + minimum_order_quantity { nil } supplier_order_unit { 'XPK' } group_order_unit { 'XPK' } billing_unit { 'XPK' } @@ -23,6 +24,7 @@ order_number: evaluator.order_number, unit_quantity: evaluator.unit_quantity, unit: evaluator.unit, + minimum_order_quantity: evaluator.minimum_order_quantity, supplier_order_unit: evaluator.supplier_order_unit, group_order_unit: evaluator.group_order_unit, billing_unit: evaluator.billing_unit, diff --git a/spec/models/order_article_spec.rb b/spec/models/order_article_spec.rb index a0bc9671..78f46d4e 100644 --- a/spec/models/order_article_spec.rb +++ b/spec/models/order_article_spec.rb @@ -213,4 +213,59 @@ def goa_reload # end end end + + describe 'minimum order quantity' do + let(:order) { create(:order, article_ids: [article.id], starts: 1.week.ago) } + let(:oa) { order.order_articles.first } + let(:go) { create(:group_order, order: order) } + let(:goa) { create(:group_order_article, group_order: go, order_article: oa) } + + shared_context 'minimum order quantity' do |quantity| + before do + goa.update_quantities(quantity[:quantity], quantity[:tolerance]) + oa.update_results! + oa.reload + end + + it 'is calculated correctly' do + expect(oa.units_to_order).to eq quantity[:expected_units_to_order] + end + end + + context 'without unit_quantity' do + let(:article) { create(:article, minimum_order_quantity: 10) } + + context 'doesn\'t order anything, if the minimum order quantity hasn\'t been reached' do + include_examples 'minimum order quantity', { quantity: 4, tolerance: 0, expected_units_to_order: 0 } + end + + context 'orders the minimum order quantity, if tolerance allows for it' do + include_examples 'minimum order quantity', { quantity: 9, tolerance: 1, expected_units_to_order: 10 } + end + + context 'orders the desired amount, if minimum order quantity has been surpassed' do + include_examples 'minimum order quantity', { quantity: 12, tolerance: 1, expected_units_to_order: 12 } + end + end + + context 'with unit_quantity' do + let(:article) { create(:article, minimum_order_quantity: 2, unit_quantity: 5) } + + context 'doesn\'t order anything if the minimum order quantity hasn\'t been reached' do + include_examples 'minimum order quantity', { quantity: 4, tolerance: 0, expected_units_to_order: 0 } + end + + context 'orders the minimum order quantity if tolerance allows for it' do + include_examples 'minimum order quantity', { quantity: 9, tolerance: 1, expected_units_to_order: 2 } + end + + context 'orders a lower amount, even if minimum order quantity has been surpassed, but unit_quantity demands it' do + include_examples 'minimum order quantity', { quantity: 12, tolerance: 1, expected_units_to_order: 2 } + end + + context 'orders the exact amount, if minimum order quantity has been surpassed and unit_quantity allows for it' do + include_examples 'minimum order quantity', { quantity: 14, tolerance: 1, expected_units_to_order: 3 } + end + end + end end