From 30d1eb1d4afec6c44288de68b1c8479344dc470c Mon Sep 17 00:00:00 2001 From: Alexis Burnaz <48258099+alxsbrz@users.noreply.github.com> Date: Sun, 16 Nov 2025 23:23:42 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Pr=C3=A9-remplissage=20depuis=20Tarif?= =?UTF-8?q?=20et=20d=C3=A9tection=20d'impact=20sur=20le=20tarif=20pour=20P?= =?UTF-8?q?rojet=20RC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout du pré-remplissage automatique des données depuis la page Tarif - Détection d'impact sur le tarif avec modal d'avertissement - Correction de la sauvegarde des grilles Ad Valorem (arrays au lieu de strings JSON) - Correction de la mise à jour du projetRC existant - Amélioration de la gestion des zones géographiques (zones désactivées) - Ajout de logs de débogage pour le chargement des grilles - Pré-remplissage automatique de 'Inclure les autres RC' si extensions RCE présentes --- tarif-rc/FICHIERS_MODIFIES.md | 90 ++ tarif-rc/public/js/projet-form-rc.js | 1474 +++++++++++++++++++++++--- 2 files changed, 1440 insertions(+), 124 deletions(-) create mode 100644 tarif-rc/FICHIERS_MODIFIES.md diff --git a/tarif-rc/FICHIERS_MODIFIES.md b/tarif-rc/FICHIERS_MODIFIES.md new file mode 100644 index 0000000..d4b19d2 --- /dev/null +++ b/tarif-rc/FICHIERS_MODIFIES.md @@ -0,0 +1,90 @@ +# Fichiers modifiés + +Ce fichier liste tous les fichiers qui ont été modifiés dans le cadre de l'implémentation de la fonctionnalité de pré-remplissage et de détection d'impact sur le tarif pour la page Projet RC. + +## Fichiers modifiés + +### 1. `/public/js/projet-form-rc.js` + +**Modifications principales :** + +#### Pré-remplissage depuis le Tarif +- Ajout de la fonction `prefillFromTarif()` pour pré-remplir les données du projet depuis le tarif (activités, marchandises, zones, activités complémentaires, type de cotisation, CA, RCE, Protection Juridique, garanties RCC) +- Modification de `populateFormData()` pour appeler `prefillFromTarif()` si un tarif existe +- Ajout du pré-remplissage automatique de "Inclure les autres RC" si des extensions RCE sont présentes + +#### Détection d'impact sur le tarif +- Ajout des variables globales pour les modulateurs (modRCActRCC, modRCMar, modRCZone, modRCActCompl, modRCGarAdd) +- Ajout de la fonction `loadModulateurs()` pour charger les modulateurs depuis l'API +- Ajout de la fonction `saveOriginalTarifData()` pour sauvegarder l'état initial du tarif +- Ajout de la fonction `checkTarifImpact()` pour détecter si une modification impacte le tarif +- Ajout des fonctions de détection d'impact spécifiques : + - `checkActivityImpact()` : détecte les modifications d'activités principales + - `checkMarchandiseImpact()` : détecte les modifications de marchandises + - `checkZoneImpact()` : détecte les modifications de zones géographiques (compare les coefficients maximums) + - `checkActiviteComplImpact()` : détecte les modifications d'activités complémentaires + - `checkGarantieRCCImpact()` : détecte les modifications de garanties RCC impactantes +- Ajout des fonctions de récupération des données actuelles : + - `getCurrentActivityData()` : récupère les activités principales actuelles + - `getCurrentMarchandiseData()` : récupère les marchandises actuelles + - `getCurrentZoneData()` : récupère les zones géographiques actuelles (prend en compte les zones désactivées) + - `getCurrentGarantieRCCData()` : récupère les garanties RCC actuelles + - `getCurrentActiviteComplData()` : récupère les activités complémentaires actuelles + +#### Modal d'avertissement +- Ajout de la fonction `showTarifImpactModal()` pour afficher le modal d'avertissement avec restauration intelligente des valeurs +- Le modal permet de restaurer la valeur originale sans recharger la page +- Ajout d'un flag `isRestoringValue` pour éviter les boucles infinies lors de la restauration + +#### Écouteurs d'événements +- Ajout de la fonction `setupTarifImpactListeners()` pour configurer les écouteurs d'événements sur tous les champs impactant le tarif : + - Sélecteur d'activités + - Sélecteur de marchandises + - Cases à cocher des zones géographiques + - Sélecteur de garanties RCC + - Boutons radio de type de cotisation + - Cases à cocher d'activités complémentaires + - Champs de saisie des capitaux d'activités (avec MutationObserver pour les champs dynamiques) + - Champ CA (Chiffre d'affaires) + - Switch Protection Juridique + +#### Sauvegarde des données +- Modification de `handleSubmitForm()` et `saveProjetRC()` pour : + - Mettre à jour le projetRC existant au lieu de toujours en créer un nouveau + - Envoyer les grilles Ad Valorem comme arrays directement (sans JSON.stringify) car PocketBase les parse automatiquement + - Sauvegarder correctement les zones même si elles sont désactivées +- Amélioration de `extractGrilleAdvalo()` pour : + - Gérer les tables cachées en les rendant temporairement visibles + - Extraire toutes les valeurs correctement, y compris les valeurs vides + - Restaurer correctement les styles après extraction + +#### Chargement des données +- Amélioration de `populateGrAdvalo()` pour : + - Ajouter des logs de débogage + - Vérifier que les données existent et sont valides avant de remplir le tableau + - Gérer les erreurs de parsing +- Amélioration de la logique de chargement des grilles Ad Valorem pour : + - Vérifier que les données existent avant de les charger + - Gérer les cas où les données sont vides ou invalides + - Afficher des messages d'avertissement dans la console + +#### Zones géographiques +- Correction de la logique de chargement des zones pour prendre en compte les zones désactivées +- Correction de la logique de sauvegarde pour inclure les zones désactivées (zone1 et zone2 quand zone2 ou zone3 sont sélectionnées) +- Amélioration de `getCurrentZoneData()` pour retourner `true` pour zone1 et zone2 si elles sont désactivées + +#### Protection Juridique et RCE +- Ajout du pré-remplissage de Protection Juridique depuis `tarif.checkPJ` +- Ajout du pré-remplissage des garanties RCC (contenant-confie, TPPC, ferroutage, etc.) depuis `rc` +- Ajout de la vérification automatique de "Inclure les autres RC" si des extensions RCE sont présentes +- Ajout de plusieurs vérifications avec setTimeout pour s'assurer que la case est cochée après tous les chargements + +## Date de modification +Date: 2025-01-27 + +## Notes importantes + +- Les grilles Ad Valorem sont maintenant envoyées comme arrays directement (sans JSON.stringify) car PocketBase les parse automatiquement +- Le modal d'avertissement se déclenche uniquement si une modification impacte réellement le tarif (par exemple, pour les zones, seulement si le coefficient maximum change) +- Les zones désactivées (zone1/zone2 quand zone2/zone3 sont sélectionnées) sont maintenant correctement sauvegardées et chargées +- La mise à jour du projetRC existant est maintenant gérée correctement au lieu de toujours créer un nouvel enregistrement diff --git a/tarif-rc/public/js/projet-form-rc.js b/tarif-rc/public/js/projet-form-rc.js index c7e25ba..a2c6dbf 100644 --- a/tarif-rc/public/js/projet-form-rc.js +++ b/tarif-rc/public/js/projet-form-rc.js @@ -9,6 +9,8 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio // Variables globales du module let parcours, contrat, client, intermediaire, rc, projet, tarif; + let modRCActRCC, modRCMar, modRCZone, modRCActCompl, modRCGarAdd; + // Initialisation des tag pour select var tagAnimauxVivants = false; var tagMultimodal = false; @@ -43,12 +45,948 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio console.log("Initialisation pour formulaire projet :", parcours); + loadModulateurs(); + // Appel des différentes fonctions d'initialisation setupEventListeners(); populateFormData(); + setupTarifImpactListeners(); updateSubmitButtonState('projetForm'); } + let tarifOriginalData = null; + + async function loadModulateurs() { + try { + const response = await fetch('/rc/modulo/activiteRCC'); + const data = await response.json(); + if (data.valid) { + modRCActRCC = data.objRetourne; + } + const response2 = await fetch('/rc/modulo/marchandiseRC'); + const data2 = await response2.json(); + if (data2.valid) { + modRCMar = data2.objRetourne; + } + const response3 = await fetch('/rc/modulo/zoneRC'); + const data3 = await response3.json(); + if (data3.valid) { + modRCZone = data3.objRetourne; + } + const response4 = await fetch('/rc/modulo/activiteComplRC'); + const data4 = await response4.json(); + if (data4.valid) { + modRCActCompl = data4.objRetourne; + } + const response5 = await fetch('/rc/modulo/garAdditionelRC'); + const data5 = await response5.json(); + if (data5.valid) { + modRCGarAdd = data5.objRetourne; + } + } catch (error) { + console.error('Erreur lors du chargement des modulateurs:', error); + } + } + + function saveOriginalTarifData() { + if (!tarif || !tarif.id) return; + + const garantieRCCSelector = document.getElementById('garantieRCC-selector'); + let garantiesRCC = []; + if (garantieRCCSelector) { + garantiesRCC = Array.from(garantieRCCSelector.selectedOptions).map(opt => opt.value); + } else if (projet) { + if (projet.extRCCConfie) garantiesRCC.push('contenant-confie'); + if (projet.extRCCTPPC) garantiesRCC.push('tppc'); + if (projet.extRCCModifCalArrim) garantiesRCC.push('modif-calage-arrimage'); + if (projet.extRCCFerroutage) garantiesRCC.push('ferroutage'); + if (projet.extRCCFraisRecons) garantiesRCC.push('frais-reconstitution'); + if (projet.extRCCRegie) garantiesRCC.push('regie'); + if (projet.extRCCSansMontageDemontage) garantiesRCC.push('sans-montage-demontage'); + } + + const parseArray = (value) => { + if (Array.isArray(value)) return value; + if (typeof value === 'string') { + try { + return JSON.parse(value); + } catch { + return []; + } + } + return []; + }; + + tarifOriginalData = { + checkVoiturier: rc?.checkVoiturier || false, + checkLoueur: rc?.checkLoueur || false, + checkCommissionnaire: rc?.checkCommissionnaire || false, + checkDemenageur: rc?.checkDemenageur || false, + checkLogistique: rc?.checkLogistique || false, + checkAutocariste: rc?.checkAutocariste || false, + checkAutres: rc?.checkAutres || false, + capitalVoiturier: rc?.capitalVoiturier || 0, + capitalCommissionnaire: rc?.capitalCommissionnaire || 0, + capitalDemenageur: rc?.capitalDemenageur || 0, + capitalLogistique: rc?.capitalLogistique || 0, + capitalAutocariste: rc?.capitalAutocariste || 0, + capitalAutres: rc?.capitalAutres || 0, + marchandisesVoiturier: parseArray(rc?.marchandisesVoiturier), + marchandisesCommissionnaire: parseArray(rc?.marchandisesCommissionnaire), + marchandisesDemenageur: parseArray(rc?.marchandisesDemenageur), + marchandisesLogistique: parseArray(rc?.marchandisesLogistique), + marchandisesAutocariste: parseArray(rc?.marchandisesAutocariste), + marchandisesAutres: parseArray(rc?.marchandisesAutres), + activitesVoiturier: parseArray(rc?.activitesVoiturier), + activitesCommissionnaire: parseArray(rc?.activitesCommissionnaire), + activitesDemenageur: parseArray(rc?.activitesDemenageur), + activitesLogistique: parseArray(rc?.activitesLogistique), + zone1: rc?.zone1 || false, + zone2: rc?.zone2 || false, + zone3: rc?.zone3 || false, + zone4: rc?.zone4 || false, + zone5: rc?.zone5 || false, + zone6: rc?.zone6 || false, + typeCotisation: rc?.typeCotisation || 'revisable', + checkRCE: rc?.checkRCE || false, + garantiesRCC: garantiesRCC, + ca: rc?.chiffreAffaires || tarif?.ca || '', + pj: tarif?.checkPJ || false + }; + } + + function checkTarifImpact(fieldType, fieldValue) { + if (!tarif || !tarif.id || !tarifOriginalData) return false; + + switch(fieldType) { + case 'activity': + return checkActivityImpact(fieldValue); + case 'marchandise': + return checkMarchandiseImpact(fieldValue); + case 'zone': + return checkZoneImpact(fieldValue); + case 'activiteCompl': + return checkActiviteComplImpact(fieldValue); + case 'typeCotisation': + return fieldValue === 'forfaitaire' && tarifOriginalData.typeCotisation === 'forfaitaire'; + default: + return false; + } + } + + function checkActivityImpact(activityData) { + if (!modRCActRCC) return false; + + const activities = ['checkVoiturier', 'checkCommissionnaire', 'checkDemenageur', 'checkLogistique', 'checkAutocariste', 'checkAutres']; + for (let act of activities) { + if (activityData[act] !== tarifOriginalData[act]) return true; + const capitalKey = act.replace('check', 'capital'); + const originalCapital = parseFloat(tarifOriginalData[capitalKey]) || 0; + const currentCapital = parseFloat(activityData[capitalKey]) || 0; + if (Math.abs(originalCapital - currentCapital) > 0.01) return true; + } + return false; + } + + function checkMarchandiseImpact(marchandiseData) { + if (!modRCMar) return false; + + const normalizeArray = (arr) => { + if (!arr) return []; + const normalized = Array.isArray(arr) ? arr : (typeof arr === 'string' ? JSON.parse(arr) : []); + return normalized.map(item => String(item).trim()).sort(); + }; + + const marchandiseKeys = ['marchandisesVoiturier', 'marchandisesCommissionnaire', 'marchandisesDemenageur', + 'marchandisesLogistique', 'marchandisesAutocariste', 'marchandisesAutres']; + for (let key of marchandiseKeys) { + const original = normalizeArray(tarifOriginalData[key]); + const current = normalizeArray(marchandiseData[key]); + if (JSON.stringify(original) !== JSON.stringify(current)) return true; + } + return false; + } + + function checkZoneImpact(zoneData) { + if (!modRCZone) return false; + + function getMaxZoneCoefficient(zones) { + let maxRCC = 1; + let maxRCE = 1; + + const zoneLabels = [ + "France Métropolitaine et pays limitrophes", + "Union Européenne", + "Autres pays européens sauf Russie et Ukraine (y compris UK et Norvège)", + "Pays du Maghreb et Amérique du Nord ( USA / Canada / Mexique )", + "Amérique Centrale et Sud / Caraïbes, Asie et Océanie", + "Afrique Hors Maghreb / Proche Orient / Moyen Orient" + ]; + + for (let i = 1; i <= 6; i++) { + if (zones[`zone${i}`]) { + const zoneKey = zoneLabels[i - 1]; + if (modRCZone[zoneKey]) { + if (typeof modRCZone[zoneKey].modRCC === "number") { + maxRCC = Math.max(maxRCC, modRCZone[zoneKey].modRCC); + } + if (typeof modRCZone[zoneKey].modRCE === "number") { + maxRCE = Math.max(maxRCE, modRCZone[zoneKey].modRCE); + } + } + } + } + + return { maxRCC, maxRCE }; + } + + const originalMax = getMaxZoneCoefficient(tarifOriginalData); + const currentMax = getMaxZoneCoefficient(zoneData); + + return originalMax.maxRCC !== currentMax.maxRCC || originalMax.maxRCE !== currentMax.maxRCE; + } + + function checkActiviteComplImpact(activiteComplData) { + if (!modRCActCompl) return false; + + const activiteKeys = ['activitesVoiturier', 'activitesCommissionnaire', 'activitesDemenageur', 'activitesLogistique']; + for (let key of activiteKeys) { + const original = Array.isArray(tarifOriginalData[key]) ? tarifOriginalData[key] : (tarifOriginalData[key] ? JSON.parse(tarifOriginalData[key]) : []); + const current = Array.isArray(activiteComplData[key]) ? activiteComplData[key] : (activiteComplData[key] ? JSON.parse(activiteComplData[key]) : []); + if (JSON.stringify(original.sort()) !== JSON.stringify(current.sort())) return true; + } + return false; + } + + function getCurrentActiviteComplData() { + const activitesCompl = { + activitesVoiturier: getActivitesComplFromForm('actComplVoiturier/Loueur'), + activitesCommissionnaire: getActivitesComplFromForm('actComplCommissionnaire de Transport'), + activitesDemenageur: getActivitesComplFromForm('actComplDéménageur'), + activitesLogistique: getActivitesComplFromForm('actComplLogistique') + }; + return activitesCompl; + } + + function getActivitesComplFromForm(containerName) { + const container = document.querySelector(`[name="${containerName}"]`); + if (!container) return []; + const checkboxes = container.querySelectorAll('input[type="checkbox"]:checked'); + const activites = []; + checkboxes.forEach(cb => { + const text = cb.nextElementSibling ? cb.nextElementSibling.textContent.trim() : cb.value; + activites.push(text); + }); + return activites; + } + + let lastChangedField = null; + let lastChangedValue = null; + let isRestoringValue = false; + + function showTarifImpactModal(callback, fieldElement, originalValue) { + const modal = document.getElementById('modalModif'); + if (!modal) return; + + const instance = M.Modal.getInstance(modal); + + lastChangedField = fieldElement; + lastChangedValue = originalValue; + + const okBtn = document.getElementById('modif-OK'); + const noBtn = document.getElementById('modif-NO'); + + if (okBtn) { + okBtn.onclick = function() { + instance.close(); + if (callback) callback(true); + }; + } + + if (noBtn) { + noBtn.onclick = function() { + instance.close(); + isRestoringValue = true; + + if (lastChangedField && lastChangedValue !== null) { + if (lastChangedField.tagName === 'INPUT') { + lastChangedField.value = lastChangedValue; + } else if (lastChangedField.tagName === 'SELECT') { + if (lastChangedField.multiple && Array.isArray(lastChangedValue)) { + Array.from(lastChangedField.options).forEach(opt => { + opt.selected = lastChangedValue.includes(opt.value); + }); + } else { + lastChangedField.value = lastChangedValue; + } + M.FormSelect.init(lastChangedField); + + if (lastChangedField.id === 'activity-selector') { + handleActivitySelection(); + } + } else if (lastChangedField.type === 'checkbox' || lastChangedField.type === 'radio') { + lastChangedField.checked = lastChangedValue; + } + } + + setTimeout(() => { + isRestoringValue = false; + }, 100); + + if (callback) callback(false); + }; + } + + instance.open(); + } + + function setupTarifImpactListeners() { + if (!tarif || !tarif.id) return; + + setTimeout(() => { + saveOriginalTarifData(); + }, 500); + + const activitySelector = document.getElementById('activity-selector'); + if (activitySelector) { + activitySelector.addEventListener('change', function(e) { + if (isRestoringValue) return; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentActivityData(); + if (checkTarifImpact('activity', currentData)) { + e.stopImmediatePropagation(); + e.preventDefault(); + const originalSelection = Array.from(this.options).filter(opt => { + const wasSelected = tarifOriginalData.checkVoiturier && (opt.value === 'voiturier' || opt.value === 'loueur') || + tarifOriginalData.checkCommissionnaire && opt.value === 'commissionnaire-multimodal' || + tarifOriginalData.checkDemenageur && (opt.value === 'demenageur-particulier' || opt.value === 'demenageur-entreprise' || opt.value === 'demenageur-interne') || + tarifOriginalData.checkLogistique && (opt.value === 'entrepositaire-depositaire' || opt.value === 'prestataire-logistique') || + tarifOriginalData.checkAutocariste && opt.value === 'autocariste' || + tarifOriginalData.checkAutres && opt.value === 'autres'; + return wasSelected; + }).map(opt => opt.value); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalSelection); + return false; + } + }, 200); + }, true); + } + + const marchandiseSelector = document.getElementById('marchandise-selector'); + if (marchandiseSelector) { + let lastMarchandiseSelection = Array.from(marchandiseSelector.selectedOptions).map(opt => opt.value); + + marchandiseSelector.addEventListener('mousedown', function() { + if (!isRestoringValue) { + lastMarchandiseSelection = Array.from(this.selectedOptions).map(opt => opt.value); + } + }, true); + + marchandiseSelector.addEventListener('change', function(e) { + if (isRestoringValue) { + handleMarchandiseSelection(); + return; + } + + const originalSelection = lastMarchandiseSelection; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentMarchandiseData(); + if (checkTarifImpact('marchandise', currentData)) { + e.stopImmediatePropagation(); + e.preventDefault(); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalSelection); + } else { + lastMarchandiseSelection = Array.from(this.selectedOptions).map(opt => opt.value); + handleMarchandiseSelection(); + } + }, 200); + }, true); + } + + for (let i = 1; i <= 6; i++) { + const zoneCheckbox = document.getElementById(`zone${i}`); + if (zoneCheckbox) { + zoneCheckbox.addEventListener('change', function(e) { + if (isRestoringValue) return; + + const checkboxId = this.id; + const originalChecked = tarifOriginalData[checkboxId] || false; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentZoneData(); + if (checkTarifImpact('zone', currentData)) { + e.stopImmediatePropagation(); + e.preventDefault(); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalChecked); + } + }, 200); + }, true); + } + } + + const garantieRCCSelector = document.getElementById('garantieRCC-selector'); + if (garantieRCCSelector) { + garantieRCCSelector.addEventListener('change', function(e) { + if (isRestoringValue) return; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentGarantieRCCData(); + if (checkGarantieRCCImpact(currentData)) { + e.stopImmediatePropagation(); + const originalSelection = Array.from(this.selectedOptions).map(opt => opt.value); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalSelection); + } + }, 200); + }, true); + } + + const activiteComplContainers = [ + 'actComplVoiturier/Loueur', + 'actComplCommissionnaire de Transport', + 'actComplDéménageur', + 'actComplLogistique' + ]; + + activiteComplContainers.forEach(containerName => { + const container = document.querySelector(`[name="${containerName}"]`); + if (container) { + const checkboxes = container.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(checkbox => { + checkbox.addEventListener('change', function(e) { + if (isRestoringValue) return; + + const originalChecked = !this.checked; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentActiviteComplData(); + if (checkTarifImpact('activiteCompl', currentData)) { + e.stopImmediatePropagation(); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalChecked); + } + }, 200); + }, true); + }); + } + }); + + const radioButtonsCot = document.getElementsByName('cotisation'); + for (let i = 0; i < radioButtonsCot.length; i++) { + radioButtonsCot[i].addEventListener('change', function(e) { + if (isRestoringValue) return; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const originalValue = tarifOriginalData.typeCotisation; + if (this.value !== originalValue) { + e.stopImmediatePropagation(); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalValue); + } + }, 200); + }, true); + } + + const capitalFields = ['voiturier', 'loueur', 'commissionnaire-multimodal', 'demenageur-particulier', + 'demenageur-particulier-dommage', 'demenageur-particulier-advalorem', + 'demenageur-entreprise', 'demenageur-interne', 'entrepositaire-depositaire', + 'prestataire-logistique', 'autocariste', 'autres']; + + capitalFields.forEach(fieldId => { + const field = document.getElementById(fieldId); + if (field) { + let originalValue = field.value || field.dataset.defaultValue || ''; + field.addEventListener('input', function(e) { + if (isRestoringValue) return; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentActivityData(); + if (checkTarifImpact('activity', currentData)) { + const currentValue = this.value; + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalValue); + } else { + originalValue = this.value; + } + }, 200); + }); + } + }); + + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.addedNodes.length) { + capitalFields.forEach(fieldId => { + const field = document.getElementById(fieldId); + if (field && !field.hasAttribute('data-tarif-listener')) { + field.setAttribute('data-tarif-listener', 'true'); + let originalValue = field.value || field.dataset.defaultValue || ''; + field.addEventListener('input', function(e) { + if (isRestoringValue) return; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + const currentData = getCurrentActivityData(); + if (checkTarifImpact('activity', currentData)) { + const currentValue = this.value; + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalValue); + } else { + originalValue = this.value; + } + }, 200); + }); + } + }); + } + }); + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); + + const switchPJ = document.getElementById('switchPJ'); + if (switchPJ) { + switchPJ.addEventListener('change', function(e) { + if (isRestoringValue) return; + + const originalChecked = tarifOriginalData.pj || false; + + setTimeout(() => { + if (!tarif || !tarif.id || !tarifOriginalData || isRestoringValue) return; + if (this.checked !== originalChecked) { + e.stopImmediatePropagation(); + e.preventDefault(); + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalChecked); + } + }, 200); + }, true); + } + } + + function checkGarantieRCCImpact(garantieData) { + if (!modRCActCompl && !modRCGarAdd) return false; + + const garantiesImpactantes = ['contenant-confie', 'tppc']; + const originalGaranties = tarifOriginalData?.garantiesRCC || []; + const currentGaranties = garantieData || []; + + for (let garantie of garantiesImpactantes) { + const wasSelected = originalGaranties.includes(garantie); + const isSelected = currentGaranties.includes(garantie); + if (wasSelected !== isSelected) return true; + } + + return false; + } + + function getCurrentActivityData() { + const activitySelector = document.getElementById('activity-selector'); + const selectedActivities = Array.from(activitySelector.selectedOptions).map(opt => opt.value); + + return { + checkVoiturier: selectedActivities.includes('voiturier') || selectedActivities.includes('loueur'), + checkCommissionnaire: selectedActivities.includes('commissionnaire-multimodal'), + checkDemenageur: selectedActivities.includes('demenageur-particulier') || selectedActivities.includes('demenageur-entreprise') || selectedActivities.includes('demenageur-interne'), + checkLogistique: selectedActivities.includes('entrepositaire-depositaire') || selectedActivities.includes('prestataire-logistique'), + checkAutocariste: selectedActivities.includes('autocariste'), + checkAutres: selectedActivities.includes('autres'), + capitalVoiturier: document.getElementById("voiturier") ? parseFloat(document.getElementById("voiturier").value) || 0 : (document.getElementById("select-voiturier")?.dataset.defaultValue ? parseFloat(document.getElementById("select-voiturier").dataset.defaultValue) : 0), + capitalCommissionnaire: document.getElementById("commissionnaire-multimodal") ? parseFloat(document.getElementById("commissionnaire-multimodal").value) || 0 : (document.getElementById("select-commissionnaire-multimodal")?.dataset.defaultValue ? parseFloat(document.getElementById("select-commissionnaire-multimodal").dataset.defaultValue) : 0), + capitalDemenageur: document.getElementById("demenageur-particulier") ? parseFloat(document.getElementById("demenageur-particulier").value) || 0 : (document.getElementById("select-demenageur-particulier")?.dataset.defaultValue ? parseFloat(document.getElementById("select-demenageur-particulier").dataset.defaultValue) : 0), + capitalLogistique: document.getElementById("entrepositaire-depositaire") ? parseFloat(document.getElementById("entrepositaire-depositaire").value) || 0 : (document.getElementById("select-entrepositaire-depositaire")?.dataset.defaultValue ? parseFloat(document.getElementById("select-entrepositaire-depositaire").dataset.defaultValue) : 0) + }; + } + + function getCurrentMarchandiseData() { + const selectedMarchandises = getSelectedMarchandises(); + const marchandiseTexts = selectedMarchandises.map(val => { + const option = document.querySelector(`#marchandise-selector option[value="${val}"]`); + return option ? option.textContent.trim() : val; + }); + + return { + marchandisesVoiturier: marchandiseTexts, + marchandisesCommissionnaire: marchandiseTexts, + marchandisesDemenageur: marchandiseTexts, + marchandisesLogistique: marchandiseTexts, + marchandisesAutocariste: marchandiseTexts, + marchandisesAutres: marchandiseTexts + }; + } + + function getCurrentZoneData() { + const zone1 = document.getElementById("zone1"); + const zone2 = document.getElementById("zone2"); + return { + zone1: zone1 && (zone1.checked || zone1.disabled), + zone2: zone2 && (zone2.checked || zone2.disabled), + zone3: document.getElementById("zone3") && document.getElementById("zone3").checked, + zone4: document.getElementById("zone4") && document.getElementById("zone4").checked, + zone5: document.getElementById("zone5") && document.getElementById("zone5").checked, + zone6: document.getElementById("zone6") && document.getElementById("zone6").checked + }; + } + + function getCurrentGarantieRCCData() { + const selector = document.getElementById('garantieRCC-selector'); + return Array.from(selector.selectedOptions).map(opt => opt.value); + } + + function getSelectedMarchandises() { + const selector = document.getElementById('marchandise-selector'); + return Array.from(selector.selectedOptions).map(opt => opt.value); + } + + function prefillFromTarif() { + if (!tarif || !rc) return; + + function parseArray(value) { + if (Array.isArray(value)) return value; + if (typeof value === 'string') { + try { + return JSON.parse(value); + } catch { + return []; + } + } + return []; + } + + const activitySelector = document.getElementById('activity-selector'); + const marchandiseSelector = document.getElementById('marchandise-selector'); + + if (rc.checkVoiturier && !projet?.actVoiturier && activitySelector) { + const voiturierOption = activitySelector.querySelector('option[value="voiturier"]'); + if (voiturierOption && !voiturierOption.selected) { + voiturierOption.selected = true; + if (rc.capitalVoiturier && document.getElementById("select-voiturier")) { + document.getElementById("select-voiturier").dataset.defaultValue = rc.capitalVoiturier; + } + } + } + + if (rc.checkLoueur && !projet?.actLoueur && activitySelector) { + const loueurOption = activitySelector.querySelector('option[value="loueur"]'); + if (loueurOption && !loueurOption.selected) { + loueurOption.selected = true; + } + } + + if (rc.checkCommissionnaire && !projet?.actMultimodal && activitySelector) { + const multimodalOption = activitySelector.querySelector('option[value="commissionnaire-multimodal"]'); + if (multimodalOption && !multimodalOption.selected) { + multimodalOption.selected = true; + if (rc.capitalCommissionnaire && document.getElementById("select-commissionnaire-multimodal")) { + document.getElementById("select-commissionnaire-multimodal").dataset.defaultValue = rc.capitalCommissionnaire; + } + } + } + + if (rc.checkDemenageur && !projet?.actDemPar && activitySelector) { + const demenageurOption = activitySelector.querySelector('option[value="demenageur-particulier"]'); + if (demenageurOption && !demenageurOption.selected) { + demenageurOption.selected = true; + if (rc.capitalDemenageur && document.getElementById("select-demenageur-particulier")) { + document.getElementById("select-demenageur-particulier").dataset.defaultValue = rc.capitalDemenageur; + } + } + } + + if (rc.checkLogistique && !projet?.actEntDep && !projet?.actPrestaLog && activitySelector) { + const entrepositaireOption = activitySelector.querySelector('option[value="entrepositaire-depositaire"]'); + if (entrepositaireOption && !entrepositaireOption.selected) { + entrepositaireOption.selected = true; + if (rc.capitalLogistique && document.getElementById("select-entrepositaire-depositaire")) { + document.getElementById("select-entrepositaire-depositaire").dataset.defaultValue = rc.capitalLogistique; + } + } + } + + if (rc.checkAutocariste && activitySelector) { + const autocaristeOption = activitySelector.querySelector('option[value="autocariste"]'); + if (autocaristeOption && !autocaristeOption.selected) { + autocaristeOption.selected = true; + if (rc.capitalAutocariste && document.getElementById("select-autocariste")) { + document.getElementById("select-autocariste").dataset.defaultValue = rc.capitalAutocariste; + } + } + } + + if (rc.checkAutres && activitySelector) { + const autresOption = activitySelector.querySelector('option[value="autres"]'); + if (autresOption && !autresOption.selected) { + autresOption.selected = true; + if (rc.capitalAutres && document.getElementById("select-autres")) { + document.getElementById("select-autres").dataset.defaultValue = rc.capitalAutres; + } + } + } + + if (marchandiseSelector) { + const allMarchandises = [ + ...(parseArray(rc.marchandisesVoiturier)), + ...(parseArray(rc.marchandisesCommissionnaire)), + ...(parseArray(rc.marchandisesDemenageur)), + ...(parseArray(rc.marchandisesLogistique)), + ...(parseArray(rc.marchandisesAutocariste)), + ...(parseArray(rc.marchandisesAutres)) + ]; + + const uniqueMarchandises = [...new Set(allMarchandises)]; + + const marchandiseMapping = { + 'Marchandises ordinaires': 'ordinaire', + 'Marchandises ordinaires et assimilées, les marchandises dangereuses dans le respect de la réglementation': 'ordinaire', + 'Véhicules roulants': 'roulant', + 'Engins de chantier et engins agricoles': 'engins-chantier-agricole', + 'Engins de chantier': 'engins-chantier-agricole', + 'Véhicules roulants dans le cadre d\'une activité de déménagement': 'roulant-demenagement', + 'Mobiliers usagés – Objets et effets personnels en déménagement': 'mobilier-usages', + 'Mobiliers en déménagement': 'mobilier-usages', + 'Marchandises périssables sous température dirigée': 'perissable-temperature-dirigee', + 'Marchandises périssables': 'perissable-temperature-dirigee', + 'Animaux vivants': 'animaux-vivant', + 'Marchandises en citerne': 'citerne', + 'Transports de béton': 'beton', + 'Transport de béton': 'beton', + 'Transports exceptionnels': 'exceptionnels', + 'Marchandises en vrac transportées en benne': 'vrac', + 'Marchandises en benne': 'vrac' + }; + + uniqueMarchandises.forEach(marchText => { + const mappedValue = marchandiseMapping[marchText] || marchText.toLowerCase().replace(/\s+/g, '-'); + const option = marchandiseSelector.querySelector(`option[value="${mappedValue}"]`); + if (option && !option.selected) { + option.selected = true; + } else if (!option) { + const options = marchandiseSelector.querySelectorAll('option'); + options.forEach(opt => { + if (opt.textContent.trim().includes(marchText) || marchText.includes(opt.textContent.trim().substring(0, 20))) { + if (!opt.selected) opt.selected = true; + } + }); + } + }); + } + + if (rc.zone1 !== undefined && !projet?.zone1) { + const zone1El = document.getElementById("zone1"); + if (zone1El) zone1El.checked = rc.zone1; + } + if (rc.zone2 !== undefined && !projet?.zone2) { + const zone2El = document.getElementById("zone2"); + if (zone2El) zone2El.checked = rc.zone2; + } + if (rc.zone3 !== undefined && !projet?.zone3) { + const zone3El = document.getElementById("zone3"); + if (zone3El) zone3El.checked = rc.zone3; + } + if (rc.zone4 !== undefined && !projet?.zone4) { + const zone4El = document.getElementById("zone4"); + if (zone4El) zone4El.checked = rc.zone4; + } + if (rc.zone5 !== undefined && !projet?.zone5) { + const zone5El = document.getElementById("zone5"); + if (zone5El) zone5El.checked = rc.zone5; + } + if (rc.zone6 !== undefined && !projet?.zone6) { + const zone6El = document.getElementById("zone6"); + if (zone6El) zone6El.checked = rc.zone6; + } + + if (rc.typeCotisation && !projet?.typeCot) { + const radioCot = document.getElementById(rc.typeCotisation); + if (radioCot) radioCot.checked = true; + } + + if (rc.chiffreAffaires && !projet?.ca) { + const caEl = document.getElementById("CA"); + if (caEl) caEl.value = rc.chiffreAffaires; + } + + const hasRCEFromRC = rc && rc.checkRCE; + const hasRCEFromTarif = tarif && tarif.checkRCE; + if (hasRCEFromRC || hasRCEFromTarif) { + const choixRCEEl = document.getElementById("choixRCE"); + if (choixRCEEl) { + choixRCEEl.checked = true; + const garantieRCEEl = document.getElementById('garantieRCE'); + if (garantieRCEEl) garantieRCEEl.style.display = 'block'; + const rce1El = document.getElementById('RCE1'); + if (rce1El) rce1El.style.display = ''; + const rce2El = document.getElementById('RCE2'); + if (rce2El) rce2El.style.display = ''; + } + } + + if (tarif && tarif.checkPJ && !projet?.pj) { + const switchPJEl = document.getElementById("switchPJ"); + if (switchPJEl) { + switchPJEl.checked = true; + const pj1El = document.getElementById('PJ1'); + if (pj1El) pj1El.style.display = ''; + const pj2El = document.getElementById('PJ2'); + if (pj2El) pj2El.style.display = ''; + + if (tarif.cotPJHT && !projet?.cotPJHT) { + const cotPJHTEl = document.getElementById('cotPJHT'); + if (cotPJHTEl) cotPJHTEl.value = tarif.cotPJHT; + } + if (tarif.cotPJTTC && !projet?.cotPJTTC) { + const cotPJTTCEl = document.getElementById('cotPJTTC'); + if (cotPJTTCEl) cotPJTTCEl.value = tarif.cotPJTTC; + } + } + } + + const garantieRCCSelector = document.getElementById('garantieRCC-selector'); + if (garantieRCCSelector && !projet) { + if (rc.extRCCModifCalArrim) { + const option = garantieRCCSelector.querySelector('option[value="modif-calage-arrimage"]'); + if (option) option.selected = true; + } + if (rc.extRCCFerroutage) { + const option = garantieRCCSelector.querySelector('option[value="ferroutage"]'); + if (option) option.selected = true; + } + if (rc.extRCCFraisRecons) { + const option = garantieRCCSelector.querySelector('option[value="frais-reconstitution"]'); + if (option) option.selected = true; + } + if (rc.extRCCConfie) { + const option = garantieRCCSelector.querySelector('option[value="contenant-confie"]'); + if (option) option.selected = true; + } + if (rc.extRCCTPPC) { + const option = garantieRCCSelector.querySelector('option[value="tppc"]'); + if (option) option.selected = true; + } + if (rc.extRCCRegie) { + const option = garantieRCCSelector.querySelector('option[value="regie"]'); + if (option) option.selected = true; + } + if (rc.extRCCSansMontageDemontage) { + const option = garantieRCCSelector.querySelector('option[value="sans-montage-demontage"]'); + if (option) option.selected = true; + } + } + + const activitesVoiturier = parseArray(rc.activitesVoiturier); + if (activitesVoiturier.length > 0) { + const container = document.querySelector('[name="actComplVoiturier/Loueur"]'); + if (container) { + activitesVoiturier.forEach(activite => { + const checkboxes = container.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(cb => { + const label = cb.nextElementSibling; + if (label && label.textContent.trim() === activite) { + cb.checked = true; + } + }); + }); + } + } + + const activitesCommissionnaire = parseArray(rc.activitesCommissionnaire); + if (activitesCommissionnaire.length > 0) { + const container = document.querySelector('[name="actComplCommissionnaire de Transport"]'); + if (container) { + activitesCommissionnaire.forEach(activite => { + const checkboxes = container.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(cb => { + const label = cb.nextElementSibling; + if (label && label.textContent.trim() === activite) { + cb.checked = true; + } + }); + }); + } + } + + const activitesDemenageur = parseArray(rc.activitesDemenageur); + if (activitesDemenageur.length > 0) { + const container = document.querySelector('[name="actComplDéménageur"]'); + if (container) { + activitesDemenageur.forEach(activite => { + const checkboxes = container.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(cb => { + const label = cb.nextElementSibling; + if (label && label.textContent.trim() === activite) { + cb.checked = true; + } + }); + }); + } + } + + const activitesLogistique = parseArray(rc.activitesLogistique); + if (activitesLogistique.length > 0) { + const container = document.querySelector('[name="actComplLogistique"]'); + if (container) { + activitesLogistique.forEach(activite => { + const checkboxes = container.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(cb => { + const label = cb.nextElementSibling; + if (label && label.textContent.trim() === activite) { + cb.checked = true; + } + }); + }); + } + } + + if (activitySelector) { + activitySelector.dispatchEvent(new Event('change')); + } + if (marchandiseSelector) { + marchandiseSelector.dispatchEvent(new Event('change')); + } + } + // Configuration des écouteurs d'événements function setupEventListeners() { document.getElementById('projetFormBtn').addEventListener('click', handleSubmitForm); @@ -368,14 +1306,33 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio }); document.getElementById('CA').addEventListener('input', function () { - // Alerte : modification du CA nécessite de retourner au tarif - if (tarif && tarif.id) { - M.toast({ - html: '⚠️ Attention : La modification du CA nécessite de recalculer le tarif !', - classes: 'orange darken-2', - displayLength: 6000 - }); + if (isRestoringValue) { + validateField('CA', true); + updateSubmitButtonState('projetForm'); + calcCotFromTauxCA('tauxRCCHT', 'cotRCCHT'); + calcAddTaxe('cotRCCHT', 0, 'cotRCCTTC'); + calcCotFromTauxCA('tauxRCEHT', 'cotRCEHT'); + calcAddTaxe('cotRCEHT', 0.09, 'cotRCETTC'); + calcCotIrreductible(); + calcCotTotal(); + return; } + + if (tarif && tarif.id && tarifOriginalData) { + const currentValue = this.value.trim(); + const originalValue = tarifOriginalData.ca || ''; + + if (currentValue !== originalValue) { + const originalValueToRestore = originalValue; + showTarifImpactModal((confirmed) => { + if (confirmed) { + window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`; + } + }, this, originalValueToRestore); + return; + } + } + validateField('CA', true); updateSubmitButtonState('projetForm'); calcCotFromTauxCA('tauxRCCHT', 'cotRCCHT'); @@ -732,8 +1689,57 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio M.FormSelect.init(idSelect); } + // Pré-remplir depuis le tarif si disponible (même si projet existe, on complète avec les données du tarif) + if (tarif && tarif.id) { + setTimeout(() => { + prefillFromTarif(); + + // S'assurer que "Inclure les autres RC" est coché après prefillFromTarif + setTimeout(() => { + const hasRCEProjet = projet && (projet.autresRC || projet.extRCEBraDebra || projet.extRCEMontageDemontage); + const hasRCERC = rc && rc.checkRCE; + const hasRCETarif = tarif && tarif.checkRCE; + const hasRCE = hasRCEProjet || hasRCERC || hasRCETarif; + + if (hasRCE) { + const choixRCEEl = document.getElementById("choixRCE"); + if (choixRCEEl) { + choixRCEEl.checked = true; + const garantieRCEEl = document.getElementById('garantieRCE'); + if (garantieRCEEl) garantieRCEEl.style.display = 'block'; + const rce1El = document.getElementById('RCE1'); + if (rce1El) rce1El.style.display = ''; + const rce2El = document.getElementById('RCE2'); + if (rce2El) rce2El.style.display = ''; + } + } + }, 200); + }, 300); + } + + // S'assurer que "Inclure les autres RC" est coché si nécessaire (après le chargement de toutes les données projet) + setTimeout(() => { + const hasRCEProjet = projet && (projet.autresRC || projet.extRCEBraDebra || projet.extRCEMontageDemontage); + const hasRCERC = rc && rc.checkRCE; + const hasRCETarif = tarif && tarif.checkRCE; + const hasRCE = hasRCEProjet || hasRCERC || hasRCETarif; + + if (hasRCE) { + const choixRCEEl = document.getElementById("choixRCE"); + if (choixRCEEl && !choixRCEEl.checked) { + choixRCEEl.checked = true; + const garantieRCEEl = document.getElementById('garantieRCE'); + if (garantieRCEEl) garantieRCEEl.style.display = 'block'; + const rce1El = document.getElementById('RCE1'); + if (rce1El) rce1El.style.display = ''; + const rce2El = document.getElementById('RCE2'); + if (rce2El) rce2El.style.display = ''; + } + } + }, 600); + // Populate par défaut Voiturier / Loueur - if (!projet) { + if (!projet && !tarif) { document.getElementById('activity-selector').querySelector('option[value="voiturier"]').selected = true; document.getElementById('activity-selector').querySelector('option[value="loueur"]').selected = true; document.getElementById('activity-selector').dispatchEvent(new Event('change')); @@ -856,22 +1862,44 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio // Populate territorialité - depuis projet OU depuis rc (tarif) en fallback const zonesSource = projet || rc; - if (zonesSource && zonesSource.zone1) { document.getElementById("zone1").checked = true }; - if (zonesSource && zonesSource.zone2) { - document.getElementById("zone2").checked = true; - document.getElementById("zone1").checked = true; - document.getElementById("zone1").disabled = true; - }; - if (zonesSource && zonesSource.zone3) { - document.getElementById("zone3").checked = true; - document.getElementById("zone2").checked = true; - document.getElementById("zone2").disabled = true; - document.getElementById("zone1").checked = true; - document.getElementById("zone1").disabled = true; - }; - if (zonesSource && zonesSource.zone4) { document.getElementById("zone4").checked = true }; - if (zonesSource && zonesSource.zone5) { document.getElementById("zone5").checked = true }; - if (zonesSource && zonesSource.zone6) { document.getElementById("zone6").checked = true }; + if (zonesSource) { + if (zonesSource.zone1) { + document.getElementById("zone1").checked = true; + document.getElementById("zone1").disabled = false; + } + if (zonesSource.zone2) { + document.getElementById("zone2").checked = true; + document.getElementById("zone2").disabled = false; + if (!zonesSource.zone1) { + document.getElementById("zone1").checked = true; + document.getElementById("zone1").disabled = true; + } + } + if (zonesSource.zone3) { + document.getElementById("zone3").checked = true; + document.getElementById("zone3").disabled = false; + if (!zonesSource.zone2) { + document.getElementById("zone2").checked = true; + document.getElementById("zone2").disabled = true; + } + if (!zonesSource.zone1) { + document.getElementById("zone1").checked = true; + document.getElementById("zone1").disabled = true; + } + } + if (zonesSource.zone4) { + document.getElementById("zone4").checked = true; + document.getElementById("zone4").disabled = false; + } + if (zonesSource.zone5) { + document.getElementById("zone5").checked = true; + document.getElementById("zone5").disabled = false; + } + if (zonesSource.zone6) { + document.getElementById("zone6").checked = true; + document.getElementById("zone6").disabled = false; + } + } // Populate extensions de garantie RCC const garantieRCCSelector = document.getElementById('garantieRCC-selector'); @@ -894,20 +1922,45 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio document.getElementById('garantieRCC-selector').dispatchEvent(new Event('change')); - // Populate extensions de garantie RCC - if (projet && projet.autresRC) { - document.getElementById("choixRCE").checked = true; - document.getElementById('garantieRCE').style.display = 'block'; - document.getElementById('RCE1').style.display = ''; - document.getElementById('RCE2').style.display = ''; - } + // Populate extensions de garantie RCE - DOIT être fait APRÈS le chargement des données projet + setTimeout(() => { + const hasRCEProjet = projet && (projet.autresRC || projet.extRCEBraDebra || projet.extRCEMontageDemontage); + const hasRCERC = rc && rc.checkRCE; + const hasRCETarif = tarif && tarif.checkRCE; + const hasRCE = hasRCEProjet || hasRCERC || hasRCETarif; + + if (hasRCE) { + const choixRCEEl = document.getElementById("choixRCE"); + if (choixRCEEl) { + choixRCEEl.checked = true; + const garantieRCEEl = document.getElementById('garantieRCE'); + if (garantieRCEEl) { + garantieRCEEl.style.display = 'block'; + } + const rce1El = document.getElementById('RCE1'); + if (rce1El) { + rce1El.style.display = ''; + } + const rce2El = document.getElementById('RCE2'); + if (rce2El) { + rce2El.style.display = ''; + } + } + } + }, 100); const garantieRCESelector = document.getElementById('garantieRCE-selector'); - - if (projet && projet.extRCEBraDebra) { garantieRCESelector.querySelector('option[value="branchement-debranchement"]').selected = true; }; - if (projet && projet.extRCEMontageDemontage) { garantieRCESelector.querySelector('option[value="montage-demontage"]').selected = true; }; - - document.getElementById('garantieRCE-selector').dispatchEvent(new Event('change')); + if (garantieRCESelector) { + if (projet && projet.extRCEBraDebra) { + const option = garantieRCESelector.querySelector('option[value="branchement-debranchement"]'); + if (option) option.selected = true; + } + if (projet && projet.extRCEMontageDemontage) { + const option = garantieRCESelector.querySelector('option[value="montage-demontage"]'); + if (option) option.selected = true; + } + garantieRCESelector.dispatchEvent(new Event('change')); + } // Populate temporalité if (projet && projet.tempo) { document.getElementById(projet.tempo).checked = true }; @@ -991,28 +2044,32 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio // Populate Grille Advalorem if (rc.actMultimodal) { if (projet.grilleAerien) { - populateGrAdvalo(projet.grilleAerien, "tabAdvaloAerien"); + const grilleAerien = Array.isArray(projet.grilleAerien) ? projet.grilleAerien : (typeof projet.grilleAerien === 'string' ? JSON.parse(projet.grilleAerien) : []); + populateGrAdvalo(grilleAerien, "tabAdvaloAerien"); document.getElementById('divAdvaloAerien').style.display = "block"; document.getElementById('divAdvaloTerrestre').style.display = "none"; document.getElementById('divAdvaloMultimodal').style.display = "none"; }; if (projet.grilleTerrestre) { - populateGrAdvalo(projet.grilleTerrestre, "tabAdvaloTerrestre"); + const grilleTerrestre = Array.isArray(projet.grilleTerrestre) ? projet.grilleTerrestre : (typeof projet.grilleTerrestre === 'string' ? JSON.parse(projet.grilleTerrestre) : []); + populateGrAdvalo(grilleTerrestre, "tabAdvaloTerrestre"); document.getElementById('divAdvaloTerrestre').style.display = "block"; document.getElementById('divAdvaloAerien').style.display = "none"; document.getElementById('divAdvaloMultimodal').style.display = "none"; }; if (projet.grilleMultimodal) { - populateGrAdvalo(projet.grilleMultimodal, "tabAdvaloMultimodal"); + const grilleMultimodal = Array.isArray(projet.grilleMultimodal) ? projet.grilleMultimodal : (typeof projet.grilleMultimodal === 'string' ? JSON.parse(projet.grilleMultimodal) : []); + populateGrAdvalo(grilleMultimodal, "tabAdvaloMultimodal"); document.getElementById('divAdvaloMultimodal').style.display = "block"; document.getElementById('divAdvaloAerien').style.display = "none"; document.getElementById('divAdvaloTerrestre').style.display = "none"; }; } else { if (projet.grilleTerrestre) { - populateGrAdvalo(projet.grilleTerrestre, "tabAdvaloTerrestre"); + const grilleTerrestre = Array.isArray(projet.grilleTerrestre) ? projet.grilleTerrestre : (typeof projet.grilleTerrestre === 'string' ? JSON.parse(projet.grilleTerrestre) : []); + populateGrAdvalo(grilleTerrestre, "tabAdvaloTerrestre"); document.getElementById('divAdvaloTerrestre').style.display = "block"; document.getElementById('divAdvaloAerien').style.display = "none"; document.getElementById('divAdvaloMultimodal').style.display = "none"; @@ -1022,20 +2079,35 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio function populateGrAdvalo(jsonData, tableID) { var table = document.getElementById(tableID); + if (!table) { + console.warn('Table non trouvée:', tableID); + return; + } + + if (!jsonData || !Array.isArray(jsonData) || jsonData.length === 0) { + console.warn('Données grille vides ou invalides pour', tableID, ':', jsonData); + return; + } + + console.log('Remplissage de la grille', tableID, 'avec', jsonData.length, 'catégories'); for (var i = 0; i < jsonData.length; i++) { var category = jsonData[i].name; + if (!category) continue; for (var j = 1; j < table.rows.length; j++) { - var categoryName = table.rows[j].cells[0].innerText.trim(); + var categoryName = table.rows[j].cells[0] ? table.rows[j].cells[0].innerText.trim() : ''; if (categoryName === category) { var categoryRow = table.rows[j]; for (var k = 1; k <= 6; k++) { var zoneKey = "zone" + k; - var zoneInput = categoryRow.cells[k].querySelector("input[type='text']"); - zoneInput.value = jsonData[i][zoneKey]; + var zoneInput = categoryRow.cells[k] ? categoryRow.cells[k].querySelector("input[type='text']") : null; + if (zoneInput && jsonData[i][zoneKey]) { + zoneInput.value = jsonData[i][zoneKey]; + console.log('Rempli:', category, zoneKey, '=', jsonData[i][zoneKey]); + } } break; @@ -1174,21 +2246,32 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio // Iterate over each selected option Array.from(select.options).forEach(option => { - if (option.selected && option.value && !document.getElementById(option.value + "-chip")) { - const activityName = option.textContent; - const activityDiv = document.createElement('div'); - activityDiv.classList.add('activity-input', 'row'); - activityDiv.style.marginBottom = '10px'; - activityDiv.innerHTML = ` -