85bdf28f91
see https://github.com/foodcoops/foodsoft/pull/907 for reference and original work by viehlieb Co-authored-by: viehlieb <pf@pragma-shift.net> fix PDF Pdf
114 lines
4 KiB
Ruby
114 lines
4 KiB
Ruby
# A GroupOrder represents an Order placed by an Ordergroup.
|
|
class GroupOrder < ApplicationRecord
|
|
include FindEachWithOrder
|
|
|
|
attr_accessor :group_order_articles_attributes
|
|
|
|
belongs_to :order
|
|
belongs_to :ordergroup, optional: true
|
|
has_many :group_order_articles, dependent: :destroy
|
|
has_many :order_articles, through: :group_order_articles
|
|
has_one :financial_transaction
|
|
has_one :group_order_invoice
|
|
belongs_to :updated_by, optional: true, class_name: 'User', foreign_key: 'updated_by_user_id'
|
|
|
|
validates :order_id, presence: true
|
|
validates :price, numericality: true
|
|
validates :ordergroup_id, uniqueness: { scope: :order_id } # order groups can only order once per order
|
|
|
|
scope :in_open_orders, -> { joins(:order).merge(Order.open) }
|
|
scope :in_finished_orders, -> { joins(:order).merge(Order.finished_not_closed) }
|
|
scope :stock, -> { where(ordergroup: 0) }
|
|
|
|
scope :ordered, -> { includes(:ordergroup).order('groups.name') }
|
|
|
|
def self.ransackable_attributes(_auth_object = nil)
|
|
%w[id price]
|
|
end
|
|
|
|
def self.ransackable_associations(_auth_object = nil)
|
|
%w[order group_order_articles]
|
|
end
|
|
|
|
# Generate some data for the javascript methods in ordering view
|
|
def load_data
|
|
data = {}
|
|
data[:account_balance] = ordergroup.nil? ? BigDecimal('+Infinity') : ordergroup.account_balance
|
|
data[:available_funds] = ordergroup.nil? ? BigDecimal('+Infinity') : ordergroup.get_available_funds(self)
|
|
|
|
# load prices and other stuff....
|
|
data[:order_articles] = {}
|
|
order.articles_grouped_by_category.each do |_article_category, order_articles|
|
|
order_articles.each do |order_article|
|
|
# Get the result of last time ordering, if possible
|
|
goa = group_order_articles.detect { |goa| goa.order_article_id == order_article.id }
|
|
|
|
# Build hash with relevant data
|
|
data[:order_articles][order_article.id] = {
|
|
price: order_article.article.fc_price,
|
|
unit: order_article.article.unit_quantity,
|
|
quantity: (goa ? goa.quantity : 0),
|
|
others_quantity: order_article.quantity - (goa ? goa.quantity : 0),
|
|
used_quantity: (goa ? goa.result(:quantity) : 0),
|
|
tolerance: (goa ? goa.tolerance : 0),
|
|
others_tolerance: order_article.tolerance - (goa ? goa.tolerance : 0),
|
|
used_tolerance: (goa ? goa.result(:tolerance) : 0),
|
|
total_price: (goa ? goa.total_price : 0),
|
|
missing_units: order_article.missing_units,
|
|
quantity_available: (order.stockit? ? order_article.article.quantity_available : 0)
|
|
}
|
|
end
|
|
end
|
|
|
|
data
|
|
end
|
|
|
|
def save_group_order_articles
|
|
for order_article in order.order_articles
|
|
# Find the group_order_article, create a new one if necessary...
|
|
group_order_article = group_order_articles.where(order_article_id: order_article.id).first_or_create
|
|
|
|
# Get ordered quantities and update group_order_articles/_quantities...
|
|
if group_order_articles_attributes
|
|
quantities = group_order_articles_attributes.fetch(order_article.id.to_s, { quantity: 0, tolerance: 0 })
|
|
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
|
|
end
|
|
|
|
# Also update results for the order_article
|
|
logger.debug '[save_group_order_articles] update order_article.results!'
|
|
order_article.update_results!
|
|
end
|
|
|
|
# set attributes to nil to avoid and infinite loop of
|
|
end
|
|
|
|
# Updates the "price" attribute.
|
|
def update_price!
|
|
total = group_order_articles.includes(order_article: %i[article article_price]).to_a.sum(&:total_price)
|
|
update_attribute(:price, total)
|
|
end
|
|
|
|
# Save GroupOrder and updates group_order_articles/quantities accordingly
|
|
def save_ordering!
|
|
transaction do
|
|
save!
|
|
save_group_order_articles
|
|
update_price!
|
|
end
|
|
end
|
|
|
|
def ordergroup_name
|
|
if ordergroup
|
|
ordergroup.name
|
|
else
|
|
I18n.t('model.group_order.stock_ordergroup_name',
|
|
user: updated_by.try(:name) || '?')
|
|
end
|
|
end
|
|
|
|
def total
|
|
return price + transport if transport
|
|
|
|
price
|
|
end
|
|
end
|