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



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

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

.ransackable_attributes(_auth_object = nil) ⇒ Object



25
26
27
# File 'app/models/order_article.rb', line 25

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


85
86
87
88
89
90
# File 'app/models/order_article.rb', line 85

def calculate_units_to_order(quantity, tolerance = 0)
  unit_size = price.unit_quantity
  units = quantity / unit_size
  remainder = quantity % unit_size
  units += ((remainder > 0) && (remainder + tolerance >= unit_size) ? 1 : 0)
end

#difference_received_orderedObject



204
205
206
# File 'app/models/order_article.rb', line 204

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.



49
50
51
52
# File 'app/models/order_article.rb', line 49

def group_orders_sum
  quantity = group_order_articles.collect(&:result).sum
  { quantity: quantity, price: quantity * price.fc_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.



191
192
193
# File 'app/models/order_article.rb', line 191

def missing_units
  _missing_units(price.unit_quantity, quantity, tolerance)
end

#missing_units_wasObject



195
196
197
# File 'app/models/order_article.rb', line 195

def missing_units_was
  _missing_units(price.unit_quantity, quantity_was, tolerance_was)
end

#ordered_quantities_different_from_group_orders?(ordered_mark = '!', billed_mark = '?', received_mark = '?') ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
105
106
107
108
109
110
# File 'app/models/order_article.rb', line 102

def ordered_quantities_different_from_group_orders?(ordered_mark = '!', billed_mark = '?', received_mark = '?')
  if !units_received.nil?
    (units_received * price.unit_quantity) == group_orders_sum[:quantity] ? false : received_mark
  elsif !units_billed.nil?
    (units_billed * price.unit_quantity) == group_orders_sum[:quantity] ? false : billed_mark
  elsif !units_to_order.nil?
    (units_to_order * price.unit_quantity) == group_orders_sum[:quantity] ? false : ordered_mark
  end
end

#priceObject

This method returns either the ArticlePrice or the Article The first will be set, when the the order is finished



35
36
37
# File 'app/models/order_article.rb', line 35

def price
  article_price || article
end

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

redistribute articles over ordergroups

quantity       Number of units to distribute
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



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
150
151
152
153
154
# File 'app/models/order_article.rb', line 120

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)


200
201
202
# File 'app/models/order_article.rb', line 200

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

#total_gross_priceObject

Calculate gross price for ordered qunatity.



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

def total_gross_price
  units * price.unit_quantity * price.gross_price
end

#total_priceObject

Calculate price for ordered quantity.



93
94
95
# File 'app/models/order_article.rb', line 93

def total_price
  units * price.unit_quantity * price.price
end

#unitsObject

latest information on available units



40
41
42
43
44
45
# File 'app/models/order_article.rb', line 40

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

  units_to_order
end

#update_article_and_price!(order_article_attributes, article_attributes, price_attributes = nil) ⇒ Object

Updates order_article and belongings during balancing process



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'app/models/order_article.rb', line 157

def update_article_and_price!(order_article_attributes, article_attributes, price_attributes = nil)
  OrderArticle.transaction do
    # Updates self
    update!(order_article_attributes)

    # Updates article
    article.update!(article_attributes)

    # Updates article_price belonging to current order article
    if price_attributes.present?
      article_price.attributes = price_attributes
      if article_price.changed?
        # Updates also price attributes of article if update_global_price is selected
        if update_global_price
          article.update!(price_attributes)
          self.article_price = article.article_prices.first and save # Assign new created article price to order article
        else
          # Creates a new article_price if neccessary
          # Set created_at timestamp to order ends, to make sure the current article price isn't changed
          create_article_price!(price_attributes.merge(article_id: article_id, created_at: order.ends)) and save
        end

        # Updates ordergroup values
        update_ordergroup_prices
      end
    end
  end
end

#update_results!Object

Update quantity/tolerance/units_to_order from group_order_articles



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

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