//! jdevis.js let chkPageLoad = true; // indique que la page vient d'être chargée pour la première fois let idDevis = 0; let fkUser = 0; let fkRole = 0; let devIp = '0'; let fkUserDevis = 0; let fkStatutDevis = 0; let chkValidat = 0; let oldColorLn; let oldIdLn; let chkChange = 0; let idMarche = ''; let idNewMarche = ''; // dans le cas on l'utilisateur change de marché sur un devis déjà créé let chkClientsSecteur; let chkShowDevisArchives = false; // indique si on affiche les devis archivés ou non let chkCreateClient = false; // On charge les produits du marché du devis en cours dans un tableau pour ne pas avoir à les recharger à chaque fois let dataProduitsMarche = []; //! Pour ne charger les clients du secteur ou de toute la France qu'en cas de changement de la valeur du chkbox let oldChkClientsSecteur = 2; let clients = []; let chkPrixNets = false; // le marché du devis en cours est-il en prix nets ou pas let remiseMarcheDeBase = 0; // la remise de base du marché let chkSaisieRemise = false; let chkRemisesMarche = true; // indique si toutes les lignes du devis appliquent la remise du marché ou pas let aRemisesMarches = []; let devisTotalHT = 0; let devisTotalRemHT = 0; let devisTotalMarge = 0; let chkRegleSeuilsMarge = false; // indique si le marché sélectionné prend en compte les seuils de marge fixés dans les familles de produits let seuilMargeRR = 30; // le seuil de marge du RR sur ce devis, par défaut à 30 % let seuilMargeDV = 20; // le seuil de marge du DV sur ce devis, par défaut à 20 % let intervalRefresh; let nbCommentChat = 0; let draggedElement = null; // l'élément qui est en train d'être déplacé (la ligne du produit du devis lors d'un drag and drop) window.addEventListener('DOMContentLoaded', (event) => { console.log('#'); // Initialisation des éléments utilisés let elCelDevis = document.getElementsByClassName('celDevis'); let elCelArchives = document.getElementsByClassName('celArchives'); let elBtnDupDevis = document.getElementsByClassName('btnDupDevis'); let elBtnSupprDevis = document.getElementsByClassName('btnSupprDevis'); let elBtnExpExcelDevis = document.getElementsByClassName('btnExpExcelDevis'); let elBtnValDevis = document.getElementsByClassName('btnValDevis'); let elBtnPdfDevis = document.getElementsByClassName('btnPdfDevis'); let elBtnValidationRR = document.getElementById('btnValidationRR'); let elBtnRefusRR = document.getElementById('btnRefusRR'); let elBtnCloseRR = document.getElementById('btnCloseRR'); let elBtnClosePDF = document.getElementById('btnClosePDF'); let elBtnDevisArchives = document.getElementById('btnDevisArchives'); let elBtnCreateDevis = document.getElementById('btnCreateDevis'); let elBtnCreateClient = document.getElementById('btnCreateClient'); let elBtnCancelCreateClient = document.getElementById('btnCancelCreateClient'); let elBtnSaveCreateClient = document.getElementById('btnSaveCreateClient'); let elBtnSpeciaux = document.getElementById('btnSpeciaux'); let elBtnCancelSpeciaux = document.getElementById('btnCancelSpeciaux'); let elBtnSaveSpeciaux = document.getElementById('btnSaveSpeciaux'); let elBtnSaveEnTete = document.getElementById('btnSaveEnTete'); let elBtnSaveSelProduits = document.getElementById('btnSaveSelProduits'); let elBtnSaveDevis = document.getElementById('btnSaveDevis'); let elBtnSaveDevisAndSend = document.getElementById('btnSaveDevisAndSend'); let elChkClientsSecteur = document.getElementById('inp_chk_clients_secteur'); let elInputSearchProducts = document.querySelectorAll("input[id^='inpSearchProduct_']"); let elInputQtes = document.querySelectorAll("input[name^='inpQte_']"); let elInputRemises = document.querySelectorAll("input[name^='inpRemise_']"); let elChkVariantes = document.querySelectorAll("input[type='checkbox'][name^='chkVariante_']"); let elInputDateDemande = document.getElementById('inp_date_demande'); let elInputDateRemise = document.getElementById('inp_date_remise'); let elListOngletsProduits = document.getElementById('listOngletsProduits'); let elOngletsProduits = document.querySelectorAll('[id^="onglet_"]'); let elProdSelect = document.querySelectorAll('input[type="checkbox"][name^="chkBoxProd_"]'); let elInpCommentGesteComm = document.getElementById('inpCommentGesteComm'); let elChatBtnSend = document.getElementById('chatBtnSend'); let elBtnCancelCommentProd = document.getElementById('btnCancelCommentProd'); let elBtnSaveCommentProd = document.getElementById('btnSaveCommentProd'); //! Au chargement de la page on affiche le menu vertical de choix du devis et on cache les 3 onglets const elDivDevis = document.getElementById('divDevis'); const elDossStatuts = document.getElementById('vb-dossiers-statuts'); const elDossArchives = document.getElementById('vb-dossiers-archives'); // Par défaut on n'affiche pas le chat document.getElementById('chat-container').style.display = 'none'; const elVerticalBar = document.getElementById('verticalBar'); const elBtnSideBarDevis = document.getElementById('btnSideBarDevis'); // par défaut on affiche les dossiers par statuts de devis elDossStatuts.classList.remove('hidden'); elDossArchives.classList.add('hidden'); elVerticalBar.style.width = '1100px'; elDivDevis.style.display = 'none'; //! On récupère les données contextuelles propres à l'utilisateur fetch('/jxpost/get_context', { method: 'POST', headers: { 'Content-Type': 'application/json;charset=utf-8', Accept: 'application/json;charset=utf-8', }, }).then((response) => { const ret = response.json(); ret.then(function (data) { const user = data.user; fkUser = user.rowid; fkRole = user.fk_role; devIp = data.devip; const session = data.session; }); }); let clickDevisArchives = function () { // click sur le bouton de la sidebar pour afficher les devis archivés ou revenir sur les devis en cours elDossStatuts.classList.toggle('hidden'); idDevis = 0; const archivesHidden = elDossArchives.classList.toggle('hidden'); if (archivesHidden) { this.innerHTML = 'Mes devis archivés'; chkShowDevisArchives = false; document.getElementById('chat-message-input').classList.remove('hidden'); // Il faut afficher tous les boutons d'enregistrement elBtnSaveEnTete.classList.remove('hidden'); elBtnSaveSelProduits.classList.remove('hidden'); elBtnSaveDevis.classList.remove('hidden'); elBtnSaveDevisAndSend.classList.remove('hidden'); elBtnSaveSpeciaux.classList.remove('hidden'); } else { this.innerHTML = 'Mes devis en cours'; chkShowDevisArchives = true; document.getElementById('chat-message-input').classList.add('hidden'); // Il faut cacher tous les boutons d'enregistrement elBtnSaveEnTete.classList.add('hidden'); elBtnSaveSelProduits.classList.add('hidden'); elBtnSaveDevis.classList.add('hidden'); elBtnSaveDevisAndSend.classList.add('hidden'); elBtnSaveSpeciaux.classList.add('hidden'); } document.getElementById('chat-container').style.display = 'none'; elDivDevis.style.display = 'none'; return false; }; let clickLigDevis = function () { //! L'utilisateur vient de cliquer sur un devis dans la liste de gauche //! On ne fait rien si l'utilisateur clique sur le même devis if (this.getAttribute('data-rid') != idDevis) { if (chkChange == 1) { if (confirm('Attention, vous avez des modifications non enregistrées sur ce devis. Voulez-vous continuer ?')) { chkChange = 0; } else { return false; } } idDevis = this.getAttribute('data-rid'); showLoading(); // on met à jour l'input caché contenant l'id du devis sélectionné document.getElementById('inpIdDevis').value = idDevis; let dataFamilles; //! on charge les familles de groupes de produits pour mettre à jour le tableau de chaque onglet fetch('/jxdevis/load_familles', { method: 'POST', headers: { 'Content-Type': 'application/json;charset=utf-8', Accept: 'application/json;charset=utf-8', }, }).then((response) => { if (!response.ok) { showNotification('Erreur', "Le chargement des familles de produits n'a pas abouti", 'error'); } else { const ret = response.json(); ret.then(function (data) { dataFamilles = data; }); } }); // effectue la requête ajax fetch pour charger les produits du marché fetch('/jxdevis/load_devis', { method: 'POST', body: JSON.stringify({ cid: idDevis }), headers: { 'Content-Type': 'application/json;charset=utf-8', Accept: 'application/json;charset=utf-8', }, }) .then((response) => { if (!response.ok) { showNotification('Erreur', "Le chargement des infos de l'en-tête de ce devis n'a pas abouti", 'error'); } else { const ret = response.json(); ret .then(function (data) { fkUserDevis = data[0].fk_user; fkStatutDevis = data[0].fk_statut_devis; chkValidat = data[0].chk_validat; idMarche = data[0].fk_marche; idNewMarche = data[0].fk_marche; // par défaut le nouveau marché est le même que le marché en cours sur ce devis chkClientsSecteur = data[0].chk_clients_secteur; showDevisEnTete(data); updateBtnSpeciaux(data[0].chk_speciaux); showDevisTotaux(data); }) .then(function () { //! Une fois le marché trouvé, on charge les infos du marché préchargé dans l'en-tête du devis fetch('/jxdevis/load_devis_marche_infos', { method: 'POST', body: JSON.stringify({ cid: idMarche }), headers: { 'Content-Type': 'application/json;charset=utf-8', Accept: 'application/json;charset=utf-8', }, }).then((response) => { if (!response.ok) { showNotification('Erreur', "Le chargement des infos du marché n'a pas abouti", 'error'); } else { const ret = response.json(); //! Boucle sur le résultat de la requête ajax ret.then(function (data) { showDevisMarcheInfos(data); chkRegleSeuilsMarge = data[0].chk_regle_seuils_marge; //! On charge ensuite les produits du marché de ce devis fetch('/jxdevis/load_devis_marche_produits', { method: 'POST', body: JSON.stringify({ cid: idMarche }), headers: { 'Content-Type': 'application/json;charset=utf-8', Accept: 'application/json;charset=utf-8', }, }).then((response) => { if (!response.ok) { showNotification('Erreur', "Le chargement des produits du marché n'a pas abouti", 'error'); } else { const ret = response.json(); ret.then(function (data) { dataProduitsMarche = data; showDevisMarcheProduits(dataFamilles, data); // on charge les produits enregistrés pour ce devis dans 2 tableaux distincts tblProduitsSelect (2ème onglet) et tblDevisPro (3ème onglet) fetch('/jxdevis/load_devis_produits', { method: 'POST', body: JSON.stringify({ cid: idDevis }), headers: { 'Content-Type': 'application/json;charset=utf-8', Accept: 'application/json;charset=utf-8', }, }).then((response) => { if (!response.ok) { showNotification('Erreur', "Le chargement des produits de ce devis n'a pas abouti", 'error'); } else { const ret = response.json(); //! Boucle sur le résultat de la requête ajax ret.then(function (data) { showDevisProduits(data); }); } }); }); } }); }); } }); }); } }) .catch((error) => { showNotification('Erreur', "Le chargement des infos de l'en-tête de ce devis n'a pas abouti", 'error'); }); hideLoading(); chkPageLoad = false; elDivDevis.style.display = 'block'; refreshChat(); //! On met enfin en évidence la ligne cliquée Array.from(elCelDevis).forEach(function (ligDevis) { if (ligDevis.getAttribute('data-rid') == oldIdLn) { ligDevis.style.backgroundColor = oldColorLn; } else if (ligDevis.getAttribute('data-rid') == idDevis) { oldColorLn = ligDevis.style.backgroundColor; ligDevis.style.backgroundColor = '#9bbce7'; } }); oldIdLn = idDevis; chkChange = 0; } }; let clickLigArchives = function () { //! L'utilisateur vient de cliquer sur un devis archivé dans la liste de gauche //! On ne fait rien si l'utilisateur clique sur le même devis if (this.getAttribute('data-rid') != idDevis) { if (chkChange == 1) { if (confirm('Attention, vous avez des modifications non enregistrées sur le devis en cours. Voulez-vous continuer ?')) { chkChange = 0; } else { return false; } } idDevis = this.getAttribute('data-rid'); refreshChat(); //! On met enfin en évidence la ligne cliquée Array.from(elCelArchives).forEach(function (ligArchive) { if (ligArchive.getAttribute('data-rid') == oldIdLn) { ligArchive.style.backgroundColor = oldColorLn; } else if (ligArchive.getAttribute('data-rid') == idDevis) { oldColorLn = ligArchive.style.backgroundColor; ligArchive.style.backgroundColor = '#9bbce7'; } }); oldIdLn = idDevis; chkChange = 0; } }; function showDevisEnTete(ret) { // Affiche les données de l'en-tête du devis const data = ret[0]; document.getElementById('inp_rowid').value = data.rowid; document.getElementById('inp_num_opportunite').value = data.num_opportunite; document.getElementById('inp_date_demande').value = data.date_demande; document.getElementById('inp_date_remise').value = data.date_remise; document.getElementById('inp_fk_user').value = data.fk_user; document.getElementById('inp_fk_marche').value = data.fk_marche; // On surveille un changement dans le champ fk_marche, ce qui peut provoquer la suppression des produits du devis s'il enregistre ce changement document.getElementById('inp_fk_marche').addEventListener('change', function () { idNewMarche = this.value; console.log('idNewMarche :' + idNewMarche); }); if (data.chk_clients_secteur == '1') { document.getElementById('inp_chk_clients_secteur').checked = true; } else { document.getElementById('inp_chk_clients_secteur').checked = false; } if (data.chk_clients_secteur != oldChkClientsSecteur) { // la valeur du chk_clients_secteur est différente de l'actuelle, on charge les clients du commercial sur son secteur ou sur toute la France changeClientsSecteur(); oldChkClientsSecteur == 2 ? (chkChange = 0) : (chkChange = 1); oldChkClientsSecteur = data.chk_clients_secteur; } document.getElementById('inp_fk_client').value = data.fk_client; console.log('fk_type_new :' + data.type_new_client); if (data.fk_client == 0) { document.getElementById('inp_lib_client').value = data.lib_new_client; document.getElementById('inp_adresse1').value = data.adresse1_new_client; document.getElementById('inp_adresse2').value = data.adresse2_new_client; document.getElementById('inp_adresse3').value = data.adresse3_new_client; document.getElementById('inp_cp').value = data.cp_new_client; document.getElementById('inp_ville').value = data.ville_new_client; document.getElementById('inp_contact_nom').value = data.contact_new_nom; document.getElementById('inp_contact_prenom').value = data.contact_new_prenom; document.getElementById('inp_contact_fonction').value = data.contact_new_fonction; document.getElementById('inp_email').value = data.new_email; document.getElementById('inp_telephone').value = data.new_telephone; document.getElementById('inp_mobile').value = data.new_mobile; document.getElementById('selTypeEtab').value = data.type_new_client; elBtnCreateClient.innerHTML = 'Modifier ce nouveau client'; if (elBtnCreateClient.classList.contains('btn-primary')) { elBtnCreateClient.classList.remove('btn-primary'); elBtnCreateClient.classList.add('btn-info'); } } else { document.getElementById('inp_lib_client').value = data.libelle; document.getElementById('inp_adresse1').value = data.adresse1; document.getElementById('inp_adresse2').value = data.adresse2; document.getElementById('inp_adresse3').value = data.adresse3; document.getElementById('inp_cp').value = data.cp; document.getElementById('inp_ville').value = data.ville; document.getElementById('inp_contact_nom').value = data.contact_nom; document.getElementById('inp_contact_prenom').value = data.contact_prenom; document.getElementById('inp_contact_fonction').value = data.contact_fonction; document.getElementById('inp_email').value = data.email; document.getElementById('inp_telephone').value = data.telephone; document.getElementById('inp_mobile').value = data.mobile; document.getElementById('selTypeEtab').value = data.type_client; elBtnCreateClient.innerHTML = 'Créer un nouveau client'; if (elBtnCreateClient.classList.contains('btn-info')) { elBtnCreateClient.classList.remove('btn-info'); elBtnCreateClient.classList.add('btn-primary'); } } if (data.chk_devis_photos == '1') { document.getElementById('inp_chk_devis_photos').checked = true; } else { document.getElementById('inp_chk_devis_photos').checked = false; } // Gestion et affichage des commentaires document.getElementById('inp_commentaire').value = data.commentaire; document.getElementById('inpCommentDevis').value = data.comment_devis; elInpCommentGesteComm.value = data.comment_geste_comm; // On supprime systématiquement la ligne de validation du devis let rowCommentValidatDevis = document.getElementById('rowCommentValidatDevis'); if (rowCommentValidatDevis !== null) { rowCommentValidatDevis.remove(); } if (fkUserDevis != fkUser && fkRole < 3) { // Le user actuel n'est pas le créateur du devis, et son rôle est le DIR-CO ou un DV const tblBodyComment = document.getElementById('tblCommentDevis').getElementsByTagName('tbody')[0]; // Insertion d'une nouvelle ligne et création de ses colonnes : on prend ici le fk_produit let newRowComment = tblBodyComment.insertRow(0); newRowComment.id = 'rowCommentValidatDevis'; let celLabel = newRowComment.insertCell(0); celLabel.innerHTML = ''; let celComment = newRowComment.insertCell(1); celComment.classList.add('w-60'); celComment.innerHTML = ''; let celBtnValid = newRowComment.insertCell(2); celBtnValid.classList.add('w-40'); celBtnValid.innerHTML = '