Class: OrderArticle

Inherits:
ApplicationRecord show all
Includes:
FindEachWithOrder
Defined in:
app/models/order_article.rb

Overview

An OrderArticle represents a single Article that is part of an Order.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#update_global_priceObject

Returns the value of attribute update_global_price.



5
6
7
# File 'app/models/order_article.rb', line 5

def update_global_price
  @update_global_price
end

Class Method Details

.ransackable_associations(_auth_object = nil) ⇒ Object



33
34
35
# File 'app/models/order_article.rb', line 33

def self.ransackable_associations(_auth_object = nil)
  %w[order article]
end

.ransackable_attributes(_auth_object = nil) ⇒ Object



29
30
31
# File 'app/models/order_article.rb', line 29

def self.ransackable_attributes(_auth_object = nil)
  %w[id order_id article_id quantity tolerance units_to_order]
end

Instance Method Details

#calculate_units_to_order(quantity, tolerance = 0) ⇒ Object

Returns how many units of the belonging article need to be ordered given the specified order quantity and tolerance. This is determined by calculating how many units can be ordered from the given order quantity, using the tolerance to order an additional unit if the order quantity is not quiet sufficient. There must always be at least one item in a unit that is an ordered quantity (no units are ever entirely filled by tolerance items only).

Example:

unit_quantity | quantity | tolerance | calculate_units_to_order ————–----------———–+———————–

4        |    0     |     2     |           0
4        |    0     |     5     |           0
4        |    2     |     2     |           1
4        |    4     |     2     |           1
4        |    4     |     4     |           1
4        |    5     |     3     |           2
4        |    5     |     4     |           2


83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/models/order_article.rb', line 83

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)
  if price.supplier_order_unit_is_si_convertible
    quantity / unit_size
  else
    units = (quantity / unit_size).floor
    remainder = quantity % unit_size
    units += ((remainder > 0) && (remainder + tolerance >= unit_size) ? 1 : 0)
  end
end

#difference_received_orderedObject



189
190
191
# File 'app/models/order_article.rb', line 189

def difference_received_ordered
  (units_received || 0) - units_to_order
end

#group_orders_sumObject

Count quantities of belonging group_orders. In balancing this can differ from ordered (by supplier) quantity for this article.



47
48
49
50
# File 'app/models/order_article.rb', line 47

def group_orders_sum
  quantity = group_order_articles.collect(&:result).sum
  { quantity: quantity, price: quantity * price.fc_group_order_price }
end

#missing_unitsNumber

Returns Units missing for the last unit_quantity of the article.

Returns:

  • (Number)

    Units missing for the last unit_quantity of the article.



174
175
176
177
# File 'app/models/order_article.rb', line 174

def missing_units
  unit_ratio = price.convert_quantity(1, price.supplier_order_unit, price.group_order_unit)
  _missing_units(unit_ratio, quantity, tolerance, price.minimum_order_quantity)
end

#missing_units_wasObject



179
180
181
182
# File 'app/models/order_article.rb', line 179

def missing_units_was
  unit_ratio = price.convert_quantity(1, price.supplier_order_unit, price.group_order_unit)
  _missing_units(unit_ratio, quantity_was, tolerance_was, price.minimum_order_quantity)
end

#redistribute(quantity, surplus = [:tolerance], update_totals = true) ⇒ Object

redistribute articles over ordergroups

quantity       Number of units to distribute (in group_order_unit)
surplus        What to do when there are more articles than ordered quantity
                 :tolerance   fill member orders' tolerance
                 :stock       move to stock
                 nil          nothing; for catching the remaining count
update_totals  Whether to update group_order and ordergroup totals

returns array with counts for each surplus method



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/models/order_article.rb', line 115

def redistribute(quantity, surplus = [:tolerance], update_totals = true)
  qty_left = quantity
  counts = [0] * surplus.length

  if surplus.index(:tolerance).nil?
    qty_for_members = [qty_left, self.quantity].min
  else
    qty_for_members = [qty_left, self.quantity + tolerance].min
    counts[surplus.index(:tolerance)] = [0, qty_for_members - self.quantity].max
  end

  # Recompute
  group_order_articles.each { |goa| goa.save_results! qty_for_members }
  qty_left -= qty_for_members

  # if there's anything left, move to stock if wanted
  if qty_left > 0 && surplus.index(:stock)
    counts[surplus.index(:stock)] = qty_left
    # 1) find existing stock article with same name, unit, price
    # 2) if not found, create new stock article
    #      avoiding duplicate stock article names
  end
  counts[surplus.index(nil)] = qty_left if qty_left > 0 && surplus.index(nil)

  # Update GroupOrder prices & Ordergroup stats
  # TODO only affected group_orders, and once after redistributing all articles
  if update_totals
    update_ordergroup_prices
    order.ordergroups.each(&:update_stats!)
  end

  # TODO: notifications

  counts
end

#result_manually_changed?Boolean

Check if the result of any associated GroupOrderArticle was overridden manually

Returns:

  • (Boolean)


185
186
187
# File 'app/models/order_article.rb', line 185

def result_manually_changed?
  group_order_articles.any? { |goa| goa.result_manually_changed? }
end

#total_gross_priceObject

Calculate gross price for ordered qunatity.



103
104
105
# File 'app/models/order_article.rb', line 103

def total_gross_price
  units * price.gross_price
end

#total_priceObject

Calculate price for ordered quantity.



98
99
100
# File 'app/models/order_article.rb', line 98

def total_price
  units * price.price
end

#unitsObject

latest information on available units



38
39
40
41
42
43
# File 'app/models/order_article.rb', line 38

def units
  return units_received unless units_received.nil?
  return units_billed unless units_billed.nil?

  units_to_order
end

#update_handling_versioning!(order_article_attributes, version_attributes) ⇒ Object

Updates order_article and belongings during balancing process



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'app/models/order_article.rb', line 152

def update_handling_versioning!(order_article_attributes, version_attributes)
  OrderArticle.transaction do
    # Updates self
    update!(order_article_attributes)

    # Updates article_version belonging to current order article
    original_article_version = article_version.duplicate_including_article_unit_ratios
    article_version.assign_attributes(version_attributes)
    if article_version.changed?
      update_or_create_article_version(version_attributes, original_article_version)

      # Updates ordergroup values
      update_ordergroup_prices
    end
  end
end

#update_results!Object

Update quantity/tolerance/units_to_order from group_order_articles



53
54
55
56
57
58
59
60
61
62
63
# File 'app/models/order_article.rb', line 53

def update_results!
  if order.open?
    self.quantity = group_order_articles.collect(&:quantity).sum
    self.tolerance = group_order_articles.collect(&:tolerance).sum
    self.units_to_order = calculate_units_to_order(quantity, tolerance)
    enforce_boxfill if order.boxfill?
    save!
  elsif order.finished?
    update_attribute(:units_to_order, group_order_articles.collect(&:result).sum)
  end
end