This repository has been archived on 2021-11-24. You can view files and clone it, but cannot push or open issues or pull requests.
phone_app/app/models/price_line_block.rb
Philippe b32ddd37f5 Add front validations for p_article form, add p_article to stock_movement, add AJAX on price_line update method
TODO:
- AJAX for add_p_article and add_stock_movement_p_article in stock_movement views
- Fix select p_article with in stock_movement partial view
- Fix query to display available p_article in stock_movement partial
2021-11-23 20:20:41 +01:00

886 lines
24 KiB
Ruby

class PriceLineBlock < ApplicationRecord
belongs_to :price_lineable, :polymorphic => true
#validates :wish_date, :presence => true, :if => :wish_date_needed?
has_many :price_lines
accepts_nested_attributes_for :price_lines, allow_destroy: true
belongs_to :p_devise
validates :p_customer_id, :presence => true, :if => :p_customer_needed?
#validates :p_fournisseur_id, :presence => true, :if => :p_fournisseur_needed?
#validates :particular_bill_id, :presence => true, :if => :particular_bill_needed?
#validates :particular_send_id, :presence => true, :if => :particular_send_needed?
belongs_to :particular_bill, :class_name => "Particular"#, :dependent => :destroy
accepts_nested_attributes_for :particular_bill
belongs_to :particular_send, :class_name => "Particular"#, :dependent => :destroy
accepts_nested_attributes_for :particular_send
has_many :line_blocks
belongs_to :p_customer
belongs_to :p_payment_type
attr_accessor :same_adress
PURCHASE_BLOCKS = ["Réponse fournisseur", "Consultation fournisseur", "Facture d'achat", "Commande achat", "Demande prix", "Bon de commande achat", "Bon de réception achat", "Facture achat", "Avoir achat", "Catalogue fournisseur"]
SALE_BLOCKS = ["Demande de commande", "Bon de commande", "Devis", "Bon de livraison", "Facture", "Avoir"]
belongs_to :p_fournisseur
accepts_nested_attributes_for :p_fournisseur
belongs_to :price_document
def to_no_archive
if self.imported
%w()
else
%w(cost_ht marge_ht)
end
end
def ca_cost_ht
self.price_lines.sum(:cc_cost_ht)
end
def ca_marge_ht
self.tot_amount_ht - self.ca_cost_ht
end
def test_if_stock_ok?
to_r = true
self.price_lines.each do |pl|
if pl.p_product_ref && pl.p_product_ref.stocked
if pl.p_product_ref.assembled
pl.p_product_ref.p_product_assembleds.all.each do |ppa|
if LineStock.where(:p_product_ref_id => ppa.p_product_ref_id).sum(:qte_available) >= (pl.qte.to_f * ppa.qte.to_f)
else
to_r = false
end
end
else
if LineStock.where(:p_product_ref_id => pl.p_product_ref_id).sum(:qte_available) >= pl.qte
else
to_r = false
end
end
end
end
return to_r
end
def test_if_price_stock_ok?
to_r = true
self.price_lines.each do |pl|
if pl.p_product_ref && pl.p_product_ref.stocked
puts pl.p_product_ref.p_product_id
if pl.p_product_ref.p_product and pl.p_product_ref.p_product.ct_purchase_price_ht.to_f > 0.0
else
to_r = false
end
end
end
return to_r
end
def update_stocks_from_average
if self.block_type == "Facture" and !self.cost_ok
if self.test_if_price_stock_ok?
self.price_lines.each do |pl|
if pl.p_product_ref
pl.ct_cost_ht = pl.p_product_ref.p_product.ct_purchase_price_ht.to_f * pl.qte.to_f
pl.save
end
end
self.cost_ok = true
self.save
self.price_lineable.save if self.price_lineable
end
end
end
def update_stocks_for(p_product_ref, qte, pl)
if !pl.p_articles.empty?
pl.p_articles.each do |p_article|
decr_line_stock = LineStock.new(:date => self.price_lineable.date,
:p_product_ref => p_product_ref,
:qte => -1,
:description => "Attribution à la ligne d'une facture",
:price_ht => 0.0,
:price_line => pl,
:price_line_block => self,
:stockable => self.price_lineable)
price = 0.0
line_stock_usages = []
#qte_to_affect = qte
lsu_p_art = LineStockUsage.where(p_article_id: p_article.id)
line_stocks_p_article = p_article.line_stocks.where("qte_available > ?", 0) #LineStock.joins(:p_articles).where("p_articles.id = ?", p_article.id)
ls = nil
line_stocks_p_article.each do |p_article_line_stock|
if p_article_line_stock.line_stock_usages.where(p_article_id: p_article).empty?
ls = p_article_line_stock
end
end
#ls = LineStock.joins(:p_articles).where("p_articles.id = ?", p_article.id).joins(:line_stock_usages)
#ls.qte_available = ls.qte_available - 1
#qte_to_affect = qte_to_affect - qte_here
lsu = LineStockUsage.create(:qte => 1, :line_stock => ls, :dest_line_stock_id => decr_line_stock.id, p_article_id: p_article.id)
#line_stock_usages << lsu
price += lsu.price_ht
ls.save
decr_line_stock.price_ht = price * -1
decr_line_stock.save
ls_p_art = LineStockPArticle.new(
p_article: p_article,
line_stock: decr_line_stock
)
ls_p_art.save
#p_article.line_stocks << decr_line_stock fonctionne aussi selon la doc : https://guides.rubyonrails.org/association_basics.html#:~:text=The%20collection%20of%20join%20models%20can%20be%20managed
end
else
#===================================================================================================================
puts "TEST"
puts "Référence : #{p_product_ref.id} #{p_product_ref.p_product.name}"
if qte.to_f != 0.0
decr_line_stock = LineStock.create(:date => self.price_lineable.date,
:p_product_ref => p_product_ref,
:qte => qte*-1,
:description => "Attribution à la ligne d'une facture",
:price_ht => 0.0,
:price_line => pl,
:price_line_block => self,
:stockable => self.price_lineable)
price = 0.0
line_stock_usages = []
qte_to_affect = qte
#LineStock.where(:p_product_ref_id => p_product_ref.id).where("date <= ?", self.price_lineable.date).where("qte_available > 0.0").each do |ls|
LineStock.where(:p_product_ref_id => p_product_ref.id).where("date <= ?", self.price_lineable.date).where("qte_available > 0.0").each do |ls|
if qte_to_affect <= ls.qte_available
qte_here = qte_to_affect
else
qte_here = ls.qte_available
end
qte_to_affect = qte_to_affect - qte_here
lsu = LineStockUsage.create(:qte => qte_here, :line_stock => ls, :dest_line_stock_id => decr_line_stock.id)
line_stock_usages << lsu
price += lsu.price_ht
ls.save
break if qte_to_affect == 0.0
#price_u_ht
end
decr_line_stock.p_articles = pl.p_articles
decr_line_stock.price_ht = price * -1
decr_line_stock.save
end
#===================================================================================================================
end
end
def update_stocks
if self.block_type == "Facture" or self.block_type == "Bon de commande client" or self.block_type == "Bon de réception achat" && !self.cost_ok
if self.test_if_stock_ok?
self.price_lines.each do |pl|
if pl.p_product_ref && pl.p_product_ref.stocked
if pl.p_product_ref.assembled
pl.p_product_ref.p_product_assembleds.all.each do |ppa|
self.update_stocks_for(ppa.p_product_ref, (pl.qte.to_f * ppa.qte.to_f), pl)
end
else
self.update_stocks_for(pl.p_product_ref, pl.qte, pl)
end
end
end
self.cost_ok = true
self.save
self.save # deuxième sauvegarde pour prendre en compte les couts de price_line
self.price_lineable.save if self.price_lineable
return true
end
end
end
def generate_stock
self.price_lines.each do |pl|
if pl.p_product_ref
ls = LineStock.new(
:dluo => pl.dluo,
:date => self.price_lineable.date,
:p_product_ref => pl.p_product_ref,
:description => "Entrée en stock par facture d'achat",
:qte => pl.qte,
:price_ht => pl.local_tot_amount_ht,
:price_line => pl,
:price_line_block => self,
:stockable => self.price_lineable)
ls.p_articles = pl.p_articles
ls.save
end
pl.p_articles.joins(:p_grade).where(p_grades: {grade: "RMA"}).each do |p_article|
decr_line_stock = LineStock.new(
:date => self.price_lineable.date,
:p_product_ref => pl.p_product_ref,
:qte => -1,
:description => "Sortie de stock automatique des RMA",
:price_ht => 0.0,
:price_line => pl,
:price_line_block => self,
:stockable => self.price_lineable)
decr_line_stock.p_articles << p_article
decr_line_stock.save
end
end
self.stock_ok = true
self.save
self.price_lineable.save if self.price_lineable
end
def purchase?
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
true
else
false
end
end
def sale?
if PriceLineBlock::SALE_BLOCKS.include?(self.block_type)
true
else
false
end
end
def devise_symbol
if self.p_devise
self.p_devise.symbol
else
""
end
end
def ca_devise_rate
if self.local_amount_ttc
if self.tot_amount_ttc != 0.0
self.local_amount_ttc / self.tot_amount_ttc
else
0.0
end
elsif self.p_devise
return self.p_devise.rate.to_f
else
1.0
end
end
def wish_date_needed?
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis" or self.block_type == "Demande de commande"
false
else
raise
true
end
end
def particular_bill_needed?
if !self.imported
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis"
false
else
true
end
end
end
def particular_send_needed?
if !self.imported
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis"
false
else
true
end
end
end
def p_fournisseur_needed?
if ["Demande prix", "Consultation fournisseur", "Réponse fournisseur"].include?(self.block_type)
false
elsif PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
true
else
false
end
end
def p_customer_needed?
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis"
false
else
true
end
end
acts_as_caching :fields => [:state, :solded_nbr_days, :solded_at, :cost_ht, :marge_ht, :devise_rate, :bon_de_commande_id, :bon_de_livraison_id, :facture_id, :reliquat, :customer_market_discount_percent, :block_type, :discount_comptant, :fdp_tva_rate, :weight_tot, :accounting_zone_id, :accounting_zone_name, :tot_lines_ht, :tot_lines_tva, :tot_lines_ttc, :tot_fdp_ht, :tot_fdp_tva, :tot_fdp_ttc, :tot_discount_ht, :tot_discount_tva, :tot_discount_ttc, :tot_amount_af_discount_ht, :tot_amount_af_discount_tva, :tot_amount_af_discount_ttc, :gen_discount_percent, :tot_gen_discount_ht, :tot_gen_discount_tva, :tot_gen_discount_ttc, :tot_amount_ht, :tot_amount_tva, :tot_amount_ttc, :remise_enrobage_ok, :remise_ecole_ok, :remise_pre_order_ok, :remise_qte_ok, :payment_comptant, :payment_delais, :payment_month_end, :payment_end_at, :acompte, :acompte_percent, :payment_days, :nbr_ship, :creation_date, :p_customer_cat_id]
def ca_state
self.price_lineable.state rescue nil
end
BON_DE_COMMANDE_TO_RESET = %w(weight_tot tot_lines_ht tot_lines_tva tot_lines_ttc tot_fdp_ht tot_fdp_tva tot_fdp_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_af_discount_ht tot_amount_af_discount_tva tot_amount_af_discount_ttc gen_discount_percent tot_gen_discount_ht tot_gen_discount_tva tot_gen_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc nbr_ship)
BON_DE_LIVRAISON_TO_RESET = %w(weight_tot tot_lines_ht tot_lines_tva tot_lines_ttc tot_fdp_ht tot_fdp_tva tot_fdp_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_af_discount_ht tot_amount_af_discount_tva tot_amount_af_discount_ttc gen_discount_percent tot_gen_discount_ht tot_gen_discount_tva tot_gen_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc nbr_ship)
FACTURE_ACHAT_TO_RESET = %w(devise_rate weight_tot tot_lines_ht tot_lines_tva tot_lines_ttc tot_fdp_ht tot_fdp_tva tot_fdp_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_af_discount_ht tot_amount_af_discount_tva tot_amount_af_discount_ttc gen_discount_percent tot_gen_discount_ht tot_gen_discount_tva tot_gen_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc nbr_ship)
BON_DE_RECEPTION_ACHAT_TO_RESET = %w(devise_rate weight_tot tot_lines_ht tot_lines_tva tot_lines_ttc tot_fdp_ht tot_fdp_tva tot_fdp_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_af_discount_ht tot_amount_af_discount_tva tot_amount_af_discount_ttc gen_discount_percent tot_gen_discount_ht tot_gen_discount_tva tot_gen_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc nbr_ship)
COMMANDE_ACHAT_TO_RESET = %w(weight_tot tot_lines_ht tot_lines_tva tot_lines_ttc tot_fdp_ht tot_fdp_tva tot_fdp_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_af_discount_ht tot_amount_af_discount_tva tot_amount_af_discount_ttc gen_discount_percent tot_gen_discount_ht tot_gen_discount_tva tot_gen_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc nbr_ship)
def reset_for_update
self.price_lines.each do |pl|
pl.reset_for_update
end
self.price_lines.each do |pl|
pl.bk_price_ht = pl.default_price_u_ht if !pl.bk_price_ht
pl.save
end
eval("#{self.block_type_slug.upcase}_TO_RESET").each do |qid|
eval("self.ac_#{qid} = nil")
end
self.archive_now()
self.price_lines.each do |pl|
pl.archive_now()
end
end
def ca_solded_at
if self.price_lineable and self.price_lineable_type == "PriceDocument"
self.price_lineable.solded_at
end
end
def ca_solded_nbr_days
if self.price_lineable and self.price_lineable_type == "PriceDocument"
self.price_lineable.solded_nbr_days
end
end
def ca_customer_market_discount_percent
self.p_customer.market_discount.percent if self.p_customer and self.p_customer.market_discount
end
def personalised_archive
self.price_lines.each do |pl|
pl.archive_now
end
end
def personalised_unarchive
self.price_lines.each do |pl|
pl.unarchive_now
end
end
def ca_bon_de_commande_id
self.price_lineable.bon_de_commande_id if self.price_lineable_type == "PriceDocument" and self.price_lineable
end
def ca_bon_de_livraison_id
self.price_lineable.bon_de_livraison_id if self.price_lineable_type == "PriceDocument" and self.price_lineable
end
def ca_facture_id
self.price_lineable.facture_id if self.price_lineable_type == "PriceDocument" and self.price_lineable
end
def ca_reliquat
self.price_lineable.reliquat if self.price_lineable_type == "PriceDocument" and self.price_lineable
end
def ca_block_type
self.price_lineable.block_type if self.price_lineable
end
def block_type_slug
self.block_type.to_slug.gsub("-", "_")
end
before_validation do
self.cancelled = self.price_lineable.cancelled if self.price_lineable and self.price_lineable_type == "PriceDocument"
if !self.id and self.p_customer
self.p_commercial_id = self.p_customer.p_commercial_id
self.p_payment_type_id = self.p_customer.p_payment_type_id
self.ct_payment_comptant = self.p_customer.comptant
self.ct_acompte = self.p_customer.acompte
self.ct_acompte_percent = self.p_customer.acompte_percent
self.ct_payment_delais = self.p_customer.payment_delais
self.ct_payment_month_end = self.p_customer.payment_fin_de_mois
end
if self.particular_bill_needed? and (!self.p_customer or !self.particular_bill or !self.particular_bill.owner or self.particular_bill.owner != self.p_customer)
errors.add(:particular_bill_id, 'doit être une adresse du client')
end
if self.particular_send_needed? and (!self.p_customer or !self.particular_send or !self.particular_send.owner or self.particular_send.owner != self.p_customer)
errors.add(:particular_send_id, 'doit être une adresse du client')
end
end
def ca_remise_pre_order_ok
if self.p_customer and self.p_customer_cat_id == 1 and self.wish_date and self.created_at and (self.wish_date >= (self.creation_date + 8.weeks))
true
else
false
end
end
def ca_remise_qte_ok
if self.p_customer and self.p_customer_cat_id == 1
true
else
false
end
end
def ca_remise_enrobage_ok
if !self.remise_ecole_ok and self.p_customer and self.p_customer.discount_enrobage
true
else
false
end
end
def ca_remise_ecole_ok
if self.p_customer and self.p_customer_cat_id == 3
true
else
false
end
end
def ca_discount_comptant
if self.p_customer
self.p_customer.discount_comptant
end
end
after_save do
self.price_lines.each do |pl|
pl.save
end
end
def ca_weight_tot
r = 0.0
self.price_lines.each do |pl|
r+= pl.weight_tot
end
return r
end
def ca_accounting_zone_id
self.price_lineable.accounting_zone_id if self.price_lineable
end
def ca_accounting_zone_name
self.price_lineable.accounting_zone_name if self.price_lineable
end
def ca_tot_lines_ht
r = 0.0
self.price_lines.each do |pl|
r+= pl.tot_amount_ht
end
return r
end
def ca_tot_lines_ht_for_discount
r = 0.0
self.price_lines.each do |pl|
r+= pl.tot_amount_ht if !pl.product_no_remise
end
return r
end
def ca_tot_lines_tva
r = 0.0
self.price_lines.each do |pl|
r+= pl.tot_amount_tva if pl
end
return r
end
def ca_tot_lines_tva_for_discount
r = 0.0
self.price_lines.each do |pl|
r+= pl.tot_amount_tva if !pl.product_no_remise
end
return r
end
def ca_tot_lines_ttc
r = 0.0
self.price_lines.each do |pl|
r+= pl.tot_amount_ttc
end
return r
end
def default_tot_fdp_ht
return 0.0 # Skip default FDP
if self.p_customer_cat_id == 2
if (self.tot_lines_ht + self.tot_discount_ht) >= 290.0
0.0
elsif (self.tot_lines_ht + self.tot_discount_ht) >= 150.0
15.0
else
30.0
end
else
if ca_weight_tot >= 45.0
0.0
elsif ca_weight_tot >= 30
25.0
else
40.0
end
end
end
def ca_tot_fdp_ht
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
return 0.0
else
if self.reliquat #false #self.price_lineable_type == "PriceDocument" and self.price_lineable and self.price_lineable.label == "Avoir"
if self.reliquat_fdp_ht
self.reliquat_fdp_ht
else
0.0
end
else
if self.ct_tot_fdp_ht
self.ct_tot_fdp_ht
elsif self.bk_tot_fdp_ht
self.bk_tot_fdp_ht
else
self.default_tot_fdp_ht
end
end
end
end
def ca_fdp_tva_rate
if self.accounting_zone_id == 1
20.0
else
0.0
end
end
def ca_tot_fdp_tva
self.tot_fdp_ht * (self.fdp_tva_rate/100)
end
def ca_tot_fdp_ttc
self.tot_fdp_ht + self.tot_fdp_tva
end
def ca_tot_discount_ht
if self.ct_tot_discount_percent
(self.ct_tot_discount_percent / -100.0) * self.ca_tot_lines_ht_for_discount
else
0.0
end
end
def ca_tot_discount_tva
if self.ct_tot_discount_percent
(self.ct_tot_discount_percent / -100.0) * self.ca_tot_lines_tva_for_discount
else
0.0
end
end
def ca_tot_discount_ttc
self.tot_discount_ht + self.tot_discount_tva
end
def ca_tot_amount_af_discount_ht
self.tot_lines_ht + self.tot_discount_ht + self.tot_fdp_ht
end
def ca_tot_amount_af_discount_tva
self.tot_lines_tva + self.tot_discount_tva + self.tot_fdp_tva
end
def ca_tot_amount_af_discount_ttc
self.tot_lines_ttc + self.tot_discount_ttc + self.tot_fdp_ttc
end
def ca_gen_discount_percent
0.0
end
def ca_tot_gen_discount_ht
0.0
end
def ca_tot_gen_discount_tva
0.0
end
def ca_tot_gen_discount_ttc
0.0
end
def ca_tot_amount_ht
if self.ct_tot_amount_ht
return self.ct_tot_amount_ht
else
self.tot_amount_af_discount_ht + self.tot_gen_discount_ht
end
end
def ca_tot_amount_tva
self.tot_amount_af_discount_tva + self.tot_gen_discount_tva
end
def ca_tot_amount_ttc
self.tot_amount_af_discount_ttc + self.tot_gen_discount_ttc
end
def ca_payment_comptant
if self.ct_payment_comptant
self.ct_payment_comptant
else
if self.p_customer
self.p_customer.comptant
else
nil
end
end
end
def ca_payment_delais
if self.ct_payment_delais
self.ct_payment_delais
else
if self.p_customer
self.p_customer.payment_delais
else
nil
end
end
end
def ca_payment_month_end
if self.ct_payment_month_end
self.ct_payment_month_end
else
if self.p_customer
self.p_customer.payment_fin_de_mois
else
nil
end
end
end
def ca_payment_end_at
if self.price_lineable_type == "PriceDocument" and self.price_lineable
start_date = self.price_lineable.date
elsif self.price_lineable_type == "PCustomerSheet" and self.price_lineable
start_date = self.price_lineable.price_line_block.creation_date
end
if start_date
if self.payment_delais.to_i == 0
start_date
else
start_date + self.payment_delais.to_i.days
end
end
end
def ca_acompte
if self.p_customer
self.p_customer.acompte
else
nil
end
end
def ca_acompte_percent
if self.p_customer
self.p_customer.acompte_percent
else
nil
end
end
def ca_payment_days
end
def ca_nbr_ship
if self.ct_nbr_ship
self.ct_nbr_ship
else
nil
end
end
def ca_creation_date
if self.ct_creation_date
self.ct_creation_date
elsif self.price_lineable_type == "PriceDocument" and self.price_lineable and self.price_lineable.ref_element and self.price_lineable.ref_element.price_line_block
self.price_lineable.ref_element.price_line_block.creation_date
elsif self.id
self.created_at
else
Date.today
end
end
def ca_p_customer_cat_id
if self.p_customer
self.p_customer.p_customer_cat_id
else
nil
end
end
def cumul_discount_ht
r = 0.0
self.price_lines.each do |pl|
r += pl.ca_tot_discount_ht
end
return r
end
AVOIR_TO_RESET = %w(weight_tot tot_lines_ht tot_lines_tva tot_lines_ttc tot_fdp_ht tot_fdp_tva tot_fdp_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_af_discount_ht tot_amount_af_discount_tva tot_amount_af_discount_ttc gen_discount_percent tot_gen_discount_ht tot_gen_discount_tva tot_gen_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc nbr_ship)
end