diff --git a/Gemfile b/Gemfile index 92d980f..bab2ceb 100644 --- a/Gemfile +++ b/Gemfile @@ -106,7 +106,7 @@ group :development do gem 'capistrano-bundler', '~> 1.1', require: false gem "capistrano-rvm", group: :development gem 'capistrano3-nginx', '~> 2.0', group: :development - + gem "awesome_print" end gem 'zip-zip' @@ -117,3 +117,4 @@ gem 'axlsx', '3.0.0.pre' gem 'axlsx_rails' gem 'mimemagic', "0.3.10" +gem "roo" diff --git a/Gemfile.lock b/Gemfile.lock index 207dffb..93c6cac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -63,6 +63,7 @@ GEM public_suffix (>= 2.0.2, < 5.0) airbrussh (1.3.3) sshkit (>= 1.6.1, != 1.7.0) + awesome_print (1.9.2) axlsx (3.0.0.pre) htmlentities (~> 4.3, >= 4.3.4) mimemagic (~> 0.3) @@ -276,6 +277,9 @@ GEM ffi (~> 1.0) regexp_parser (1.6.0) rmagick (4.2.2) + roo (2.8.2) + nokogiri (~> 1) + rubyzip (>= 1.2.1, < 2.0.0) ruby-vips (2.0.14) ffi (~> 1.9) ruby_dep (1.5.0) @@ -363,6 +367,7 @@ PLATFORMS DEPENDENCIES acts_as_commentable acts_as_tree + awesome_print axlsx (= 3.0.0.pre) axlsx_rails bcrypt (~> 3.1.7) @@ -398,6 +403,7 @@ DEPENDENCIES rails (= 6.0.3.4) rails_autolink rmagick + roo sass-rails (~> 5) searchkick selenium-webdriver diff --git a/app/assets/javascripts/admin.coffee b/app/assets/javascripts/admin.coffee index 7a571ec..ea98f59 100644 --- a/app/assets/javascripts/admin.coffee +++ b/app/assets/javascripts/admin.coffee @@ -56,6 +56,7 @@ #= require freeze-table +#= require admin/random_hexa @@ -856,6 +857,4 @@ $(document).on 'click', '.datepicker', (e) -> $(this).next('.' + autocomplete_object + '_id').val ui.item.id return return - - - + \ No newline at end of file diff --git a/app/assets/javascripts/admin/random_hexa.js b/app/assets/javascripts/admin/random_hexa.js new file mode 100644 index 0000000..910cebf --- /dev/null +++ b/app/assets/javascripts/admin/random_hexa.js @@ -0,0 +1,2 @@ +const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join(''); + \ No newline at end of file diff --git a/app/assets/javascripts/manager.js b/app/assets/javascripts/manager.js index 10623e4..49a11fb 100644 --- a/app/assets/javascripts/manager.js +++ b/app/assets/javascripts/manager.js @@ -42,7 +42,7 @@ function manager_show(url){ function manager_hide(){ $("#manager_box_place").removeClass("manager_box_place_active"); - + $('#manager_box').html(""); $("body").css("overflow", "auto"); 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}); +} + + + diff --git a/app/assets/javascripts/nested_fields.coffee b/app/assets/javascripts/nested_fields.coffee index c589739..c0a6ca7 100644 --- a/app/assets/javascripts/nested_fields.coffee +++ b/app/assets/javascripts/nested_fields.coffee @@ -10,9 +10,11 @@ if $(link).closest("p").next("." + association + "_form").length > 0 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") - + else + form_element = $(link).closest(".qi_field_wrapper").find("." + association + "_form") + form_element.append content_final $(".new_field").removeClass "new_field" diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index a53341c..cb1ee54 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -1782,4 +1782,88 @@ td{ } -// Fin \ No newline at end of file + +// 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 diff --git a/app/assets/stylesheets/manager.scss b/app/assets/stylesheets/manager.scss index eb296d2..f03e584 100644 --- a/app/assets/stylesheets/manager.scss +++ b/app/assets/stylesheets/manager.scss @@ -2,7 +2,8 @@ #manager_box_place{ position:fixed; height:0; - width:100%; + left:100px; + right:30px; z-index:1500; top:0px; margin:0px; diff --git a/app/controllers/admin/buy_lists_controller.rb b/app/controllers/admin/buy_lists_controller.rb index e555dcc..cad3a2f 100644 --- a/app/controllers/admin/buy_lists_controller.rb +++ b/app/controllers/admin/buy_lists_controller.rb @@ -8,7 +8,7 @@ class Admin::BuyListsController < ApplicationController @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) @@ -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 - 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 - @start = Date.parse(params[:start]).beginning_of_day - params[:start]= @start.strftime('%d/%m/%Y') + @cc_creation_date_start = Date.parse(params[:cc_creation_date_start]).beginning_of_day + params[:cc_creation_date_start]= @cc_creation_date_start.strftime('%d/%m/%Y') else - @start = nil + @cc_creation_date_start = nil end 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 - @stop = Date.parse(params[:stop]).end_of_day + if params[:cc_creation_date_stop].to_s != "" # and params[:stop] =~ date_regex + @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 - @stop = nil + @cc_creation_date_stop = nil 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 <= ?", @stop.end_of_day) if @stop + @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 <= ?", @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| format.html{ diff --git a/app/controllers/admin/import_csvs_controller.rb b/app/controllers/admin/import_csvs_controller.rb index 4f8ae2c..7a3ed47 100644 --- a/app/controllers/admin/import_csvs_controller.rb +++ b/app/controllers/admin/import_csvs_controller.rb @@ -31,13 +31,20 @@ class Admin::ImportCsvsController < ApplicationController 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 @import_csv = ImportCsv.find(params[:id]) @import_csv.load - redirect_to :action => :index + # redirect_to :action => :index + redirect_to match_refs_admin_import_csvs_path end + def new @import_csv = ImportCsv.new(:parent_id => params[:parent_id]) if @import_csv.parent @@ -85,4 +92,13 @@ class Admin::ImportCsvsController < ApplicationController @import_csv.destroy 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 diff --git a/app/controllers/admin/p_customer_sheets_controller.rb b/app/controllers/admin/p_customer_sheets_controller.rb index 5729f1c..fbc5058 100644 --- a/app/controllers/admin/p_customer_sheets_controller.rb +++ b/app/controllers/admin/p_customer_sheets_controller.rb @@ -280,6 +280,89 @@ class Admin::PCustomerSheetsController < ApplicationController 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 diff --git a/app/controllers/admin/p_fournisseur_refs_controller.rb b/app/controllers/admin/p_fournisseur_refs_controller.rb new file mode 100644 index 0000000..31e86bc --- /dev/null +++ b/app/controllers/admin/p_fournisseur_refs_controller.rb @@ -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 diff --git a/app/controllers/admin/p_fournisseurs_controller.rb b/app/controllers/admin/p_fournisseurs_controller.rb index 3b8b041..992106e 100644 --- a/app/controllers/admin/p_fournisseurs_controller.rb +++ b/app/controllers/admin/p_fournisseurs_controller.rb @@ -22,8 +22,7 @@ class Admin::PFournisseursController < ApplicationController end end - - + def index @p_fournisseurs = PFournisseur.order(:name).all diff --git a/app/controllers/admin/p_product_refs_controller.rb b/app/controllers/admin/p_product_refs_controller.rb index c187e7f..4e0a2b7 100644 --- a/app/controllers/admin/p_product_refs_controller.rb +++ b/app/controllers/admin/p_product_refs_controller.rb @@ -1,6 +1,8 @@ # -*- encoding : utf-8 -*- class Admin::PProductRefsController < ApplicationController + include ActionView::RecordIdentifier # adds `dom_id` + layout "admin" before_action :auth_admin @@ -58,6 +60,14 @@ class Admin::PProductRefsController < ApplicationController @p_product_refs = sort_by_sorting(@p_product_refs, "id DESC") 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{ params[:search][:per_page] = params[:search][:per_page] || 100 @@ -68,6 +78,11 @@ class Admin::PProductRefsController < ApplicationController } end + + if params[:manager].to_s == "true" + @manager = true + render :layout => false + end end @@ -100,13 +115,17 @@ class Admin::PProductRefsController < ApplicationController def update + @p_product_ref = PProductRef.find(params[:id]) - - 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 - render action: "edit" + + render action: "edit" end diff --git a/app/controllers/admin/p_products_controller.rb b/app/controllers/admin/p_products_controller.rb index ff04834..4e918df 100644 --- a/app/controllers/admin/p_products_controller.rb +++ b/app/controllers/admin/p_products_controller.rb @@ -81,9 +81,12 @@ class Admin::PProductsController < ApplicationController @p_product = PProduct.new #(:p_customer_cat_ids => [3]) - # @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_spec_type = @p_product_ref_specs.build_p_spec_type @p_spec_value = @p_product_ref_specs.build_p_spec_value diff --git a/app/controllers/admin/p_spec_values_controller.rb b/app/controllers/admin/p_spec_values_controller.rb index 2dfd736..4ddb464 100644 --- a/app/controllers/admin/p_spec_values_controller.rb +++ b/app/controllers/admin/p_spec_values_controller.rb @@ -13,7 +13,7 @@ class Admin::PSpecValuesController < ApplicationController def index @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| format.html{ diff --git a/app/controllers/admin/price_documents_controller.rb b/app/controllers/admin/price_documents_controller.rb index c839a72..b23a578 100644 --- a/app/controllers/admin/price_documents_controller.rb +++ b/app/controllers/admin/price_documents_controller.rb @@ -224,7 +224,7 @@ class Admin::PriceDocumentsController < ApplicationController def show @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 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]) if @price_document.price_document_type.label == "Demande prix" - p_product_ref_id = params[:qte].keys - p_product_ref_qte = params[:qte].values + p_product_ref_id = params[:p_product_ref_ids] - [""] + p_product_ref_qte = params[:qte].permit!.to_hash - p_product_ref_id.each_with_index do |key, i| - @price_document.price_line_block.price_lines << PriceLine.new(:p_product_ref_id => key, :qte => p_product_ref_qte[i]) + p_product_ref_id.each do |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 # @ref_price_lines = PriceLine.where(:id => params[:price_line_ids]) @@ -322,7 +324,11 @@ class Admin::PriceDocumentsController < ApplicationController @price_document.date = Date.today @avoir = true if @price_document.label == "Avoir" 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 render action: "new" @@ -337,18 +343,28 @@ class Admin::PriceDocumentsController < ApplicationController @avoir = true if @price_document.label == "Avoir" if @price_document.update_attributes(params.require(:price_document).permit!) - if params[:public_edit].to_s == "true" @price_document.reset_for_update #@price_document.unarchive_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] else redirect_to [:admin, @price_document] 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 redirect_to [:admin, @price_document] end @@ -602,9 +618,199 @@ class Admin::PriceDocumentsController < ApplicationController @price_document = PriceDocument.find(params[:id]) 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 @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 diff --git a/app/controllers/admin/price_line_resp_selects_controller.rb b/app/controllers/admin/price_line_resp_selects_controller.rb new file mode 100644 index 0000000..24020fd --- /dev/null +++ b/app/controllers/admin/price_line_resp_selects_controller.rb @@ -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 diff --git a/app/controllers/admin/sorecop_cats_controller.rb b/app/controllers/admin/sorecop_cats_controller.rb new file mode 100644 index 0000000..9a0803e --- /dev/null +++ b/app/controllers/admin/sorecop_cats_controller.rb @@ -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 diff --git a/app/controllers/admin/sorecop_taxes_controller.rb b/app/controllers/admin/sorecop_taxes_controller.rb new file mode 100644 index 0000000..4f62458 --- /dev/null +++ b/app/controllers/admin/sorecop_taxes_controller.rb @@ -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 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c9fffcc..dab1fa6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. 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] v[:elements].each do |a,b| - puts "TEST" - puts b[0] - puts "B" if b[:sub_elements] and b[:sub_elements][sym.to_sym] @qi_menu_active = k @qi_menu_sub_menu_active = sym.to_sym @@ -129,7 +126,11 @@ 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_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, :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 @@ -168,7 +169,7 @@ class ApplicationController < ActionController::Base 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 - if cookies[:admin_remember_token] - if @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token]) - @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token]) - else - cookies[:admin_remember_token] =nil - end + if @current_admin + return @current_admin + else + if cookies[:admin_remember_token] + if @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token]) + @current_admin = Admin.find_by_remember_token(cookies[:admin_remember_token]) + else + cookies[:admin_remember_token] =nil + end + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9e30dd0..31e8de0 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -13,7 +13,20 @@ module ApplicationHelper end return raw(r) 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='' ) raw ('
') diff --git a/app/helpers/document_line_helper.rb b/app/helpers/document_line_helper.rb index 6dbbc93..0e54205 100644 --- a/app/helpers/document_line_helper.rb +++ b/app/helpers/document_line_helper.rb @@ -28,13 +28,17 @@ module DocumentLineHelper fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| render("admin/"+association.to_s + "/essentials_form", :form => builder) 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 fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| render("admin/"+association.to_s + "/form", :form => builder) 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 diff --git a/app/models/import_csv.rb b/app/models/import_csv.rb index 7414d1b..d0d1dd1 100644 --- a/app/models/import_csv.rb +++ b/app/models/import_csv.rb @@ -10,7 +10,7 @@ class ImportCsv < ApplicationRecord validates :file, :presence => true validates :table_name, :presence => true - + has_many :import_csv_champs, :dependent => :destroy accepts_nested_attributes_for :import_csv_champs, :allow_destroy => true @@ -21,72 +21,97 @@ class ImportCsv < ApplicationRecord :name => {:name => "Nom", :reorder => true}, :file => {:name => "Fichier", :reorder => true}, :table_name => {:name => "Table", :reorder => true}, - + :nbr_headers => {:name => "Nbr champs", :reorder => true}, :nbr_elements => {:name => "Nbr elements", :reorder => true}, - - - + + + :actions => {:name => "Actions", :reorder => false} } after_create do - - csv_text = File.read(self.file.path, :encoding => 'UTF-8') - @csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") - - @csv.headers.each do |header| + if file_is_csv? + csv_text = File.read(self.file.path, :encoding => 'UTF-8') + csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") + headers = csv.headers + 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) end self.table_name.classify.constantize.import_csv_fields.each do |h| if self.parent and c = self.parent.import_csv_champs.where(:champ => h.to_s).first - self.import_csv_champs.new(:champ => h.to_s, :header => c.header) + self.import_csv_champs.new(:champ => h.to_s, :header => c.header) else - self.import_csv_champs.new(:champ => h.to_s) + self.import_csv_champs.new(:champ => h.to_s) end end - self.save - - end + + def file_is_csv? + File.read(self.file.path, :encoding => 'utf-8').valid_encoding? + end + + def charge - + self.import_csv_elements.each do |e| e.element.destroy if e.element e.destroy end - csv_text = File.read(self.file.path, :encoding => 'UTF-8') - @csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") r = [] - @csv.each do |row| - line = {} - 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}\"" + + if file_is_csv? + csv_text = File.read(self.file.path, :encoding => 'UTF-8') + csv = CSV.parse(csv_text, :headers => true, :col_sep => ";") + csv.each do |row| + line = {} + 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 - + r << line end - - r << line - + return r + 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 - - return r end def load self.table_name.classify.constantize.import_csv(self.charge, self) - + end diff --git a/app/models/p_bank.rb b/app/models/p_bank.rb index cbd7d79..097616d 100644 --- a/app/models/p_bank.rb +++ b/app/models/p_bank.rb @@ -1,2 +1,3 @@ class PBank < ApplicationRecord + has_many :particulars, :as => :owner, :dependent => :destroy end diff --git a/app/models/p_contact.rb b/app/models/p_contact.rb index 28706f5..6da354d 100644 --- a/app/models/p_contact.rb +++ b/app/models/p_contact.rb @@ -5,5 +5,5 @@ class PContact < ApplicationRecord has_many :p_contact_contact_types, :dependent => :destroy has_many :p_contact_types, :through => :p_contact_contact_types - + belongs_to :p_payment_type end diff --git a/app/models/p_customer.rb b/app/models/p_customer.rb index a9decf8..d622a3a 100644 --- a/app/models/p_customer.rb +++ b/app/models/p_customer.rb @@ -65,6 +65,26 @@ class PCustomer < ApplicationRecord has_many :order_hists # 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 @@ -258,6 +278,7 @@ class PCustomer < ApplicationRecord end 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) end @@ -482,5 +503,437 @@ class PCustomer < ApplicationRecord end while PCustomer.exists?(column => self[column]) 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 diff --git a/app/models/p_customer_rib.rb b/app/models/p_customer_rib.rb index 856d1d3..2b4a176 100644 --- a/app/models/p_customer_rib.rb +++ b/app/models/p_customer_rib.rb @@ -1,7 +1,7 @@ class PCustomerRib < ActiveRecord::Base belongs_to :p_customer - has_many :p_documents, :dependent => :nullify + # has_many :p_documents, :dependent => :nullify def generate_rum if self.sign_date diff --git a/app/models/p_customer_sheet.rb b/app/models/p_customer_sheet.rb index 70d1426..9ab4cf7 100644 --- a/app/models/p_customer_sheet.rb +++ b/app/models/p_customer_sheet.rb @@ -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_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}, + :check_box => {:name => "Export excel #{''}", :reorder => false}, :actions => {:name => "Actions", :reorder => false}, } @@ -256,7 +257,7 @@ class PCustomerSheet < ApplicationRecord after_create do - #self.state = "brouillon" if self.state != "Panier web" + self.state = "brouillon" if self.state != "Panier web" self.save end diff --git a/app/models/p_fournisseur.rb b/app/models/p_fournisseur.rb index b24d696..6f0cacb 100644 --- a/app/models/p_fournisseur.rb +++ b/app/models/p_fournisseur.rb @@ -1,2 +1,136 @@ 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 diff --git a/app/models/p_fournisseur_ref.rb b/app/models/p_fournisseur_ref.rb new file mode 100644 index 0000000..5c8fa6c --- /dev/null +++ b/app/models/p_fournisseur_ref.rb @@ -0,0 +1,4 @@ +class PFournisseurRef < ApplicationRecord + belongs_to :p_product_ref + belongs_to :p_fournisseur +end diff --git a/app/models/p_payment_type.rb b/app/models/p_payment_type.rb index a6cfaa8..fbd2f02 100644 --- a/app/models/p_payment_type.rb +++ b/app/models/p_payment_type.rb @@ -1,7 +1,8 @@ class PPaymentType < ApplicationRecord belongs_to :p_bank_account has_many :p_payments - + has_many :p_fournisseurs + after_save do if self.p_bank_account self.p_payments.where(:remise => false).update_all(:p_bank_account_id => self.p_bank_account_id) diff --git a/app/models/p_product.rb b/app/models/p_product.rb index 78ee662..a28d2a7 100644 --- a/app/models/p_product.rb +++ b/app/models/p_product.rb @@ -28,14 +28,13 @@ class PProduct < ApplicationRecord has_many :p_product_images belongs_to :p_customer - + belongs_to :sorecop_cat belongs_to :p_product_cat belongs_to :s_brand - validates :name, :presence => true - validates :code, :presence => true, :uniqueness => true - + validates :name, :presence => true, exclusion: { in: ["--> Selectioner un produit <--"], message: "Selectioner un produit avant de valider" } + 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 :tva_rates, :through => :tvable_tva_rates @@ -81,6 +80,11 @@ class PProduct < ApplicationRecord tsearch: { prefix: true } } + before_validation do + if self.code.blank? + generate_code + end + end def self.for_search(search) @@ -114,15 +118,21 @@ class PProduct < ApplicationRecord after_create do - end after_save do self.p_product_refs.each do |ppr| ppr.save end + self.class.destroy_temp_p_product 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) 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 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 diff --git a/app/models/p_product_ref.rb b/app/models/p_product_ref.rb index 348ef3e..ce4686a 100644 --- a/app/models/p_product_ref.rb +++ b/app/models/p_product_ref.rb @@ -1,6 +1,8 @@ class PProductRef < ApplicationRecord belongs_to :p_product + belongs_to :sorecop_cat + has_many :sorecop_taxes, through: :sorecop_cat has_one :s_brand, 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 accepts_nested_attributes_for :p_article_serial_nums, allow_destroy: true - has_many :p_product_ref_specs - accepts_nested_attributes_for :p_product_ref_specs, allow_destroy: true + has_many :p_product_ref_specs, dependent: :destroy + accepts_nested_attributes_for :p_product_ref_specs, allow_destroy: true, reject_if: :all_blank #validates :ct_price_ht, :presence => true - + validate :ean, :is_integer has_many :p_customer_product_prices, :dependent => :destroy accepts_nested_attributes_for :p_customer_product_prices, allow_destroy: true + has_many :p_fournisseur_refs scope :enableds, -> {where(:enabled => true)} @@ -41,14 +44,17 @@ class PProductRef < ApplicationRecord :p_product_cat => {:name => "Catégorie", :reorder => true}, :ref => {:name => "Référence"}, :cc_name => {:name => "Produit"}, - :description => {:name => "Description"}, - :ct_sub_name => {:name => "Nom référence"}, + # :description => {:name => "Description"}, + :cc_name => {:name => "Nom référence"}, :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} } + acts_as_caching :fields => [:sorecop, :deee, :name, :code] include PgSearch::Model pg_search_scope :global_search, against: [:ref, :cc_name], @@ -61,6 +67,19 @@ class PProductRef < ApplicationRecord 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? if !self.p_product or !self.p_product.imported true @@ -83,9 +102,35 @@ class PProductRef < ApplicationRecord def ca_name - if self.p_product - self.p_product.name + " - " + self.ct_sub_name - end + storage = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Stockage")).first + cellular = self.p_product_ref_specs.where(p_spec_type: PSpecType.find_by(name: "Connectivité")).first + 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 def ca_code @@ -96,11 +141,11 @@ class PProductRef < ApplicationRecord self.p_product.p_product_cat_id 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) p_customer = PCustomer.find(options[:p_customer_id]) if options[:p_customer_id] @@ -159,7 +204,55 @@ class PProductRef < ApplicationRecord end 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 diff --git a/app/models/p_product_ref_spec.rb b/app/models/p_product_ref_spec.rb index a036951..e15b3f1 100644 --- a/app/models/p_product_ref_spec.rb +++ b/app/models/p_product_ref_spec.rb @@ -5,6 +5,8 @@ class PProductRefSpec < ApplicationRecord 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 => { :id => {:name => "ID"}, :p_product_ref => {:name => "Référence produit", :reorder => true}, diff --git a/app/models/p_spec_type.rb b/app/models/p_spec_type.rb index 42875d3..ec3b632 100644 --- a/app/models/p_spec_type.rb +++ b/app/models/p_spec_type.rb @@ -1,6 +1,7 @@ class PSpecType < ApplicationRecord has_many :p_product_ref_specs - TYPES = ["Ram", "Stockage"] + + TYPES = self.distinct.pluck(:name) acts_as_sorting :fields => { :id => {:name => "ID"}, diff --git a/app/models/p_spec_value.rb b/app/models/p_spec_value.rb index 8471de5..c9aade6 100644 --- a/app/models/p_spec_value.rb +++ b/app/models/p_spec_value.rb @@ -1,7 +1,7 @@ class PSpecValue < ApplicationRecord has_many :p_product_ref_specs - UNITS = ["Go", "Mo"] + UNITS = self.distinct.pluck(:unit) def member_label "#{value} #{unit}" diff --git a/app/models/price_document.rb b/app/models/price_document.rb index 07c348c..125545e 100644 --- a/app/models/price_document.rb +++ b/app/models/price_document.rb @@ -25,12 +25,13 @@ class PriceDocument < ApplicationRecord 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 - 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"] # AVANCEMENT = ["0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"] AVANCEMENT = ["0%", "25%", "50%", "75%", "100"] 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? if self.label == "Réponse fournisseur" @@ -707,6 +708,58 @@ class PriceDocument < ApplicationRecord 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 diff --git a/app/models/price_line.rb b/app/models/price_line.rb index 1dabff0..897399c 100644 --- a/app/models/price_line.rb +++ b/app/models/price_line.rb @@ -3,9 +3,18 @@ class PriceLine < ApplicationRecord belongs_to :p_product belongs_to :p_product_ref 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') } 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 @@ -13,7 +22,8 @@ class PriceLine < ApplicationRecord has_many :line_stocks - + after_update :memorize_p_fournisseur_ref, if: :p_fournisseur_ref_is_memorizable? + acts_as_sorting :fields => { :ref => {:name => "Ref", :reorder => true}, :title => {:name => "Désignation", :reorder => true}, @@ -44,11 +54,13 @@ 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) - 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) - + def to_no_archive if !self.imported %w(cost_ht marge_ht) @@ -160,7 +172,13 @@ class PriceLine < ApplicationRecord true end end - + + def p_product_needed? + if !self.ct_title? and !self.imported + true + end + end + def personalised_archive end @@ -538,38 +556,36 @@ class PriceLine < ApplicationRecord - - def ca_tot_amount_ht - if ct_tot_amount_ht + if self.ct_tot_amount_ht self.ct_tot_amount_ht 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 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 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 - - - + + + 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 - - - + + + 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 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 @@ -609,6 +625,12 @@ class PriceLine < ApplicationRecord return [asap, non_asap] 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 diff --git a/app/models/price_line_block.rb b/app/models/price_line_block.rb index 14b7469..223aab1 100644 --- a/app/models/price_line_block.rb +++ b/app/models/price_line_block.rb @@ -23,9 +23,10 @@ class PriceLineBlock < ApplicationRecord 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"] - + belongs_to :p_fournisseur accepts_nested_attributes_for :p_fournisseur @@ -261,7 +262,9 @@ class PriceLineBlock < ApplicationRecord end 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 else true @@ -270,7 +273,9 @@ class PriceLineBlock < ApplicationRecord def particular_bill_needed? 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 else true @@ -280,7 +285,9 @@ class PriceLineBlock < ApplicationRecord def particular_send_needed? 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 else true @@ -289,7 +296,9 @@ class PriceLineBlock < ApplicationRecord end 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 else false @@ -297,9 +306,11 @@ class PriceLineBlock < ApplicationRecord end 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 - elsif !self.imported + elsif self.block_type == "Devis" + false + else true 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) - 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) @@ -337,12 +350,12 @@ class PriceLineBlock < ApplicationRecord eval("self.ac_#{qid} = nil") end - self.archive_now(:skip_personalised_archive => true) + self.archive_now() self.price_lines.each do |pl| - pl.archive_now(:skip_personalised_archive => true) + pl.archive_now() end diff --git a/app/models/price_line_resp_select.rb b/app/models/price_line_resp_select.rb new file mode 100644 index 0000000..f656ff3 --- /dev/null +++ b/app/models/price_line_resp_select.rb @@ -0,0 +1,4 @@ +class PriceLineRespSelect < ApplicationRecord + belongs_to :price_line_demand, class_name: "PriceLine" + belongs_to :price_line_resp, class_name: "PriceLine" +end diff --git a/app/models/s_brand.rb b/app/models/s_brand.rb index 10fa791..d86a059 100644 --- a/app/models/s_brand.rb +++ b/app/models/s_brand.rb @@ -2,4 +2,25 @@ class SBrand < ApplicationRecord has_many :p_products has_many :p_product_refs, through: :p_products 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 diff --git a/app/models/sorecop_cat.rb b/app/models/sorecop_cat.rb new file mode 100644 index 0000000..ebb0575 --- /dev/null +++ b/app/models/sorecop_cat.rb @@ -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 diff --git a/app/models/sorecop_tax.rb b/app/models/sorecop_tax.rb new file mode 100644 index 0000000..66bec55 --- /dev/null +++ b/app/models/sorecop_tax.rb @@ -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 diff --git a/app/views/admin/buy_lists/index.html.haml b/app/views/admin/buy_lists/index.html.haml index b84b535..0e25caf 100644 --- a/app/views/admin/buy_lists/index.html.haml +++ b/app/views/admin/buy_lists/index.html.haml @@ -11,20 +11,20 @@ =form_tag "", :method => "get", :onsubmit => "" do -params[:search] =params[:search] || {} - %p Date de consultation : %table %tr.form-inline %td + Date saisie commande : Début %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 %span.input-group-text{:onclick => "$(this).prev('input').val('');"} =ic(:times) %td.pl-4 Fin %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 %span.input-group-text{:onclick => "$(this).prev('input').val('');"} =ic(:times) @@ -39,17 +39,45 @@ Code client : =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 %td{width: "110px"} %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.mr-auto - -if @start and @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" + -if @wish_date_start and @wish_date_stop + =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;" @@ -72,7 +100,8 @@ =form_tag new_admin_price_document_path(), :method => "get" do =hidden_field_tag :"document_type", "Demande prix" - =hidden_field_tag :"price_line_ids[]", "" + =hidden_field_tag :"p_product_ref_ids[]", "" + .freezeTable %table.table.table-striped.table-hover.table-bordered.data_table %thead.header @@ -104,6 +133,9 @@ Qté en stock %th.mask Qté souhaité + %span.info + =ic("info-circle") + %span.info-text-bottom BPA - Qté en stock %th.mask BPA %th.mask AV BPA %th.mask PAS BPA @@ -131,6 +163,9 @@ -ppr_lines = @price_lines.where(:p_product_ref_id => plr.p_product_ref.id) %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 %td @@ -165,13 +200,15 @@ =ic(:hourglass) =ppr_lines.asap_triage(20).last %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 - =text_field_tag "qte[#{plr.p_product_ref.id}]", '', class: "small-input" - - %td.mask - =ppr_lines.where(:cc_state => "BPA").sum(:qte).to_i + = bpa_qte %td.mask =ppr_lines.where(:cc_state => "AV BPA").sum(:qte).to_i %td.mask @@ -271,9 +308,11 @@ } :javascript + // TOOGLE ORDERS DETAILS - set to hidden $('.detail').hide() $('.col-detail').hide() let state = 0 + // TOGGLE ORDER LINE DETAILS $('.plus').click(function(event){ if( event.currentTarget.className == "plus") { $(event.currentTarget).removeClass('plus').addClass('minus') @@ -292,6 +331,7 @@ $('.col-detail').show() } }); + // TOOGLE ALL ORDERS DETAILS $('.plus-all').click(function(event){ if( event.currentTarget.className == "mask plus-all") { state += $('.plus').length @@ -315,6 +355,15 @@ $('.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) + } + }) diff --git a/app/views/admin/import_csvs/_form.html.haml b/app/views/admin/import_csvs/_form.html.haml index f115a9c..71bbec7 100644 --- a/app/views/admin/import_csvs/_form.html.haml +++ b/app/views/admin/import_csvs/_form.html.haml @@ -6,7 +6,7 @@ = f.input :name, :label => "Nom de l'import :" = 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 %table.import_csv_champs_form @@ -23,4 +23,4 @@ .actions=f.submit "sauvegarder", :class => "btn btn-primary" - \ No newline at end of file + diff --git a/app/views/admin/import_csvs/_form_temp_p_product.html.haml b/app/views/admin/import_csvs/_form_temp_p_product.html.haml new file mode 100644 index 0000000..c27d130 --- /dev/null +++ b/app/views/admin/import_csvs/_form_temp_p_product.html.haml @@ -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) + } + }); + }); diff --git a/app/views/admin/import_csvs/index.html.haml b/app/views/admin/import_csvs/index.html.haml index 78aa6d9..70eead3 100644 --- a/app/views/admin/import_csvs/index.html.haml +++ b/app/views/admin/import_csvs/index.html.haml @@ -1,6 +1,6 @@ .qi_header .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} -=debug OrderHistLine.new.class.type_for_attribute("ff") \ No newline at end of file +=#debug OrderHistLine.new.class.type_for_attribute("ff") diff --git a/app/views/admin/import_csvs/match_refs.html.haml b/app/views/admin/import_csvs/match_refs.html.haml new file mode 100644 index 0000000..c55dd77 --- /dev/null +++ b/app/views/admin/import_csvs/match_refs.html.haml @@ -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" diff --git a/app/views/admin/import_csvs/temp_p_product.js.erb b/app/views/admin/import_csvs/temp_p_product.js.erb new file mode 100644 index 0000000..0562b62 --- /dev/null +++ b/app/views/admin/import_csvs/temp_p_product.js.erb @@ -0,0 +1 @@ +show_pane_hover("<%= escape_javascript(render(:partial => "form_temp_p_product"))%>",700,900); diff --git a/app/views/admin/p_customer_sheets/_form.html.haml b/app/views/admin/p_customer_sheets/_form.html.haml index c8c82b9..2c1194a 100755 --- a/app/views/admin/p_customer_sheets/_form.html.haml +++ b/app/views/admin/p_customer_sheets/_form.html.haml @@ -1,24 +1,28 @@ =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 .qi_row - .qi_pannel.qi_plain.padding - -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 :past_id, :label => "N° système actuel" - - .price_line_block_form - =form.semantic_fields_for :price_line_block do |f| - =render :partial => "admin/price_line_blocks/form", :locals => {:f => f} + .qi_pannel.qi_plain.padding.row + .col-2 + -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 :past_id, :label => "N° système actuel" + =yield :discount + .col-2 + =yield :shipping_date + .col-8 + =yield :particular - - - .right.actions - =link_to "Annuler", admin_p_customer_sheets_path(), :class => "btn" - =form.submit "sauvegarder", :class => "btn btn-primary btn-ap-add" + =yield :price_lines + .large_actions + .actions + =link_to "Annuler", admin_p_customer_sheets_path(), :class => "btn" + =form.submit "sauvegarder", :class => "btn btn-primary btn-ap-add" .clear diff --git a/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml b/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml index 5a8f2b5..7d589a3 100644 --- a/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml +++ b/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml @@ -43,9 +43,11 @@ -tr[:tot_amount_ttc] = capture do %td.numeraire =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 %td.actions -if p_customer_sheet.state == "brouillon" and p_customer_sheet.demande_type.to_s == "Brouillon" diff --git a/app/views/admin/p_customer_sheets/index.html.haml b/app/views/admin/p_customer_sheets/index.html.haml index 2ba4b79..afbae90 100644 --- a/app/views/admin/p_customer_sheets/index.html.haml +++ b/app/views/admin/p_customer_sheets/index.html.haml @@ -1,7 +1,6 @@ .qi_header .right =link_to ic(:plus)+" Demande de commande", admin_p_customers_path(:offre => true), :class => "btn btn-primary btn-ap-add" - %h1 Ventes %span @@ -179,5 +178,77 @@ ="-" =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"} + × + .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} diff --git a/app/views/admin/p_customers/_form.html.haml b/app/views/admin/p_customers/_form.html.haml index 36b96f5..ee76638 100755 --- a/app/views/admin/p_customers/_form.html.haml +++ b/app/views/admin/p_customers/_form.html.haml @@ -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 :code, :label => "Code client" + -if false + =form.input :code, :label => "Code client" -if !@p_customer.id diff --git a/app/views/admin/p_fournisseur_refs/_form.html.haml b/app/views/admin/p_fournisseur_refs/_form.html.haml new file mode 100644 index 0000000..0fdf241 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/_form.html.haml @@ -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" + \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/_p_fournisseur_ref.html.haml b/app/views/admin/p_fournisseur_refs/_p_fournisseur_ref.html.haml new file mode 100644 index 0000000..b9969b4 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/_p_fournisseur_ref.html.haml @@ -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} + + + + \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/create.js.erb b/app/views/admin/p_fournisseur_refs/create.js.erb new file mode 100644 index 0000000..a57e725 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/create.js.erb @@ -0,0 +1,2 @@ +$('#p_fournisseur_refs_rows').prepend("<%= escape_javascript(render(@p_fournisseur_ref))%>"); +close_pane_hover(); \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/destroy.js.erb b/app/views/admin/p_fournisseur_refs/destroy.js.erb new file mode 100644 index 0000000..72148c9 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/destroy.js.erb @@ -0,0 +1 @@ +$('#p_fournisseur_ref_row_<%= @p_fournisseur_ref.id %>').remove(); \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/edit.js.erb b/app/views/admin/p_fournisseur_refs/edit.js.erb new file mode 100644 index 0000000..6c8f015 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/edit.js.erb @@ -0,0 +1 @@ +show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900); \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/index.html.haml b/app/views/admin/p_fournisseur_refs/index.html.haml new file mode 100644 index 0000000..bcead3b --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/index.html.haml @@ -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} + + + diff --git a/app/views/admin/p_fournisseur_refs/new.js.erb b/app/views/admin/p_fournisseur_refs/new.js.erb new file mode 100644 index 0000000..6c8f015 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/new.js.erb @@ -0,0 +1 @@ +show_pane_hover("<%= escape_javascript(render(:partial => "form"))%>",700,900); \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/show.html.haml b/app/views/admin/p_fournisseur_refs/show.html.haml new file mode 100644 index 0000000..213e4c6 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/show.html.haml @@ -0,0 +1,10 @@ +.qi_header + %h1 + + %span + + + +.qi_row + .qi_pannel.qi_plain.padding + =debug @p_fournisseur_ref \ No newline at end of file diff --git a/app/views/admin/p_fournisseur_refs/update.js.erb b/app/views/admin/p_fournisseur_refs/update.js.erb new file mode 100644 index 0000000..b135464 --- /dev/null +++ b/app/views/admin/p_fournisseur_refs/update.js.erb @@ -0,0 +1,2 @@ +$('#p_fournisseur_ref_row_<%= @p_fournisseur_ref.id %>').replaceWith("<%= escape_javascript(render(@p_fournisseur_ref))%>"); +close_pane_hover(); \ No newline at end of file diff --git a/app/views/admin/p_fournisseurs/import.html.haml b/app/views/admin/p_fournisseurs/import.html.haml index 276b6d1..41199bd 100644 --- a/app/views/admin/p_fournisseurs/import.html.haml +++ b/app/views/admin/p_fournisseurs/import.html.haml @@ -1,13 +1,14 @@ --@import= true +-if false + -@import= true --i = 0 --@csv.each do |csv| - -i += 1 + -i = 0 + -@csv.each do |csv| + -i += 1 - =csv["code"] - -if csv["code"].to_s != "" - 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"]) + =csv["code"] + -if csv["code"].to_s != "" + 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"]) diff --git a/app/views/admin/p_fournisseurs/index.html.haml b/app/views/admin/p_fournisseurs/index.html.haml index f77d543..3423253 100644 --- a/app/views/admin/p_fournisseurs/index.html.haml +++ b/app/views/admin/p_fournisseurs/index.html.haml @@ -1,7 +1,6 @@ .qi_header .right = link_to 'Ajouter un fournisseur', new_admin_p_fournisseur_path(), :class => "btn btn-primary", :remote => true - %h1 Achats %span @@ -28,4 +27,4 @@ %tbody#p_fournisseurs_rows =render @p_fournisseurs - \ No newline at end of file + diff --git a/app/views/admin/p_product_ref_specs/_form.html.haml b/app/views/admin/p_product_ref_specs/_form.html.haml index ffde9d3..d369fed 100644 --- a/app/views/admin/p_product_ref_specs/_form.html.haml +++ b/app/views/admin/p_product_ref_specs/_form.html.haml @@ -15,15 +15,15 @@ %table %tr %td - %h4 spec : - + %h4 Specs : + %tr %td -#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.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 - = 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 diff --git a/app/views/admin/p_product_refs/_form.html.haml b/app/views/admin/p_product_refs/_form.html.haml index b7ff800..aa46f8e 100644 --- a/app/views/admin/p_product_refs/_form.html.haml +++ b/app/views/admin/p_product_refs/_form.html.haml @@ -1,5 +1,6 @@ +=#debug form.object.errors.messages =# form.input :ref, :label => "Ref :" -.qi_row.field +.qi_row.field{id: dom_id(form.object)} .qi_pannel.qi_plain.padding %table.form-table @@ -10,7 +11,9 @@ %td = form.input :ref, :label => "Réf int. :" =#form.hidden_field :ref_id - + -if @price_line + =form.hidden_field :price_line_id, value: @price_line.id + %td = form.input :ct_sub_name, :label => "Désignation :" @@ -18,7 +21,17 @@ = 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 + =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 %td{:colspan => 2} %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 %tr diff --git a/app/views/admin/p_product_refs/_p_product_ref.html.haml b/app/views/admin/p_product_refs/_p_product_ref.html.haml index 33e3f52..3fb1b23 100644 --- a/app/views/admin/p_product_refs/_p_product_ref.html.haml +++ b/app/views/admin/p_product_refs/_p_product_ref.html.haml @@ -31,10 +31,16 @@ %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 =#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} - \ No newline at end of file + diff --git a/app/views/admin/p_product_refs/index.html.haml b/app/views/admin/p_product_refs/index.html.haml index f301f4e..d186f00 100644 --- a/app/views/admin/p_product_refs/index.html.haml +++ b/app/views/admin/p_product_refs/index.html.haml @@ -1,17 +1,19 @@ -.qi_header - .right= link_to ic(:plus)+' Ajouter un produit', new_admin_p_product_path(), :class => "btn btn-primary btn-ap-add", :remote => false - %h1 - Achats - %span - Produits +-if !@manager + .qi_header + .right= link_to ic(:plus)+' Ajouter un produit', new_admin_p_product_path(), :class => "btn btn-primary btn-ap-add", :remote => false + %h1 + Achats + %span + Références + .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 :direction, params[:direction] - + =hidden_field_tag :manager, params[:manager] %table %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} @@ -66,4 +68,7 @@ }); - + +:coffeescript + $(".qi_search_row form").on "submit", -> + $("#p_product_refs_index_wrapper").html('recherche en cours ...') \ No newline at end of file diff --git a/app/views/admin/p_product_refs/index.js.erb b/app/views/admin/p_product_refs/index.js.erb new file mode 100644 index 0000000..ab3b84a --- /dev/null +++ b/app/views/admin/p_product_refs/index.js.erb @@ -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(' Rechercher'); \ No newline at end of file diff --git a/app/views/admin/p_product_refs/update.js.erb b/app/views/admin/p_product_refs/update.js.erb index 49eb092..8b84b1e 100644 --- a/app/views/admin/p_product_refs/update.js.erb +++ b/app/views/admin/p_product_refs/update.js.erb @@ -1,2 +1,8 @@ $('#p_product_ref_row_<%= @p_product_ref.id %>').replaceWith("<%= escape_javascript(render(@p_product_ref))%>"); -close_pane_hover(); \ No newline at end of file + +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(); diff --git a/app/views/admin/p_products/_form.html.haml b/app/views/admin/p_products/_form.html.haml index dcc5078..d298195 100755 --- a/app/views/admin/p_products/_form.html.haml +++ b/app/views/admin/p_products/_form.html.haml @@ -19,7 +19,8 @@ =# 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 @@ -112,4 +113,4 @@ - \ No newline at end of file + diff --git a/app/views/admin/price_documents/_form.html.haml b/app/views/admin/price_documents/_form.html.haml index 1a74d5a..60a7314 100644 --- a/app/views/admin/price_documents/_form.html.haml +++ b/app/views/admin/price_documents/_form.html.haml @@ -20,8 +20,8 @@ =hidden_field_tag :public_edit, params[:public_edit] - - = @price_document.price_line_block.block_type + %h3 + = @price_document.price_line_block.block_type -if @price_document.label == "Demande prix" .row diff --git a/app/views/admin/price_documents/_form_p_fournisseur.html.haml b/app/views/admin/price_documents/_form_p_fournisseur.html.haml index 3514749..a860e68 100644 --- a/app/views/admin/price_documents/_form_p_fournisseur.html.haml +++ b/app/views/admin/price_documents/_form_p_fournisseur.html.haml @@ -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 =f.object.errors.messages diff --git a/app/views/admin/price_documents/_price_document.html.haml b/app/views/admin/price_documents/_price_document.html.haml index 1422646..a18ec45 100644 --- a/app/views/admin/price_documents/_price_document.html.haml +++ b/app/views/admin/price_documents/_price_document.html.haml @@ -22,7 +22,7 @@ -tr[:p_fournisseur] = capture do %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? = price_document.p_fournisseur.name - else @@ -69,12 +69,15 @@ %td - if price_document.avancement = price_document.avancement.to_s + " %" - - elsif parent_doc.avancement + - elsif parent_doc and parent_doc.avancement = parent_doc.avancement.to_s + " %" -tr[:list_designaton] = capture do %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 %td @@ -87,11 +90,17 @@ -tr[:dp_comment] = capture do %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 %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 %td @@ -135,7 +144,7 @@ -tr[:actions] = capture do %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) -if !price_document.imported -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.id), :remote => false -if PriceLineBlock::PURCHASE_BLOCKS.include?(price_document.block_type) =# 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(: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} diff --git a/app/views/admin/price_documents/_relicats.html.haml b/app/views/admin/price_documents/_relicats.html.haml new file mode 100644 index 0000000..035846f --- /dev/null +++ b/app/views/admin/price_documents/_relicats.html.haml @@ -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 + + + diff --git a/app/views/admin/price_documents/analyse_reponses.html.haml b/app/views/admin/price_documents/analyse_reponses.html.haml index 96050ca..8627aca 100644 --- a/app/views/admin/price_documents/analyse_reponses.html.haml +++ b/app/views/admin/price_documents/analyse_reponses.html.haml @@ -2,13 +2,13 @@ %h1 Achats %span - Analyse des réponces à la consiltation n° + Analyse des réponces à la demande de prix n° = link_to @price_document.d_number, admin_price_document_path(@price_document) \- = @price_document.list_designaton - -=semantic_form_for [:admin, @price_document], :html => {:class => "qi_price_form"}, :remote => false do |form| +-unmatched_fournisseur = 0 +=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| - price_line_block = f.object .qi_pannel.padding.new_table_container @@ -26,9 +26,23 @@ Consultation %th{colspan: nb_resp} Fournisseurs - .btn.btn-light.ml-4#reset-radio + .btn.btn-light.mx-4#reset-radio 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 %th Qté à @@ -77,17 +91,23 @@ %th -if resp.p_fournisseur =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 -# price_lines = f.object.price_lines - + -price_lines_child_index = {} -consult_price_lines = @price_document.price_line_block.price_lines =f.semantic_fields_for :price_lines do |form| - price_line = form.object -#price_lines = @price_document.price_line_block.price_lines -#price_lines.each do |price_line| - %tr %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 @@ -127,22 +147,35 @@ / Date du px de référence %td.limit / spec + + =#form.input :price_line_resp_ids, collection: PriceLine.where(:price_line_ref_id => form.object.id).all, as: :check_boxes , :member_label => :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}" - =form.input :selected_price_line_id, collection: PriceLine.where(:price_line_ref_id => form.object.id).all, as: :radio, :member_label => :id - =debug form.object.id - @price_document_responses.each do |resp| -line = resp.price_line_block.price_lines.where(p_product_ref: price_line.p_product_ref).first -cell = [] - if line.qte_available.to_i > 0 - -if line.qte_available >= price_line.qte.to_i + - if line.id == best_price[0] + -cell << "#{ic(:money)} Meilleur prix" + - if line.qte_available >= price_line.qte.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 << "PA: #{line.ct_u_price_ht} €" - # mp = calcul de la marge prévisionelle TODO - line.id.odd? ? mp = 0.17 : mp = 0.11 - - if mp.present? + - if false -if mp > 0.15 - cell << "#{ic(:check)} MP: #{mp * 100} %" -else @@ -155,14 +188,47 @@ - display_comment = "#{line.comment[0..10]} (..)" - else - display_comment = line.comment - - cell << "#{ic('info-circle')} #{display_comment}#{line.comment}" + - cell << "#{ic('info-circle')} #{display_comment}#{line.comment}" + + %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('