Merge branch 'import-base' into pg-X-import-base

This commit is contained in:
Barnabé 2021-10-19 11:03:00 +02:00
commit 50ffeae1f5
146 changed files with 4376 additions and 882 deletions

View File

@ -106,7 +106,7 @@ group :development do
gem 'capistrano-bundler', '~> 1.1', require: false gem 'capistrano-bundler', '~> 1.1', require: false
gem "capistrano-rvm", group: :development gem "capistrano-rvm", group: :development
gem 'capistrano3-nginx', '~> 2.0', group: :development gem 'capistrano3-nginx', '~> 2.0', group: :development
gem "awesome_print"
end end
gem 'zip-zip' gem 'zip-zip'
@ -117,3 +117,4 @@ gem 'axlsx', '3.0.0.pre'
gem 'axlsx_rails' gem 'axlsx_rails'
gem 'mimemagic', "0.3.10" gem 'mimemagic', "0.3.10"
gem "roo"

View File

@ -63,6 +63,7 @@ GEM
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
airbrussh (1.3.3) airbrussh (1.3.3)
sshkit (>= 1.6.1, != 1.7.0) sshkit (>= 1.6.1, != 1.7.0)
awesome_print (1.9.2)
axlsx (3.0.0.pre) axlsx (3.0.0.pre)
htmlentities (~> 4.3, >= 4.3.4) htmlentities (~> 4.3, >= 4.3.4)
mimemagic (~> 0.3) mimemagic (~> 0.3)
@ -276,6 +277,9 @@ GEM
ffi (~> 1.0) ffi (~> 1.0)
regexp_parser (1.6.0) regexp_parser (1.6.0)
rmagick (4.2.2) rmagick (4.2.2)
roo (2.8.2)
nokogiri (~> 1)
rubyzip (>= 1.2.1, < 2.0.0)
ruby-vips (2.0.14) ruby-vips (2.0.14)
ffi (~> 1.9) ffi (~> 1.9)
ruby_dep (1.5.0) ruby_dep (1.5.0)
@ -363,6 +367,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
acts_as_commentable acts_as_commentable
acts_as_tree acts_as_tree
awesome_print
axlsx (= 3.0.0.pre) axlsx (= 3.0.0.pre)
axlsx_rails axlsx_rails
bcrypt (~> 3.1.7) bcrypt (~> 3.1.7)
@ -398,6 +403,7 @@ DEPENDENCIES
rails (= 6.0.3.4) rails (= 6.0.3.4)
rails_autolink rails_autolink
rmagick rmagick
roo
sass-rails (~> 5) sass-rails (~> 5)
searchkick searchkick
selenium-webdriver selenium-webdriver

View File

@ -56,6 +56,7 @@
#= require freeze-table #= require freeze-table
#= require admin/random_hexa
@ -857,5 +858,3 @@ $(document).on 'click', '.datepicker', (e) ->
return return
return return

View File

@ -0,0 +1,2 @@
const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');

View File

@ -42,7 +42,7 @@ function manager_show(url){
function manager_hide(){ function manager_hide(){
$("#manager_box_place").removeClass("manager_box_place_active"); $("#manager_box_place").removeClass("manager_box_place_active");
$('#manager_box').html("");
$("body").css("overflow", "auto"); $("body").css("overflow", "auto");
slider_enabled = null; slider_enabled = null;
@ -239,3 +239,23 @@ function select_video_from_manager(input_id){
} }
function select_product_from_manager(input_id){
manager_prompt(p_product_refs_url,function(m_return){
$('#p_product_ref_id_'+input_id).val(m_return.id);
$('#p_product_ref_name_'+input_id).val(m_return.name);
$('#p_product_ref_qte_'+input_id).focus()
});
}
function send_manager_product(product_id, product_name){
manager_send_response({id : product_id, name : product_name});
}

View File

@ -10,8 +10,10 @@
if $(link).closest("p").next("." + association + "_form").length > 0 if $(link).closest("p").next("." + association + "_form").length > 0
form_element = $(link).closest("p").next("." + association + "_form") form_element = $(link).closest("p").next("." + association + "_form")
else else if $(link).closest("p").prev("." + association + "_form").length > 0
form_element = $(link).closest("p").prev("." + association + "_form") form_element = $(link).closest("p").prev("." + association + "_form")
else
form_element = $(link).closest(".qi_field_wrapper").find("." + association + "_form")
form_element.append content_final form_element.append content_final

View File

@ -1782,4 +1782,88 @@ td{
} }
// Html5 Tooltip
.info {
color: #009bbf;
position: relative;
display: inline-block;
text-overflow: ellipsis;
.info-text-top {
visibility: hidden;
background-color: #555;
color: #fff;
text-align: center;
padding: 5px;
border-radius: 6px;
max-width: 500px;
min-width: fit-content;
white-space: normal;
/* Position the tooltip text */
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
/* Fade in tooltip */
opacity: 0;
transition: opacity 0.3s;
}
.info-text-top::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.info-text-bottom {
visibility: hidden;
background-color: #555;
color: #fff;
text-align: center;
padding: 5px;
border-radius: 6px;
max-width: 500px;
min-width: fit-content;
white-space: normal;
/* Position the tooltip text */
position: absolute;
z-index: 1;
top: 125%;
left: 200%;
margin-left: -60px;
/* Fade in tooltip */
opacity: 0;
transition: opacity 0.3s;
}
.info-text-bottom::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent #555 transparent;
}
}
.info:hover {
.info-text-top {
visibility: visible;
opacity: 1;
}
.info-text-bottom {
visibility: visible;
opacity: 1;
}
}
// Fin // Fin

View File

@ -2,7 +2,8 @@
#manager_box_place{ #manager_box_place{
position:fixed; position:fixed;
height:0; height:0;
width:100%; left:100px;
right:30px;
z-index:1500; z-index:1500;
top:0px; top:0px;
margin:0px; margin:0px;

View File

@ -8,7 +8,7 @@ class Admin::BuyListsController < ApplicationController
@p_customer_sheets = PCustomerSheet.all @p_customer_sheets = PCustomerSheet.all
@p_customer_sheets = @p_customer_sheets.where(:state => ["AV BPA", "PAS BPA", "BPA"]) @p_customer_sheets = @p_customer_sheets.where(:state => ["brouillon", "offre", "commande"])
@price_line_blocks = PriceLineBlock.where(:price_lineable_type => "PCustomerSheet", :price_lineable_id => @p_customer_sheets.ids) @price_line_blocks = PriceLineBlock.where(:price_lineable_type => "PCustomerSheet", :price_lineable_id => @p_customer_sheets.ids)
@ -33,35 +33,61 @@ class Admin::BuyListsController < ApplicationController
date_regex = /^(0[1-9]|[12][0-9]|3[01])[\/](0[1-9]|1[012])[\/](19|20)\d\d$/i date_regex = /^(0[1-9]|[12][0-9]|3[01])[\/](0[1-9]|1[012])[\/](19|20)\d\d$/i
params[:start] = Date.today.beginning_of_month.strftime('%d/%m/%Y') if !params[:start] params[:cc_creation_date_start] = Date.today.beginning_of_month.strftime('%d/%m/%Y') if !params[:cc_creation_date_start]
if params[:start] and params[:start] =~ date_regex if params[:cc_creation_date_start] and params[:cc_creation_date_start] =~ date_regex
#fsfds = sdfsfd #fsfds = sdfsfd
@start = Date.parse(params[:start]).beginning_of_day @cc_creation_date_start = Date.parse(params[:cc_creation_date_start]).beginning_of_day
params[:start]= @start.strftime('%d/%m/%Y') params[:cc_creation_date_start]= @cc_creation_date_start.strftime('%d/%m/%Y')
else else
@start = nil @cc_creation_date_start = nil
end end
if true if true
params[:stop] = Date.today.end_of_month.strftime('%d/%m/%Y') if !params[:stop] params[:cc_creation_date_stop] = Date.today.end_of_month.strftime('%d/%m/%Y') if !params[:cc_creation_date_stop]
if params[:stop].to_s != "" # and params[:stop] =~ date_regex if params[:cc_creation_date_stop].to_s != "" # and params[:stop] =~ date_regex
@stop = Date.parse(params[:stop]).end_of_day @cc_creation_date_stop = Date.parse(params[:cc_creation_date_stop]).end_of_day
params[:stop]= @stop.strftime('%d/%m/%Y') params[:cc_creation_date_stop]= @cc_creation_date_stop.strftime('%d/%m/%Y')
else else
@stop = nil @cc_creation_date_stop = nil
end end
end end
@price_lines = @price_lines.where("price_lines.cc_creation_date >= ?", @start) if @start @price_lines = @price_lines.where("price_lines.cc_creation_date >= ?", @cc_creation_date_start) if @cc_creation_date_start
@price_lines = @price_lines.where("price_lines.cc_creation_date <= ?", @stop.end_of_day) if @stop @price_lines = @price_lines.where("price_lines.cc_creation_date <= ?", @cc_creation_date_stop.end_of_day) if @cc_creation_date_stop
@price_lines = @price_lines.where(:cc_block_type => "Demande de commande") params[:wish_date_start] = Date.today.beginning_of_month.strftime('%d/%m/%Y') if !params[:wish_date_start]
if params[:wish_date_start] and params[:wish_date_start] =~ date_regex
#fsfds = sdfsfd
@wish_date_start = Date.parse(params[:wish_date_start]).beginning_of_day
params[:wish_date_start]= @wish_date_start.strftime('%d/%m/%Y')
else
@wish_date_start = nil
end
if true
params[:wish_date_stop] = Date.today.end_of_month.strftime('%d/%m/%Y') if !params[:wish_date_stop]
if params[:wish_date_stop].to_s != "" # and params[:stop] =~ date_regex
@wish_date_stop = Date.parse(params[:wish_date_stop]).end_of_day
params[:wish_date_stop]= @wish_date_stop.strftime('%d/%m/%Y')
else
@wish_date_stop = nil
end
end
@price_lines = @price_lines.joins(:price_line_block).where("price_line_blocks.wish_date >= ?", @wish_date_start) if @wish_date_start
@price_lines = @price_lines.joins(:price_line_block).where("price_line_blocks.wish_date <= ?", @wish_date_stop.end_of_day) if @wish_date_stop
respond_to do |format| respond_to do |format|
format.html{ format.html{

View File

@ -31,13 +31,20 @@ class Admin::ImportCsvsController < ApplicationController
end end
def match_refs
@price_documents = PriceDocument.joins(price_line_block: :price_lines).where({price_line_block: {price_lines: {p_product_ref: nil}}}).distinct
redirect_to :action => :index if @price_documents.empty?
end
def charge def charge
@import_csv = ImportCsv.find(params[:id]) @import_csv = ImportCsv.find(params[:id])
@import_csv.load @import_csv.load
redirect_to :action => :index # redirect_to :action => :index
redirect_to match_refs_admin_import_csvs_path
end end
def new def new
@import_csv = ImportCsv.new(:parent_id => params[:parent_id]) @import_csv = ImportCsv.new(:parent_id => params[:parent_id])
if @import_csv.parent if @import_csv.parent
@ -85,4 +92,13 @@ class Admin::ImportCsvsController < ApplicationController
@import_csv.destroy @import_csv.destroy
end end
def temp_p_product
if params[:price_line_id]
@price_line = PriceLine.find(params[:price_line_id])
p_product = PProduct.find_or_create_by(name: "--> Selectioner un produit <--", code: "--> Indiquer un code produit <--")
@p_product_ref = PProductRef.find_or_create_by(p_product: p_product, description: @price_line.title, ct_price_ht: @price_line.ct_u_price_ht)
@p_product_ref.p_product_ref_specs.build
end
end
end end

View File

@ -280,6 +280,89 @@ class Admin::PCustomerSheetsController < ApplicationController
end end
def export_xls
@p_customer_sheets = PCustomerSheet.all
if params[:p_customer_sheet_ids].present?
@p_customer_sheets = PCustomerSheet.where(id: params[:p_customer_sheet_ids])
end
respond_to do |format|
format.csv {
@headers = ["BUID", "DATE", "NUMERO", "CLIENT", "REFERENCE", "EAN", "DESIGNATION", "QTE", "PRIX 1", "PRIX 2", "DEEE", "SORECOP", "FOURNISSEUR", "CODE ARTICLE MAG", "NomMarque", "Code Douanier", "Type SORECOP"]
@columns = []
# PCustomerSheet.qi_table_order.each do |key, value|
# if value.instance_of? Hash
# name = value[:name]
# else
# name = value
# end
# if name != "Actions"
# @headers << name.to_s
# @columns << key
# end
# end
xlsx_package = Axlsx::Package.new
wb = xlsx_package.workbook
wb.add_worksheet(name: "BASIC extract to Chronopost") do |sheet|
sheet.add_row @headers
@p_customer_sheets.each do |p_customer_sheet|
p_customer_sheet.price_line_block.price_lines.each do |price_line|
line = []
line << price_line.id
line << p_customer_sheet.created_at.strftime("%d/%d/%Y")
line << p_customer_sheet.id
line << p_customer_sheet.p_customer.code + " - " + p_customer_sheet.p_customer.particulars.first.organisation
line << price_line.p_product_ref.cc_name
# line << price_line.p_product_ref.cc_ean
line << price_line.p_product_ref.ean
line << price_line.p_product_ref.cc_name
line << price_line.qte
line << price_line.cc_price_u_ht
line << price_line.ct_u_price_ht
line << price_line.p_product_ref.deee
line << price_line.p_product_ref.sorecop
# line << price_line.p_product_ref.referal_fournisseur
line << "Fournisseur"
line << ""
line << price_line.p_product_ref.p_product.s_brand.name
line << "Code douanier"
line << price_line.p_product_ref.sorecop_comment
sheet.add_row line, types: line.map{|t| cell_type_from_value(t)}
# puts line
end
# @columns.each do |column|
# if (p_customer_sheet.respond_to?("csv_"+column.to_s))
# line << p_customer_sheet.send("csv_"+column.to_s)
# elsif (p_customer_sheet.respond_to?(column))
# if p_customer_sheet.send(column.to_s).class.to_s == "BigDecimal"
# line << p_customer_sheet.send(column.to_s).to_s.gsub('.', ',')
# else
# line << p_customer_sheet.send(column.to_s)
# end
# else
# line << column.to_s
# end
# end
# sheet.add_row line, types: line.map{|t| cell_type_from_value(t)}
end
end
@final_file = "#{Rails.root}/private_medias/export-inscrits-#{Time.now.to_s.to_slug}.xlsx"
xlsx_package.serialize(@final_file)
send_file @final_file
}
end
end
end end

View File

@ -0,0 +1,76 @@
# -*- encoding : utf-8 -*-
class Admin::PFournisseurRefsController < ApplicationController
layout "admin"
before_action :auth_admin
before_action :admin_space
def admin_space
@admin_space = "default"
end
def index
@p_fournisseur_refs = PFournisseurRef.all
@p_fournisseur_refs = sort_by_sorting(@p_fournisseur_refs, "id DESC")
respond_to do |format|
format.html{
params[:search][:per_page] = params[:search][:per_page] || 100
per_page = params[:search][:per_page]
page = (params[:page] and params[:page] != "") ? params[:page] : 1
@p_fournisseur_refs = @p_fournisseur_refs.page(page).per(per_page)
}
end
end
def show
@p_fournisseur_ref = PFournisseurRef.find(params[:id])
end
def new
@p_fournisseur_ref = PFournisseurRef.new
end
def edit
@p_fournisseur_ref = PFournisseurRef.find(params[:id])
end
def create
@p_fournisseur_ref = PFournisseurRef.new(params.require(:p_fournisseur_ref).permit!)
if @p_fournisseur_ref.save
else
render action: "new"
end
end
def update
@p_fournisseur_ref = PFournisseurRef.find(params[:id])
if @p_fournisseur_ref.update_attributes(params.require(:p_fournisseur_ref).permit!)
else
render action: "edit"
end
end
def destroy
@p_fournisseur_ref = PFournisseurRef.find(params[:id])
@p_fournisseur_ref.destroy
end
end

View File

@ -23,7 +23,6 @@ class Admin::PFournisseursController < ApplicationController
end end
def index def index
@p_fournisseurs = PFournisseur.order(:name).all @p_fournisseurs = PFournisseur.order(:name).all

View File

@ -1,6 +1,8 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Admin::PProductRefsController < ApplicationController class Admin::PProductRefsController < ApplicationController
include ActionView::RecordIdentifier # adds `dom_id`
layout "admin" layout "admin"
before_action :auth_admin before_action :auth_admin
@ -58,6 +60,14 @@ class Admin::PProductRefsController < ApplicationController
@p_product_refs = sort_by_sorting(@p_product_refs, "id DESC") @p_product_refs = sort_by_sorting(@p_product_refs, "id DESC")
respond_to do |format| respond_to do |format|
format.js{
params[:search][:per_page] = params[:search][:per_page] || 100
per_page = params[:search][:per_page]
page = (params[:page] and params[:page] != "") ? params[:page] : 1
@p_product_refs = @p_product_refs.page(page).per(per_page)
}
format.html{ format.html{
params[:search][:per_page] = params[:search][:per_page] || 100 params[:search][:per_page] = params[:search][:per_page] || 100
@ -69,6 +79,11 @@ class Admin::PProductRefsController < ApplicationController
end end
if params[:manager].to_s == "true"
@manager = true
render :layout => false
end
end end
def show def show
@ -100,13 +115,17 @@ class Admin::PProductRefsController < ApplicationController
def update def update
@p_product_ref = PProductRef.find(params[:id]) @p_product_ref = PProductRef.find(params[:id])
if @p_product_ref.update_attributes(params.require(:p_product_ref).permit!) if @p_product_ref.update_attributes(params.require(:p_product_ref).permit!)
if params[:update_price_line_id]
@price_line = PriceLine.find(params[:update_price_line_id])
@price_line.update(p_product_ref: @p_product_ref)
end
# redirect_to admin_p_products_path(@p_product_ref.p_product, anchor: dom_id(@p_product_ref))
else else
render action: "edit"
render action: "edit"
end end

View File

@ -81,9 +81,12 @@ class Admin::PProductsController < ApplicationController
@p_product = PProduct.new #(:p_customer_cat_ids => [3]) @p_product = PProduct.new #(:p_customer_cat_ids => [3])
# @p_product.p_product_refs << PProductRef.new # @p_product.p_product_refs << PProductRef.new
@p_product_refs = @p_product.p_product_refs.build fournisseur_label = params[:fournisseur_label] if params[:fournisseur_label]
if params[:price_line_id]
@price_line = PriceLine.find(params[:price_line_id])
end
@p_product_refs = @p_product.p_product_refs.build(ct_sub_name: fournisseur_label)
@p_product_ref_specs = @p_product_refs.p_product_ref_specs.build @p_product_ref_specs = @p_product_refs.p_product_ref_specs.build
@p_spec_type = @p_product_ref_specs.build_p_spec_type @p_spec_type = @p_product_ref_specs.build_p_spec_type
@p_spec_value = @p_product_ref_specs.build_p_spec_value @p_spec_value = @p_product_ref_specs.build_p_spec_value

View File

@ -13,7 +13,7 @@ class Admin::PSpecValuesController < ApplicationController
def index def index
@p_spec_values = PSpecValue.all @p_spec_values = PSpecValue.all
@p_spec_values = sort_by_sorting(@p_spec_values, "id DESC") @p_spec_values = sort_by_sorting(@p_spec_values, "value + 0 ASC")
respond_to do |format| respond_to do |format|
format.html{ format.html{

View File

@ -224,7 +224,7 @@ class Admin::PriceDocumentsController < ApplicationController
def show def show
@price_document = PriceDocument.find(params[:id]) @price_document = PriceDocument.find(params[:id])
@facture_achat_childrens = PriceDocument.where(doc_ref_id: @price_document.id, price_document_type: PriceDocumentType.find_by_label("Facture achat"))
end end
def new def new
@ -235,11 +235,13 @@ class Admin::PriceDocumentsController < ApplicationController
@price_document.price_line_block = PriceLineBlock.new(:p_customer_id => params[:p_customer_id], :p_fournisseur_id => params[:p_fournisseur_id]) @price_document.price_line_block = PriceLineBlock.new(:p_customer_id => params[:p_customer_id], :p_fournisseur_id => params[:p_fournisseur_id])
if @price_document.price_document_type.label == "Demande prix" if @price_document.price_document_type.label == "Demande prix"
p_product_ref_id = params[:qte].keys p_product_ref_id = params[:p_product_ref_ids] - [""]
p_product_ref_qte = params[:qte].values p_product_ref_qte = params[:qte].permit!.to_hash
p_product_ref_id.each_with_index do |key, i| p_product_ref_id.each do |i|
@price_document.price_line_block.price_lines << PriceLine.new(:p_product_ref_id => key, :qte => p_product_ref_qte[i]) if p_product_ref_qte[i.to_s].to_i > 0
@price_document.price_line_block.price_lines << PriceLine.new(:p_product_ref_id => i, :qte => p_product_ref_qte[i.to_s])
end
end end
# @ref_price_lines = PriceLine.where(:id => params[:price_line_ids]) # @ref_price_lines = PriceLine.where(:id => params[:price_line_ids])
@ -322,7 +324,11 @@ class Admin::PriceDocumentsController < ApplicationController
@price_document.date = Date.today @price_document.date = Date.today
@avoir = true if @price_document.label == "Avoir" @avoir = true if @price_document.label == "Avoir"
if @price_document.save if @price_document.save
redirect_to admin_price_documents_path(:price_document_type_id => @price_document.price_document_type_id) if @price_document.cc_label == "Demande prix"
render action: :show
else
redirect_to admin_price_documents_path(:price_document_type_id => @price_document.price_document_type_id)
end
else else
render action: "new" render action: "new"
@ -337,18 +343,28 @@ class Admin::PriceDocumentsController < ApplicationController
@avoir = true if @price_document.label == "Avoir" @avoir = true if @price_document.label == "Avoir"
if @price_document.update_attributes(params.require(:price_document).permit!) if @price_document.update_attributes(params.require(:price_document).permit!)
if params[:public_edit].to_s == "true" if params[:public_edit].to_s == "true"
@price_document.reset_for_update @price_document.reset_for_update
#@price_document.unarchive_now #@price_document.unarchive_now
#@price_document.archive_now #@price_document.archive_now
if @price_document.ref_element if ["Facture achat", "Commande achat"].include?(@price_document.cc_label)
redirect_to [:admin, @price_document]
elsif @price_document.doc_ref_id
redirect_to [:admin, PriceDocument.find(@price_document.doc_ref_id)]
elsif @price_document.ref_element
redirect_to [:admin, @price_document.ref_element] redirect_to [:admin, @price_document.ref_element]
else else
redirect_to [:admin, @price_document] redirect_to [:admin, @price_document]
end end
elsif @price_document.doc_ref_id
redirect_to [:admin, PriceDocument.find(@price_document.doc_ref_id)]
elsif @price_document.ref_element
redirect_to [:admin, @price_document.ref_element]
elsif @price_document.label == "Catalogue fournisseur"
redirect_to match_refs_admin_import_csvs_path
else else
redirect_to [:admin, @price_document] redirect_to [:admin, @price_document]
end end
@ -602,9 +618,199 @@ class Admin::PriceDocumentsController < ApplicationController
@price_document = PriceDocument.find(params[:id]) @price_document = PriceDocument.find(params[:id])
end end
def match_p_fournisseur_save
@price_document = PriceDocument.find(params[:id])
if @price_document.update_attributes(params.require(:price_document).permit!)
# redirect_back(fallback_location: price_documents_ptath)
else
render action: "edit"
end
end
def analyse_reponses def analyse_reponses
@price_document = PriceDocument.find(params[:id]) @price_document = PriceDocument.find(params[:id])
@price_document_responses = PriceDocument.where(:doc_ref_id => @price_document.id ) @price_document_responses = PriceDocument.where(:doc_ref_id => @price_document.id, :price_document_type_id => PriceDocumentType.find_by_label("Réponse fournisseur").id )
end
def analyse_reponses_save
@price_document = PriceDocument.find(params[:id])
if @price_document.update_attributes(params.require(:price_document).permit!)
redirect_to :analyse_reponses_admin_price_document
else
render :edit
end
end
def generate_final_consult
price_lines_to_add = {}
@price_document_demand = PriceDocument.find(params[:id])
@price_document_demand.price_line_block.price_lines.each do |pl_demand|
pl_demand.price_line_resps.all.each do |price_line_resp|
price_lines_to_add[price_line_resp.p_fournisseur.id] = price_lines_to_add[price_line_resp.p_fournisseur.id] || {:p_fournisseur => price_line_resp.p_fournisseur, :price_lines => [] }
price_lines_to_add[price_line_resp.p_fournisseur.id][:price_lines] << price_line_resp
end
end
price_lines_to_add.each do |k,v|
new_final_consult = PriceDocument.new(:doc_ref_id => @price_document_demand.id,:date => Date.today, :price_document_type => PriceDocumentType.find_by_label("Consultation fournisseur"))
new_final_consult.price_line_block = PriceLineBlock.new(:p_fournisseur => v[:p_fournisseur])
v[:price_lines].each do |price_line_resp|
new_final_consult.price_line_block.price_lines << PriceLine.new(:p_product_ref => price_line_resp.p_product_ref, :qte => price_line_resp.qte_available, :ct_u_price_ht => price_line_resp.price_u_ht )
end
new_final_consult.save
end
@final_consult = PriceDocument.where(price_document_type: PriceDocumentType.find_by_label("Consultation fournisseur")).last
redirect_to admin_price_document_path(@price_document_demand, anchor: "consult")
end
def buy_order_create
@final_consult = PriceDocument.find(params[:id])
price_line_block = PriceLineBlock.new(p_fournisseur: @final_consult.price_line_block.p_fournisseur)
price_lines = PriceLine.where(price_line_block: @final_consult.price_line_block)
@price_document = PriceDocument.new(date: Date.today, price_line_block: price_line_block, doc_ref_id: @final_consult.id, demande_de_prix_id: @final_consult.id ,:price_document_type => PriceDocumentType.find_by_label("Commande achat"))
price_lines.each do |pl|
@price_document.price_line_block.price_lines << PriceLine.new(p_product_ref: pl.p_product_ref, qte: pl.qte, ct_u_price_ht: pl.price_u_ht)
end
if @price_document.save!
redirect_to admin_price_document_path(@price_document)
end
end
def bon_de_reception
@past_price_document = PriceDocument.find(params[:id])
@p_customer_sheet = @past_price_document.ref_element
if @p_customer_sheet
price_document = @p_customer_sheet.price_documents.new(:price_document_type => PriceDocumentType.find_by_label("Bon de réception achat"), :demande_de_prix_id => @past_price_document.id, :date => Date.today)
else
price_document = PriceDocument.new(:price_document_type => PriceDocumentType.find_by_label("Bon de réception achat"), :date => Date.today)
end
price_document.doc_ref_id = @past_price_document.id
price_document.p_fournisseur = @past_price_document.p_fournisseur
price_document.price_line_block = @past_price_document.price_line_block.dup
if @past_price_document.cc_label == "Commande achat"
price_document.bon_de_commande_achat_id = @past_price_document.id
price_document.reliquat = true if PriceDocument.where(:bon_de_commande_achat_id => @past_price_document.id, :price_document_type => PriceDocumentType.find_by_label("Bon de réception achat")).count > 0
end
if @past_price_document.cc_label == "Facture achat"
price_document.facture_achat_id = @past_price_document.id
end
price_document.price_line_block.ac_bon_de_commande_id = nil
price_document.price_line_block.ac_bon_de_livraison_id = nil
price_document.price_line_block.ac_facture_id = nil
price_document.price_line_block.ac_block_type = nil
price_document.price_line_block.ac_reliquat = nil
@past_price_document.price_line_block.price_lines.each do |pl|
new_pl = pl.dup
new_pl.price_line_ref_id = pl.id
new_pl.ac_block_type = nil
if price_document.reliquat #and @p_customer_sheet
bls = PriceDocument.where(:bon_de_commande_achat_id => @past_price_document.id, :price_document_type => PriceDocumentType.find_by_label("Bon de réception achat"))
qte_ok = PriceLine.where(:price_line_ref_id => new_pl.price_line_ref_id).where(:price_line_block_id => PriceLineBlock.where(:price_lineable_type => "PriceDocument", :price_lineable_id => bls.ids)).sum(:qte)
new_pl.qte = new_pl.qte - qte_ok
end
price_document.price_line_block.price_lines << new_pl
end
if price_document.save
#price_document.reset_for_update
#price_document.archive_now
if @p_customer_sheet
@p_customer_sheet.state = "Bon de réception achat"
@p_customer_sheet.save
end
if price_document.doc_ref_id
redirect_to [:admin, @past_price_document]
else
redirect_to [:admin, price_document]
end
else
render :inline => price_document.errors.messages.to_s
end
end
def facture_achat
@past_price_document = PriceDocument.find(params[:id])
@p_customer_sheet = @past_price_document.ref_element
if @p_customer_sheet
price_document = @p_customer_sheet.price_documents.new(:price_document_type => PriceDocumentType.find_by_label("Facture achat"), :demande_de_prix_id => @past_price_document.id, :date => Date.today)
else
price_document = PriceDocument.new(:price_document_type => PriceDocumentType.find_by_label("Facture achat"), :date => Date.today)
end
price_document.doc_ref_id = @past_price_document.id
price_document.p_fournisseur = @past_price_document.p_fournisseur
price_document.price_line_block = @past_price_document.price_line_block.dup
price_document.price_line_block.ac_bon_de_commande_id = nil
price_document.price_line_block.ac_bon_de_livraison_id = nil
price_document.price_line_block.ac_facture_id = nil
price_document.price_line_block.ac_block_type = nil
price_document.price_line_block.ac_reliquat = nil
@past_price_document.price_line_block.price_lines.each do |pl|
new_pl = pl.dup
new_pl.price_line_ref_id = pl.id
new_pl.ac_block_type = nil
price_document.price_line_block.price_lines << new_pl
end
if price_document.save
#price_document.reset_for_update
#price_document.archive_now
if @p_customer_sheet
@p_customer_sheet.state = "Facture"
@p_customer_sheet.save
end
if price_document.doc_ref_id
redirect_to [:admin, @past_price_document]
else
redirect_to [:admin, price_document]
end
else
render :inline => price_document.errors.messages.to_s
end
end end
end end

View File

@ -0,0 +1,76 @@
# -*- encoding : utf-8 -*-
class Admin::PriceLineRespSelectsController < ApplicationController
layout "admin"
before_action :auth_admin
before_action :admin_space
def admin_space
@admin_space = "default"
end
def index
@price_line_resp_selects = PriceLineRespSelect.all
@price_line_resp_selects = sort_by_sorting(@price_line_resp_selects, "id DESC")
respond_to do |format|
format.html{
params[:search][:per_page] = params[:search][:per_page] || 100
per_page = params[:search][:per_page]
page = (params[:page] and params[:page] != "") ? params[:page] : 1
@price_line_resp_selects = @price_line_resp_selects.page(page).per(per_page)
}
end
end
def show
@price_line_resp_select = PriceLineRespSelect.find(params[:id])
end
def new
@price_line_resp_select = PriceLineRespSelect.new
end
def edit
@price_line_resp_select = PriceLineRespSelect.find(params[:id])
end
def create
@price_line_resp_select = PriceLineRespSelect.new(params.require(:price_line_resp_select).permit!)
if @price_line_resp_select.save
else
render action: "new"
end
end
def update
@price_line_resp_select = PriceLineRespSelect.find(params[:id])
if @price_line_resp_select.update_attributes(params.require(:price_line_resp_select).permit!)
else
render action: "edit"
end
end
def destroy
@price_line_resp_select = PriceLineRespSelect.find(params[:id])
@price_line_resp_select.destroy
end
end

View File

@ -0,0 +1,76 @@
# -*- encoding : utf-8 -*-
class Admin::SorecopCatsController < ApplicationController
layout "admin"
before_action :auth_admin
before_action :admin_space
def admin_space
@admin_space = "default"
end
def index
@sorecop_cats = SorecopCat.all
@sorecop_cats = sort_by_sorting(@sorecop_cats, "id DESC")
respond_to do |format|
format.html{
params[:search][:per_page] = params[:search][:per_page] || 100
per_page = params[:search][:per_page]
page = (params[:page] and params[:page] != "") ? params[:page] : 1
@sorecop_cats = @sorecop_cats.page(page).per(per_page)
}
end
end
def show
@sorecop_cat = SorecopCat.find(params[:id])
end
def new
@sorecop_cat = SorecopCat.new
end
def edit
@sorecop_cat = SorecopCat.find(params[:id])
end
def create
@sorecop_cat = SorecopCat.new(params.require(:sorecop_cat).permit!)
if @sorecop_cat.save
else
render action: "new"
end
end
def update
@sorecop_cat = SorecopCat.find(params[:id])
if @sorecop_cat.update_attributes(params.require(:sorecop_cat).permit!)
else
render action: "edit"
end
end
def destroy
@sorecop_cat = SorecopCat.find(params[:id])
@sorecop_cat.destroy
end
end

View File

@ -0,0 +1,76 @@
# -*- encoding : utf-8 -*-
class Admin::SorecopTaxesController < ApplicationController
layout "admin"
before_action :auth_admin
before_action :admin_space
def admin_space
@admin_space = "default"
end
def index
@sorecop_taxes = SorecopTax.all
@sorecop_taxes = sort_by_sorting(@sorecop_taxes, "sorecop_cat_id ASC")
respond_to do |format|
format.html{
params[:search][:per_page] = params[:search][:per_page] || 100
per_page = params[:search][:per_page]
page = (params[:page] and params[:page] != "") ? params[:page] : 1
@sorecop_taxes = @sorecop_taxes.page(page).per(per_page)
}
end
end
def show
@sorecop_tax = SorecopTax.find(params[:id])
end
def new
@sorecop_tax = SorecopTax.new
end
def edit
@sorecop_tax = SorecopTax.find(params[:id])
end
def create
@sorecop_tax = SorecopTax.new(params.require(:sorecop_tax).permit!)
if @sorecop_tax.save
else
render action: "new"
end
end
def update
@sorecop_tax = SorecopTax.find(params[:id])
if @sorecop_tax.update_attributes(params.require(:sorecop_tax).permit!)
else
render action: "edit"
end
end
def destroy
@sorecop_tax = SorecopTax.find(params[:id])
@sorecop_tax.destroy
end
end

View File

@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception. # Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead. # For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception protect_from_forgery with: :exception
before_action :set_current_p_customer_sheet #before_action :set_current_p_customer_sheet
@ -33,9 +33,6 @@ class ApplicationController < ActionController::Base
elsif v[:elements] elsif v[:elements]
v[:elements].each do |a,b| v[:elements].each do |a,b|
puts "TEST"
puts b[0]
puts "B"
if b[:sub_elements] and b[:sub_elements][sym.to_sym] if b[:sub_elements] and b[:sub_elements][sym.to_sym]
@qi_menu_active = k @qi_menu_active = k
@qi_menu_sub_menu_active = sym.to_sym @qi_menu_sub_menu_active = sym.to_sym
@ -129,6 +126,10 @@ class ApplicationController < ActionController::Base
set_sub_sub_menu :stocks, :p_preferences_products_menu, :p_grades, "Grades" if PGrade::ACTIVATED set_sub_sub_menu :stocks, :p_preferences_products_menu, :p_grades, "Grades" if PGrade::ACTIVATED
set_sub_sub_menu :stocks, :p_preferences_products_menu, :p_product_powers, "Types de chargeurs" set_sub_sub_menu :stocks, :p_preferences_products_menu, :p_product_powers, "Types de chargeurs"
set_sub_sub_menu :stocks, :p_preferences_products_menu, :p_product_zones, "Zones produits" set_sub_sub_menu :stocks, :p_preferences_products_menu, :p_product_zones, "Zones produits"
set_sub_sub_menu :stocks, :p_preferences_products_menu, :import_csvs, "Import Excel"
set_sub_sub_menu :stocks, :p_preferences_products_menu, :import_csv_match_refs, "Rapprochement références", match_refs_admin_import_csvs_path
set_sub_sub_menu :stocks, :p_preferences_products_menu, :sorecop_cats, "Catégories SORECOP"
set_sub_sub_menu :stocks, :p_preferences_products_menu, :sorecop_taxes, "taxe SORECOP"
end end
@ -168,7 +169,7 @@ class ApplicationController < ActionController::Base
end end
set_sub_menu :documents, :"p_document_type_reponse_fournisseur", "Réponses fournisseurs", admin_price_documents_path(:price_document_type_id => 2) # set_sub_menu :documents, :"p_document_type_reponse_fournisseur", "Réponses fournisseurs", admin_price_documents_path(:price_document_type_id => PriceDocumentType.find_by(label: "Réponse fournisseur").id)
@ -474,13 +475,17 @@ class ApplicationController < ActionController::Base
def current_admin def current_admin
if cookies[:admin_remember_token] if @current_admin
if @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token]) return @current_admin
@current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token]) else
else if cookies[:admin_remember_token]
cookies[:admin_remember_token] =nil if @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token])
end @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token])
else
cookies[:admin_remember_token] =nil
end
end
end end

View File

@ -14,6 +14,19 @@ module ApplicationHelper
return raw(r) return raw(r)
end end
def qi_js_field_price_line_form(form, model, method, options = {})
r = ""
if options[:hidden]
r += hidden_field_tag(method, eval("form.object.#{method}"), :class => "input_#{model}_#{method} form-control",:disabled => true)
else
if options[:label]
r += label_tag(:input, options[:label], class: options[:label_class])
end
r += text_field_tag(method, (options[:value] ? options[:value] : eval("form.object.#{method}")), :class => "input_#{model}_#{method} form-control",:disabled => true)
end
return raw(r)
end
def edit_watcher(element_type, element_id, key='' ) def edit_watcher(element_type, element_id, key='' )
raw ('<script type="text/javascript">')+("edit_watcher('"+element_type+"', '"+element_id.to_s+"','"+key+"');")+("setInterval(function(){ edit_watcher('"+element_type+"', '"+element_id.to_s+"','"+key+"');}, 1000);")+('</script><div id="edit_watcher_result"></div>') raw ('<script type="text/javascript">')+("edit_watcher('"+element_type+"', '"+element_id.to_s+"','"+key+"');")+("setInterval(function(){ edit_watcher('"+element_type+"', '"+element_id.to_s+"','"+key+"');}, 1000);")+('</script><div id="edit_watcher_result"></div>')

View File

@ -28,13 +28,17 @@ module DocumentLineHelper
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render("admin/"+association.to_s + "/essentials_form", :form => builder) render("admin/"+association.to_s + "/essentials_form", :form => builder)
end end
elsif options[:slug]
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render("admin/"+association.to_s + "/form_#{options[:slug]}", :form => builder)
end
else else
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render("admin/"+association.to_s + "/form", :form => builder) render("admin/"+association.to_s + "/form", :form => builder)
end end
end end
link_to name,"#", :onclick => "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\");return false;", :class => (options[:class]) link_to name,"#", :onclick => "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\");return false;", :class => (options[:class]), tabindex: options[:tabindex], style: options[:style]
end end
end end

View File

@ -32,11 +32,15 @@ class ImportCsv < ApplicationRecord
after_create do after_create do
if file_is_csv?
csv_text = File.read(self.file.path, :encoding => 'UTF-8') csv_text = File.read(self.file.path, :encoding => 'UTF-8')
@csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") csv = CSV.parse(csv_text, :headers => true, :col_sep => ";")
headers = csv.headers
@csv.headers.each do |header| else
xlsx = Roo::Spreadsheet.open(self.file.path, extension: :xlsx) # open spreadsheet
headers = xlsx.row(1)
end
headers.each do |header|
self.import_csv_headers << ImportCsvHeader.new(:name => header) self.import_csv_headers << ImportCsvHeader.new(:name => header)
end end
@ -50,12 +54,15 @@ class ImportCsv < ApplicationRecord
end end
self.save self.save
end end
def file_is_csv?
File.read(self.file.path, :encoding => 'utf-8').valid_encoding?
end
def charge def charge
self.import_csv_elements.each do |e| self.import_csv_elements.each do |e|
@ -63,25 +70,43 @@ class ImportCsv < ApplicationRecord
e.destroy e.destroy
end end
csv_text = File.read(self.file.path, :encoding => 'UTF-8')
@csv = CSV.parse(csv_text, :headers => true, :col_sep => ";")
r = [] r = []
@csv.each do |row|
line = {} if file_is_csv?
self.import_csv_champs.each do |import_csv_champ| csv_text = File.read(self.file.path, :encoding => 'UTF-8')
if import_csv_champ.header? csv = CSV.parse(csv_text, :headers => true, :col_sep => ";")
eval "line['#{import_csv_champ.champ}'] = row[\"#{import_csv_champ.header}\"]" csv.each do |row|
elsif import_csv_champ.value? line = {}
eval "line['#{import_csv_champ.champ}'] = \"#{import_csv_champ.value}\"" self.import_csv_champs.each do |import_csv_champ|
if import_csv_champ.header?
eval "line['#{import_csv_champ.champ}'] = row[\"#{import_csv_champ.header}\"]"
elsif import_csv_champ.value?
eval "line['#{import_csv_champ.champ}'] = \"#{import_csv_champ.value}\""
end
end end
r << line
end end
return r
r << line else
xlsx = Roo::Spreadsheet.open(self.file.path, extension: :xlsx) # open spreadsheet
headers = xlsx.row(1) # get header row
xlsx.each_with_index do |row, idx|
line = {}
next if idx == 0 # skip header
# create hash from headers and cells
data = Hash[[headers, row].transpose]
self.import_csv_champs.each do |import_csv_champ|
# raise
if import_csv_champ.header?
eval "line['#{import_csv_champ.champ}'] = data[\"#{import_csv_champ.header}\"]"
elsif import_csv_champ.value?
eval "line['#{import_csv_champ.champ}'] = \"#{import_csv_champ.value}\""
end
end
r << line
end
return r
end end
return r
end end
def load def load

View File

@ -1,2 +1,3 @@
class PBank < ApplicationRecord class PBank < ApplicationRecord
has_many :particulars, :as => :owner, :dependent => :destroy
end end

View File

@ -5,5 +5,5 @@ class PContact < ApplicationRecord
has_many :p_contact_contact_types, :dependent => :destroy has_many :p_contact_contact_types, :dependent => :destroy
has_many :p_contact_types, :through => :p_contact_contact_types has_many :p_contact_types, :through => :p_contact_contact_types
belongs_to :p_payment_type
end end

View File

@ -65,6 +65,26 @@ class PCustomer < ApplicationRecord
has_many :order_hists has_many :order_hists
# before_validation :set_auth_token, on: [:create, :update] # before_validation :set_auth_token, on: [:create, :update]
before_validation do
if self.code.blank?
generate_code
end
end
def generate_code
if !self.code
last_used_code = self.class.all.order(code: :desc).limit(1)[0].code
last_number = last_used_code.match(/\d+/).to_s.to_i + 1
code = "CLI%04d" % [last_number]
while self.class.find_by(code: code)
last_number += 1
code = "CLI%04d" % [last_number]
end
self.code = code
end
end
def self.qi_table_order def self.qi_table_order
@ -258,6 +278,7 @@ class PCustomer < ApplicationRecord
end end
def solde_avoir_and_bills(date = Date.today) def solde_avoir_and_bills(date = Date.today)
raise # p_document_id à remplacer
self.p_documents.where(:p_document_type_id => [4,7]).where("created_at < ?", date.to_time.end_of_day).sum(:cache_total_ttc) self.p_documents.where(:p_document_type_id => [4,7]).where("created_at < ?", date.to_time.end_of_day).sum(:cache_total_ttc)
end end
@ -482,5 +503,437 @@ class PCustomer < ApplicationRecord
end while PCustomer.exists?(column => self[column]) end while PCustomer.exists?(column => self[column])
end end
acts_as_csv_import :fields => [
:code,
:societe_raison_sociale,
:nom_enseigne,
:adresse_facturation_1,
:adresse_livraison_2,
:adresse_3,
:cp,
:cp2,
:ville_1,
:ville_2,
:pays,
:societe_livraison,
:forme_juridique,
:famille_client,
:facturer_ttc,
:mode_reglement,
:libelle_mode_reglement,
:telephone_1,
:telephone_2,
:fax,
:risque,
:bloque,
:credit_accorde,
:mode_tva,
:nii,
:nom_banque,
:adresse_banque_1,
:adresse_banque_2,
:adresse_banque_3,
:code_banque,
:ville_banque,
:pays_banque,
:code_banque,
:code_guichet,
:numero_compte,
:cle_rib,
:compte_comptable,
:analytique,
:taux_remise,
:observation,
:export_compta,
:releve_compte,
:email,
:url,
:siret,
:representant,
:nom_representant,
:encour_initial,
:credit_disponible,
:code_tarif,
:telephone_livraison,
:portable_livraison,
:fax_livraison,
:encours_courant,
:encours,
:client_divers,
:contacts_client,
:date_creation,
:code_iban,
:code_bic,
:nom_contact,
:societe_contact,
:titre_contact,
:fonction_contact,
:telephone_contact,
:portable_contact,
:email_contact
]
def self.custom_csv_import(list, import_csv)
#OK Code AUTO :code OK :code
#OK Société - Raison Sociale :particular.organisation OK :societe_raison_sociale
#OK Nom enseigne :particular.com_name OK :nom_enseigne
#OK Adresse facturation 1 :particular.address_1 OK :adresse_facturation_1
#OK Adresse Livraison 2 :particular.address_2 OK :adresse_livraison_2
#OK Adresse 3 :particular.address_3 OK :adresse_3
#OK Code Postal 1 :particular.cp OK :cp
#OK Code Postal 2 VIDE OK :cp2
#OK Ville 1 :particular_city OK :ville_1
#OK Ville 2 VIDE OK :ville_2
#OK Pays :particular.country OK :pays
#OK Société Livraison :particular.address_4 OK :societe_livraison
#OK Forme juridique livraison :particular.address_5 OK :forme_juridique
#OK Famille Client VIDE OK :famille_client
#OK Facturer en TTC VIDE OK :facturer_ttc
#OK Mode Règlement :p_payment_type OK :mode_reglement
#OK Libellé Mode Règlement :payment_delais OK :libelle_mode_reglement
#OK Téléphone 1 :particular.tel OK :telephone_1
#OK Téléphone 2 :particular.tel2 OK :telephone_2
#OK Fax :particular.fax OK :fax
#OK Risque VIDE OK :risque
#OK Bloqué VIDE OK :bloque
#OK Crédit accordé VIDE OK :credit_accorde
#OK Mode TVA VIDE OK :mode_tva
#OK N.I.I. VIDE OK :nii
#OK Nom Banque :p_bank.name OK :nom_banque
#OK Adresse 1 Banque :p_bank.particular.address_1 OK :adresse_banque_1
#OK Adresse 2 Banque :p_bank.particular.address_2 OK :adresse_banque_2
#OK Adresse 3 Banque VIDE OK :adresse_banque_3
#OK Code Postal Banque :p_bank.particular.cp OK :code_banque
#OK Ville Banque :p_bank.particular.ville OK :ville_banque
#OK Pays Banque :p_bank.particular.pays OK :pays_banque
#OK Code Banque INUTILE OK :code_banque
#OK Code Guichet INUTILE OK :code_guichet
#OK Numéro Compte INUTILE OK :numero_compte
#OK Clé RIB INUTILE OK :cle_rib
# Compte Comptable ??? ?? :compte_comptable
#OK Analytique VIDE OK :analytique
#OK Taux Remise VIDE OK :taux_remise
#OK Observations AUTO :p_customer_sheet_note OK :observation
#OK Export Compta VIDE OK :export_compta
# Relevé Compte Bboolean à ajouter dans la base ?? :releve_compte
#OK E-mail AUTO :email OK :email
#OK URL VIDE OK :url
#OK SIRET AUTO :siret OK :siret
#OK Représentant :p_commercial_code OK :representant
#OK Nom Représentant :p_commercial_firstname OK :nom_representant
# Encours initial ??? ?? :encour_initial
# Crédit Disponible ??? ?? :credit_disponible
#OK Code Tarif VIDE OK :code_tarif
#OK Téléphone Livraison :particular.send_tel OK :telephone_livraison
#OK Portable Livraison :particular.send_tel2 OK :portable_livraison
#OK Fax Livraison :particular.send_fax OK :fax_livraison
# Encours courant ??? ?? :encours_courant
# encours_courant ??? ?? :encours
# Client divers ??? ?? :client_divers
#OK Contacts client INUTILE OK :contacts_client
#OK Date de création INUTILE OK :date_creation
#OK Code IBAN :p_customer_ribs.iban OK :code_iban
#OK Code BIC :p_customer_ribs.bic OK :code_bic
#OK Nom du contact :p_contact_name OK :nom_contact
#OK Société du contact VIDE OK :societe_contact
#OK Titre du contact :p_contact.civilite OK :titre_contact
#OK Fonction du contact :p_contact.comment OK :fonction_contact
#OK Téléphone du contact :p_contact.tel OK :telephone_contact
#OK Portable du contact :p_contact.tel2 OK :portable_contact
#OK E-mail du contact :p_contact.email OK :email_contact
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap list
# ap list.class
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap import_csv
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
list.each do |row|
n = self.new(imported: true, p_customer_cat: PCustomerCat.find_by_name("Professionnel"))
# particular = Particular.new(pro: true)
particular_bill = Particular.new
bank = bic = iban = p_commercial = particular_send = send_tel = send_tel2 = send_fax = send_address_2 = p_commercial_code = p_commercial_firstname = contact_2 = nil
bank_particular = Particular.new
contact = PContact.new
row.each do |key, value|
if self.type_for_attribute(key) and self.type_for_attribute(key).type == :decimal
eval "n.#{key} = value.to_s.gsub(' ', '').gsub(',', '.')"
else
case key
when "societe_raison_sociale"
particular_bill.organisation = value if !value.blank?
when "nom_enseigne"
particular_bill.com_name = value if !value.blank?
when "adresse_facturation_1"
particular_bill.address_1 = value if !value.blank?
when "adresse_livraison_2"
send_address_2 = value if !value.blank?
when "adresse_3"
particular_bill.address_3 = value if !value.blank?
when "cp"
particular_bill.cp = value if !value.blank?
when "ville_1"
particular_bill.city = value if !value.blank?
when "pays"
particular_bill.country = value if !value.blank?
when "societe_livraison"
particular_bill.address_4 = value if !value.blank?
when "forme_juridique"
particular_bill.address_5 = value if !value.blank?
when "telephone_1"
particular_bill.tel = value if !value.blank?
when "telephone_2"
particular_bill.tel2 = value if !value.blank?
when "fax"
particular_bill.fax = value if !value.blank?
when "mode_reglement"
if value.present?
if value == "VIR" || "VIR COM" || "VIR 60 J NET" || "VIR 30 J NET"
n.p_payment_type_id = PPaymentType.find_or_create_by!(name: "Virement").id
elsif value == "TRAITE"
n.p_payment_type_id = PPaymentType.find_or_create_by!(name: "Traite").id
else
n.p_payment_type_id = PPaymentType.find_or_create_by!(name: value).id
end
end
when "libelle_mode_reglement"
case value
when "Virement à la commande"
n.payment_delais = 0
when "Chèque à la commande"
n.payment_delais = 0
when "Chèque à réception"
n.payment_delais = 0
when "30 JOURS FIN DE MOIS"
n.payment_delais = 30
n.comptant = false
when "VIR 60J NET DATE RELEVE"
n.payment_delais = 60
n.comptant = false
when "TRAITE A 60 JOURS FIN DE MOIS"
n.payment_delais = 60
n.comptant = false
when "Mensuel - 30j fin de mois du dépôt"
n.payment_delais = 30
n.comptant = false
else
n.payment_delais = value if !value.blank?
end
when "nom_banque"
if value.present?
bank = PBank.find_or_create_by!(name: value)
end
when "adresse_banque_1"
bank_particular.address_1 = value if !value.blank?
when "adresse_banque_2"
bank_particular.address_2 = value if !value.blank?
when "code_banque"
bank_particular.cp = value if !value.blank?
when "ville_banque"
bank_particular.city = value if !value.blank?
when "pays_banque"
bank_particular.country = value if !value.blank?
when "telephone_livraison"
send_tel = value if !value.blank?
when "portable_livraison"
send_tel2 = value if !value.blank?
when "fax_livraison"
send_fax = value if !value.blank?
when "representant"
p_commercial_code = value if !value.blank?
when "nom_representant"
p_commercial_firstname = value if !value.blank?
when "code_iban"
iban = value if !value.blank?
when "code_bic"
bic = value if !value.blank?
when "nom_contact"
contact.name = value if !value.blank?
when "titre_contact"
particular_bill.civilite = value if !value.blank?
when "fonction_contact"
if value.present?
contact.p_contact_types << PContactType.find_or_create_by!(name: value)
end
when "telephone_contact"
contact.tel = value if !value.blank?
when "portable_contact"
if value.present?
if contact.tel.nil?
contact.tel = value if !value.blank?
else
contact_2 = PContact.new(tel: value)
end
end
when "email_contact"
contact.email = value if !value.blank?
when "observation"
n.p_customer_sheet_note = value if !value.blank?
# champs vides ou inutiles :
when "cp2"
when "ville_2"
when "famille_client"
when "facturer_ttc"
when "risque"
when "bloque"
when "credit_accorde"
when "mode_tva"
when "nii"
when "adresse_banque_3"
when "code_banque"
when "code_guichet"
when "numero_compte"
when "cle_rib"
when "analytique"
when "taux_remise"
when "export_compta"
when "url"
when "code_tarif"
when "contacts_client"
when "date_creation"
when "societe_contact"
# Champs ???
when "compte_comptable"
when "encour_initial"
when "credit_disponible"
when "releve_compte"
when "encours_courant"
when "releve_compte"
when "encours"
when "client_divers"
else
eval "n.#{key} = value if !value.blank?"
end
end
end
n.particulars << particular_bill
n.save!
if bank
bank.bic = bic
bank.particulars << bank_particular if bank_particular.address_1
bank.save!
import_csv.import_csv_elements << ImportCsvElement.new(:element => bank)
end
if bic || iban
rib = PCustomerRib.find_or_create_by!(bic: bic, iban: iban)
rib.bank = bank.name if bank
account = PBankAccount.find_or_create_by!(bic: bic, iban: iban, p_customer: n)
account.update(p_bank: bank) if bank
n.p_customer_ribs << rib
import_csv.import_csv_elements << ImportCsvElement.new(:element => rib)
import_csv.import_csv_elements << ImportCsvElement.new(:element => account)
end
if p_commercial_code || p_commercial_firstname
p_commercial = PCommercial.find_or_create_by!(code: p_commercial_code, firstname: p_commercial_firstname)
n.p_commercial = p_commercial
import_csv.import_csv_elements << ImportCsvElement.new(:element => p_commercial)
end
if send_tel || send_tel2 || send_fax || send_address_2
particular_send = Particular.new
particular_send.tel = send_tel if send_tel
particular_send.tel2 = send_tel2 if send_tel2
particular_send.fax = send_fax if send_fax
n.particulars << particular_send
n.particular_send_id = particular_send.id
end
n.p_contacts << contact if (contact.name || contact.tel || contact.email)
n.p_contacts << contact_2 if contact_2
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ contact §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap contact
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.contacts §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.p_contacts
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.particulars §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.particulars
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.p_customer_ribs §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.p_customer_ribs
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.p_commercial §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.p_commercial
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
import_csv.import_csv_elements << ImportCsvElement.new(:element => n)
end
end
end end

View File

@ -1,7 +1,7 @@
class PCustomerRib < ActiveRecord::Base class PCustomerRib < ActiveRecord::Base
belongs_to :p_customer belongs_to :p_customer
has_many :p_documents, :dependent => :nullify # has_many :p_documents, :dependent => :nullify
def generate_rum def generate_rum
if self.sign_date if self.sign_date

View File

@ -40,6 +40,7 @@ class PCustomerSheet < ApplicationRecord
:tot_amount_ht => {:name => "Total HT", :reorder => true, :sort_name => "cc_tot_amount_ht", :sort_name => "p_customer_sheets.cc_tot_amount_ht"}, :tot_amount_ht => {:name => "Total HT", :reorder => true, :sort_name => "cc_tot_amount_ht", :sort_name => "p_customer_sheets.cc_tot_amount_ht"},
:tot_amount_ttc => {:name => "Total TTC", :reorder => true, :sort_name => "cc_tot_amount_ttc", :sort_name => "p_customer_sheets.cc_tot_amount_ttc"}, :tot_amount_ttc => {:name => "Total TTC", :reorder => true, :sort_name => "cc_tot_amount_ttc", :sort_name => "p_customer_sheets.cc_tot_amount_ttc"},
:state => {:name => "Statut", :reorder => false, :as => :state}, :state => {:name => "Statut", :reorder => false, :as => :state},
:check_box => {:name => "Export excel #{'<i id="check-all" class="fa fa-check-square" aria-hidden="true"></i>'}", :reorder => false},
:actions => {:name => "Actions", :reorder => false}, :actions => {:name => "Actions", :reorder => false},
} }
@ -256,7 +257,7 @@ class PCustomerSheet < ApplicationRecord
after_create do after_create do
#self.state = "brouillon" if self.state != "Panier web" self.state = "brouillon" if self.state != "Panier web"
self.save self.save
end end

View File

@ -1,2 +1,136 @@
class PFournisseur < ApplicationRecord class PFournisseur < ApplicationRecord
# has_many :particulars, :as => :owner, :dependent => :destroy
has_many :p_contacts, :as => :contactable, :dependent => :destroy
has_many :p_fournisseur_refs
acts_as_csv_import :fields => [
:nom_fournisseur,
:address,
:cp,
:ville,
:pays,
:tva_intracom,
:delai_paiement,
:interlocuteur,
:fonction,
:tel,
:skype,
:email_1,
:email_2,
:email_3,
:iban,
:bic,
:reglement_par
]
def self.custom_csv_import(list, import_csv)
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap list
# ap list.class
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap import_csv
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
list.each do |row|
n = self.new
# particular = Particular.new(pro: true)
contact_1 = PContact.new
contact_2 = nil
contact_3 = nil
row.each do |key, value|
if self.type_for_attribute(key) and self.type_for_attribute(key).type == :decimal
eval "n.#{key} = value.to_s.gsub(' ', '').gsub(',', '.')"
else
case key
when "nom_fournisseur"
n.name = value if !value.blank?
when "address"
n.address1 = value if !value.blank?
when "ville"
n.city = value if !value.blank?
when "pays"
n.country = value if !value.blank?
when "tva_intracom"
n.tva_num = value if !value.blank?
when "delai_paiement"
if value.present?
case value
when "A la commande"
n.payment_delais = 0
when "A réception"
n.payment_delais = 0
when "7 jours net"
n.payment_delais = 7
when "21 jours net"
n.payment_delais = 21
when "30 jours"
n.payment_delais = 30
when "30 jours net"
n.payment_delais = 30
when "30 jours fin de mois"
n.payment_delais = 30
when "35 jours net"
n.payment_delais = 35
when "40 jours net"
n.payment_delais = 40
when "60 jours net"
n.payment_delais = 60
when "60 jours fin de mois"
n.payment_delais = 60
else
n.payment_delais = value if !value.blank?
end
end
when "interlocuteur"
contact_1.name = value if !value.blank?
when "fonction"
contact_1.p_contact_types << PContactType.find_or_create_by!(name: value)
when "tel"
contact_1.tel = value if !value.blank?
when "skype"
contact_1.skype = value if !value.blank?
when "email_1"
contact_1.email = value if !value.blank?
when "email_2"
contact_2 = PContact.new(email: value)
when "email_3"
contact_3 = PContact.new(email: value)
when "reglement_par"
n.p_payment_type_id = PPaymentType.find_or_create_by!(name: value).id
else
eval "n.#{key} = value if !value.blank?"
end
end
end
# particular.organisation = self.name
n.save!
if (contact_1.name || contact_1.tel || contact_1.skype || contact_1.email)
n.p_contacts << contact_1
import_csv.import_csv_elements << ImportCsvElement.new(:element => contact_1)
end
if contact_2
n.p_contacts << contact_2
import_csv.import_csv_elements << ImportCsvElement.new(:element => contact_2)
end
if contact_3
n.p_contacts << contact_3
import_csv.import_csv_elements << ImportCsvElement.new(:element => contact_3)
end
import_csv.import_csv_elements << ImportCsvElement.new(:element => n)
end
end
end end

View File

@ -0,0 +1,4 @@
class PFournisseurRef < ApplicationRecord
belongs_to :p_product_ref
belongs_to :p_fournisseur
end

View File

@ -1,6 +1,7 @@
class PPaymentType < ApplicationRecord class PPaymentType < ApplicationRecord
belongs_to :p_bank_account belongs_to :p_bank_account
has_many :p_payments has_many :p_payments
has_many :p_fournisseurs
after_save do after_save do
if self.p_bank_account if self.p_bank_account

View File

@ -28,14 +28,13 @@ class PProduct < ApplicationRecord
has_many :p_product_images has_many :p_product_images
belongs_to :p_customer belongs_to :p_customer
belongs_to :sorecop_cat
belongs_to :p_product_cat belongs_to :p_product_cat
belongs_to :s_brand belongs_to :s_brand
validates :name, :presence => true validates :name, :presence => true, exclusion: { in: ["--> Selectioner un produit <--"], message: "Selectioner un produit avant de valider" }
validates :code, :presence => true, :uniqueness => true validates :code, :presence => true, :uniqueness => true, exclusion: { in: ["--> Indiquer un code produit <--"], message: "Indiquer un code produit avant de valider" }
has_many :tvable_tva_rates, :as => :tvable has_many :tvable_tva_rates, :as => :tvable
has_many :tva_rates, :through => :tvable_tva_rates has_many :tva_rates, :through => :tvable_tva_rates
@ -81,6 +80,11 @@ class PProduct < ApplicationRecord
tsearch: { prefix: true } tsearch: { prefix: true }
} }
before_validation do
if self.code.blank?
generate_code
end
end
def self.for_search(search) def self.for_search(search)
@ -114,15 +118,21 @@ class PProduct < ApplicationRecord
after_create do after_create do
end end
after_save do after_save do
self.p_product_refs.each do |ppr| self.p_product_refs.each do |ppr|
ppr.save ppr.save
end end
self.class.destroy_temp_p_product
end end
def self.destroy_temp_p_product
temp_p_product = PProduct.find_by(name: "--> Selectioner un produit <--", code: "--> Indiquer un code produit <--")
if temp_p_product.present?
temp_p_product.destroy
end
end
def tva_rate(accounting_zone_id) def tva_rate(accounting_zone_id)
if r = self.tva_rates.where(:accounting_zone_id => accounting_zone_id).first if r = self.tva_rates.where(:accounting_zone_id => accounting_zone_id).first
@ -171,4 +181,277 @@ class PProduct < ApplicationRecord
self.p_product_images.order(:position).first self.p_product_images.order(:position).first
end end
def generate_code
if !self.code
arr = []
brand = self.s_brand.code.to_s if self.s_brand
cat = self.p_product_cat.name.slice(0, 5).to_slug.upcase.to_s if self.p_product_cat
last_number = 1
arr << brand if brand.present?
arr << cat if cat.present?
arr << "%02d" % [last_number]
arr.prepend("PRODUCT") if arr.length < 2
code = arr.join('-')
while self.class.find_by(code: code)
arr = []
last_number += 1
arr << brand if brand.present?
arr << cat if cat.present?
arr << "%02d" % [last_number]
arr.prepend("PRODUCT") if arr.length < 2
code = arr.join('-')
end
self.code = code
end
end
acts_as_csv_import :fields => [
:identifiant,
:gencode,
:id,
:marque,
:famille,
:reference,
:modele,
:couleur,
:color,
:connectivite,
:sim,
:taille,
:capacite,
:infos_supp,
:reference_fabricant,
:etat,
:code_hs,
:indice_reparabilite,
:duree_dispo_pces_detachees,
:das_tete,
:das_corps,
:das_membre,
:poids,
:nb_pcs_colis,
:code_om,
:dtl,
:gbh_code_971,
:gbh_code_972,
:gbh_code_973,
:code_art,
:sorecop,
:pmp_hors_sorecop,
:target_hors_sorecop,
:frs,
:date,
:spec,
:dtl_targ,
:commentaires,
:com
]
def self.custom_csv_import(list, import_csv)
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
ap "*********************************************************************************************************"
# ap list.size
# ap list.class
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap import_csv
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
# ap "*********************************************************************************************************"
soreco_cat_hash = {
"Smartphone" => "Smartphones & Téléphones mobiles",
"Mobile" => "Smartphones & Téléphones mobiles",
"Tablette" => "Tablettes média et tablette PC",
"MP4" => "Baladeur MP4",
"Clé USB" => "Clés USB",
"Carte Mémoire" => "Cartes mémoires",
"Boitier Multimédia" => "Décodeurs, téléviseurs, enregistreurs"
}
list.each do |row|
next if row["marque"].blank?
n = self.find_or_initialize_by(s_brand: SBrand.find_by(name: row["marque"]), name: row["reference"])
n.imported = true
n.sorecop_cat = SorecopCat.find_by(name: soreco_cat_hash[row["famille"]])
ref = n.p_product_refs.build
row.each do |key, value|
if value.present?
puts key
case key
when "identifiant"
ref.description = value if !value.blank?
when "gencode"
ref.genecode = value if !value.blank?
when "id"
when "marque"
n.s_brand = SBrand.find_or_create_by!(name: value)
when "famille"
n.p_product_cat = PProductCat.find_or_create_by!(name: value)
when "reference"
n.name = value if !value.blank?
when "modele"
ref.ct_sub_name = value if !value.blank?
when "couleur"
ref.p_product_color = PProductColor.find_or_create_by!(name: value)
when "color"
if ref.p_product_color.nil?
ref.p_product_color = PProductColor.find_or_create_by!(color: value)
end
when "connectivite"
arr = []
cellular = [ "5G", "3G", "3G+", "4G", "4G+", "2G", "wifi", "BT"]
video = ["4K","HD" ]
power = ["5W", "12W", "18W", "20W", "96W", "40W", "10W", "40W"]
mix = ["<87W/4K", "5G/4K", "wifi/BT" ]
geoloc = [ "GPS" ]
if mix.include?(value)
arr = value.split('/')
else
arr << value
end
arr.each do |value|
spec = nil
if cellular.include?(value)
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Connectivité"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
elsif video.include?(value)
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Résolution"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
elsif power.include?(value)
PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Puissance éléctrique"), p_spec_value: PSpecValue.find_or_create_by!(value: value.gsub('W', ''), unit: "W"))
elsif geoloc.include?(value)
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Géolocalisation"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
else
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Autre"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
end
import_csv.import_csv_elements << ImportCsvElement.new(:element => spec)
end
when "sim"
if ["DS", "SS"].include?(value)
PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Sim"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
elsif value == "4G"
PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Connectivité"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
end
when "taille"
PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Taille"), p_spec_value: PSpecValue.find_or_create_by!(value: value.to_s))
when "capacite"
unit = value.match(/\D+/)
num = value.match(/\d+/)
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Stockage"), p_spec_value: PSpecValue.find_or_create_by!(value: num.to_s, unit: unit.to_s))
import_csv.import_csv_elements << ImportCsvElement.new(:element => spec)
when "infos_supp"
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Autre"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
import_csv.import_csv_elements << ImportCsvElement.new(:element => spec)
when "reference_fabricant"
ref.manufacturer_ref = value if !value.blank?
when "etat"
ref.used_state = value if !value.blank?
when "code_hs"
ref.i_code_hs = value if !value.blank?
when "indice_reparabilite"
ref.prepair_score = value if !value.blank?
when "duree_dispo_pces_detachees"
ref.part_delay = value if !value.blank?
when "das_tete"
ref.das_head = value if !value.blank?
when "das_corps"
ref.das_body = value if !value.blank?
when "das_membre"
ref.das_membre = value if !value.blank?
when "poids"
ref.weight = value if !value.blank?
when "nb_pcs_colis"
ref.nb_pcs_colis = value if !value.blank?
when "code_om"
ref.code_om = value if !value.blank?
when "gbh_code_971"
ref.gbh_code_971 = value if !value.blank?
when "gbh_code_972"
ref.gbh_code_972 = value if !value.blank?
when "gbh_code_973"
ref.gbh_code_973 = value if !value.blank?
when "code_art"
ref.code_art = value if !value.blank?
when "sorecop"
ref.p_product.sorecop_cat = SorecopCat.find_by(name: soreco_cat_hash[row["famille"]])
if ref.sorecop.kind_of?(String)
ref.ct_sorecop = value if !value.blank?
end
when "pmp_hors_sorecop"
ref.i_pmp_hors_sorecop = value if !value.blank?
when "target_hors_sorecop"
ref.i_target_hors_sorecop = value if !value.blank?
when "frs"
ref.p_fournisseur_id = PFournisseur.find_or_create_by!(name: value).id
when "spec"
spec = PProductRefSpec.create!(p_product_ref: ref, p_spec_type: PSpecType.find_by(name: "Version ROM"), p_spec_value: PSpecValue.find_or_create_by!(value: value))
import_csv.import_csv_elements << ImportCsvElement.new(:element => spec)
when "commentaires"
ref.i_comment = value if !value.blank?
# champs ignorés
when "date"
# colonne vide
when "dtl_targ"
when "dtl"
when "com"
else
eval "n.#{key} = value"
end
# if self.type_for_attribute(key) and self.type_for_attribute(key).type == :decimal
# eval "n.#{key} = value.to_s.gsub(' ', '').gsub(',', '.')"
# end
end
end
n.save!
import_csv.import_csv_elements << ImportCsvElement.new(:element => ref)
import_csv.import_csv_elements << ImportCsvElement.new(:element => n)
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.ref §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap ref
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.contacts §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.p_contacts
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.particulars §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.particulars
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.p_customer_ribs §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.p_customer_ribs
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ n.p_commercial §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap n.p_commercial
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
# ap "§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"
end
end
end end

View File

@ -1,6 +1,8 @@
class PProductRef < ApplicationRecord class PProductRef < ApplicationRecord
belongs_to :p_product belongs_to :p_product
belongs_to :sorecop_cat
has_many :sorecop_taxes, through: :sorecop_cat
has_one :s_brand, through: :p_product has_one :s_brand, through: :p_product
has_many :p_customer_cats, :through => :p_product has_many :p_customer_cats, :through => :p_product
@ -15,14 +17,15 @@ class PProductRef < ApplicationRecord
has_many :p_article_serial_nums, through: :p_articles has_many :p_article_serial_nums, through: :p_articles
accepts_nested_attributes_for :p_article_serial_nums, allow_destroy: true accepts_nested_attributes_for :p_article_serial_nums, allow_destroy: true
has_many :p_product_ref_specs has_many :p_product_ref_specs, dependent: :destroy
accepts_nested_attributes_for :p_product_ref_specs, allow_destroy: true accepts_nested_attributes_for :p_product_ref_specs, allow_destroy: true, reject_if: :all_blank
#validates :ct_price_ht, :presence => true #validates :ct_price_ht, :presence => true
validate :ean, :is_integer
has_many :p_customer_product_prices, :dependent => :destroy has_many :p_customer_product_prices, :dependent => :destroy
accepts_nested_attributes_for :p_customer_product_prices, allow_destroy: true accepts_nested_attributes_for :p_customer_product_prices, allow_destroy: true
has_many :p_fournisseur_refs
scope :enableds, -> {where(:enabled => true)} scope :enableds, -> {where(:enabled => true)}
@ -41,14 +44,17 @@ class PProductRef < ApplicationRecord
:p_product_cat => {:name => "Catégorie", :reorder => true}, :p_product_cat => {:name => "Catégorie", :reorder => true},
:ref => {:name => "Référence"}, :ref => {:name => "Référence"},
:cc_name => {:name => "Produit"}, :cc_name => {:name => "Produit"},
:description => {:name => "Description"}, # :description => {:name => "Description"},
:ct_sub_name => {:name => "Nom référence"}, :cc_name => {:name => "Nom référence"},
:ct_price_ht => {:name => "Prix de vente", :as => :currency}, :ct_price_ht => {:name => "Prix de vente", :as => :currency},
:ean => {:name => "EAN"},
:deee => {:name => "DEEE", :as => :currency},
:sorecop => {:name => "Sorecop", :as => :currency},
:sorecop_comment => {:name => "Commentaire Sorecop"},
:actions => {:name => "Actions", :reorder => false} :actions => {:name => "Actions", :reorder => false}
} }
acts_as_caching :fields => [:sorecop, :deee, :name, :code]
include PgSearch::Model include PgSearch::Model
pg_search_scope :global_search, pg_search_scope :global_search,
against: [:ref, :cc_name], against: [:ref, :cc_name],
@ -61,6 +67,19 @@ class PProductRef < ApplicationRecord
tsearch: { prefix: true } tsearch: { prefix: true }
} }
attr_accessor :price_line_id
after_create do
if self.price_line_id
pl = PriceLine.find(self.price_line_id)
pl.update(p_product_ref: self)
end
end
after_save do
PProduct.destroy_temp_p_product
end
def not_imported? def not_imported?
if !self.p_product or !self.p_product.imported if !self.p_product or !self.p_product.imported
true true
@ -83,9 +102,35 @@ class PProductRef < ApplicationRecord
def ca_name def ca_name
if self.p_product storage = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Stockage")).first
self.p_product.name + " - " + self.ct_sub_name cellular = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Connectivité")).first
end screen = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Résolution")).first
power = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Puissance éléctrique")).first
geoloc = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Géolocalisation")).first
sim = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Sim")).first
size = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Taille")).first
version = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Version ROM")).first
arr = []
arr << self.p_product.name if self.p_product
arr << self.ct_sub_name
arr << storage.p_spec_value.member_label if storage
arr << cellular.p_spec_value.member_label if cellular
arr << screen.p_spec_value.member_label if screen
arr << power.p_spec_value.member_label if power
arr << geoloc.p_spec_value.member_label if geoloc
arr << sim.p_spec_value.member_label if sim
arr << size.p_spec_value.member_label if size
arr << version.p_spec_value.member_label if version
arr << self.p_product_color.name if p_product_color
arr.compact.each{|el| el.strip!}.join(' ')
# if self.p_product
# self.p_product.name + " - " + self.ct_sub_name
# end
end end
def ca_code def ca_code
@ -96,11 +141,11 @@ class PProductRef < ApplicationRecord
self.p_product.p_product_cat_id self.p_product.p_product_cat_id
end end
QI_DYNAMICS = %w(name code p_product_cat_id sub_cat_names cat_name) # QI_DYNAMICS = %w(name code p_product_cat_id sub_cat_names cat_name)
eval(QI_DYNAMICS_CORE) # eval(QI_DYNAMICS_CORE)
before_validation :qi_dynamics_cache # before_validation :qi_dynamics_cache
def get_price(options) def get_price(options)
p_customer = PCustomer.find(options[:p_customer_id]) if options[:p_customer_id] p_customer = PCustomer.find(options[:p_customer_id]) if options[:p_customer_id]
@ -159,7 +204,55 @@ class PProductRef < ApplicationRecord
end end
def member_label def member_label
"#{self.ref} | #{self.p_product.name} - #{self.ct_sub_name} - #{self.p_product_color.name if self.p_product_color} | #{self.cat_name}" "#{self.ref} | #{self.p_product.name} - #{self.ct_sub_name} - #{self.p_product_color.name if self.p_product_color} | #{self.ca_name}"
end
def ca_sorecop
return ct_sorecop if ct_sorecop
return "Pas de catégorie Sorecop" if self.p_product.sorecop_cat.blank?
# if self.cc_sorecop and self.cc_sorecop > 0.0
# return self.cc_sorecop
# else
find_sorecop_tax
# end
end
def find_sorecop_tax
p_product_ref_spec = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by_name("Stockage")).first
return "Pas de stockage" if p_product_ref_spec.blank?
storage_capacity = p_product_ref_spec.p_spec_value.value.to_f
if p_product_ref_spec.p_spec_value.unit.casecmp?("Gb")
tax = self.p_product.sorecop_cat.sorecop_taxes.where('critere_min < ? AND critere_max >= ?', storage_capacity, storage_capacity).first
elsif p_product_ref_spec.p_spec_value.unit.casecmp?("Tb")
tax = self.p_product.sorecop_cat.sorecop_taxes.where('critere_min < ? AND critere_max >= ?', storage_capacity * 1000, storage_capacity * 1000).first
elsif p_product_ref_spec.p_spec_value.unit.casecmp?("Mb")
tax = self.p_product.sorecop_cat.sorecop_taxes.where('critere_min < ? AND critere_max >= ?', storage_capacity / 1000, storage_capacity / 1000).first
end
if tax.fixed_price
tax.price
else
tax.price * storage_capacity
end
end
def ca_deee
if ct_deee
return ct_deee
end
if self.cc_deee
return self.cc_deee
else
"DEEE à renseigner"
end
end
def is_integer
if ean.present? && ean.match(/\A[+-]?\d+\z/).nil?
errors.add(:ean, "ne doit être composé que de chiffres")
end
end end
end end

View File

@ -5,6 +5,8 @@ class PProductRefSpec < ApplicationRecord
accepts_nested_attributes_for :p_spec_type, :p_spec_value accepts_nested_attributes_for :p_spec_type, :p_spec_value
validates :p_spec_type_id, :p_spec_value_id, presence: true
acts_as_sorting :fields => { acts_as_sorting :fields => {
:id => {:name => "ID"}, :id => {:name => "ID"},
:p_product_ref => {:name => "Référence produit", :reorder => true}, :p_product_ref => {:name => "Référence produit", :reorder => true},

View File

@ -1,6 +1,7 @@
class PSpecType < ApplicationRecord class PSpecType < ApplicationRecord
has_many :p_product_ref_specs has_many :p_product_ref_specs
TYPES = ["Ram", "Stockage"]
TYPES = self.distinct.pluck(:name)
acts_as_sorting :fields => { acts_as_sorting :fields => {
:id => {:name => "ID"}, :id => {:name => "ID"},

View File

@ -1,7 +1,7 @@
class PSpecValue < ApplicationRecord class PSpecValue < ApplicationRecord
has_many :p_product_ref_specs has_many :p_product_ref_specs
UNITS = ["Go", "Mo"] UNITS = self.distinct.pluck(:unit)
def member_label def member_label
"#{value} #{unit}" "#{value} #{unit}"

View File

@ -25,12 +25,13 @@ class PriceDocument < ApplicationRecord
has_many :avoir_p_payment_documents, :dependent => :destroy, :foreign_key => :avoir_id, :class_name => "PPaymentDocument" has_many :avoir_p_payment_documents, :dependent => :destroy, :foreign_key => :avoir_id, :class_name => "PPaymentDocument"
accepts_nested_attributes_for :avoir_p_payment_documents, allow_destroy: true accepts_nested_attributes_for :avoir_p_payment_documents, allow_destroy: true
PURCHASES = ["Demande prix", "Commande achat", "Facture d'achat"] PURCHASES = ["Demande prix", "Réponse fournisseur", "Commande achat", "Facture achat", "Consultation fournisseur"]
SALES = ["Bon de commande", "Devis", "Bon de livraison", "Facture", "Avoir"] SALES = ["Bon de commande", "Devis", "Bon de livraison", "Facture", "Avoir"]
# AVANCEMENT = ["0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"] # AVANCEMENT = ["0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"]
AVANCEMENT = ["0%", "25%", "50%", "75%", "100"] AVANCEMENT = ["0%", "25%", "50%", "75%", "100"]
validates :public_fournisseur_name, :presence => true, :if => :public_fournisseur_name_needed? validates :public_fournisseur_name, :presence => true, :if => :public_fournisseur_name_needed?
acts_as_csv_import :fields => [:p_fournisseur_id, :p_fournisseur_name, :p_fournisseur_ref_ref, :p_fournisseur_ref_label, :p_product_ref_name, :price_line_qte, :date, :price_line_ct_u_price_ht, :p_devise ]
def public_fournisseur_name_needed? def public_fournisseur_name_needed?
if self.label == "Réponse fournisseur" if self.label == "Réponse fournisseur"
@ -707,6 +708,58 @@ class PriceDocument < ApplicationRecord
end end
def self.custom_csv_import(list, import_csv)
list.each do |row|
p_product_ref = nil
p_devise = PDevise.find_by(symbol: row["p_devise"])
p_fournisseur = PFournisseur.find_by(id: row["p_fournisseur_id"])
if row["p_fournisseur_id"].nil?
p_fournisseur = PFournisseur.find_by(name: row["p_fournisseur_name"])
end
if p_fournisseur.nil?
# TODO : envoyer une alerte sans bloquer l'import.
# idée ? creer une priceline vide => pour la retrouver dans les ref à matcher.
end
n = self.find_or_initialize_by(price_document_type: PriceDocumentType.find_by_label("Catalogue fournisseur"), p_fournisseur: p_fournisseur, date: row["date"], p_devise: p_devise )
if n.price_line_block.nil?
n.price_line_block = PriceLineBlock.new(p_devise: p_devise, p_fournisseur: p_fournisseur, imported: true)
end
if row["p_fournisseur_ref_ref"].present?
p_fournisseur_ref = PFournisseurRef.find_by(p_fournisseur: p_fournisseur, ref: row["p_fournisseur_ref_ref"])
p_product_ref = p_fournisseur_ref.p_product_ref if p_fournisseur_ref
else
p_fournisseur_ref = PFournisseurRef.find_by(p_fournisseur: p_fournisseur, label: row["p_fournisseur_ref_label"])
p_product_ref = p_fournisseur_ref.p_product_ref if p_fournisseur_ref
end
if row["price_line_qte"].kind_of? Float
qte = row["price_line_qte"]
elsif row["price_line_qte"].kind_of? Integer
qte = row["price_line_qte"].to_f
elsif row["price_line_qte"].kind_of? String
qte = row["price_line_qte"].split.map {|x| x[/\d+/]}[0].to_f
else
qte = 0
end
price_line = PriceLine.new(p_product_ref: p_product_ref, ct_ref: row["p_fournisseur_ref_ref"], ct_title: row["p_fournisseur_ref_label"], price_line_block: n.price_line_block, qte: qte || 0.0, ct_u_price_ht: row["price_line_ct_u_price_ht"], imported: true )
price_line.p_product = p_product_ref.p_product if p_product_ref && p_product_ref.p_product
n.price_line_block.price_lines << price_line
n.save
import_csv.import_csv_elements << ImportCsvElement.new(:element => n)
import_csv.import_csv_elements << ImportCsvElement.new(:element => price_line)
end
end
end end

View File

@ -3,9 +3,18 @@ class PriceLine < ApplicationRecord
belongs_to :p_product belongs_to :p_product
belongs_to :p_product_ref belongs_to :p_product_ref
belongs_to :p_product_power belongs_to :p_product_power
has_many :price_line_resp_selects, :foreign_key => :price_line_demand
has_many :price_line_resps, through: :price_line_resp_selects, :source => :price_line_resp
has_one :p_fournisseur, :through => :price_line_block
#has_many :price_line_demands, through: :price_line_resp_selects
default_scope { order('position ASC') } default_scope { order('position ASC') }
validates :p_product_ref_id, :presence => true, :if => :p_product_ref_needed? validates :p_product_ref_id, :presence => true, :if => :p_product_ref_needed?
validates :p_product_id, :presence => true, :if => :p_product_needed?
validates :qte, :presence => true validates :qte, :presence => true
@ -13,6 +22,7 @@ class PriceLine < ApplicationRecord
has_many :line_stocks has_many :line_stocks
after_update :memorize_p_fournisseur_ref, if: :p_fournisseur_ref_is_memorizable?
acts_as_sorting :fields => { acts_as_sorting :fields => {
:ref => {:name => "Ref", :reorder => true}, :ref => {:name => "Ref", :reorder => true},
@ -44,7 +54,9 @@ class PriceLine < ApplicationRecord
BON_DE_LIVRAISON_TO_RESET = %w(block_type weight_tot tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc) BON_DE_LIVRAISON_TO_RESET = %w(block_type weight_tot tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc)
FACTURE_DACHAT_TO_RESET = %w(devise_rate local_tot_amount_ht block_type product_no_remise price_calc weight_u weight_tot tva_account_id tva_account_value ref title description price_u_ht price_u_tva price_u_ttc tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc discount_market_percent discount_qte_percent discount_delay_percent discount_enrobage_percent discount_ecole_percent discount_comptant_percent product_remise_enrobage_ok uv p_product_specific_customer_id) FACTURE_ACHAT_TO_RESET = %w(devise_rate local_tot_amount_ht block_type product_no_remise price_calc weight_u weight_tot tva_account_id tva_account_value ref title description price_u_ht price_u_tva price_u_ttc tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc discount_market_percent discount_qte_percent discount_delay_percent discount_enrobage_percent discount_ecole_percent discount_comptant_percent product_remise_enrobage_ok uv p_product_specific_customer_id)
BON_DE_RECEPTION_ACHAT_TO_RESET = %w(devise_rate local_tot_amount_ht block_type product_no_remise price_calc weight_u weight_tot tva_account_id tva_account_value ref title description price_u_ht price_u_tva price_u_ttc tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc discount_market_percent discount_qte_percent discount_delay_percent discount_enrobage_percent discount_ecole_percent discount_comptant_percent product_remise_enrobage_ok uv p_product_specific_customer_id)
COMMANDE_ACHAT_TO_RESET = %w(block_type product_no_remise price_calc weight_u weight_tot tva_account_id tva_account_value ref title description price_u_ht price_u_tva price_u_ttc tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc discount_market_percent discount_qte_percent discount_delay_percent discount_enrobage_percent discount_ecole_percent discount_comptant_percent product_remise_enrobage_ok uv p_product_specific_customer_id) COMMANDE_ACHAT_TO_RESET = %w(block_type product_no_remise price_calc weight_u weight_tot tva_account_id tva_account_value ref title description price_u_ht price_u_tva price_u_ttc tot_line_ht tot_line_tva tot_line_ttc tot_discount_ht tot_discount_tva tot_discount_ttc tot_amount_ht tot_amount_tva tot_amount_ttc discount_market_percent discount_qte_percent discount_delay_percent discount_enrobage_percent discount_ecole_percent discount_comptant_percent product_remise_enrobage_ok uv p_product_specific_customer_id)
@ -161,6 +173,12 @@ class PriceLine < ApplicationRecord
end end
end end
def p_product_needed?
if !self.ct_title? and !self.imported
true
end
end
def personalised_archive def personalised_archive
end end
@ -538,38 +556,36 @@ class PriceLine < ApplicationRecord
def ca_tot_amount_ht def ca_tot_amount_ht
if ct_tot_amount_ht if self.ct_tot_amount_ht
self.ct_tot_amount_ht self.ct_tot_amount_ht
else else
(self.ca_price_u_kg_net_ht * self.weight_qte.to_f).round(2) (self.ca_price_u_ht * self.qte.to_f).round(3)
end end
end end
def ca_tot_amount_tva def ca_tot_amount_tva
(self.tot_amount_ht * (self.tva_account_value/100)).round(2) (self.tot_amount_ht * (self.tva_account_value/100)).round(3)
end end
def ca_tot_amount_ttc def ca_tot_amount_ttc
(self.tot_amount_ht + self.tot_amount_tva).round(2) (self.tot_amount_ht + self.tot_amount_tva).round(3)
end end
def ca_tot_discount_ht def ca_tot_discount_ht
(self.ca_price_u_ht * self.qte.to_f).round(2) - self.ca_tot_amount_ht (self.ca_price_u_ht * self.qte.to_f).round(3) - self.ca_tot_amount_ht
end end
def ca_tot_discount_tva def ca_tot_discount_tva
(self.tot_discount_ht * (self.tva_account_value/100)).round(2) (self.tot_discount_ht * (self.tva_account_value/100)).round(3)
end end
def ca_tot_discount_ttc def ca_tot_discount_ttc
(self.tot_discount_ht+self.tot_discount_tva).round(2) (self.tot_discount_ht+self.tot_discount_tva).round(3)
end end
@ -609,6 +625,12 @@ class PriceLine < ApplicationRecord
return [asap, non_asap] return [asap, non_asap]
end end
def p_fournisseur_ref_is_memorizable?
self.p_product_ref.present? && self.imported? && PFournisseurRef.where(p_fournisseur: self.p_fournisseur, ref: self.ct_ref, label: self.ct_title).empty?
end
def memorize_p_fournisseur_ref
PFournisseurRef.create(p_fournisseur: self.p_fournisseur, p_product_ref: self.p_product_ref, ref: self.ct_ref, label: self.ct_title)
end
end end

View File

@ -23,7 +23,8 @@ class PriceLineBlock < ApplicationRecord
belongs_to :p_payment_type belongs_to :p_payment_type
PURCHASE_BLOCKS = ["Facture d'achat", "Commande achat"] 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"] SALE_BLOCKS = ["Demande de commande", "Bon de commande", "Devis", "Bon de livraison", "Facture", "Avoir"]
belongs_to :p_fournisseur belongs_to :p_fournisseur
@ -261,7 +262,9 @@ class PriceLineBlock < ApplicationRecord
end end
def wish_date_needed? def wish_date_needed?
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type) or self.block_type == "Réponse fournisseur" if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis"
false false
else else
true true
@ -270,7 +273,9 @@ class PriceLineBlock < ApplicationRecord
def particular_bill_needed? def particular_bill_needed?
if !self.imported if !self.imported
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type) or self.block_type == "Demande prix" or self.block_type == "Réponse fournisseur" if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis"
false false
else else
true true
@ -280,7 +285,9 @@ class PriceLineBlock < ApplicationRecord
def particular_send_needed? def particular_send_needed?
if !self.imported if !self.imported
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type) or self.block_type == "Demande prix" or self.block_type == "Réponse fournisseur" if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false
elsif self.block_type == "Devis"
false false
else else
true true
@ -289,7 +296,9 @@ class PriceLineBlock < ApplicationRecord
end end
def p_fournisseur_needed? def p_fournisseur_needed?
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type) if ["Demande prix", "Consultation fournisseur", "Réponse fournisseur"].include?(self.block_type)
false
elsif PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
true true
else else
false false
@ -297,9 +306,11 @@ class PriceLineBlock < ApplicationRecord
end end
def p_customer_needed? def p_customer_needed?
if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type) or self.block_type == "Demande prix" or self.block_type == "Réponse fournisseur" if PriceLineBlock::PURCHASE_BLOCKS.include?(self.block_type)
false false
elsif !self.imported elsif self.block_type == "Devis"
false
else
true true
end end
end end
@ -315,7 +326,9 @@ class PriceLineBlock < ApplicationRecord
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) 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_DACHAT_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) 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) 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)
@ -337,12 +350,12 @@ class PriceLineBlock < ApplicationRecord
eval("self.ac_#{qid} = nil") eval("self.ac_#{qid} = nil")
end end
self.archive_now(:skip_personalised_archive => true) self.archive_now()
self.price_lines.each do |pl| self.price_lines.each do |pl|
pl.archive_now(:skip_personalised_archive => true) pl.archive_now()
end end

View File

@ -0,0 +1,4 @@
class PriceLineRespSelect < ApplicationRecord
belongs_to :price_line_demand, class_name: "PriceLine"
belongs_to :price_line_resp, class_name: "PriceLine"
end

View File

@ -2,4 +2,25 @@ class SBrand < ApplicationRecord
has_many :p_products has_many :p_products
has_many :p_product_refs, through: :p_products has_many :p_product_refs, through: :p_products
validates :name, :presence => true, :uniqueness => true validates :name, :presence => true, :uniqueness => true
before_save do
if self.code.blank?
generate_code
end
end
def generate_code
if self.code.blank?
prefix = self.name.slice(0, 4).to_slug.upcase
last_number = 1
code = prefix + "%02d" % [last_number]
while self.class.find_by(code: code)
last_number += 1
code = prefix + "%02d" % [last_number]
end
self.code = code
end
end
end end

10
app/models/sorecop_cat.rb Normal file
View File

@ -0,0 +1,10 @@
class SorecopCat < ApplicationRecord
has_many :p_products
has_many :sorecop_taxes, dependent: :destroy
acts_as_sorting :fields => {
:id => {:name => "ID"},
:name => {:name => "Catégorie", :reorder => true},
:actions => {:name => "Actions", :reorder => true}
}
end

15
app/models/sorecop_tax.rb Normal file
View File

@ -0,0 +1,15 @@
class SorecopTax < ApplicationRecord
belongs_to :sorecop_cat
acts_as_sorting :fields => {
:id => {:name => "ID"},
:title => {:name => "Désignation", :reorder => true},
:critere_min => {:name => "Critère mini (Go)", :reorder => true},
:critere_max => {:name => "Critère maxi (Go)", :reorder => true},
:fixed_price => {:name => "Prix forfaitaire", :reorder => true, :format => :boolean},
:sorecop_cat => {:name => "Catégorie SORECOP",member_label: :name, :reorder => true, :sort_name => "sorecop_taxes.sorecop_cat_id"},
:price => {:name => "Prix", :reorder => false, as: :currency},
:actions => {:name => "Actions", :reorder => true}
}
end

View File

@ -11,20 +11,20 @@
=form_tag "", :method => "get", :onsubmit => "" do =form_tag "", :method => "get", :onsubmit => "" do
-params[:search] =params[:search] || {} -params[:search] =params[:search] || {}
%p Date de consultation :
%table %table
%tr.form-inline %tr.form-inline
%td %td
Date saisie commande :
Début Début
%td.input-group %td.input-group
=text_field_tag :start, params[:start],:class => "form-control datepicker", :placeholder => "Début" =text_field_tag :cc_creation_date_start, params[:cc_creation_date_start],:class => "form-control datepicker", :placeholder => "Début"
.input-group-append .input-group-append
%span.input-group-text{:onclick => "$(this).prev('input').val('');"} %span.input-group-text{:onclick => "$(this).prev('input').val('');"}
=ic(:times) =ic(:times)
%td.pl-4 %td.pl-4
Fin Fin
%td.input-group %td.input-group
=text_field_tag :stop, params[:stop],:class => "form-control datepicker", :placeholder => "Fin" =text_field_tag :cc_creation_date_stop, params[:cc_creation_date_stop],:class => "form-control datepicker", :placeholder => "Fin"
.input-group-append .input-group-append
%span.input-group-text{:onclick => "$(this).prev('input').val('');"} %span.input-group-text{:onclick => "$(this).prev('input').val('');"}
=ic(:times) =ic(:times)
@ -39,17 +39,45 @@
Code client : Code client :
=text_field_tag "search[p_customer_code]", params[:search][:p_customer_code],:class => "form-control" =text_field_tag "search[p_customer_code]", params[:search][:p_customer_code],:class => "form-control"
%tr.form-inline
%td{width: "110px"}
%td.right.mx-4
-if @cc_creation_date_start and @cc_creation_date_stop
=link_to "< Mois précédent",request.query_parameters.merge({cc_creation_date_start: ((@cc_creation_date_start - 1.month).beginning_of_month.strftime('%d/%m/%Y')), cc_creation_date_stop: ((@cc_creation_date_stop - 1.month).end_of_month.strftime('%d/%m/%Y'))}), :class => "btn btn-tertiary"
%td{width: "20px"}
%td.mr-auto
-if @cc_creation_date_start and @cc_creation_date_stop
=link_to "Mois suivant >",request.query_parameters.merge({cc_creation_date_start: ((@cc_creation_date_start + 1.month).beginning_of_month.strftime('%d/%m/%Y')), cc_creation_date_stop: ((@cc_creation_date_stop + 1.month).end_of_month.strftime('%d/%m/%Y'))}), :class => "btn btn-tertiary"
%tr.form-inline
%td
Date ETA :
Début
%td.input-group
=text_field_tag :wish_date_start, params[:wish_date_start],:class => "form-control datepicker", :placeholder => "Début"
.input-group-append
%span.input-group-text{:onclick => "$(this).prev('input').val('');"}
=ic(:times)
%td.pl-4
Fin
%td.input-group
=text_field_tag :wish_date_stop, params[:wish_date_stop],:class => "form-control datepicker", :placeholder => "Fin"
.input-group-append
%span.input-group-text{:onclick => "$(this).prev('input').val('');"}
=ic(:times)
%tr.form-inline %tr.form-inline
%td{width: "110px"} %td{width: "110px"}
%td.right.mx-4 %td.right.mx-4
-if @start and @stop -if @wish_date_start and @wish_date_stop
=link_to "< Mois précédent",request.query_parameters.merge({start: ((@start - 1.month).beginning_of_month.strftime('%d/%m/%Y')), stop: ((@stop - 1.month).end_of_month.strftime('%d/%m/%Y'))}), :class => "btn btn-tertiary" =link_to "< Mois précédent",request.query_parameters.merge({wish_date_start: ((@wish_date_start - 1.month).beginning_of_month.strftime('%d/%m/%Y')), wish_date_stop: ((@wish_date_stop - 1.month).end_of_month.strftime('%d/%m/%Y'))}), :class => "btn btn-tertiary"
%td{width: "20px"} %td{width: "20px"}
%td.mr-auto %td.mr-auto
-if @start and @stop -if @wish_date_start and @wish_date_stop
=link_to "Mois suivant >",request.query_parameters.merge({start: ((@start + 1.month).beginning_of_month.strftime('%d/%m/%Y')), stop: ((@stop + 1.month).end_of_month.strftime('%d/%m/%Y'))}), :class => "btn btn-tertiary" =link_to "Mois suivant >",request.query_parameters.merge({wish_date_start: ((@wish_date_start + 1.month).beginning_of_month.strftime('%d/%m/%Y')), wish_date_stop: ((@wish_date_stop + 1.month).end_of_month.strftime('%d/%m/%Y'))}), :class => "btn btn-tertiary"
=link_to ic(:search)+" Rechercher", "#", :class => "btn btn-default btn-qi-search", :onclick => "$(this).closest('form').submit();$(this).html('...');return false;" =link_to ic(:search)+" Rechercher", "#", :class => "btn btn-default btn-qi-search", :onclick => "$(this).closest('form').submit();$(this).html('...');return false;"
@ -72,7 +100,8 @@
=form_tag new_admin_price_document_path(), :method => "get" do =form_tag new_admin_price_document_path(), :method => "get" do
=hidden_field_tag :"document_type", "Demande prix" =hidden_field_tag :"document_type", "Demande prix"
=hidden_field_tag :"price_line_ids[]", "" =hidden_field_tag :"p_product_ref_ids[]", ""
.freezeTable .freezeTable
%table.table.table-striped.table-hover.table-bordered.data_table %table.table.table-striped.table-hover.table-bordered.data_table
%thead.header %thead.header
@ -104,6 +133,9 @@
Qté en stock Qté en stock
%th.mask %th.mask
Qté souhaité Qté souhaité
%span.info
=ic("info-circle")
%span.info-text-bottom BPA - Qté en stock
%th.mask BPA %th.mask BPA
%th.mask AV BPA %th.mask AV BPA
%th.mask PAS BPA %th.mask PAS BPA
@ -131,6 +163,9 @@
-ppr_lines = @price_lines.where(:p_product_ref_id => plr.p_product_ref.id) -ppr_lines = @price_lines.where(:p_product_ref_id => plr.p_product_ref.id)
%tr.ref_tr %tr.ref_tr
- bpa_qte = ppr_lines.where(:cc_state => "BPA").sum(:qte).to_i
- qte_available = LineStock.where(p_product_ref_id: plr.p_product_ref.id).sum(:qte_available).to_i
-if checkbox -if checkbox
%td %td
@ -165,13 +200,15 @@
=ic(:hourglass) =ic(:hourglass)
=ppr_lines.asap_triage(20).last =ppr_lines.asap_triage(20).last
%td.mask %td.mask
= LineStock.where(p_product_ref_id: plr.p_product_ref.id).sum(:qte_available).to_i = qte_available
%td.mask
- default_qte = [bpa_qte - qte_available, 0].max
=check_box_tag :"p_product_ref_ids[]", plr.p_product_ref.id, (true if default_qte > 0 )
=number_field_tag "qte[#{plr.p_product_ref.id}]", '', class: "small-input", value: default_qte, min: 0
%td.mask %td.mask
=text_field_tag "qte[#{plr.p_product_ref.id}]", '', class: "small-input" = bpa_qte
%td.mask
=ppr_lines.where(:cc_state => "BPA").sum(:qte).to_i
%td.mask %td.mask
=ppr_lines.where(:cc_state => "AV BPA").sum(:qte).to_i =ppr_lines.where(:cc_state => "AV BPA").sum(:qte).to_i
%td.mask %td.mask
@ -271,9 +308,11 @@
} }
:javascript :javascript
// TOOGLE ORDERS DETAILS - set to hidden
$('.detail').hide() $('.detail').hide()
$('.col-detail').hide() $('.col-detail').hide()
let state = 0 let state = 0
// TOGGLE ORDER LINE DETAILS
$('.plus').click(function(event){ $('.plus').click(function(event){
if( event.currentTarget.className == "plus") { if( event.currentTarget.className == "plus") {
$(event.currentTarget).removeClass('plus').addClass('minus') $(event.currentTarget).removeClass('plus').addClass('minus')
@ -292,6 +331,7 @@
$('.col-detail').show() $('.col-detail').show()
} }
}); });
// TOOGLE ALL ORDERS DETAILS
$('.plus-all').click(function(event){ $('.plus-all').click(function(event){
if( event.currentTarget.className == "mask plus-all") { if( event.currentTarget.className == "mask plus-all") {
state += $('.plus').length state += $('.plus').length
@ -315,6 +355,15 @@
$('.col-detail').show() $('.col-detail').show()
} }
}); });
// CHECK QTE IF QTE CHANGE
$('.small-input').change(function(){
let checkbox = $(this).closest('td').find("input[type=checkbox]")
if (this.value > 0) {
checkbox.prop("checked", true)
} else {
checkbox.prop("checked", false)
}
})

View File

@ -6,7 +6,7 @@
= f.input :name, :label => "Nom de l'import :" = f.input :name, :label => "Nom de l'import :"
= f.input :file, :label => "file :" = f.input :file, :label => "file :"
= f.input :table_name, :label => "Table :" , :as => :select, :collection => ["order_hist_lines"] = f.input :table_name, :label => "Type d'import :" , :as => :select, :collection => [["Mise à jour catalogue prix","price_document"], ["Base fournisseurs", "p_fournisseur"], ["Base client", "p_customer"], ["Base produit", "p_product"]]
-if f.object.id -if f.object.id
%table.import_csv_champs_form %table.import_csv_champs_form

View File

@ -0,0 +1,109 @@
=semantic_form_for [:admin, @p_product_ref], remote: true do |form|
=hidden_field_tag :update_price_line_id, @price_line.id
.content
.qi_row.field
.padding
%h1 Ajouter une référence
.card.border.border-primary.mb-3
%h5.card-header.border-bottom Rappel des infos fournisseurs
%ul.list-group.list-group-flush
%li.list-group-item
.d-inline-flex
%h5{style: "min-width: 80px;"} libellé :
%p.card-text=@p_product_ref.description
%li.list-group-item
.d-inline-flex
%h5{style: "min-width: 80px;"} Qté :
%p.card-text
=@price_line.qte
%li.list-group-item
.d-inline-flex
%h5{style: "min-width: 80px;"} Prix :
%p.card-text
=number_to_currency @p_product_ref.ct_price_ht
%table.form-table
%tr
%td{colspan: 3}
%label Selectionner le produit parent :
.input-group
%input.p_product_autocomplete_input.form-control{:type => "text", :style => "", tabindex: 1, autofocus: true, :class => "p_product_name"}
=form.hidden_field :p_product_id, :class => "p_product_id"
=link_to ic(:plus)+ " Ajouter produit", new_admin_p_product_path(fournisseur_label: @p_product_ref.description, price_line_id: @price_line.id)
%br
%tr{height: "20px"}
-if false
%tr
%td{:colspan => 3}
= form.input :ct_sub_name, :label => "Désignation ARCOM :"
%tr
%td
= form.input :ref, :label => "Réf int. :"
%td
= form.input :ct_price_ht, :label => "Prix vente € HT:"
%td
=form.input :p_product_color_id, :label => "Couleur :", :collection => PProductColor.all, :as => :select, :include_blank => true, input_html: {class: "custom-select"}
%tr
%td
=form.input :ct_sorecop, :label => "Sorecop personalisée (€) :"
%td
=form.input :sorecop_comment, :label => "Commentaire Sorecop :"
%td
=form.input :ct_deee, :label => "DEEE personalisée (€):"
%tr
%td
=form.input :ean
%td{:colspan => 2}
= form.input :description, :label => "Désignation longue :" , :input_html => {rows: 1}
%tr
%td{:colspan => 3}
.qi_pannel.qi_plain.padding
.p_product_ref_specs_form
= form.semantic_fields_for :p_product_ref_specs do |f|
=render :partial => "admin/p_product_ref_specs/form", :locals => {:form => f}
%p= link_to_add_fields "Ajouter une spec", form, :p_product_ref_specs
.actions=form.submit "sauvegarder", :class => "btn btn-primary"
:javascript
$('.p_product_autocomplete_input').focus()
$( function() {
$('.p_product_autocomplete_input').autocomplete({
source: function( request, response ) {
$.ajax( {
url: "/admin/p_products/autocomplete.json",
dataType: "json",
data: {
search: request.term,
},
success: function(data){
arr = jQuery.map( data, function( item ) {
return {
label: item.name,
value: item.name,
id: item.id
}
});
response(arr)
}
});
},
minLength: 2,
select: function( event, ui ) {
$(this).next(".p_product_id").val(ui.item.id)
}
});
});

View File

@ -1,6 +1,6 @@
.qi_header .qi_header
.right= link_to ic(:plus)+' Ajouter', new_admin_import_csv_path(), :class => "btn btn-primary btn-ap-add", :remote => true .right= link_to ic(:plus)+' Ajouter', new_admin_import_csv_path(), :class => "btn btn-primary btn-ap-add", :remote => true
%h1 %h1 Import xls
@ -12,4 +12,4 @@
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @import_csvs} =render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @import_csvs}
=debug OrderHistLine.new.class.type_for_attribute("ff") =#debug OrderHistLine.new.class.type_for_attribute("ff")

View File

@ -0,0 +1,27 @@
:javascript
var p_product_refs_url = "#{admin_p_product_refs_path(:manager => true)}"
.qi_row
%h1 Rapprochement de références produits
-@price_documents.each do |price_document|
%br
.qi_pannel.qi_plain.padding.mt-4
=semantic_form_for [:admin, price_document] do |f|
=f.semantic_fields_for :price_line_block do |f|
%h2= "Import catalogue : " + f.object.p_fournisseur.name
%div{:style=>"padding:0 30px;"}
.row.qi_field_wrapper
%table{:style => "width:100%;border-collapse:separate;"}
%thead
%tr
%th
%th Référence Produit Arcom
%th Créer une référence
%th Libélé fournisseur
%th Prix unitaire
%th Quantité
%tbody.price_lines_form
=f.semantic_fields_for :price_lines do |form|
-if form.object.p_product_ref.nil?
=render :partial => "admin/price_lines/form_match_refs", :locals => {:form => form}
=f.submit "Valider", class: "btn btn-primary mt-3"

View File

@ -0,0 +1 @@
show_pane_hover("<%= escape_javascript(render(:partial => "form_temp_p_product"))%>",700,900);

View File

@ -1,24 +1,28 @@
=semantic_form_for [:admin, @p_customer_sheet], :html => {:class => "qi_price_form"}, :remote => false do |form| =semantic_form_for [:admin, @p_customer_sheet], :html => {:class => "qi_price_form"}, :remote => false do |form|
=form.semantic_fields_for :price_line_block do |f|
=render :partial => "admin/price_line_blocks/form", :locals => {:f => f}
.content .content
.qi_row .qi_row
.qi_pannel.qi_plain.padding .qi_pannel.qi_plain.padding.row
-if @p_customer_sheet and @p_customer_sheet.state != "commande" .col-2
=#form.input :demande_type, :collection => ["Brouillon", "Demande de bon de commande","Demande de devis"], :as => :select, :include_blank => false, :label => "Type de demande :" -if @p_customer_sheet and @p_customer_sheet.state != "commande"
=#form.input :demande_type, :collection => ["Brouillon", "Demande de bon de commande","Demande de devis"], :as => :select, :include_blank => false, :label => "Type de demande :"
=form.input :state, :collection => ["AV BPA", "PAS BPA","BPA", "Traitée"], :as => :select, :include_blank => false, :label => "Statut :" =form.input :state, :collection => ["AV BPA", "PAS BPA","BPA", "Traitée"], :as => :select, :include_blank => false, :label => "Statut :"
=form.input :past_id, :label => "N° système actuel" =form.input :past_id, :label => "N° système actuel"
=yield :discount
.price_line_block_form .col-2
=form.semantic_fields_for :price_line_block do |f| =yield :shipping_date
=render :partial => "admin/price_line_blocks/form", :locals => {:f => f} .col-8
=yield :particular
=yield :price_lines
.large_actions
.right.actions .actions
=link_to "Annuler", admin_p_customer_sheets_path(), :class => "btn" =link_to "Annuler", admin_p_customer_sheets_path(), :class => "btn"
=form.submit "sauvegarder", :class => "btn btn-primary btn-ap-add" =form.submit "sauvegarder", :class => "btn btn-primary btn-ap-add"
.clear .clear

View File

@ -44,7 +44,9 @@
%td.numeraire %td.numeraire
=number_to_currency p_customer_sheet.cc_tot_amount_ttc =number_to_currency p_customer_sheet.cc_tot_amount_ttc
-tr[:check_box] = capture do
%td
=check_box_tag "p_customer_sheet_ids[]", p_customer_sheet.id, false, data: { client: p_customer_sheet.p_customer.id }, id: "p_customer_sheet_id_checkbox_#{p_customer_sheet.id}"
-tr[:actions] = capture do -tr[:actions] = capture do
%td.actions %td.actions

View File

@ -1,7 +1,6 @@
.qi_header .qi_header
.right .right
=link_to ic(:plus)+" Demande de commande", admin_p_customers_path(:offre => true), :class => "btn btn-primary btn-ap-add" =link_to ic(:plus)+" Demande de commande", admin_p_customers_path(:offre => true), :class => "btn btn-primary btn-ap-add"
%h1 %h1
Ventes Ventes
%span %span
@ -179,5 +178,77 @@
="-" ="-"
=link_to ic(:times)+" Supprimer ce filtre", params.permit!.merge({ :active_kpi => nil, :p_customer_sheet_ids => nil}) =link_to ic(:times)+" Supprimer ce filtre", params.permit!.merge({ :active_kpi => nil, :p_customer_sheet_ids => nil})
%div
=form_tag export_xls_admin_p_customer_sheets_path(format: :csv), id: 'export-form', :method => "get" do
.table
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_customer_sheets}
%button.btn.btn-primary.ml-4{onclick: "checkMultipleClient()"}
=ic("file-excel-o")
Export xls
.modal.fade#multi-client-export{"tab-index" => "-1", "role" => "dialog", "aria-labelledby" => "Raprochement Fournisseur", "aria-hidden" => "true"}
.modal-dialog{role: "dialog"}
.modal-content
.modal-header
%h5.modal-title
Export Excel
%button.close{"data-dismiss" => "modal", "aria-label" => "Close"}
%span{"aria-hidden" => "true"}
&times;
.modal-body
Attention !
%br
%br
Selection de plusieurs clients détéctée
%br
Vous avez selectionné des commandes liées à différents clients.
%br
Etes-vous sûr ?
.modal-footer
%button.btn.btn-light{"data-dismiss" => "modal"}
Annuler l'export
%button.btn.btn-primary{"data-dismiss" => "modal", onclick: "submitExport()"}
=ic("file-excel-o")
Confirmer
:javascript
$("#check-all").parent().on("click", function(event) {
console.log(event.currentTarget)
event.currentTarget.classList.toggle("checked")
if(event.currentTarget.classList.contains("checked")){
$('.table input[type=checkbox]').prop("checked", true)
}else{
$('.table input[type=checkbox]').prop("checked", false)
}
})
"#dataTable tbody tr"
function submitExport() {
$('#export-form').submit()
}
function checkDiff(arr) {
return arr.every(e => e == arr[0]);
}
const checkMultipleClient = () => {
let arr = []
$('.table input[type=checkbox]').each(function( i ) {
if ( this.checked === true)
arr.push($(this).data('client'))
})
if (checkDiff(arr) === false) {
$('#multi-client-export').modal('show')
} else {
submitExport()
}
}
:scss
th > i {
cursor: pointer;
}
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_customer_sheets}

View File

@ -61,7 +61,8 @@
= form.input :particular_send_id, :collection => form.object.particulars.all, :as => :select, :member_label => :address_line, :include_blank => true, :label => "Adresse de livraison :" = form.input :particular_send_id, :collection => form.object.particulars.all, :as => :select, :member_label => :address_line, :include_blank => true, :label => "Adresse de livraison :"
=form.input :code, :label => "Code client" -if false
=form.input :code, :label => "Code client"
-if !@p_customer.id -if !@p_customer.id

View File

@ -0,0 +1,14 @@
=semantic_form_for [:admin, @p_fournisseur_ref], :remote => true do |f|
.content
=f.inputs do
= f.input :ref, :label => f.object.label_for(:ref)
= f.input :p_product_ref, :label => f.object.label_for(:p_product_ref)
= f.input :p_fournisseur, :label => f.object.label_for(:p_fournisseur)
.actions=f.submit "sauvegarder", :class => "btn btn-primary"

View File

@ -0,0 +1,16 @@
%tr#p_fournisseur_ref_row{:id => p_fournisseur_ref.id}
-tr = {}
-tr[:actions] = capture do
%td.actions
= link_to i(:"trash-o"), [:admin, p_fournisseur_ref], method: :delete, data: { confirm: 'Voulez-vous vraiment supprimer cet enregistrement ? ' } , :remote => true
= link_to i(:pencil), edit_admin_p_fournisseur_ref_path(p_fournisseur_ref), :remote => true
= link_to i(:eye), admin_p_fournisseur_ref_path(p_fournisseur_ref), :remote => true
=render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => p_fournisseur_ref}

View File

@ -0,0 +1,2 @@
$('#p_fournisseur_refs_rows').prepend("<%= escape_javascript(render(@p_fournisseur_ref))%>");
close_pane_hover();

View File

@ -0,0 +1 @@
$('#p_fournisseur_ref_row_<%= @p_fournisseur_ref.id %>').remove();

View File

@ -0,0 +1 @@
show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900);

View File

@ -0,0 +1,16 @@
.qi_header
.right= link_to ic(:plus)+' Ajouter', new_admin_p_fournisseur_ref_path(), :class => "btn btn-primary btn-ap-add", :remote => true
%h1
=PFournisseurRef.human rescue ""
.qi_search_row
=form_tag "", :method => "get", :onsubmit => "" do
=render :partial => "qi/qi_ordered_table_search_footer", :locals => {:collection_object => @p_fournisseur_refs}
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_fournisseur_refs}

View File

@ -0,0 +1 @@
show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900);

View File

@ -0,0 +1,10 @@
.qi_header
%h1
%span
.qi_row
.qi_pannel.qi_plain.padding
=debug @p_fournisseur_ref

View File

@ -0,0 +1,2 @@
$('#p_fournisseur_ref_row_<%= @p_fournisseur_ref.id %>').replaceWith("<%= escape_javascript(render(@p_fournisseur_ref))%>");
close_pane_hover();

View File

@ -1,13 +1,14 @@
-@import= true -if false
-@import= true
-i = 0 -i = 0
-@csv.each do |csv| -@csv.each do |csv|
-i += 1 -i += 1
=csv["code"] =csv["code"]
-if csv["code"].to_s != "" -if csv["code"].to_s != ""
sfsd sfsd
-PFournisseur.create(:code => csv["code"],:name => csv["nom"],:address1 => csv["adresse 1"],:address2 => csv["adresse 2"],:cp => csv["code postal"],:city => csv["city"],:country => csv["country"],:email => csv["email"],:tel => csv["tel"]) -PFournisseur.create(:code => csv["code"],:name => csv["nom"],:address1 => csv["adresse 1"],:address2 => csv["adresse 2"],:cp => csv["code postal"],:city => csv["city"],:country => csv["country"],:email => csv["email"],:tel => csv["tel"])

View File

@ -1,7 +1,6 @@
.qi_header .qi_header
.right .right
= link_to 'Ajouter un fournisseur', new_admin_p_fournisseur_path(), :class => "btn btn-primary", :remote => true = link_to 'Ajouter un fournisseur', new_admin_p_fournisseur_path(), :class => "btn btn-primary", :remote => true
%h1 %h1
Achats Achats
%span %span

View File

@ -15,15 +15,15 @@
%table %table
%tr %tr
%td %td
%h4 spec : %h4 Specs :
%tr
%td %td
-#form.object.p_spec_type = PSpecType.new if !form.object.p_spec_type -#form.object.p_spec_type = PSpecType.new if !form.object.p_spec_type
-#form.object.p_spec_value = PSpecValue.new if !form.object.p_spec_value -#form.object.p_spec_value = PSpecValue.new if !form.object.p_spec_value
= form.input :p_spec_type_id, :label => "Type", as: :select, collection: PSpecType.all, :include_blank => false = form.input :p_spec_type_id, :label => "Type", as: :select, collection: PSpecType.all, :include_blank => true,input_html: {class: "custom-select"}
%td %td
= form.input :p_spec_value_id, :label => "Valeur", as: :select, collection: PSpecValue.all, :include_blank => false, :member_label => :member_label = form.input :p_spec_value_id, :label => "Valeur", as: :select, collection: PSpecValue.all, :include_blank => true, :member_label => :member_label, input_html: {class: "custom-select"}
=#form.inputs do =#form.inputs do

View File

@ -1,5 +1,6 @@
=#debug form.object.errors.messages
=# form.input :ref, :label => "Ref :" =# form.input :ref, :label => "Ref :"
.qi_row.field .qi_row.field{id: dom_id(form.object)}
.qi_pannel.qi_plain.padding .qi_pannel.qi_plain.padding
%table.form-table %table.form-table
@ -10,6 +11,8 @@
%td %td
= form.input :ref, :label => "Réf int. :" = form.input :ref, :label => "Réf int. :"
=#form.hidden_field :ref_id =#form.hidden_field :ref_id
-if @price_line
=form.hidden_field :price_line_id, value: @price_line.id
%td %td
= form.input :ct_sub_name, :label => "Désignation :" = form.input :ct_sub_name, :label => "Désignation :"
@ -18,7 +21,17 @@
= form.input :ct_price_ht, :label => "Prix vente HT :" = form.input :ct_price_ht, :label => "Prix vente HT :"
%td %td
=form.input :p_product_color_id, :label => "Couleur :", :collection => PProductColor.all, :as => :select, :include_blank => true =form.input :p_product_color_id, :label => "Couleur :", :collection => PProductColor.all, :as => :select, :include_blank => true, input_html: {class: "custom-select"}
%td
=form.input :ean
%tr
%td
=form.input :ct_sorecop, :label => "Sorecop personalisée :"
%td
=form.input :sorecop_comment, :label => "Commentaire de Sorecop :"
%td
=form.input :ct_deee, :label => "DEEE personalisée :"
@ -34,7 +47,7 @@
%tr %tr
%td{:colspan => 2} %td{:colspan => 2}
%td{:colspan => 4} %td{:colspan => 4}
= form.input :description, :label => "Désignation longue :" , :input_html => {:style => "height:100px;"} = form.input :description, :label => "Désignation longue :" , :input_html => {rows: 1}
-if false -if false
%tr %tr

View File

@ -31,8 +31,14 @@
%td.actions %td.actions
=# link_to i(:"trash-o"), [:admin, p_product_ref], method: :delete, data: { confirm: 'Voulez-vous vraiment supprimer ce produit ? ' } , :remote => true if !PriceLine.where(:p_product_ref_id => p_product_ref).first =# link_to i(:"trash-o"), [:admin, p_product_ref], method: :delete, data: { confirm: 'Voulez-vous vraiment supprimer ce produit ? ' } , :remote => true if !PriceLine.where(:p_product_ref_id => p_product_ref).first
=#debug PriceLine.where(:p_product_ref_id => p_product_ref.id).first =#debug PriceLine.where(:p_product_ref_id => p_product_ref.id).first
= link_to i(:pencil), edit_admin_p_product_path(p_product_ref.p_product), :remote => false
= link_to i(:eye), admin_p_product_ref_path(p_product_ref), :remote => false -if @manager
= link_to i(:eye), admin_p_product_ref_path(p_product_ref), :remote => false, :target => "_blank"
= link_to i(:"check"), "#",:onclick => "send_manager_product('"+p_product_ref.id.to_s+"', '"+escape_javascript(p_product_ref.member_label.to_s)+"');return false;"
-else
= link_to i(:pencil), edit_admin_p_product_path(p_product_ref.p_product, anchor: dom_id(p_product_ref)), :remote => false
= link_to i(:eye), admin_p_product_ref_path(p_product_ref), :remote => false
=render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => p_product_ref} =render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => p_product_ref}

View File

@ -1,17 +1,19 @@
.qi_header -if !@manager
.right= link_to ic(:plus)+' Ajouter un produit', new_admin_p_product_path(), :class => "btn btn-primary btn-ap-add", :remote => false .qi_header
%h1 .right= link_to ic(:plus)+' Ajouter un produit', new_admin_p_product_path(), :class => "btn btn-primary btn-ap-add", :remote => false
Achats %h1
%span Achats
Produits %span
Références
.qi_search_row .qi_search_row
=form_tag "", :method => "get", :onsubmit => "" do =form_tag admin_p_product_refs_path, :method => "get", :onsubmit => "", :remote => true do
=hidden_field_tag :column, params[:column] =hidden_field_tag :column, params[:column]
=hidden_field_tag :direction, params[:direction] =hidden_field_tag :direction, params[:direction]
=hidden_field_tag :manager, params[:manager]
%table %table
%tr %tr
@ -56,7 +58,7 @@
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_product_refs} #p_product_refs_index_wrapper=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_product_refs, :remote => true}
@ -67,3 +69,6 @@
}); });
:coffeescript
$(".qi_search_row form").on "submit", ->
$("#p_product_refs_index_wrapper").html('recherche en cours ...')

View File

@ -0,0 +1,9 @@
var p_product_refs_url = "<%= escape_javascript(request.url) %>";
$('#p_product_refs_index_wrapper').html("<%= escape_javascript(render(:partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_product_refs, :remote => true}))%>");
$(".btn-qi-search").html('<i class="fa fa-search "></i> Rechercher');

View File

@ -1,2 +1,8 @@
$('#p_product_ref_row_<%= @p_product_ref.id %>').replaceWith("<%= escape_javascript(render(@p_product_ref))%>"); $('#p_product_ref_row_<%= @p_product_ref.id %>').replaceWith("<%= escape_javascript(render(@p_product_ref))%>");
if ($('#<%= dom_id(@price_line) %>').parents('.qi_pannel.qi_plain').find('tbody').find('tr').length === 1) {
$('#<%= dom_id(@price_line) %>').parents('.qi_pannel.qi_plain').remove()
}
$('#<%= dom_id(@price_line) %>').remove();
close_pane_hover(); close_pane_hover();

View File

@ -19,7 +19,8 @@
=# f.input :stocked, :label => "Suivi de stock ?" =# f.input :stocked, :label => "Suivi de stock ?"
.col-sm-2
=f.input :sorecop_cat, label: "Catgorie Sorecop :", :collection => SorecopCat.all, :as => :select, :include_blank => true

View File

@ -20,8 +20,8 @@
=hidden_field_tag :public_edit, params[:public_edit] =hidden_field_tag :public_edit, params[:public_edit]
%h3
= @price_document.price_line_block.block_type = @price_document.price_line_block.block_type
-if @price_document.label == "Demande prix" -if @price_document.label == "Demande prix"
.row .row

View File

@ -1,4 +1,4 @@
=semantic_form_for [:admin, @price_document], :html => {:class => "qi_price_form"}, :remote => false do |f| =semantic_form_for [:admin, @price_document], url: match_p_fournisseur_save_admin_price_document_path, :html => {:class => "qi_price_form"}, :remote => true do |f|
=diag do =diag do
=f.object.errors.messages =f.object.errors.messages

View File

@ -22,7 +22,7 @@
-tr[:p_fournisseur] = capture do -tr[:p_fournisseur] = capture do
%td %td
- if price_document.price_document_type_id == 2 - if price_document.price_document_type.label == "Réponse fournisseur"
-if price_document.p_fournisseur.present? -if price_document.p_fournisseur.present?
= price_document.p_fournisseur.name = price_document.p_fournisseur.name
- else - else
@ -69,12 +69,15 @@
%td %td
- if price_document.avancement - if price_document.avancement
= price_document.avancement.to_s + " %" = price_document.avancement.to_s + " %"
- elsif parent_doc.avancement - elsif parent_doc and parent_doc.avancement
= parent_doc.avancement.to_s + " %" = parent_doc.avancement.to_s + " %"
-tr[:list_designaton] = capture do -tr[:list_designaton] = capture do
%td %td
= price_document.list_designaton || parent_doc.list_designaton -if price_document.list_designaton
= price_document.list_designaton
-elsif parent_doc
=parent_doc.list_designaton
-tr[:end_date] = capture do -tr[:end_date] = capture do
%td %td
@ -87,11 +90,17 @@
-tr[:dp_comment] = capture do -tr[:dp_comment] = capture do
%td %td
= price_document.dp_comment || parent_doc.dp_comment -if price_document.dp_comment
= price_document.dp_comment
-elsif parent_doc
=parent_doc.dp_comment
-tr[:acheteur_text] = capture do -tr[:acheteur_text] = capture do
%td %td
= price_document.acheteur_text || parent_doc.acheteur_text -if price_document.acheteur_text
= price_document.acheteur_text
-elsif parent_doc
=parent_doc.acheteur_text
-tr[:customer_ref] = capture do -tr[:customer_ref] = capture do
%td %td
@ -135,7 +144,7 @@
-tr[:actions] = capture do -tr[:actions] = capture do
%td.actions %td.actions
-if price_document.price_document_type_id == 1 -if price_document.price_document_type.label == "Demande prix"
=link_to i("bar-chart"), analyse_reponses_admin_price_document_path(price_document) =link_to i("bar-chart"), analyse_reponses_admin_price_document_path(price_document)
-if !price_document.imported -if !price_document.imported
-if current_admin.has_permission?("payments") -if current_admin.has_permission?("payments")
@ -177,7 +186,6 @@
=# link_to i(:eye), admin_price_document_path(price_document), :remote => true =# link_to i(:eye), admin_price_document_path(price_document), :remote => true
= link_to i(:eye), admin_price_document_path(price_document.id), :remote => false = link_to i(:eye), admin_price_document_path(price_document.id), :remote => false
-if PriceLineBlock::PURCHASE_BLOCKS.include?(price_document.block_type) -if PriceLineBlock::PURCHASE_BLOCKS.include?(price_document.block_type)
=# link_to i(:eye), admin_price_document_path(price_document.id), :remote => false =# link_to i(:eye), admin_price_document_path(price_document.id), :remote => false
@ -192,6 +200,9 @@
= link_to i(:pencil), edit_admin_price_document_path(price_document) = link_to i(:pencil), edit_admin_price_document_path(price_document)
= link_to i(:eye), admin_price_document_path(price_document.id), :remote => false, :target => "_blank" = link_to i(:eye), admin_price_document_path(price_document.id), :remote => false, :target => "_blank"
-if price_document.cc_label == "Bon de réception achat"
%br
=link_to "Générer la facture", facture_achat_admin_price_document_path(price_document)
=render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => price_document} =render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => price_document}

View File

@ -0,0 +1,62 @@
#bills
.qi_tab_header
%h3 Bons de réception associés
.right
-params[:search][:per_page] = params[:search][:per_page] || 50
-per_page = params[:search][:per_page]
-page = (params[:page] and params[:page] != "") ? params[:page] : 1
-@price_documents = PriceDocument.where(:bon_de_commande_achat_id => bca.id, :price_document_type_id => [5]).order("date DESC, created_at DESC")
-@price_documents = sort_by_sorting(@price_documents, "created_at DESC")
-@all_price_documents = @price_documents
-@price_documents = @price_documents.page(page).per(per_page)
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @price_documents, :key => "projet-factures"}
%h3 Etat des réceptions par articles
- bca_price_line_blocks = PriceLineBlock.where(:price_lineable_type => "PriceDocument", :price_lineable_id => bca.id)
- bra_price_line_blocks = PriceLineBlock.where(:price_lineable_type => "PriceDocument", :price_lineable_id => @all_price_documents.ids)
%table.table.table-striped.table-hover.table-bordered.data_table
%thead
%tr
%th
Code produit
%th
Produit
%th Quantité commandée
%th Quantité réceptionnée
%th Différence
%tbody
- PriceLine.where(:price_line_block_id => (bca_price_line_blocks.ids + bra_price_line_blocks.ids)).map {|pl| pl.p_product_ref_id}.uniq.each do |p_product_ref_id|
-if p_product_ref = PProductRef.where(:id => p_product_ref_id).first
%tr
%td
=link_to [:admin, p_product_ref] do
=p_product_ref.ref
%td
=link_to [:admin, p_product_ref] do
=p_product_ref.cc_name
%td
=a = PriceLine.where(:p_product_ref_id => p_product_ref_id, :price_line_block_id => bca_price_line_blocks).sum(:qte)
%td
=b = PriceLine.where(:p_product_ref_id => p_product_ref_id, :price_line_block_id => bra_price_line_blocks).sum(:qte)
%td
= a -b

View File

@ -2,13 +2,13 @@
%h1 %h1
Achats Achats
%span %span
Analyse des réponces à la consiltation Analyse des réponces à la demande de prix
= link_to @price_document.d_number, admin_price_document_path(@price_document) = link_to @price_document.d_number, admin_price_document_path(@price_document)
\- \-
= @price_document.list_designaton = @price_document.list_designaton
-unmatched_fournisseur = 0
=semantic_form_for [:admin, @price_document], :html => {:class => "qi_price_form"}, :remote => false do |form| =semantic_form_for [:admin, @price_document],url: analyse_reponses_save_admin_price_document_path, method: :post, :html => {:class => "qi_price_form"}, :remote => false do |form|
=form.semantic_fields_for :price_line_block do |f| =form.semantic_fields_for :price_line_block do |f|
- price_line_block = f.object - price_line_block = f.object
.qi_pannel.padding.new_table_container .qi_pannel.padding.new_table_container
@ -26,9 +26,23 @@
Consultation Consultation
%th{colspan: nb_resp} %th{colspan: nb_resp}
Fournisseurs Fournisseurs
.btn.btn-light.ml-4#reset-radio .btn.btn-light.mx-4#reset-radio
reset reset
.legend.d-flex
légende :
.inlie-block.d-flex.flex-wrap.justify-content-end
.mx-2.red
= ic("diamond") + " Spot detecté !"
.mx-2.green
= ic("money") + " Meilleur prix"
.mx-2.red
= ic(:times) + " Alerte marge basse"
.mx-2.green
= ic(:check) + " Marge ok"
.mx-2.orange
= ic(:warning) + " Alerte Qté"
.mx-2.info
= ic('info-circle') + " Commentaire fournisseur"
%tr %tr
%th %th
Qté à Qté à
@ -77,17 +91,23 @@
%th %th
-if resp.p_fournisseur -if resp.p_fournisseur
=resp.p_fournisseur.name =resp.p_fournisseur.name
-else
-unmatched_fournisseur += 1
nom renseigné par le fournisseur :
%br
="(#{resp.public_fournisseur_name})"
%br
=link_to ic('pencil') + " rapprocher le fournisseur", match_p_fournisseur_admin_price_document_path(resp), remote: true
%tbody %tbody
-# price_lines = f.object.price_lines -# price_lines = f.object.price_lines
-price_lines_child_index = {}
-consult_price_lines = @price_document.price_line_block.price_lines -consult_price_lines = @price_document.price_line_block.price_lines
=f.semantic_fields_for :price_lines do |form| =f.semantic_fields_for :price_lines do |form|
- price_line = form.object - price_line = form.object
-#price_lines = @price_document.price_line_block.price_lines -#price_lines = @price_document.price_line_block.price_lines
-#price_lines.each do |price_line| -#price_lines.each do |price_line|
%tr %tr
%td %td
=# ATTENTION ! On a plus accès direct aux commandes qui on engendré cette demande de prix. donc plus accès aux délais différent entre les différentes commades pour une ref donée =# ATTENTION ! On a plus accès direct aux commandes qui on engendré cette demande de prix. donc plus accès aux délais différent entre les différentes commades pour une ref donée
@ -128,21 +148,34 @@
%td.limit %td.limit
/ spec / spec
=form.input :selected_price_line_id, collection: PriceLine.where(:price_line_ref_id => form.object.id).all, as: :radio, :member_label => :id =#form.input :price_line_resp_ids, collection: PriceLine.where(:price_line_ref_id => form.object.id).all, as: :check_boxes , :member_label => :id
=debug form.object.id
-#NICO : j'ai commenté l'input qu'on a fait ensemble, par contre, pour toute la suite, j'ai en fait fait un copié collé du rendu de cet inpu ou j'ai remis les champs dynamics en correspondance.
-#NICO : j'ai créé un hash plus haut, vide, qui va me permettre de faire correspondre à chaque ID de price_line leur index dans le nested form (qui est différent, une itération, de l'ID de l'élement... Là c'est la magie de rails.)
- price_lines_child_index[form.object.id.to_s] = form.options[:child_index]
-best_price = PriceLine.where(price_line_ref_id: price_line.id).where("ct_u_price_ht > 0").order(:ct_u_price_ht).ids
-#Nico : je commence, pour chaque price line, par faire une checkbox vide. J'aurais pu faire un checkbox tag mais par facilité j'ai copé l'HTML dans HTML2HAML et je suis partid du résultat. Les checkboxes sont ensuite dans ta boucle
%input{:autocomplete => "off", :id => "price_document[price_line_block_attributes][price_lines_attributes][#{form.options[:child_index] }]_price_line_resp_ids_none", :name => "price_document[price_line_block_attributes][price_lines_attributes][#{form.options[:child_index] }][price_line_resp_ids][]", :type => "hidden", :value => ""}/
=#{}"price doc id : #{@price_document_responses.ids}"
- @price_document_responses.each do |resp| - @price_document_responses.each do |resp|
-line = resp.price_line_block.price_lines.where(p_product_ref: price_line.p_product_ref).first -line = resp.price_line_block.price_lines.where(p_product_ref: price_line.p_product_ref).first
-cell = [] -cell = []
- if line.qte_available.to_i > 0 - if line.qte_available.to_i > 0
-if line.qte_available >= price_line.qte.to_i - if line.id == best_price[0]
-cell << "<span class=green>#{ic(:money)} Meilleur prix</span>"
- if line.qte_available >= price_line.qte.to_i
- cell << "Qté dispo : #{line.qte_available.to_i}" - cell << "Qté dispo : #{line.qte_available.to_i}"
-else - else
- cell << "#{ic(:warning, class: "orange")} Qté dispo : #{line.qte_available.to_i} (#{line.qte_available.to_i - price_line.qte.to_i})" - cell << "#{ic(:warning, class: "orange")} Qté dispo : #{line.qte_available.to_i} (#{line.qte_available.to_i - price_line.qte.to_i})"
- cell << "PA: #{line.ct_u_price_ht} €" - cell << "PA: #{line.ct_u_price_ht} €"
- # mp = calcul de la marge prévisionelle TODO - # mp = calcul de la marge prévisionelle TODO
- line.id.odd? ? mp = 0.17 : mp = 0.11 - line.id.odd? ? mp = 0.17 : mp = 0.11
- if mp.present? - if false
-if mp > 0.15 -if mp > 0.15
- cell << "<span class=green>#{ic(:check)} MP: #{mp * 100} %</span>" - cell << "<span class=green>#{ic(:check)} MP: #{mp * 100} %</span>"
-else -else
@ -155,14 +188,47 @@
- display_comment = "#{line.comment[0..10]} (..)" - display_comment = "#{line.comment[0..10]} (..)"
- else - else
- display_comment = line.comment - display_comment = line.comment
- cell << "<span class='info'>#{ic('info-circle')} #{display_comment}<span class='info-text'>#{line.comment}</span></span>" - cell << "<span class='info'>#{ic('info-circle')} #{display_comment}<span class='info-text-top'>#{line.comment}</span></span>"
%td.p-0{class: ("best-price" if line.id == best_price[0])}
=# "reponse price_line ID : #{line.id}"
=# "price line origine : #{line.price_line_ref_id}" #NICO : simple contrôle, je récupère facilement par là l'ID de la price Line concernée.
-#NICO : si on a un price_line_ref_id, j'ajoute la case à cocher. Je récupère l'index de nested form dans mon hash, et je passe en value le line.id
-if line.price_line_ref_id.to_s != ""
%input.seletable_price{:id => "price_document_price_line_block_attributes_price_lines_attributes_#{price_lines_child_index[line.price_line_ref_id.to_s]}_price_line_resp_ids_#{line.id}" , :autocomplete => "off", :checked => ("checked" if PriceLine.find(line.price_line_ref_id).price_line_resp_ids.include?(line.id) ), :name => "price_document[price_line_block_attributes][price_lines_attributes][#{price_lines_child_index[line.price_line_ref_id.to_s]}][price_line_resp_ids][]", :type => "checkbox", :value => line.id}>/
%label.p-2.m-auto{:for => "price_document_price_line_block_attributes_price_lines_attributes_#{price_lines_child_index[line.price_line_ref_id.to_s]}_price_line_resp_ids_#{line.id}"}
=sanitize(cell.join('<br>'))
=# radio_button_tag "ref_price_selected_#{price_line.p_product_ref.id}", line.id, false, class: "seletable_price"
=# label_tag "ref_price_selected_#{price_line.p_product_ref.id}_#{line.id}", sanitize(cell.join('<br>')), class: "p-2 m-auto"
- if unmatched_fournisseur == 0
=submit_tag 'valider la selection', class: "btn btn-primary ml-4"
- else
%button.btn.btn-primary.ml-4{"type" => "button", "data-toggle" => "modal", "data-target" => "#unmatched-fournisseur"}
Valider la selection
.modal.fade#unmatched-fournisseur{"tab-index" => "-1", "role" => "dialog", "aria-labelledby" => "Raprochement Fournisseur", "aria-hidden" => "true"}
.modal-dialog{role: "dialog"}
.modal-content
.modal-header
%h5.modal-title
Rapprochement du fournisseur
%button.close{"data-dismiss" => "modal", "aria-label" => "Close"}
%span{"aria-hidden" => "true"}
&times;
.modal-body
Il reste des fournisseurs à prapprocher avant de pouvoir valider.
.modal-footer
%button.btn.btn-light{"data-dismiss" => "modal"}
Close
- if PriceDocument.where(doc_ref_id: @price_document, price_document_type: PriceDocumentType.find_by_label("Consultation fournisseur")).empty?
=link_to "Generer les consultations", generate_final_consult_admin_price_document_path, class: "btn btn-primary ml-4 mt-4"
=link_to "Acceder aux consultations", admin_price_document_path(@price_document, anchor: "consult"), class: "btn btn-primary ml-4 mt-4"
%td.p-0
= "reponse price_line ID : #{line.id}"
=#form.input :selected_price_offer, as: :radio
= radio_button_tag "ref_price_selected_#{price_line.p_product_ref.id}", line.id, false, class: "category-selector"
= label_tag "ref_price_selected_#{price_line.p_product_ref.id}_#{line.id}", sanitize(cell.join('<br>')), class: "p-2 m-auto"
=submit_tag 'valider la selection', class: "btn btn-primary"
@ -171,21 +237,58 @@
:scss :scss
.category-selector { .seletable_price {
position: absolute; position: absolute;
transform: scale(0); transform: scale(0);
} }
.category-selector + label { .seletable_price + label {
display: block; display: block;
min-height: 105px; min-height: 105px;
cursor: pointer; cursor: pointer;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
text-align: left; text-align: left;
&:hover{
background:linear-gradient(to top, #efefef 5%, #fdfdfd 100%);
background-color:#5cb811;
}
&:active{
position:relative;
top:1px;
}
} }
.category-selector:checked + label { .seletable_priceOLD:checked + label {
background-color: green !important;
border-radius: 1em;
border: darkgreen solid 0.2em;
mix-blend-mode: difference;
}
.seletable_price:checked + label{
box-shadow:inset 0px 1px 0px 0px #caefab;
background:linear-gradient(to bottom, #77d42a 5%, #5cb811 100%);
background-color:#77d42a;
border-radius:6px;
border:1px solid #268a16;
display:inline-block;
cursor:pointer;
color:#306108;
font-family:Arial;
font-size:15px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:0px 1px 0px #aade7c;
&:hover{
background:linear-gradient(to bottom, #5cb811 5%, #77d42a 100%);
background-color:#5cb811;
}
}
.best-price{
background-color: #b4f99e !important; background-color: #b4f99e !important;
} }
@ -202,51 +305,8 @@
.orange { .orange {
color: orange; color: orange;
} }
.info {
color: #009bbf;
position: relative;
display: inline-block;
text-overflow: ellipsis;
.info-text {
visibility: hidden;
background-color: #555;
color: #fff;
text-align: center;
padding: 5px;
border-radius: 6px;
max-width: 500px;
min-width: fit-content;
white-space: normal;
/* Position the tooltip text */
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
/* Fade in tooltip */
opacity: 0;
transition: opacity 0.3s;
}
.info-text::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
}
.info:hover {
.info-text {
visibility: visible;
opacity: 1;
}
}
.darkblue { .darkblue {
color: darkblue; color: darkblue;
} }
@ -257,5 +317,5 @@
:javascript :javascript
$( "#reset-radio" ).click(function(event){ $( "#reset-radio" ).click(function(event){
$( ":radio" ).prop('checked',false); $('input:checkbox').prop('checked',false);
}) })

View File

@ -31,26 +31,31 @@
=f.hidden_field :price_document_type_id =f.hidden_field :price_document_type_id
%center= f.input :public_fournisseur_name, :label => "Nom de votre société :" %center
.small-container
= f.input :public_fournisseur_name, :label => "Nom de votre société :"
%p{:style => "text-align:center;font-size:1.2em;"} %p{:style => "text-align:center;font-size:1.2em;"}
Vous pouvez également indiquer votre référence interne : Vous pouvez également indiquer votre référence interne :
=hidden_field_tag :public_edit, params[:public_edit] =hidden_field_tag :public_edit, params[:public_edit]
.price_line_block_form .price_line_block_form
=f.semantic_fields_for :price_line_block do |f| =f.semantic_fields_for :price_line_block do |f|
%center=render :partial => "admin/price_line_blocks/form_#{f.object.block_type_slug}", :locals => {:f => f} %center=render :partial => "admin/price_line_blocks/form_#{f.object.block_type_slug}", :locals => {:f => f}
%center %center
=f.submit "sauvegarder", :class => "btn btn-primary" =f.submit "sauvegarder", :class => "btn btn-primary"
:scss
.small-container{
max-width: 500px;
}

View File

@ -65,7 +65,7 @@
Type de document : Type de document :
%td %td
-if [1,2,6,7].include?(params[:price_document_type_id].to_i)or (params[:price_document_type_ids] and (params[:price_document_type_ids].include?("6") or params[:price_document_type_ids].include?("7"))) -if [3,4,5,6,7,9,10].include?(params[:price_document_type_id].to_i)or (params[:price_document_type_ids] and (params[:price_document_type_ids].include?("6") or params[:price_document_type_ids].include?("7")))
-PriceDocumentType.where(:label => PriceDocument::PURCHASES, :enabled => true).order("id DESC").each do |pdt| -PriceDocumentType.where(:label => PriceDocument::PURCHASES, :enabled => true).order("id DESC").each do |pdt|
%p.d-inline-flex.ml-3 %p.d-inline-flex.ml-3
= check_box_tag :"price_document_type_ids[]", pdt.id, (true if params[:price_document_type_ids].include?(pdt.id.to_s)), {:id => "price_document_type_ids_#{pdt.id}", class: "my-auto"} = check_box_tag :"price_document_type_ids[]", pdt.id, (true if params[:price_document_type_ids].include?(pdt.id.to_s)), {:id => "price_document_type_ids_#{pdt.id}", class: "my-auto"}

View File

@ -0,0 +1,2 @@
location.reload();
close_pane_hover();

View File

@ -25,61 +25,65 @@
=@price_document.d_number =@price_document.d_number
-if @price_document.label == "Réponse fournisseur" .qi_row
.qi_row
.qi_pannel.padding
%table.table.table-striped %table.table.table-striped
%tr -if @price_document.label == "Réponse fournisseur"
%td
Nom fournisseur saisi
%td
=@price_document.public_fournisseur_name
%tr
%td
Fournisseur
%td
=link_to @price_document.p_fournisseur.name, [:admin, @price_document.p_fournisseur] if @price_document.p_fournisseur
%tr
%td
Nom fournisseur saisi
%td
=@price_document.public_fournisseur_name
-if @price_document.p_fournisseur
%tr
%td
Fournisseur
%td
=link_to @price_document.p_fournisseur.name, [:admin, @price_document.p_fournisseur] if @price_document.p_fournisseur
-if @price_document.label == "Demande prix" -if @price_document.d_number?
.qi_row %tr
.qi_pannel.padding %td Numéro
%td=@price_document.d_number
%tr
%td Date
%td=l @price_document.date, :format => :date
%table.table.table-striped -if @price_document.label == "Demande prix"
%tr %tr
%td %td
Avancement (%) Avancement (%)
%td %td
=@price_document.avancement.to_s + " %" =@price_document.avancement.to_s + " %"
%tr %tr
%td %td
Désignation Désignation
%td %td
=@price_document.list_designaton =@price_document.list_designaton
%tr %tr
%td Date de fin de consultation : %td Date de fin de consultation :
%td %td
=l @price_document.end_date if @price_document.end_date =l @price_document.end_date if @price_document.end_date
%tr %tr
%td Commentaire %td Commentaire
%td %td
=simple_format @price_document.dp_comment =simple_format @price_document.dp_comment
%tr %tr
%td %td
Envoyé à Envoyé à
%td %td
=simple_format @price_document.acheteur_text =simple_format @price_document.acheteur_text
%tr %tr
%td %td
Lien pour consultation Lien pour consultation
%td %td
=link_to consult_admin_price_document_url(:id => @price_document.f_token, :lang => nil), consult_admin_price_document_url(:id => @price_document.f_token, :lang => nil) =link_to consult_admin_price_document_url(:id => @price_document.f_token, :lang => nil), consult_admin_price_document_url(:id => @price_document.f_token, :lang => nil)
@ -90,12 +94,12 @@
-if false -if true
-price_line_block = @price_document.price_line_block -price_line_block = @price_document.price_line_block
=render price_line_block =#render price_line_block
-else -else
-params[:search][:per_page] = params[:search][:per_page] || 5000 -params[:search][:per_page] = params[:search][:per_page] || 5000
@ -120,64 +124,65 @@
-if @price_document.label != "Demande prix" and @price_document.label != "Réponse fournisseur" -if @price_document.label != "Demande prix" and @price_document.label != "Réponse fournisseur"
-if current_admin and current_admin.id == 1 -if current_admin and current_admin.id == 1
%table.table -enable_stat = false
%tr -if enable_stat
%th Archivé ? %table.table
%td %tr
= diag do %th Archivé ?
-if @price_document.archived %td
Oui = diag do
=link_to "Désarchiver", unarchive_now_admin_price_document_path(@price_document.id) -if @price_document.archived
-else Oui
=link_to "Archiver", archive_now_admin_price_document_path(@price_document.id) =link_to "Désarchiver", unarchive_now_admin_price_document_path(@price_document.id)
%tr -else
%th Id bloc =link_to "Archiver", archive_now_admin_price_document_path(@price_document.id)
%td=price_line_block.id %tr
%th Id bloc
%td=price_line_block.id
%tr %tr
%th Cout block %th Cout block
%td=price_line_block.cc_cost_ht %td=price_line_block.cc_cost_ht
-params[:search][:per_page] = params[:search][:per_page] || 5000 -params[:search][:per_page] = params[:search][:per_page] || 5000
-per_page = params[:search][:per_page] -per_page = params[:search][:per_page]
-page = (params[:page] and params[:page] != "") ? params[:page] : 1 -page = (params[:page] and params[:page] != "") ? params[:page] : 1
-@stat_lines = @price_document.stat_lines.order("date DESC, created_at DESC") -@stat_lines = @price_document.stat_lines.order("date DESC, created_at DESC")
-@stat_lines = sort_by_sorting(@stat_lines, "created_at DESC") -@stat_lines = sort_by_sorting(@stat_lines, "created_at DESC")
-@stat_lines = @stat_lines.page(page).per(per_page) -@stat_lines = @stat_lines.page(page).per(per_page)
%br %br
=link_to "Générer les stats", generate_stat_lines_admin_price_document_path(@price_document), :class => "btn btn-primary" =link_to "Générer les stats", generate_stat_lines_admin_price_document_path(@price_document), :class => "btn btn-primary"
%table.table %table.table
%tr %tr
%th %th
HT HT
%td %td
=number_to_currency @stat_lines.sum(:tot_amount_ht) =number_to_currency @stat_lines.sum(:tot_amount_ht)
%tr %tr
%th %th
TTC TTC
%td %td
=number_to_currency @stat_lines.sum(:tot_amount_ttc) =number_to_currency @stat_lines.sum(:tot_amount_ttc)
%tr %tr
%th %th
Coût HT Coût HT
%td %td
=number_to_currency @stat_lines.sum(:cost_ht) =number_to_currency @stat_lines.sum(:cost_ht)
.clear .clear
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @stat_lines} =render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @stat_lines}
@ -185,13 +190,23 @@
%h3 Lignes de produits
.mb-3
- if @price_document.cc_label == "Consultation fournisseur"
= link_to ic(:clipboard) + " Copier le texte", "#", class: "btn btn-primary", "data-document" => @price_document.id, onclick: 'copyPriceLines(event)'
- existing_order = PriceDocument.where(doc_ref_id: @price_document.id, cc_label: "Commande achat")
- if existing_order.present?
= link_to ic(:eye) + " Afficher la commande", admin_price_document_path(existing_order.first), class: "btn btn-tertiary"
- else
= link_to "Generer la commande", buy_order_create_admin_price_document_path(@price_document), class: "btn btn-primary"
%table.table %table.table
%thead %thead
%tr %tr
%th %th
%th Référence %th Référence
%th Produit %th Marque
%th Désignation %th Désignation
%th Qté %th Qté
%th P.U. HT %th P.U. HT
@ -208,17 +223,17 @@
%td
=link_to price_line.p_product_ref.p_product.name, edit_admin_p_product_path(price_line.p_product_ref.p_product) if price_line.p_product_ref and price_line.p_product_ref.p_product
%td %td
=price_line.title =price_line.p_product_ref.p_product.s_brand.name
%td.numeraire %td{class: "p_product_ref_cc_name_#{@price_document.id}"}
=link_to price_line.p_product_ref.cc_name, edit_admin_p_product_path(price_line.p_product_ref.p_product) if price_line.p_product_ref and price_line.p_product_ref.p_product
%td.numeraire{class: "price_line_qte_#{@price_document.id}"}
=price_line.qte =price_line.qte
%td.numeraire %td.numeraire{class: "price_line_price_u_ht_#{@price_document.id}"}
=number_to_currency price_line.price_u_ht =number_to_currency price_line.price_u_ht
@ -231,74 +246,94 @@
%td.numeraire %td.numeraire
=number_to_currency price_line.tot_amount_ht =number_to_currency price_line.tot_amount_ht
%td / %td=# price_line.line_stocks.sum(:price_ht)
= price_line.line_stocks.sum(:price_ht)
-if current_admin.has_permission?("show-costs") .qi_row
-if current_admin.has_permission?("show-costs")
%p
-if @price_document.price_document_type_id == 6
=link_to "Générer les stocks", generate_stocks_admin_price_document_path(@price_document), :class => "btn btn-primary" if !@price_document.stock_ok
-elsif @price_document.price_document_type_id == 4 or @price_document.price_document_type_id == 5
%p
Coût :
=number_to_currency @price_document.cost_ht
%p
Marge :
=number_to_currency @price_document.marge_ht
-if !@price_document.cost_ok
=#link_to "Mettre à jour les stocks, calculer la marge", update_stocks_admin_price_document_path(@price_document), :class => "btn btn-primary"
-if @price_document.d_number
-if @price_document.cc_label == "Commande achat"
%p=link_to "Générer un bon de réception", bon_de_reception_admin_price_document_path(@price_document), :class => "btn btn-primary"
%p=link_to "Générer la facture", facture_achat_admin_price_document_path(@price_document), :class => "btn btn-primary"
-if @facture_achat_childrens.present?
%h3 Facture Achat
-params[:search][:per_page] = params[:search][:per_page] || 5000
-per_page = params[:search][:per_page]
-page = (params[:page] and params[:page] != "") ? params[:page] : 1
-@facture_achat_childrens = @facture_achat_childrens.order("date DESC, created_at DESC")
-#@line_stocks = sort_by_sorting(@line_stocks, "created_at DESC")
-@facture_achat_childrens = @facture_achat_childrens.page(page).per(per_page)
%br %br
%br .clear
%p
-if @price_document.price_document_type_id == 6
=link_to "Générer les stocks", generate_stocks_admin_price_document_path(@price_document), :class => "btn btn-primary" if !@price_document.stock_ok
-elsif @price_document.price_document_type_id == 4 or @price_document.price_document_type_id == 5
%p
Coût :
=number_to_currency @price_document.cost_ht
%p
Marge :
=number_to_currency @price_document.marge_ht
-if !@price_document.cost_ok =render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @facture_achat_childrens}
=link_to "Mettre à jour les stocks, calculer la marge", update_stocks_admin_price_document_path(@price_document), :class => "btn btn-primary"
-if false -if @price_document.cc_label == "Commande achat"
=render :partial => "admin/price_documents/relicats", :locals => {:bca => @price_document}
-if false
-if @price_document.price_document_type_id == 4 or @price_document.price_document_type_id == 5 and !@price_document.cost_ok -if @price_document.price_document_type_id == 4 or @price_document.price_document_type_id == 5 and !@price_document.cost_ok
%table.table.table-striped.table-hover.table-bordered %table.table.table-striped.table-hover.table-bordered
%thead %thead
%tr %tr
%th Produit %th Produit
%th Quantité dans cette pièce comptable %th Quantité dans cette pièce comptable
%th Quantité restante %th Quantité restante
%th %th
-@price_document.price_line_block.price_lines.all.each do |pl| -@price_document.price_line_block.price_lines.all.each do |pl|
-if pl.p_product_ref -if pl.p_product_ref
-if pl.p_product_ref.assembled -if pl.p_product_ref.assembled
-pl.p_product_ref.p_product_assembleds.all.each do |ppa| -pl.p_product_ref.p_product_assembleds.all.each do |ppa|
%tr
%td
=ppa.p_product_ref.cc_name
%td
=@a = (pl.qte.to_f * ppa.qte.to_f).to_f
%td
=link_to admin_line_stocks_path(:p_product_ref_id => ppa.p_product_ref.id) do
=@b = LineStock.where(:p_product_ref_id => ppa.p_product_ref_id).sum(:qte_available).to_f
%td
-if @a > @b
.red=ic :warning
-else
%tr %tr
%td %td
=pl.p_product_ref.cc_name =ppa.p_product_ref.cc_name
%td %td
=@a = pl.qte.to_f =@a = (pl.qte.to_f * ppa.qte.to_f).to_f
%td %td
=link_to admin_line_stocks_path(:p_product_ref_id => pl.p_product_ref.id) do =link_to admin_line_stocks_path(:p_product_ref_id => ppa.p_product_ref.id) do
=@b = LineStock.where(:p_product_ref_id => pl.p_product_ref_id).sum(:qte_available).to_f =@b = LineStock.where(:p_product_ref_id => ppa.p_product_ref_id).sum(:qte_available).to_f
%td %td
-if pl.p_product_ref.stocked and @a > @b -if @a > @b
.red=ic :warning .red=ic :warning
-else
%tr
%td
=pl.p_product_ref.cc_name
%td
=@a = pl.qte.to_f
%td
=link_to admin_line_stocks_path(:p_product_ref_id => pl.p_product_ref.id) do
=@b = LineStock.where(:p_product_ref_id => pl.p_product_ref_id).sum(:qte_available).to_f
%td
-if pl.p_product_ref.stocked and @a > @b
.red=ic :warning
-if @price_document.price_document_type_id == 6 or @price_document.price_document_type_id == 4 or @price_document.price_document_type_id == 5 -if @price_document.price_document_type_id == 6 or @price_document.price_document_type_id == 4 or @price_document.price_document_type_id == 5
-if @price_document.price_line_block.stock_ok
%h3 Stocks générés %h3 Stocks générés
#bills #bills
-params[:search][:per_page] = params[:search][:per_page] || 5000 -params[:search][:per_page] = params[:search][:per_page] || 5000
@ -321,14 +356,13 @@
-if @price_document.label == "Demande prix" -if @price_document.label == "Demande prix"
%h3.ml-2 Réponses fournisseur
%h3 Réponses fournisseur
#bills #bills
-params[:search][:per_page] = params[:search][:per_page] || 5000 -params[:search][:per_page] = params[:search][:per_page] || 5000
-per_page = params[:search][:per_page] -per_page = params[:search][:per_page]
-page = (params[:page] and params[:page] != "") ? params[:page] : 1 -page = (params[:page] and params[:page] != "") ? params[:page] : 1
-@price_documents = PriceDocument.where(:doc_ref_id => @price_document.id ) -@price_documents = PriceDocument.where(:doc_ref_id => @price_document.id, :price_document_type_id => PriceDocumentType.find_by_label("Réponse fournisseur").id)
@ -342,3 +376,103 @@
.clear .clear
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @price_documents, :key => "reponses-prix-show"} =render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @price_documents, :key => "reponses-prix-show"}
-@price_documents = PriceDocument.where(:doc_ref_id => @price_document.id, :price_document_type_id => PriceDocumentType.find_by_label("Consultation fournisseur").id)
%h3.ml-2 Consultations fournisseur :
#consult
-if @price_documents.empty?
.qi_pannel.qi_plain.padding
Pas de consultation générée.
%br
Vous devez d'abord Selectionner les prix sur le page d'analyse :
=link_to ic("bar-chart")+" analyse des réponses", analyse_reponses_admin_price_document_path(@price_document), class: "btn btn-primary"
puis Generer les consultations
-@price_documents.each do |price_document_consult|
- if price_document_consult.p_fournisseur
%h4.ml-2= price_document_consult.p_fournisseur.name
- else
%h4.ml-2=link_to ic('pencil') + " rapprocher le fournisseur", match_p_fournisseur_admin_price_document_path(price_document_consult), remote: true
= semantic_form_for [:admin, price_document_consult], :html => {:class => "qi_price_form"}, :remote => false do |form|
= form.button "Valider modifications", type: :submit, class: "btn btn-primary m-2"
= link_to ic(:clipboard) + " Copier le texte", "#", class: "btn btn-primary", "data-document" => price_document_consult.id, onclick: 'copyPriceLines(event)'
- existing_order = PriceDocument.where(doc_ref_id: price_document_consult.id, cc_label: "Commande achat")
- if existing_order.present?
= link_to ic(:eye) + " Afficher la commande", admin_price_document_path(existing_order.first), class: "btn btn-tertiary"
- else
= link_to "Generer la commande", buy_order_create_admin_price_document_path(price_document_consult), class: "btn btn-primary"
.price-lines{"data-document" => price_document_consult.id}
=form.semantic_fields_for :price_line_block do |f|
.mx-2
=f.semantic_fields_for :price_lines do |form|
=render partial: "admin/price_lines/form_consult", locals: {form: form}
-params[:search][:per_page] = params[:search][:per_page] || 5000
-per_page = params[:search][:per_page]
-page = (params[:page] and params[:page] != "") ? params[:page] : 1
-@price_documents = PriceDocument.where(:doc_ref_id => @price_document.id, :price_document_type_id => PriceDocumentType.find_by_label("Consultation fournisseur").id)
-@price_documents = sort_by_sorting(@price_documents, "created_at DESC")
-@price_documents = @price_documents.page(page).per(per_page)
%br
%h4.ml-2 Liste des consultations fournisseurs
.clear
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @price_documents, :key => "reponses-prix-show"}
:javascript
const copyPriceLines = (event) => {
event.preventDefault()
let priceDocumentId = event.target.dataset.document
let names = $(`.p_product_ref_cc_name_${priceDocumentId}`)
let qtes_input = $(`.input_price_line_qte_${priceDocumentId}`)
let qtes = $(`.price_line_qte_${priceDocumentId}`)
let prices = $(`.price_line_price_u_ht_${priceDocumentId}`)
let table = []
names.each(function( i ) {
let row = []
if(qtes_input.length > 0) {
row.push(qtes_input[i].valueAsNumber)
}else{
row.push(qtes[i].innerText.slice(0, -2))
}
row.push(" X ")
row.push(names[i].innerText)
row.push(" @ ")
row.push(prices[i].innerText)
table.push(row.join(' '))
})
copyStringToClipboard(table.join('\r\n'))
}
function copyStringToClipboard (str) {
// Create new element
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = str;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
// Select text inside element
el.select();
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
}

View File

@ -1,21 +1,21 @@
.qi_row =f.inputs do
=f.inputs do :javascript
var p_product_refs_url = "#{admin_p_product_refs_path(:manager => true)}"
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande") = f.hidden_field :p_customer_id, :class => "p_customer_id"
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"} =content_for :particular do
.row
= f.hidden_field :p_customer_id, :class => "p_customer_id" .p_customer_sheet_customer.col-12.mb-4
.p_customer_sheet_customer
-if f.object.p_customer and f.object.p_customer.particular -if f.object.p_customer and f.object.p_customer.particular
=render :partial => "admin/p_customers/apercu", :locals => {:particular => f.object.p_customer.particular} =render :partial => "admin/p_customers/apercu", :locals => {:particular => f.object.p_customer.particular}
.padding{:style => "padding:0 10px;"} .col-6
.addresses.row .addresses.row
.columns.span_6 .columns.span_6
%h3 Adresse de facturation %h4 Adresse de facturation
-if f.object.p_customer -if f.object.p_customer
=f.inputs do =f.inputs do
@ -23,9 +23,10 @@
-else -else
=f.inputs do =f.inputs do
= f.input :particular_bill_id, :collection => [], :as => :select, :include_blank => false, :label => "Adresse de facturation" = f.input :particular_bill_id, :collection => [], :as => :select, :include_blank => false, :label => "Adresse de facturation"
.col-6
.addresses.row
.columns.span_6 .columns.span_6
%h3 Adresse de livraison %h4 Adresse de livraison
-if f.object.p_customer -if f.object.p_customer
=f.inputs do =f.inputs do
@ -36,68 +37,72 @@
.clear .clear
=content_for :shipping_date do
%table{:style => "width:100%;"} = f.input :wish_date, :label => "Date de livraison souhaitée :", :as => :date
%tr = f.input :ct_creation_date, :label => "Date de commande (si différente de la date de création) :", :as => :date
%td{:style => "width:33%;"} = f.input :validation_date, :label => "Date de validation :", :as => :date
= f.input :wish_date, :label => "Date de livraison souhaitée :", :as => :date
%td{:style => "width:33%;"}
= f.input :ct_creation_date, :label => "Date de commande (si différente de la date de création) :", :as => :date
%td{:style => "width:33%;"}
= f.input :validation_date, :label => "Date de validation :", :as => :date
= f.input :customer_ref, :label => "Référence commande client :" = f.input :customer_ref, :label => "Référence commande client :"
-if current_admin.has_permission?("customer-sheets-bl") -if current_admin.has_permission?("customer-sheets-bl")
=# f.input :bl_comment, :label => "Commentaire à mettre sur le BL :", :input_html => {:style => "min-height:50px;height:50px;"} =# f.input :bl_comment, :label => "Commentaire à mettre sur le BL :", :input_html => {:style => "min-height:50px;height:50px;"}
-if @p_customer_sheet and @p_customer_sheet.p_customer and @p_customer_sheet.p_customer.p_customer_sheet_note? -if @p_customer_sheet and @p_customer_sheet.p_customer and @p_customer_sheet.p_customer.p_customer_sheet_note?
%div %div
%strong Notes pour les demandes de commandes pour ce client : %strong Notes pour les demandes de commandes pour ce client :
=simple_format @p_customer_sheet.p_customer.p_customer_sheet_note =simple_format @p_customer_sheet.p_customer.p_customer_sheet_note
%br %br
=content_for :price_lines do
%div{:style=>"padding:0 30px;"}
.row.qi_field_wrapper
%table{:style => "width:100%;border-collapse:separate;"}
%thead
%tr
%th
%th Produit
%th{:style => "width:200px;"} Prix
%th
%th{:style => "width:100px;"} Qté
%th TVA
%th
%tbody.price_lines_form
=f.semantic_fields_for :price_lines do |f|
=render :partial => "admin/price_lines/form", :locals => {:form => f}
.price_lines_form %p{:style=>"padding-top:10px;"}= link_to_add_fields ic("plus-circle") + " ligne", f, :price_lines, {:class => "btn btn-primary p-2", tabindex: 10, style: "position: sticky; top: 100px"}
=f.semantic_fields_for :price_lines do |f|
=render :partial => "admin/price_lines/form", :locals => {:form => f}
%p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {:class => "btn btn-primary"}
-if current_admin.has_permission?("payments") -if current_admin.has_permission?("payments")
.qi_pannel.qi_plain.padding.price_line_block_footer{:style => "margin:20px 0;"} =content_for :discount do
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
-if !@avoir
= f.input :ct_tot_discount_percent, :label => "Réduction pied de page (%) :", :input_html => {:class => "input_price_line_block_ct_tot_discount_percent"}
= f.input :ct_tot_fdp_ht, :label => "Frais de port personnalisés :"
-if current_admin.has_permission?("payments")
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande") -if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
- if f.object.id -if !@avoir
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"} = f.input :ct_tot_discount_percent, :label => "Réduction pied de page (%) :", :input_html => {:class => "input_price_line_block_ct_tot_discount_percent"}
%h4 Paiements = f.input :ct_tot_fdp_ht, :label => "Frais de port personnalisés :"
= f.input :p_payment_type_id, :label => "Type de paiement :", :include_blank => false, :collection => PPaymentType.order(:name).all, :as => :select, :input_html => {:id => "payment_type_id_select"}
= f.input :ct_payment_comptant, :label => "Paiement comptant nécessaire ?" -if current_admin.has_permission?("payments")
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
- if f.object.id
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"}
%h4 Paiements
-if false = f.input :p_payment_type_id, :label => "Type de paiement :", :include_blank => false, :collection => PPaymentType.order(:name).all, :as => :select, :input_html => {:id => "payment_type_id_select"}
= f.input :ct_acompte, :label => "Acompte nécessaire ?"
= f.input :ct_acompte_percent, :label => "Pourcentage d'acompte :"
= f.input :ct_payment_delais, :label => "Délais jour de paiement :"
-if false = f.input :ct_payment_comptant, :label => "Paiement comptant nécessaire ?"
= f.input :ct_payment_month_end, :label => "Fin de mois ?"
-if false
= f.input :ct_acompte, :label => "Acompte nécessaire ?"
= f.input :ct_acompte_percent, :label => "Pourcentage d'acompte :"
= f.input :ct_payment_delais, :label => "Délais jour de paiement :"
-if false
= f.input :ct_payment_month_end, :label => "Fin de mois ?"

View File

@ -0,0 +1,11 @@
=f.inputs do
.price_lines_form
=f.semantic_fields_for :price_lines do |f|
=render :partial => "admin/price_lines/form_#{f.object.block_type_slug}", :locals => {:form => f}
%p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {slug: f.object.block_type_slug , :class => "btn btn-primary", tabindex: 2}

View File

@ -4,18 +4,54 @@
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande") -if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"} .qi_pannel.qi_plain.padding{:style => "margin:20px 0;"}
= f.input :p_commercial_id, :label => "Commercial :", :collection => PCommercial.order(:name).all, :as => :select, :member_label => :long_name if f.object.id
= f.hidden_field :p_customer_id, :class => "p_customer_id"
.p_customer_sheet_customer
-if f.object.p_customer and f.object.p_customer.particular
=render :partial => "admin/p_customers/apercu", :locals => {:particular => f.object.p_customer.particular}
.addresses.row
.columns.span_6
%h3 Adresse de facturation
-if f.object.p_customer
=f.inputs do
= f.input :particular_bill_id, :collection => f.object.p_customer.particulars.all, :as => :select, :member_label => :address_line, :include_blank => false, :label => "Adresse de facturation"
-else
=f.inputs do
= f.input :particular_bill_id, :collection => [], :as => :select, :include_blank => false, :label => "Adresse de facturation"
.columns.span_6
%h3 Adresse de livraison
-if f.object.p_customer
=f.inputs do
= f.input :particular_send_id, :collection => f.object.p_customer.particulars.all, :as => :select, :member_label => :address_line, :include_blank => false, :label => "Adresse de livraison"
-else
=f.inputs do
= f.input :particular_send_id, :collection => [], :as => :select, :include_blank => false, :label => "Adresse de facturation"
.clear
%table{:style => "width:100%;"}
%tr
%td{:style => "width:50%;"}
= f.input :wish_date, :label => "Date de livraison souhaitée :", :as => :date
%td{:style => "width:50%;"}
= f.input :ct_creation_date, :label => "Date de commande (si différente de la date de création) :", :as => :date
= f.input :customer_ref, :label => "Référence commande client :"
= f.input :p_fournisseur, :label => "Fournisseur :", :collection => PFournisseur.order(:name).all, :as => :select
= f.input :customer_ref, :label => "Numéro de facture fournisseur :"
-if current_admin.has_permission?("customer-sheets-bl") -if current_admin.has_permission?("customer-sheets-bl")
=# f.input :bl_comment, :label => "Commentaire à mettre sur le BL :", :input_html => {:style => "min-height:50px;height:50px;"} = f.input :bl_comment, :label => "Commentaire à mettre sur le BL :", :input_html => {:style => "min-height:50px;height:50px;"}
-if @p_customer_sheet and @p_customer_sheet.p_customer and @p_customer_sheet.p_customer.p_customer_sheet_note? -if @p_customer_sheet and @p_customer_sheet.p_customer and @p_customer_sheet.p_customer.p_customer_sheet_note?
%div %div
@ -25,16 +61,45 @@
= f.input :p_devise_id, :label => "Devise :", :collection => PDevise.order(:id).all, :as => :select, :include_blank => false
= f.input :local_amount_ttc, :label => "Montant TTC en € réglé pour cette facture :"
.price_lines_form .price_lines_form
=f.semantic_fields_for :price_lines do |f| =f.semantic_fields_for :price_lines do |f|
=render :partial => "admin/price_lines/form_facture_dachat", :locals => {:form => f} =render :partial => "admin/price_lines/form_bon_de_reception_achat", :locals => {:form => f}
%p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {:class => "btn btn-primary", :partial => "admin/price_lines/form_facture_dachat"} %p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {:class => "btn btn-primary"}
-if current_admin.has_permission?("payments")
.qi_pannel.qi_plain.padding.price_line_block_footer{:style => "margin:20px 0;"}
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
-if !@avoir
= f.input :ct_tot_discount_percent, :label => "Réduction pied de page (%) :", :input_html => {:class => "input_price_line_block_ct_tot_discount_percent"}
= f.input :ct_tot_fdp_ht, :label => "Frais de port personnalisés :"
-if !@avoir
-if current_admin.has_permission?("customer-sheets-bl")
= f.input :ct_nbr_ship, :label => "Nombre de colis :"
-if current_admin.has_permission?("payments")
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
- if f.object.id
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"}
%h4 Paiements
= f.input :p_payment_type_id, :label => "Type de paiement :", :include_blank => false, :collection => PPaymentType.order(:name).all, :as => :select, :input_html => {:id => "payment_type_id_select"}
= f.input :ct_payment_comptant, :label => "Paiement comptant nécessaire ?"
-if false
= f.input :ct_acompte, :label => "Acompte nécessaire ?"
= f.input :ct_acompte_percent, :label => "Pourcentage d'acompte :"
= f.input :ct_payment_delais, :label => "Délais jour de paiement :"
-if false
= f.input :ct_payment_month_end, :label => "Fin de mois ?"

View File

@ -21,7 +21,7 @@
=f.semantic_fields_for :price_lines do |f| =f.semantic_fields_for :price_lines do |f|
=render :partial => "admin/price_lines/form_#{f.object.block_type_slug}", :locals => {:form => f} =render :partial => "admin/price_lines/form_#{f.object.block_type_slug}", :locals => {:form => f}
%p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {:class => "btn btn-primary"} %p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {slug: f.object.block_type_slug , :class => "btn btn-primary", tabindex: 2}

View File

@ -0,0 +1,106 @@
=f.inputs do
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"}
= f.input :p_commercial_id, :label => "Commercial :", :collection => PCommercial.order(:name).all, :as => :select, :member_label => :long_name if f.object.id
= f.hidden_field :p_customer_id, :class => "p_customer_id"
.p_customer_sheet_customer
-if f.object.p_customer and f.object.p_customer.particular
=render :partial => "admin/p_customers/apercu", :locals => {:particular => f.object.p_customer.particular}
.addresses.row
.columns.span_6
%h3 Adresse de facturation
-if f.object.p_customer
=f.inputs do
= f.input :particular_bill_id, :collection => f.object.p_customer.particulars.all, :as => :select, :member_label => :address_line, :include_blank => false, :label => "Adresse de facturation"
-else
=f.inputs do
= f.input :particular_bill_id, :collection => [], :as => :select, :include_blank => false, :label => "Adresse de facturation"
.columns.span_6
%h3 Adresse de livraison
-if f.object.p_customer
=f.inputs do
= f.input :particular_send_id, :collection => f.object.p_customer.particulars.all, :as => :select, :member_label => :address_line, :include_blank => false, :label => "Adresse de livraison"
-else
=f.inputs do
= f.input :particular_send_id, :collection => [], :as => :select, :include_blank => false, :label => "Adresse de facturation"
.clear
%table{:style => "width:100%;"}
%tr
%td{:style => "width:50%;"}
= f.input :wish_date, :label => "Date de livraison souhaitée :", :as => :date
%td{:style => "width:50%;"}
= f.input :ct_creation_date, :label => "Date de commande (si différente de la date de création) :", :as => :date
= f.input :customer_ref, :label => "Référence commande client :"
-if current_admin.has_permission?("customer-sheets-bl")
= f.input :bl_comment, :label => "Commentaire à mettre sur le BL :", :input_html => {:style => "min-height:50px;height:50px;"}
-if @p_customer_sheet and @p_customer_sheet.p_customer and @p_customer_sheet.p_customer.p_customer_sheet_note?
%div
%strong Notes pour les demandes de commandes pour ce client :
=simple_format @p_customer_sheet.p_customer.p_customer_sheet_note
%br
.price_lines_form
=f.semantic_fields_for :price_lines do |f|
=render :partial => "admin/price_lines/form_bon_de_reception_achat", :locals => {:form => f}
%p= link_to_add_fields "Ajouter une ligne", f, :price_lines, {:class => "btn btn-primary"}
-if current_admin.has_permission?("payments")
.qi_pannel.qi_plain.padding.price_line_block_footer{:style => "margin:20px 0;"}
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
-if !@avoir
= f.input :ct_tot_discount_percent, :label => "Réduction pied de page (%) :", :input_html => {:class => "input_price_line_block_ct_tot_discount_percent"}
= f.input :ct_tot_fdp_ht, :label => "Frais de port personnalisés :"
-if !@avoir
-if current_admin.has_permission?("customer-sheets-bl")
= f.input :ct_nbr_ship, :label => "Nombre de colis :"
-if current_admin.has_permission?("payments")
-if !@p_customer_sheet or (@p_customer_sheet and @p_customer_sheet.state != "commande")
- if f.object.id
.qi_pannel.qi_plain.padding{:style => "margin:20px 0;"}
%h4 Paiements
= f.input :p_payment_type_id, :label => "Type de paiement :", :include_blank => false, :collection => PPaymentType.order(:name).all, :as => :select, :input_html => {:id => "payment_type_id_select"}
= f.input :ct_payment_comptant, :label => "Paiement comptant nécessaire ?"
-if false
= f.input :ct_acompte, :label => "Acompte nécessaire ?"
= f.input :ct_acompte_percent, :label => "Pourcentage d'acompte :"
= f.input :ct_payment_delais, :label => "Délais jour de paiement :"
-if false
= f.input :ct_payment_month_end, :label => "Fin de mois ?"

View File

@ -0,0 +1,13 @@
=semantic_form_for [:admin, @price_line_resp_select], :remote => true do |f|
.content
=f.inputs do
= f.input :price_line_demand_id, :label => f.object.label_for(:price_line_demand_id)
= f.input :price_line_resp_id, :label => f.object.label_for(:price_line_resp_id)
.actions=f.submit "sauvegarder", :class => "btn btn-primary"

View File

@ -0,0 +1,16 @@
%tr#price_line_resp_select_row{:id => price_line_resp_select.id}
-tr = {}
-tr[:actions] = capture do
%td.actions
= link_to i(:"trash-o"), [:admin, price_line_resp_select], method: :delete, data: { confirm: 'Voulez-vous vraiment supprimer cet enregistrement ? ' } , :remote => true
= link_to i(:pencil), edit_admin_price_line_resp_select_path(price_line_resp_select), :remote => true
= link_to i(:eye), admin_price_line_resp_select_path(price_line_resp_select), :remote => true
=render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => price_line_resp_select}

View File

@ -0,0 +1,2 @@
$('#price_line_resp_selects_rows').prepend("<%= escape_javascript(render(@price_line_resp_select))%>");
close_pane_hover();

View File

@ -0,0 +1 @@
$('#price_line_resp_select_row_<%= @price_line_resp_select.id %>').remove();

View File

@ -0,0 +1 @@
show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900);

View File

@ -0,0 +1,16 @@
.qi_header
.right= link_to ic(:plus)+' Ajouter', new_admin_price_line_resp_select_path(), :class => "btn btn-primary btn-ap-add", :remote => true
%h1
=PriceLineRespSelect.human rescue ""
.qi_search_row
=form_tag "", :method => "get", :onsubmit => "" do
=render :partial => "qi/qi_ordered_table_search_footer", :locals => {:collection_object => @price_line_resp_selects}
=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @price_line_resp_selects}

View File

@ -0,0 +1 @@
show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900);

View File

@ -0,0 +1,10 @@
.qi_header
%h1
%span
.qi_row
.qi_pannel.qi_plain.padding
=debug @price_line_resp_select

View File

@ -0,0 +1,2 @@
$('#price_line_resp_select_row_<%= @price_line_resp_select.id %>').replaceWith("<%= escape_javascript(render(@price_line_resp_select))%>");
close_pane_hover();

View File

@ -1,133 +1,121 @@
%tr.qi_pannel.qi_plain.padding.price_line_form.col-12.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"}
.qi_pannel.qi_plain.padding.price_line_form.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"}
%table{:style => "width:100%;"}
%tr
%td{:style => "width:30px;"}
.take
=ic :arrows
%td
= form.input :ct_title, :label => "Designation personnalisée : " if @avoir
%div{:class => ("error has-error" if form.object.errors[:p_product_ref_id].size > 0 )}
%label Produit :
%input.p_product_ref_autocomplete_input.form-control{:type => "text", :value => ("#{form.object.p_product_ref.ref} #{form.object.p_product_ref.cc_name}" if form.object.p_product_ref)}
= form.hidden_field :p_product_ref_id, :class => "p_product_ref_id" %td{:style => "padding-left:10px;", :class => ("error has-error" if form.object.errors[:p_product_ref_id].size > 0 )}
.take.mr-1
:javascript =ic :arrows
$( function() { %td{:style => "white-space: nowrap;"}
$('.p_product_ref_autocomplete_input').autocomplete({
source: function( request, response ) {
$.ajax( {
url: "/admin/p_product_refs/autocomplete.json",
dataType: "json",
data: {
search: request.term,
p_customer_id: $(".p_customer_id").val()
},
success: function(data){
arr = jQuery.map( data, function( item ) {
return {
label: item.member_label,
value: item.member_label,
id: item.id
}
});
response(arr)
}
} );
},
minLength: 2,
select: function( event, ui ) {
$(this).next(".p_product_ref_id").val(ui.item.id)
form = $(this).closest(".price_line_form")
$.ajax( { .input-group
url: "/admin/p_product_refs/"+ui.item.id+"/get_infos.json", %input.p_product_ref_autocomplete_input.form-control{:type => "text", :style => "", tabindex: 1, autofocus: true, :value => ("#{form.object.p_product_ref.member_label}" if form.object.p_product_ref), :class => "p_product_ref_name"}
dataType: "json", = form.hidden_field :p_product_ref_id, :class => "p_product_ref_id"
data: {
type: "price",
qte: form.find(".input_price_line_qte").val(),
p_customer_id: $(".p_customer_id").val()
},
success: function (data) {
form.find(".input_price_line_price_u_ht").val(data.price);
form.find(".input_price_line_tva_account_id").val(data.tva_account_id);
form.find(".input_price_line_tva_account_value").val(data.tva_account_value);
form.find(".input_price_line_weight_u").val(data.weight);
}
} );
//return false .input-group-append
} =link_to "#", class: "btn btn-dark",:onclick => "key=genRanHex(12);select_product_from_manager(key);$(this).closest('tr').find('.p_product_ref_id').attr('id', 'p_product_ref_id_'+key);$(this).closest('tr').find('.p_product_ref_name').attr('id', 'p_product_ref_name_'+key);$(this).closest('tr').find('.p_product_ref_qte').attr('id', 'p_product_ref_qte_'+key);return false;" do
}); =ic(:search)
} );
%table.top_td{:style => "width:100%;margin-top:5px;"}
%tr
%td{:style => "width:30px"}
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
%td
-form.object.forced_price = true if form.object.ct_u_price_ht
-if form.object.forced_price and form.object.p_product_ref
=qi_js_field(form, :price_line, :price_u_ht, :label => "Prix U HT :", :value => form.object.th_price_u_ht)
-else
=qi_js_field(form, :price_line, :price_u_ht, :label => "Prix U HT :")
%div{:style => ("display:none;" if !current_admin or !current_admin.has_permission?("customer-sheets-personalised-price"))}
= form.input :forced_price, :label => "Prix personnalisé ?", :as => :boolean, :input_html => {:class => "input_price_line_forced_price"}
.forced_price_wrapper{:style => ("display:none;" if !form.object.forced_price)}= form.input :ct_u_price_ht, :label => false, :input_html => {:class => "input_price_line_ct_u_price_ht"}
%td
= form.input :qte, :label => "qte :", :input_html => {:class => "input_price_line_qte"}
%td
=#qi_js_field(form, :price_line, :tva_account_id, :label => "Compte TVA :")
-if @avoir
-if !form.object.ct_tva_account_id
-form.object.ct_tva_account_id = form.object.tva_account_id
= form.input :ct_tva_account_id, :collection => TvaRate.where(:accounting_zone_id => (@p_customer ? @p_customer.accounting_zone_id : nil)).all, :as => :select, :member_label => :member_label, :include_blank => false, :label => "TVA personnalisée", :input_html => { :class => "input_price_line_tva_account_id"}
-else
%label Taux de TVA :
%br
=select_tag :tva_account_id, options_from_collection_for_select(TvaRate.where(:accounting_zone_id => (@p_customer ? @p_customer.accounting_zone_id : nil)).all, "id", "member_label", form.object.tva_account_id), :class => "input_price_line_tva_account_id" #, :disabled => true
=qi_js_field(form, :price_line, :tva_account_value, :hidden => true)
= form.input :comment, :label => "Commentaire"
= form.hidden_field :position, :class => "price_line_position_input"
-form.object.forced_price = true if form.object.ct_u_price_ht
-if form.object.forced_price and form.object.p_product_ref
%td
.mx-2
.form-inline
=qi_js_field_price_line_form(form, :price_line, :price_u_ht, :label => false, label_class: "mr-1", :value => form.object.th_price_u_ht)
-else
%td
.mx-2
.form-inline
=qi_js_field_price_line_form(form, :price_line, :price_u_ht, :label =>false, label_class: "mr-1")
%td
.form-inline.mr-2{:style => ("display:none;" if !current_admin or !current_admin.has_permission?("customer-sheets-personalised-price"))}
= form.input :forced_price, :label => "Prix personnalisé ?", :as => :boolean, :input_html => {:class => "form-inline input_price_line_forced_price"}
.forced_price_wrapper.mx-2{:style => ("display:none;" if !form.object.forced_price)}= form.input :ct_u_price_ht, :label => false, :input_html => {:class => "input_price_line_ct_u_price_ht"}
%td{:style => "width:100px;"}
= form.input :qte, :label => false, :input_html => {:class => "input_price_line_qte form-control p_product_ref_qte", tabindex: 1}
%td
=form.input :ct_tva_account_id, :collection => options_from_collection_for_select(TvaRate.where(:accounting_zone_id => (@p_customer ? @p_customer.accounting_zone_id : nil)).all, "id", "member_label", form.object.tva_account_id), :as => :select ,:label => false, :include_blank => false , :input_html => {:class => "input_price_line_tva_account_id form-control custom-select"}
%td
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
=qi_js_field(form, :price_line, :tva_account_value, :hidden => true)
= form.hidden_field :position, :class => "price_line_position_input"
:javascript
$('.p_product_ref_autocomplete_input').focus()
$( function() {
$('.p_product_ref_autocomplete_input').autocomplete({
source: function( request, response ) {
$.ajax( {
url: "/admin/p_product_refs/autocomplete.json",
dataType: "json",
data: {
search: request.term,
p_customer_id: $(".p_customer_id").val()
},
success: function(data){
arr = jQuery.map( data, function( item ) {
return {
label: item.member_label,
value: item.member_label,
id: item.id
}
});
response(arr)
}
});
},
minLength: 2,
select: function( event, ui ) {
$(this).next(".p_product_ref_id").val(ui.item.id)
form = $(this).closest(".price_line_form")
$.ajax( {
url: "/admin/p_product_refs/"+ui.item.id+"/get_infos.json",
dataType: "json",
data: {
type: "price",
qte: form.find(".input_price_line_qte").val(),
p_customer_id: $(".p_customer_id").val()
},
success: function (data) {
form.find(".input_price_line_price_u_ht").val(data.price);
form.find(".input_price_line_tva_account_id").val(data.tva_account_id);
form.find(".input_price_line_tva_account_value").val(data.tva_account_value);
form.find(".input_price_line_weight_u").val(data.weight);
}
});
//return false
}
});
});
:scss
.price_line_form{
.form-group{
margin-bottom:0;}
}

View File

@ -0,0 +1,27 @@
.qi_pannel.qi_plain.padding.price_line_form.col-12.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"}
- price_line = form.object
.row
.col-6.row
.col-2.d-flex
.take.mx-3
=ic :arrows
%label
ref :
%input.p_product_ref_autocomplete_input.form-control.col{:type => "text", :value => ("#{form.object.p_product_ref.ref} #{form.object.p_product_ref.cc_name}" if form.object.p_product_ref)}
.col-3.ml-2
.form-inline
= form.input :qte, :label => "qte :", :input_html => { class: "mx-2", autofocus: true, tabindex: 1}
.col-2
.form-inline
= form.input :ct_u_price_ht, :label => "PU :", :input_html => { class: "mx-2"}
.col-1.ml-2
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
= form.hidden_field :p_product_ref_id, :class => "p_product_ref_id"
=qi_js_field(form, :price_line, :tva_account_value, :hidden => true)
= form.hidden_field :position, :class => "price_line_position_input"

View File

@ -0,0 +1,30 @@
- price_line = form.object
.qi_pannel.qi_plain.padding.price_line_form.col-12.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"}
.row
.col-6.d-flex
.take.mr-4
=ic :arrows
.mr-1
ref :
%div{class: "p_product_ref_cc_name_#{price_line.price_line_block.price_lineable_id}"}
=price_line.p_product_ref.cc_name
.col-3.d-flex
Base de prix U HT :
%div{class: "mx-1 price_line_price_u_ht_#{price_line.price_line_block.price_lineable_id}"}
= price_line.price_u_ht
.col-3
.form-inline
= form.input :qte, :label => "qte :", :input_html => {:class => "input_price_line_qte_#{price_line.price_line_block.price_lineable_id} form-control mx-2", tabindex: 1}
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
= form.hidden_field :p_product_ref_id, :class => "p_product_ref_id"
=qi_js_field(form, :price_line, :tva_account_value, :hidden => true)
= form.hidden_field :position, :class => "price_line_position_input"

View File

@ -1,98 +1,24 @@
.qi_pannel.qi_plain.padding.price_line_form.col-12.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"}
.qi_pannel.qi_plain.padding.price_line_form.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"} - price_line = form.object
%table{:style => "width:100%;"} .row
%tr .col-6.row
%td{:style => "width:30px;"} .col-2.d-flex
.take .take.mx-3
=ic :arrows =ic :arrows
%td %label
ref :
%input.p_product_ref_autocomplete_input.form-control.col{:type => "text", tabindex: 1, autofocus: true, :value => ("#{form.object.p_product_ref.ref} #{form.object.p_product_ref.cc_name}" if form.object.p_product_ref)}
= form.input :ct_title, :label => "Designation personnalisée : " if @avoir .col-3.ml-4
%div{:class => ("error has-error" if form.object.errors[:p_product_ref_id].size > 0 )} .form-inline
%label Produit : = form.input :qte, :label => "qte :", :input_html => { class: "mx-2", tabindex: 1}
%input.p_product_ref_autocomplete_input.form-control{:disabled => true, :type => "text", :value => ("#{form.object.p_product_ref.member_label}" if form.object.p_product_ref)} .col-1
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
= form.hidden_field :p_product_ref_id, :class => "p_product_ref_id"
= form.hidden_field :p_product_ref_id, :class => "p_product_ref_id"
:javascript
$( function() {
$('.p_product_ref_autocomplete_input').autocomplete({
source: function( request, response ) {
$.ajax( {
url: "/admin/p_product_refs/autocomplete.json",
dataType: "json",
data: {
search: request.term,
},
success: function(data){
arr = jQuery.map( data, function( item ) {
return {
label: item.member_label,
value: item.member_label,
id: item.id
}
});
response(arr)
}
} );
},
minLength: 2,
select: function( event, ui ) {
$(this).next(".p_product_ref_id").val(ui.item.id)
form = $(this).closest(".price_line_form")
$.ajax( { =qi_js_field(form, :price_line, :tva_account_value, :hidden => true)
url: "/admin/p_product_refs/"+ui.item.id+"/get_infos.json",
dataType: "json",
data: {
type: "price",
qte: form.find(".input_price_line_qte").val(),
p_customer_id: $(".p_customer_id").val()
},
success: function (data) {
form.find(".input_price_line_price_u_ht").val(data.price);
form.find(".input_price_line_tva_account_id").val(data.tva_account_id);
form.find(".input_price_line_tva_account_value").val(data.tva_account_value);
form.find(".input_price_line_weight_u").val(data.weight);
= form.hidden_field :position, :class => "price_line_position_input"
}
} );
//return false
}
});
} );
%table.top_td{:style => "width:100%;margin-top:5px;"}
%tr
%td{:style => "width:30px"}
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
%td
= form.input :qte, :label => "qte :", :input_html => {:class => "input_price_line_qte"}
= form.hidden_field :position, :class => "price_line_position_input"

View File

@ -0,0 +1,98 @@
.qi_pannel.qi_plain.padding.price_line_form.field{:style =>"border-left:4px solid gray;margin-bottom:10px;padding-left:5px;"}
%table{:style => "width:100%;"}
%tr
%td{:style => "width:30px;"}
.take
=ic :arrows
%td
= form.input :ct_title, :label => "Designation personnalisée : " if @avoir
%div{:class => ("error has-error" if form.object.errors[:p_product_ref_id].size > 0 )}
%label Produit :
%input.p_product_ref_autocomplete_input.form-control{:disabled => true, :type => "text", :value => ("#{form.object.p_product_ref.member_label}" if form.object.p_product_ref)}
= form.hidden_field :p_product_ref_id, :class => "p_product_ref_id"
:javascript
$( function() {
$('.p_product_ref_autocomplete_input').autocomplete({
source: function( request, response ) {
$.ajax( {
url: "/admin/p_product_refs/autocomplete.json",
dataType: "json",
data: {
search: request.term,
},
success: function(data){
arr = jQuery.map( data, function( item ) {
return {
label: item.member_label,
value: item.member_label,
id: item.id
}
});
response(arr)
}
} );
},
minLength: 2,
select: function( event, ui ) {
$(this).next(".p_product_ref_id").val(ui.item.id)
form = $(this).closest(".price_line_form")
$.ajax( {
url: "/admin/p_product_refs/"+ui.item.id+"/get_infos.json",
dataType: "json",
data: {
type: "price",
qte: form.find(".input_price_line_qte").val(),
p_customer_id: $(".p_customer_id").val()
},
success: function (data) {
form.find(".input_price_line_price_u_ht").val(data.price);
form.find(".input_price_line_tva_account_id").val(data.tva_account_id);
form.find(".input_price_line_tva_account_value").val(data.tva_account_value);
form.find(".input_price_line_weight_u").val(data.weight);
}
} );
//return false
}
});
} );
%table.top_td{:style => "width:100%;margin-top:5px;"}
%tr
%td{:style => "width:30px"}
%span.destroy=link_to_remove_fields ic(:"trash-o"), form
%td
= form.input :qte, :label => "qte :", :input_html => {:class => "input_price_line_qte"}
= form.hidden_field :position, :class => "price_line_position_input"

Some files were not shown because too many files have changed in this diff Show More