457 lines
9.7 KiB
Ruby
457 lines
9.7 KiB
Ruby
class PSheetLine < ActiveRecord::Base
|
|
belongs_to :p_customer_sheet
|
|
|
|
belongs_to :p_document
|
|
|
|
has_one :p_customer, :through => :p_customer_sheet
|
|
belongs_to :p_product
|
|
belongs_to :p_tank
|
|
|
|
|
|
belongs_to :archived_p_product, :class_name => "PProduct"
|
|
|
|
has_many :p_sheet_line_stocks, :dependent => :destroy
|
|
|
|
has_many :p_sheet_line_lines, :dependent => :destroy
|
|
accepts_nested_attributes_for :p_sheet_line_lines
|
|
#validates :qte, :presence => true
|
|
#validates :price, :presence => true
|
|
|
|
validates :ok_qte, :presence => true, :if => :validate_ok?
|
|
validates :ok_price, :presence => true, :if => :validate_ok?
|
|
validates :ok_at, :presence => true, :if => :validate_ok?
|
|
|
|
validates :p_product, :presence => true
|
|
#validates :p_tank, :presence => true, :if => :validate_tank?
|
|
|
|
|
|
scope :oks, -> {where(:shiped => true).order("ok_at DESC")}
|
|
scope :not_oks, -> {where(:shiped => false).order("ok_at DESC")}
|
|
|
|
scope :between, lambda { |start, stop|
|
|
after(start).before(stop)
|
|
}
|
|
|
|
scope :after, lambda { |date|
|
|
where("(ok_at >= ?)", date )
|
|
}
|
|
scope :before, lambda { |date|
|
|
where("(ok_at <= ?)", date )
|
|
}
|
|
|
|
after_save do
|
|
self.p_customer_sheet.save if self.p_customer_sheet
|
|
end
|
|
|
|
before_save do
|
|
self.a_total_cost_ok = self.total_cost_ok
|
|
|
|
|
|
if self.bl and self.ok
|
|
self.shiped = true
|
|
self.lock = true
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
def ship_affects
|
|
affecteds = {}
|
|
|
|
|
|
|
|
qte_to_affect = qte
|
|
|
|
last_qte = nil
|
|
self.p_product.p_qtes.order("qte DESC").each do |p_qte|
|
|
last_qte = p_qte.qte
|
|
|
|
nbr = 0
|
|
nbr = (qte_to_affect.to_f / p_qte.qte.to_f).floor
|
|
affecteds[last_qte] = nbr if nbr > 0
|
|
|
|
|
|
|
|
|
|
qte_to_affect = qte_to_affect.modulo(p_qte.qte)
|
|
end
|
|
|
|
if qte_to_affect > 0
|
|
affecteds[last_qte] = affecteds[last_qte].to_i + 1
|
|
end
|
|
|
|
r = 0
|
|
|
|
affecteds.each do |index, value|
|
|
r += value
|
|
end
|
|
return({:affecteds => affecteds, :nbr => r, :reste => qte_to_affect})
|
|
|
|
|
|
|
|
end
|
|
|
|
def fige
|
|
self.ok_price = self.price
|
|
|
|
if !self.ok_price
|
|
self.ok_price = self.price
|
|
end
|
|
|
|
if self.p_product and !self.archived_p_product
|
|
self.archived_p_product = self.p_product.dup
|
|
self.archived_p_product.archived = true
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
def product_name
|
|
if self.archived_p_product
|
|
self.archived_p_product.name
|
|
elsif self.p_product
|
|
self.p_product.name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def price
|
|
|
|
|
|
|
|
|
|
if ok_price?
|
|
price = ok_price
|
|
else
|
|
|
|
if self.p_customer and self.p_customer.p_price_cat
|
|
p_price_cat = self.p_customer.p_price_cat
|
|
else
|
|
p_price_cat = PPriceCat.first
|
|
end
|
|
|
|
|
|
|
|
|
|
product_degressif = self.p_product.p_degressifs.joins(:p_price_cats).where("nbr <= ?", self.qte).where(:p_price_cats => {:id => p_price_cat.id}).order("nbr DESC").first
|
|
if product_degressif
|
|
price = product_degressif.price.to_f
|
|
|
|
else
|
|
0.0
|
|
end
|
|
end
|
|
|
|
return price
|
|
|
|
end
|
|
|
|
def qte
|
|
self.p_sheet_line_lines.sum(:qte)
|
|
end
|
|
before_create do
|
|
|
|
if self.p_customer_sheet
|
|
self.generate_p_sheet_line_lines
|
|
end
|
|
|
|
end
|
|
|
|
def generate_p_sheet_line_lines
|
|
self.p_product.p_product_stocks.order("p_size_id ASC, p_color_id ASC").each do |ps|
|
|
|
|
self.p_sheet_line_lines << PSheetLineLine.new(:p_product_stock_id => ps.id)
|
|
|
|
end
|
|
end
|
|
|
|
|
|
def cost_u_ok
|
|
self.total_cost_ok / self.ok_qte.to_f
|
|
end
|
|
|
|
def marge_u_ok
|
|
self.marge_ok / self.ok_qte.to_f
|
|
end
|
|
|
|
def marge_ok
|
|
self.ok_price_tot - self.total_cost_ok
|
|
end
|
|
|
|
def total_cost_ok
|
|
var = 0.0
|
|
self.p_sheet_line_stocks.each do |p_sheet_line_stock|
|
|
var += p_sheet_line_stock.price_tot_ok
|
|
|
|
end
|
|
return var
|
|
end
|
|
|
|
|
|
def stock_is_ok
|
|
if !self.stock_done
|
|
if self.brut_product_needs_ok.size == self.p_sheet_line_stocks.group(:p_brut_product_id).length
|
|
|
|
self.stock_done = true
|
|
self.save
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
def update_stock
|
|
if !self.externe and !self.stock_is_ok and self.shiped
|
|
self.brut_product_needs_ok.each do |brut_index, brut_qte|
|
|
p_brut_product = PBrutProduct.find(brut_index)
|
|
qte_restante = brut_qte.to_f
|
|
|
|
p_product_brut_stocks = PProductBrutStock.where(:p_brut_product_id => p_brut_product.id).where("qte_restant > 0.0").order("ok_at ASC").limit(100)
|
|
|
|
if p_product_brut_stocks.sum(:qte_restant) >= qte_restante and self.p_sheet_line_stocks.where(:p_brut_product_id => p_brut_product.id).count == 0
|
|
|
|
i = 0
|
|
while qte_restante > 0.0
|
|
p_product_brut_stock = p_product_brut_stocks[i]
|
|
|
|
if qte_restante <= p_product_brut_stock.qte_restant
|
|
qte_to_affect = qte_restante
|
|
|
|
else
|
|
qte_to_affect = p_product_brut_stock.qte_restant
|
|
end
|
|
|
|
a = self.p_sheet_line_stocks.build(:ok_at => self.ok_at,:ok => true, :p_brut_product_id => p_brut_product.id, :qte_ok => qte_to_affect, :price_ok => p_product_brut_stock.ok_price, :p_product_brut_stock_id => p_product_brut_stock.id)
|
|
|
|
|
|
p_product_brut_stock.qte_restant = p_product_brut_stock.qte_restant.to_f - qte_to_affect
|
|
p_product_brut_stock.save
|
|
qte_restante = qte_restante - qte_to_affect
|
|
i += 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
self.save
|
|
self.stock_is_ok
|
|
end
|
|
end
|
|
|
|
def brut_product_needs
|
|
var = {}
|
|
self.p_product.p_product_brut_products.each do |p_product_brut_product|
|
|
var[p_product_brut_product.p_brut_product_id] = p_product_brut_product.qte.to_f * self.qte.to_f
|
|
end
|
|
return var
|
|
end
|
|
|
|
def brut_product_needs_ok
|
|
var = {}
|
|
self.p_product.p_product_brut_products.each do |p_product_brut_product|
|
|
var[p_product_brut_product.p_brut_product_id] = p_product_brut_product.qte.to_f * self.ok_qte.to_f
|
|
end
|
|
return var
|
|
end
|
|
|
|
def generate_bl
|
|
self.p_customer_sheet.generate_bl(self.id)
|
|
end
|
|
|
|
def validate_tank?
|
|
if self.externe
|
|
false
|
|
self.p_tank = nil
|
|
else
|
|
true
|
|
end
|
|
end
|
|
|
|
def validate_ok?
|
|
if self.ok
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def price_tot
|
|
self.qte.to_f * self.price.to_f
|
|
end
|
|
|
|
def tva
|
|
t = 0.2
|
|
|
|
t = 0.0 if self.to_export?
|
|
|
|
return t
|
|
end
|
|
|
|
def to_export?
|
|
t = false
|
|
|
|
if self.p_customer_sheet and self.p_customer_sheet.particular_bill
|
|
if self.p_customer_sheet.particular_bill.country != "FR"
|
|
t = true
|
|
end
|
|
|
|
|
|
elsif self.p_document and self.p_document.particular_bill
|
|
if self.p_document.particular_bill.country != "FR"
|
|
t = true
|
|
end
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
def price_tot_ttc
|
|
self.price_tot * (self.tva + 1.0)
|
|
end
|
|
|
|
|
|
def ok_price_tot
|
|
self.ok_qte.to_f * self.ok_price.to_f
|
|
end
|
|
|
|
def ok_price_tot_ttc
|
|
self.ok_price_tot * (self.tva + 1.0)
|
|
end
|
|
|
|
|
|
def self.totals(sheet_lines)
|
|
|
|
|
|
return {
|
|
:total => self.total_with_labels(sheet_lines)[:total][:value] ,
|
|
:total_ttc => self.total_with_labels(sheet_lines)[:total_ttc][:value],
|
|
|
|
}
|
|
end
|
|
|
|
|
|
def self.total_articles(sheet_lines)
|
|
|
|
total = 0.0
|
|
total_ttc = 0.0
|
|
|
|
|
|
sheet_lines.each do |sheet_line|
|
|
|
|
total += sheet_line.price_tot
|
|
total_ttc += sheet_line.price_tot_ttc
|
|
|
|
end
|
|
|
|
return {
|
|
:total => total,
|
|
:total_ttc => total_ttc,
|
|
|
|
}
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.total_with_labels(sheet_lines, sheet_line_container=nil)
|
|
|
|
total = 0.0
|
|
total_ttc = 0.0
|
|
r = {}
|
|
tva = 0.0
|
|
sheet_lines.each do |sheet_line|
|
|
tva = sheet_line.tva
|
|
total += sheet_line.price_tot.to_f.round(2)
|
|
total_ttc += sheet_line.price_tot_ttc.to_f.round(2)
|
|
|
|
end
|
|
|
|
r[:total_articles] = {:label =>"Total articles HT",:value => total}
|
|
fdp = 0
|
|
|
|
fdp = PSheetLine.frais_de_port(sheet_lines).to_f.round(2)
|
|
r[:fdp] = {:label =>"Frais de port HT",:value => fdp}
|
|
|
|
|
|
total = total.to_f.round(2) +fdp.to_f.round(2)
|
|
total_ttc = total_ttc.to_f.round(2) + (fdp.to_f*(1+tva)).to_f.round(2)
|
|
r[:total] = {:label =>"Total HT",:value => total}
|
|
r[:tva] = {:label =>"TVA",:value => total_ttc - total}
|
|
r[:total_ttc] = {:label =>"Total TTC",:value => total_ttc}
|
|
|
|
|
|
return r
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.frais_de_port(p_sheet_lines)
|
|
|
|
if p_sheet_lines[0] and ((p_sheet_lines[0].p_document and p_sheet_lines[0].p_document.cache_fdp?))
|
|
|
|
p_sheet_lines[0].p_document.cache_fdp
|
|
|
|
|
|
elsif p_sheet_lines[0] and ((p_sheet_lines[0].p_customer_sheet and p_sheet_lines[0].p_customer_sheet.fdp_force_price) or (p_sheet_lines[0].p_document and p_sheet_lines[0].p_document.fdp_force_price))
|
|
if p_sheet_lines[0].p_document
|
|
p_sheet_lines[0].p_document.fdp_force_price
|
|
elsif p_sheet_lines[0].p_customer_sheet
|
|
p_sheet_lines[0].p_customer_sheet.fdp_force_price
|
|
end
|
|
|
|
else
|
|
if PSheetLine.total_articles(p_sheet_lines)[:total] > PSheetLine.franco_port
|
|
0.0
|
|
else
|
|
PSheetLine.ship_affects(p_sheet_lines) * PSheetLine.carton_price
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
def self.ship_affects(p_sheet_lines)
|
|
nbr = 0
|
|
p_sheet_lines.all.each do |p_sheet_line|
|
|
nbr += p_sheet_line.ship_affects[:nbr]
|
|
end
|
|
|
|
return nbr
|
|
end
|
|
|
|
|
|
def self.franco_port
|
|
1000.0
|
|
end
|
|
|
|
def self.carton_price
|
|
15.0
|
|
end
|
|
|
|
|
|
|
|
def sheet_figed
|
|
if self.p_document and 1
|
|
end
|
|
end
|
|
|
|
end
|