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