diff --git a/ecole/public/css/global.css b/ecole/public/css/global.css
index 1413772f..50f196b0 100644
--- a/ecole/public/css/global.css
+++ b/ecole/public/css/global.css
@@ -1,5 +1,8 @@
body {
font-family: 'Roboto', sans-serif;
+ background-color: white;
+ color: black;
+ color-scheme: light;
}
h1, h2, h3, h4, h5, h6 {
diff --git a/ecole/public/js/nav-parcours.js b/ecole/public/js/nav-parcours.js
index bb6ed373..0deb1071 100644
--- a/ecole/public/js/nav-parcours.js
+++ b/ecole/public/js/nav-parcours.js
@@ -33,8 +33,16 @@ document.addEventListener('DOMContentLoaded', function() {
let produit = parcours["@expand"].contrat.produit
const produitObj = contrat?.["@expand"]?.enCours || null;
- const tarif = produitObj?.["@expand"]?.tarif || null;
- const projet = produitObj?.["@expand"]?.projet || null;
+
+ // RC utilise tarifRC/projetRC, les autres produits utilisent tarif/projet
+ let tarif, projet;
+ if (produit === "rc") {
+ tarif = produitObj?.["@expand"]?.tarifRC || null;
+ projet = produitObj?.["@expand"]?.projetRC || null;
+ } else {
+ tarif = produitObj?.["@expand"]?.tarif || null;
+ projet = produitObj?.["@expand"]?.projet || null;
+ }
let scriptSrc;
// let newScriptModuloSrc;
@@ -54,11 +62,21 @@ document.addEventListener('DOMContentLoaded', function() {
scriptSrc = `/js/${submenu}-form.js`;
}
+ // RC utilise tarifRC/projetRC, les autres produits utilisent tarif/projet
+ let tarifId, projetId;
+ if (produit === "rc") {
+ tarifId = contrat?.["@expand"]?.enCours?.["@expand"]?.tarifRC?.id || null;
+ projetId = contrat?.["@expand"]?.enCours?.["@expand"]?.projetRC?.id || null;
+ } else {
+ tarifId = contrat?.["@expand"]?.enCours?.["@expand"]?.tarif?.id || null;
+ projetId = contrat?.["@expand"]?.enCours?.["@expand"]?.projet?.id || null;
+ }
+
const etapes = {
"client": contrat?.client || null,
"intermediaire": contrat?.intermediaire || null,
- "tarif": contrat?.["@expand"]?.enCours?.["@expand"]?.tarif?.id || null,
- "projet": contrat?.["@expand"]?.enCours?.["@expand"]?.projet?.id || null,
+ "tarif": tarifId,
+ "projet": projetId,
"contrat": null
}
@@ -79,7 +97,6 @@ document.addEventListener('DOMContentLoaded', function() {
document.getElementById('step-' + key).classList.add('line')
}
}
- showLoader();
// Charger le formulaire associé
fetch(fetchUrl)
@@ -89,6 +106,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Suppression de tout script précédemment chargé
const oldScript = document.querySelector('script.dynamic-script');
+
if (oldScript) {
oldScript.remove();
}
@@ -120,26 +138,26 @@ document.addEventListener('DOMContentLoaded', function() {
inputChanged = true
})
})
- hideLoader();
})
.catch(error => console.error('Error:', error));
- //A MODIFIER UNE FOIS QUE RC SERA ADAPTé AU PARCOURS
- if (produit == "RC") {
- if (Object.keys(contrat?.["@expand"]?.enCours).length > 1) {
- document.getElementById('generateProject').disabled = false;
- }
+ // Gestion des boutons de génération pour tous les produits
+ const hasClient = parcours["@expand"]?.contrat?.client != '';
+ const hasIntermediaire = parcours["@expand"]?.contrat?.intermediaire != '';
+ const hasProduit = produitObj != undefined;
+
+ // Bouton génération déclinaison tarifaire
+ if (hasClient && hasIntermediaire && hasProduit && tarif != null) {
+ document.getElementById('generateDeclinaison').disabled = false;
} else {
- // Enable / disable bouton generate project
- if (parcours["@expand"].contrat.client != '' && parcours["@expand"].contrat.intermediaire != '' && produitObj != undefined && projet != null) {
- document.getElementById('generateProject').disabled = false;
- }
-
- // Enable / disable bouton generate déclinaison
- if (parcours["@expand"].contrat.client != '' && parcours["@expand"].contrat.intermediaire != '' && produitObj != undefined && tarif != null) {
- document.getElementById('generateDeclinaison').disabled = false;
- }
-
+ document.getElementById('generateDeclinaison').disabled = true;
+ }
+
+ // Bouton génération projet
+ if (hasClient && hasIntermediaire && hasProduit && projet != null) {
+ document.getElementById('generateProject').disabled = false;
+ } else {
+ document.getElementById('generateProject').disabled = true;
}
}
@@ -157,9 +175,6 @@ document.addEventListener('DOMContentLoaded', function() {
const parcours = JSON.parse(sessionStorage.getItem('parcours'));
var produit = parcours["@expand"].contrat.produit
- const btn = this // bouton "générer projet"
- btn.disabled = true; // le desactiver le temps du téléchargement
-
var fileName
switch (produit.toLowerCase()) {
case 'fac':
@@ -183,21 +198,26 @@ document.addEventListener('DOMContentLoaded', function() {
link.download = fileName;
link.click();
})
- .finally(() => {
- btn.disabled = false; // réactiver le bouton a la fin du téléchargement
- })
.catch(error => console.error('Error downloading file:', error));
});
// Fonction de génération de projet
- document.getElementById('generateProject').addEventListener('click', function() {
+ document.getElementById('generateProject').addEventListener('click', async function() {
const numParcours = getNumParcoursFromURL();
let filename;
const parcours = JSON.parse(sessionStorage.getItem('parcours'));
let produit = parcours["@expand"].contrat.produit
- const btn = this // bouton "générer projet"
- btn.disabled = true; // le desactiver le temps du téléchargement
+ // Sauvegarder les données du projet avant de générer le document (si RC)
+ if (produit.toLowerCase() === 'rc' && typeof window.saveProjetRC === 'function') {
+ console.log('Sauvegarde des données projet RC avant génération...');
+ const saveResult = await window.saveProjetRC();
+ if (!saveResult || !saveResult.valid) {
+ console.error('Échec de la sauvegarde du projet RC');
+ M.toast({html: 'Erreur lors de la sauvegarde du projet. Veuillez réessayer.'});
+ return;
+ }
+ }
// Envoi de la requête POST au serveur pour générer le projet
fetch(`/generate/${produit}/projet/${numParcours}`, {
@@ -228,23 +248,17 @@ document.addEventListener('DOMContentLoaded', function() {
window.URL.revokeObjectURL(url); // Nettoie l'URL objet
a.remove(); // Supprime l'élément a du document
})
- .finally(() => {
- btn.disabled = false; // réactiver le bouton a la fin du téléchargement
- })
.catch(error => console.error('Erreur lors de la génération du projet:', error));
});
- document.getElementById('generateDeclinaison').addEventListener('click', function() {
+ document.getElementById('generateDeclinaison').addEventListener('click', async function() {
const numParcours = getNumParcoursFromURL();
let filename;
const parcours = JSON.parse(sessionStorage.getItem('parcours'));
let produit = parcours["@expand"].contrat.produit
- const btn = this // bouton "générer déclinaison tarifaire"
- btn.disabled = true; // le desactiver le temps du téléchargement
-
- // Envoi de la requête POST au serveur pour générer le projet
+ // Envoi de la requête POST au serveur pour générer la déclinaison tarifaire
fetch(`/generate/${produit}/tarif/${numParcours}`, {
method: 'POST',
headers: {
@@ -274,9 +288,6 @@ document.addEventListener('DOMContentLoaded', function() {
window.URL.revokeObjectURL(url); // Nettoie l'URL objet
a.remove(); // Supprime l'élément a du document
})
- .finally(() => {
- btn.disabled = false; // réactiver le bouton a la fin du téléchargement
- })
.catch(error => console.error('Erreur lors de la génération du projet:', error));
});
@@ -323,4 +334,4 @@ document.addEventListener('DOMContentLoaded', function() {
// Exécutez init et gérez les erreurs potentielles
init().catch(error => console.error('Error initializing the form:', error));
-});
+});
\ No newline at end of file
diff --git a/ecole/public/js/projet-form-rc.js b/ecole/public/js/projet-form-rc.js
index cdaadaa7..37352452 100644
--- a/ecole/public/js/projet-form-rc.js
+++ b/ecole/public/js/projet-form-rc.js
@@ -7,7 +7,10 @@ function initSubmenuForm() {
window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollution de l'espace global
(function () {
// Variables globales du module
- let parcours, contrat, client, intermediaire;
+ let parcours, contrat, client, intermediaire, rc, projet, tarif;
+
+ let modRCActRCC, modRCMar, modRCZone, modRCActCompl, modRCGarAdd;
+ let hasSavedGrilleData = false; // évite d'écraser une grille déjà enregistrée
// Initialisation des tag pour select
var tagAnimauxVivants = false;
@@ -35,16 +38,1089 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
contrat = JSON.parse(sessionStorage.getItem('contrat'));
client = contrat?.["@expand"]?.client || null;
intermediaire = contrat?.["@expand"]?.intermediaire || null;
- rc = contrat?.["@expand"]?.enCours || null;
+
+ // Récupérer les données RC depuis la nouvelle structure (EXACTEMENT comme TPPC)
+ rc = contrat?.["@expand"]?.enCours || null; // RC principal
+ projet = rc?.["@expand"]?.projet || null; // Données projet (normalized by contratService)
+ tarif = rc?.["@expand"]?.tarif || null; // Données tarif (normalized by contratService)
+
+ // Exposer ces variables globalement pour que rc-orchestrator puisse y accéder
+ window.rc = rc;
+ window.tarif = tarif;
+ window.projet = projet;
console.log("Initialisation pour formulaire projet :", parcours);
+ console.log("📊 RC:", rc);
+ console.log("📊 Tarif:", tarif);
+ console.log("📊 Projet:", projet);
+
+ 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) {
+ console.log('⚠️ Pas de données tarif/rc pour pré-remplir');
+ return;
+ }
+
+ console.log('📝 Pré-remplissage depuis tarif...', { rc, tarif });
+
+ 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');
+
+ // ===== ACTIVITÉS =====
+
+ // Voiturier
+ if (rc.checkVoiturier && !projet?.actVoiturier && activitySelector) {
+ console.log(' ✓ Sélection Voiturier, capital:', rc.capitalVoiturier);
+ const voiturierOption = activitySelector.querySelector('option[value="voiturier"]');
+ if (voiturierOption) {
+ voiturierOption.selected = true;
+ if (rc.capitalVoiturier) {
+ voiturierOption.setAttribute('data-default-value', rc.capitalVoiturier);
+ }
+ }
+ }
+
+ // Loueur (souvent coché avec Voiturier)
+ if (rc.checkVoiturier && !projet?.actLoueur && activitySelector) {
+ console.log(' ✓ Sélection Loueur (car Voiturier coché)');
+ const loueurOption = activitySelector.querySelector('option[value="loueur"]');
+ if (loueurOption) {
+ loueurOption.selected = true;
+ }
+ }
+
+ // Commissionnaire → Commissionnaire multimodal
+ if (rc.checkCommissionnaire && !projet?.actMultimodal && activitySelector) {
+ console.log(' ✓ Sélection Commissionnaire multimodal, capital:', rc.capitalCommissionnaire);
+ const multimodalOption = activitySelector.querySelector('option[value="commissionnaire-multimodal"]');
+ if (multimodalOption) {
+ multimodalOption.selected = true;
+ if (rc.capitalCommissionnaire) {
+ multimodalOption.setAttribute('data-default-value', rc.capitalCommissionnaire);
+ }
+ }
+ }
+
+ // Déménageur → Déménageur d'entreprises (pas particuliers)
+ if (rc.checkDemenageur && !projet?.actDemEntr && activitySelector) {
+ console.log(' ✓ Sélection Déménageur d\'entreprises, capital:', rc.capitalDemenageur);
+ const demenageurOption = activitySelector.querySelector('option[value="demenageur-entreprise"]');
+ if (demenageurOption) {
+ demenageurOption.selected = true;
+ if (rc.capitalDemenageur) {
+ demenageurOption.setAttribute('data-default-value', rc.capitalDemenageur);
+ }
+ }
+ }
+
+ // Logistique → Prestataire logistique
+ if (rc.checkLogistique && !projet?.actPrestaLog && activitySelector) {
+ console.log(' ✓ Sélection Prestataire logistique, capital:', rc.capitalLogistique);
+ const logistiqueOption = activitySelector.querySelector('option[value="prestataire-logistique"]');
+ if (logistiqueOption) {
+ logistiqueOption.selected = true;
+ if (rc.capitalLogistique) {
+ logistiqueOption.setAttribute('data-default-value', rc.capitalLogistique);
+ }
+ }
+ }
+
+ // Autocariste
+ if (rc.checkAutocariste && activitySelector) {
+ console.log(' ✓ Sélection Autocariste, capital:', rc.capitalAutocariste);
+ const autocaristeOption = activitySelector.querySelector('option[value="autocariste"]');
+ if (autocaristeOption) {
+ autocaristeOption.selected = true;
+ if (rc.capitalAutocariste) {
+ autocaristeOption.setAttribute('data-default-value', rc.capitalAutocariste);
+ }
+ }
+ }
+
+ // Autres
+ if (rc.checkAutres && activitySelector) {
+ console.log(' ✓ Sélection Autres activités, capital:', rc.capitalAutres);
+ const autresOption = activitySelector.querySelector('option[value="autres"]');
+ if (autresOption) {
+ autresOption.selected = true;
+ if (rc.capitalAutres) {
+ autresOption.setAttribute('data-default-value', rc.capitalAutres);
+ }
+ }
+ }
+
+ // IMPORTANT : Trigger change event pour que Materialize mette à jour l'affichage
+ if (activitySelector) {
+ console.log(' 🔄 Trigger change event sur activity-selector');
+ const changeEvent = new Event('change', { bubbles: true });
+ activitySelector.dispatchEvent(changeEvent);
+
+ // Réinitialiser Materialize FormSelect
+ setTimeout(() => {
+ if (window.M && window.M.FormSelect) {
+ window.M.FormSelect.init(activitySelector);
+ console.log(' ✅ Materialize FormSelect réinitialisé');
+ }
+ }, 100);
+ }
+
+ // ===== MARCHANDISES =====
+
+ 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)];
+ console.log(' 📦 Marchandises:', uniqueMarchandises);
+
+ 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) {
+ // Recherche floue si mapping exact échoue
+ 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;
+ }
+ });
+ }
+ });
+
+ // Trigger change event pour Materialize
+ const changeEvent = new Event('change', { bubbles: true });
+ marchandiseSelector.dispatchEvent(changeEvent);
+
+ setTimeout(() => {
+ if (window.M && window.M.FormSelect) {
+ window.M.FormSelect.init(marchandiseSelector);
+ }
+ }, 100);
+ }
+
+ // ===== ZONES GÉOGRAPHIQUES =====
+
+ if (rc.zone1 !== undefined && !projet?.zone1) {
+ const zone1El = document.getElementById("zone1");
+ if (zone1El) {
+ zone1El.checked = rc.zone1;
+ console.log(' ✓ Zone 1:', rc.zone1);
+ }
+ }
+ if (rc.zone2 !== undefined && !projet?.zone2) {
+ const zone2El = document.getElementById("zone2");
+ if (zone2El) {
+ zone2El.checked = rc.zone2;
+ console.log(' ✓ Zone 2:', rc.zone2);
+ }
+ }
+ if (rc.zone3 !== undefined && !projet?.zone3) {
+ const zone3El = document.getElementById("zone3");
+ if (zone3El) {
+ zone3El.checked = rc.zone3;
+ console.log(' ✓ Zone 3:', rc.zone3);
+ }
+ }
+ if (rc.zone4 !== undefined && !projet?.zone4) {
+ const zone4El = document.getElementById("zone4");
+ if (zone4El) {
+ zone4El.checked = rc.zone4;
+ console.log(' ✓ Zone 4:', rc.zone4);
+ }
+ }
+ if (rc.zone5 !== undefined && !projet?.zone5) {
+ const zone5El = document.getElementById("zone5");
+ if (zone5El) {
+ zone5El.checked = rc.zone5;
+ console.log(' ✓ Zone 5:', rc.zone5);
+ }
+ }
+ if (rc.zone6 !== undefined && !projet?.zone6) {
+ const zone6El = document.getElementById("zone6");
+ if (zone6El) {
+ zone6El.checked = rc.zone6;
+ console.log(' ✓ Zone 6:', rc.zone6);
+ }
+ }
+
+ // ===== TYPE DE COTISATION =====
+
+ if (rc.typeCotisation && !projet?.typeCot) {
+ const radioCot = document.querySelector(`input[name="typeCot"][value="${rc.typeCotisation}"]`);
+ if (radioCot) {
+ radioCot.checked = true;
+ console.log(' ✓ Type cotisation:', rc.typeCotisation);
+ }
+ }
+
+ // ===== CA =====
+
+ if (rc.chiffreAffaires && !projet?.ca) {
+ const caEl = document.getElementById("CA");
+ if (caEl) {
+ caEl.value = rc.chiffreAffaires;
+ console.log(' ✓ CA:', rc.chiffreAffaires);
+ }
+ }
+
+ // ===== RCE (INCLURE LES AUTRES RC) =====
+
+ const hasRCEFromRC = rc && rc.checkRCE;
+ const hasRCEFromTarif = tarif && tarif.checkRCE;
+ if (hasRCEFromRC || hasRCEFromTarif) {
+ console.log(' ✓ RCE activée (checkRCE)');
+ 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 = '';
+ }
+ }
+
+ // ===== PROTECTION JURIDIQUE =====
+
+ if (tarif && tarif.checkPJ && !projet?.pj) {
+ console.log(' ✓ Protection Juridique activée');
+ const switchPJEl = document.getElementById("switchPJ");
+ if (switchPJEl) {
+ switchPJEl.checked = true;
+
+ // Afficher la section PJ
+ const pj1El = document.getElementById('PJ1');
+ if (pj1El) pj1El.style.display = '';
+ const pj2El = document.getElementById('PJ2');
+ if (pj2El) pj2El.style.display = '';
+
+ // Pré-remplir les cotisations PJ si disponibles
+ if (tarif.cotPJHT && !projet?.cotPJHT) {
+ const cotPJHTEl = document.getElementById('cotPJHT');
+ if (cotPJHTEl) {
+ cotPJHTEl.value = tarif.cotPJHT;
+ console.log(' ├─ Cotisation PJ HT:', tarif.cotPJHT);
+ }
+ }
+ if (tarif.cotPJTTC && !projet?.cotPJTTC) {
+ const cotPJTTCEl = document.getElementById('cotPJTTC');
+ if (cotPJTTCEl) {
+ cotPJTTCEl.value = tarif.cotPJTTC;
+ console.log(' └─ Cotisation PJ TTC:', tarif.cotPJTTC);
+ }
+ }
+ }
+ }
+
+ // Appliquer les capitaux APRÈS trigger (les inputs sont créés dynamiquement)
+ setTimeout(() => {
+ console.log(' 💰 Application des capitaux sur les inputs créés...');
+
+ // Mapping des activités vers leurs capitaux
+ const capitalMapping = {
+ 'voiturier': rc.capitalVoiturier,
+ 'commissionnaire-multimodal': rc.capitalCommissionnaire,
+ 'demenageur-entreprise': rc.capitalDemenageur,
+ 'prestataire-logistique': rc.capitalLogistique,
+ 'autocariste': rc.capitalAutocariste,
+ 'autres': rc.capitalAutres
+ };
+
+ for (const [activity, capital] of Object.entries(capitalMapping)) {
+ if (capital) {
+ const input = document.getElementById(activity);
+ if (input && !input.value) {
+ input.value = capital;
+ console.log(` ├─ ${activity}: ${capital}`);
+ }
+ }
+ }
+
+ console.log(' ✅ Capitaux appliqués');
+ }, 300);
+
+ // Autres champs (garanties RCC, etc.)
+ 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="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;
+ }
+ }
+
+ // ===== ACTIVITÉS COMPLÉMENTAIRES =====
+
+ 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);
@@ -133,10 +1209,20 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById('cotPJHT').value = '';
document.getElementById('cotPJTTC').value = '';
}
-
calcCotTotal();
});
+ function restoreZonesFromOriginal() {
+ const orig = tarifOriginalData || {};
+ ['zone1','zone2','zone3','zone4','zone5','zone6'].forEach(z => {
+ const el = document.getElementById(z);
+ if (el) {
+ el.disabled = false;
+ el.checked = Boolean(orig[z]);
+ }
+ });
+ }
+
document.getElementById('btnMondeEntier').addEventListener('click', function () {
document.getElementById('zone1').checked = true;
document.getElementById('zone1').disabled = true;
@@ -147,6 +1233,20 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById('zone5').checked = true;
document.getElementById('zone6').checked = true;
+ // Détection impact tarif : zones
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ // Revenir à l'état original visuel
+ restoreZonesFromOriginal();
+ }
+ }
+
handleGrAdvalo();
});
@@ -160,6 +1260,20 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById('zone5').checked = false;
document.getElementById('zone6').checked = false;
+ // Détection impact tarif : zones
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ // Revenir à l'état original visuel
+ restoreZonesFromOriginal();
+ }
+ }
+
handleGrAdvalo();
});
@@ -207,6 +1321,18 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById('zone1').addEventListener('click', function () {
handleGrAdvalo();
+
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ restoreZonesFromOriginal();
+ }
+ }
});
document.getElementById('zone2').addEventListener('click', function () {
@@ -219,6 +1345,18 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
}
handleGrAdvalo();
+
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ restoreZonesFromOriginal();
+ }
+ }
});
document.getElementById('zone3').addEventListener('click', function () {
@@ -235,18 +1373,66 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
}
handleGrAdvalo();
+
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ restoreZonesFromOriginal();
+ }
+ }
});
document.getElementById('zone4').addEventListener('click', function () {
handleGrAdvalo();
+
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ restoreZonesFromOriginal();
+ }
+ }
});
document.getElementById('zone5').addEventListener('click', function () {
handleGrAdvalo();
+
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ restoreZonesFromOriginal();
+ }
+ }
});
document.getElementById('zone6').addEventListener('click', function () {
handleGrAdvalo();
+
+ if (tarif && tarif.id && tarifOriginalData) {
+ const currentData = getCurrentZoneData();
+ if (checkTarifImpact('zone', currentData)) {
+ showTarifImpactModal((confirmed) => {
+ if (confirmed) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=tarif`;
+ }
+ }, null, null);
+ restoreZonesFromOriginal();
+ }
+ }
});
var radioButtonsCot = document.getElementsByName('cotisation');
@@ -365,6 +1551,33 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
});
document.getElementById('CA').addEventListener('input', function () {
+ 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');
@@ -536,14 +1749,13 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
tagDemenageur = true;
} else {
- if (!(currentSelection.includes(("demenageur-particulier" || "demenageur-particulier-dommage" || "demenageur-particulier-advalorem") && "demenageur-entreprise" && "demenageur-interne"))) {
- document.getElementById('marchandise-selector').querySelector('option[value="roulant-demenagement"]').selected = false;
- document.getElementById('marchandise-selector').querySelector('option[value="mobilier-usages"]').selected = false;
- document.getElementById('marchandise-selector').querySelector('option[value="ordinaire"]').selected = true;
- document.getElementById('marchandise-selector').dispatchEvent(new Event('change'));
-
- tagDemenageur = false;
- }
+ // Aucune activité déménageur n'est sélectionnée
+ document.getElementById('marchandise-selector').querySelector('option[value="roulant-demenagement"]').selected = false;
+ document.getElementById('marchandise-selector').querySelector('option[value="mobilier-usages"]').selected = false;
+ document.getElementById('marchandise-selector').querySelector('option[value="ordinaire"]').selected = true;
+ document.getElementById('marchandise-selector').dispatchEvent(new Event('change'));
+
+ tagDemenageur = false;
}
if (currentSelection.includes("garde-meubles")) {
@@ -617,10 +1829,9 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById('selected-voiturier-error').style.display = "block";
}
} else {
- if (!(currentSelection.includes("entrepositaire-depositaire" && "prestataire-logistique" && "manutentionnaire-levageur"))) {
- tagVoiturier = false;
- document.getElementById('selected-voiturier-error').style.display = "none";
- }
+ // Aucune activité nécessitant voiturier n'est sélectionnée
+ tagVoiturier = false;
+ document.getElementById('selected-voiturier-error').style.display = "none";
}
if (currentSelection.length == 1) {
@@ -723,22 +1934,71 @@ 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 (!rc) {
+ 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'));
}
// Populate assurés additionnel
- if (!rc || !rc.assureAdditionnel || Object.keys(rc.assureAdditionnel).length === 0) {
+ if (!projet || !projet.assureAdditionnel || Object.keys(projet.assureAdditionnel).length === 0) {
console.log("Le JSON est vide, pas d'assurés additionnels à pré-remplir.");
} else {
document.getElementById('additionel').checked = true;
document.getElementById('checkAdditionnel').style.display = "block";
- for (let i = 0; i < rc.assureAdditionnel.length; i++) {
- const row = rc.assureAdditionnel[i];
+ for (let i = 0; i < projet.assureAdditionnel.length; i++) {
+ const row = projet.assureAdditionnel[i];
addRowAdditionnel(row.nom, row.adresse, row.siret);
}
}
@@ -746,20 +2006,20 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
// Populate activite
const activitySelector = document.getElementById('activity-selector');
- if (rc.actVoiturier) {
+ if (projet && projet.actVoiturier) {
activitySelector.querySelector('option[value="voiturier"]').selected = true;
- document.getElementById("select-voiturier").dataset.defaultValue = rc.valueActVoiturier;
+ document.getElementById("select-voiturier").dataset.defaultValue = projet.valueActVoiturier;
};
- if (rc.actLoueur) {
+ if (projet && projet.actLoueur) {
activitySelector.querySelector('option[value="loueur"]').selected = true;
- document.getElementById("select-loueur").dataset.defaultValue = rc.valueActLoueur;
+ document.getElementById("select-loueur").dataset.defaultValue = projet.valueActLoueur;
};
- if (rc.actMultimodal) {
+ if (projet && projet.actMultimodal) {
tagMultimodal = true;
activitySelector.querySelector('option[value="commissionnaire-multimodal"]').selected = true;
- document.getElementById("select-commissionnaire-multimodal").dataset.defaultValue = rc.valueActMultimodal;
+ document.getElementById("select-commissionnaire-multimodal").dataset.defaultValue = projet.valueActMultimodal;
document.getElementById("btnAdvaloMultimodal").style.display = 'block';
document.getElementById("btnAdvaloAerien").style.display = 'block';
document.getElementById("btnAdvaloTerrestre").style.display = 'block';
@@ -768,59 +2028,59 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById('divAdvaloMultimodal').style.display = "block";
};
- if (rc.actDouane) {
+ if (projet && projet.actDouane) {
activitySelector.querySelector('option[value="représentant-douane"]').selected = true;
- document.getElementById("select-représentant-douane").dataset.defaultValue = rc.valueActDouane;
+ document.getElementById("select-représentant-douane").dataset.defaultValue = projet.valueActDouane;
};
- if (rc.actDemPar) {
+ if (projet && projet.actDemPar) {
activitySelector.querySelector('option[value="demenageur-particulier"]').selected = true;
- document.getElementById("select-demenageur-particulier").dataset.defaultValue = rc.valueActDemPar;
+ document.getElementById("select-demenageur-particulier").dataset.defaultValue = projet.valueActDemPar;
}
- if (rc.actDemParDom) {
+ if (projet && projet.actDemParDom) {
activitySelector.querySelector('option[value="demenageur-particulier-dommage"]').selected = true;
- document.getElementById("select-demenageur-particulier-dommage").dataset.defaultValue = rc.valueActDemParDom;
+ document.getElementById("select-demenageur-particulier-dommage").dataset.defaultValue = projet.valueActDemParDom;
}
- if (rc.actDemParAdv) {
+ if (projet && projet.actDemParAdv) {
activitySelector.querySelector('option[value="demenageur-particulier-advalorem"]').selected = true;
- document.getElementById("select-demenageur-particulier-advalorem").dataset.defaultValue = rc.valueActDemParAdv;
+ document.getElementById("select-demenageur-particulier-advalorem").dataset.defaultValue = projet.valueActDemParAdv;
}
- if (rc.actDemEntr) {
+ if (projet && projet.actDemEntr) {
activitySelector.querySelector('option[value="demenageur-entreprise"]').selected = true;
- document.getElementById("select-demenageur-entreprise").dataset.defaultValue = rc.valueActDemEntr;
+ document.getElementById("select-demenageur-entreprise").dataset.defaultValue = projet.valueActDemEntr;
}
- if (rc.actDemInterne) {
+ if (projet && projet.actDemInterne) {
activitySelector.querySelector('option[value="demenageur-interne"]').selected = true;
- document.getElementById("select-demenageur-interne").dataset.defaultValue = rc.valueActDemInterne;
+ document.getElementById("select-demenageur-interne").dataset.defaultValue = projet.valueActDemInterne;
}
- if (rc.actGardeMeuble) {
+ if (projet && projet.actGardeMeuble) {
activitySelector.querySelector('option[value="garde-meubles"]').selected = true;
- document.getElementById("select-garde-meubles").dataset.defaultValue = rc.valueActGardeMeuble;
+ document.getElementById("select-garde-meubles").dataset.defaultValue = projet.valueActGardeMeuble;
}
- if (rc.actEntDep) {
+ if (projet && projet.actEntDep) {
activitySelector.querySelector('option[value="entrepositaire-depositaire"]').selected = true;
- document.getElementById("select-entrepositaire-depositaire").dataset.defaultValue = rc.valueActEntDep;
+ document.getElementById("select-entrepositaire-depositaire").dataset.defaultValue = projet.valueActEntDep;
}
- if (rc.actPrestaLog) {
+ if (projet && projet.actPrestaLog) {
activitySelector.querySelector('option[value="prestataire-logistique"]').selected = true;
- document.getElementById("select-prestataire-logistique").dataset.defaultValue = rc.valueActPrestaLog;
+ document.getElementById("select-prestataire-logistique").dataset.defaultValue = projet.valueActPrestaLog;
}
- if (rc.actLevageur) {
+ if (projet && projet.actLevageur) {
activitySelector.querySelector('option[value="manutentionnaire-levageur"]').selected = true;
- document.getElementById("select-manutentionnaire-levageur").dataset.defaultValue = rc.valueActLevageur;
+ document.getElementById("select-manutentionnaire-levageur").dataset.defaultValue = projet.valueActLevageur;
}
- if (rc.actTransitaire) {
+ if (projet && projet.actTransitaire) {
activitySelector.querySelector('option[value="transitaire"]').selected = true;
- document.getElementById("select-transitaire").dataset.defaultValue = rc.valueActTransitaire;
+ document.getElementById("select-transitaire").dataset.defaultValue = projet.valueActTransitaire;
}
document.getElementById('activity-selector').dispatchEvent(new Event('change'));
@@ -828,98 +2088,156 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
// Populate marchandises
const marchandiseSelector = document.getElementById('marchandise-selector');
- if (rc.marOrdinaire) { marchandiseSelector.querySelector('option[value="ordinaire"]').selected = true; };
- if (rc.marRoulant) { marchandiseSelector.querySelector('option[value="roulant"]').selected = true; };
- if (rc.marEngins) { marchandiseSelector.querySelector('option[value="engins-chantier-agricole"]').selected = true; };
- if (rc.marRoulantDem) { marchandiseSelector.querySelector('option[value="roulant-demenagement"]').selected = true; };
- if (rc.marMobilerUsag) { marchandiseSelector.querySelector('option[value="mobilier-usages"]').selected = true; };
- if (rc.marPerissable) { marchandiseSelector.querySelector('option[value="perissable-temperature-dirigee"]').selected = true; };
- if (rc.marAnimaux) {
+ if (projet && projet.marOrdinaire) { marchandiseSelector.querySelector('option[value="ordinaire"]').selected = true; };
+ if (projet && projet.marRoulant) { marchandiseSelector.querySelector('option[value="roulant"]').selected = true; };
+ if (projet && projet.marEngins) { marchandiseSelector.querySelector('option[value="engins-chantier-agricole"]').selected = true; };
+ if (projet && projet.marRoulantDem) { marchandiseSelector.querySelector('option[value="roulant-demenagement"]').selected = true; };
+ if (projet && projet.marMobilerUsag) { marchandiseSelector.querySelector('option[value="mobilier-usages"]').selected = true; };
+ if (projet && projet.marPerissable) { marchandiseSelector.querySelector('option[value="perissable-temperature-dirigee"]').selected = true; };
+ if (projet && projet.marAnimaux) {
tagAnimauxVivants = true;
marchandiseSelector.querySelector('option[value="animaux-vivant"]').selected = true;
};
- if (rc.marCiterne) { marchandiseSelector.querySelector('option[value="citerne"]').selected = true; };
- if (rc.marBeton) { marchandiseSelector.querySelector('option[value="beton"]').selected = true; };
- if (rc.marExceptionnels) { marchandiseSelector.querySelector('option[value="exceptionnels"]').selected = true; };
- if (rc.marVrac) { marchandiseSelector.querySelector('option[value="vrac"]').selected = true; };
+ if (projet && projet.marCiterne) { marchandiseSelector.querySelector('option[value="citerne"]').selected = true; };
+ if (projet && projet.marBeton) { marchandiseSelector.querySelector('option[value="beton"]').selected = true; };
+ if (projet && projet.marExceptionnels) { marchandiseSelector.querySelector('option[value="exceptionnels"]').selected = true; };
+ if (projet && projet.marVrac) { marchandiseSelector.querySelector('option[value="vrac"]').selected = true; };
document.getElementById('marchandise-selector').dispatchEvent(new Event('change'));
- // Populate territorialité
- if (rc.zone1) { document.getElementById("zone1").checked = true };
- if (rc.zone2) {
- document.getElementById("zone2").checked = true;
- document.getElementById("zone1").checked = true;
- document.getElementById("zone1").disabled = true;
- };
- if (rc.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 (rc.zone4) { document.getElementById("zone4").checked = true };
- if (rc.zone5) { document.getElementById("zone5").checked = true };
- if (rc.zone6) { document.getElementById("zone6").checked = true };
+ // Populate territorialité - depuis projet OU depuis rc (tarif) en fallback
+ const zonesSource = projet || rc;
+ 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');
- if (rc.extRCCModifCalArrim) { garantieRCCSelector.querySelector('option[value="modif-calage-arrimage"]').selected = true; };
- if (rc.extRCCFerroutage) { garantieRCCSelector.querySelector('option[value="ferroutage"]').selected = true; };
- if (rc.extRCCFraisRecons) { garantieRCCSelector.querySelector('option[value="frais-reconstitution"]').selected = true; };
- if (rc.extRCCConfie) {
+ if (projet && projet.extRCCModifCalArrim) { garantieRCCSelector.querySelector('option[value="modif-calage-arrimage"]').selected = true; };
+ if (projet && projet.extRCCFerroutage) { garantieRCCSelector.querySelector('option[value="ferroutage"]').selected = true; };
+ if (projet && projet.extRCCFraisRecons) { garantieRCCSelector.querySelector('option[value="frais-reconstitution"]').selected = true; };
+ if (projet && projet.extRCCConfie) {
garantieRCCSelector.querySelector('option[value="contenant-confie"]').selected = true;
- if (rc.typeExtConfies == "ADVALOREM") {
+ if (projet.typeExtConfies == "ADVALOREM") {
document.getElementById("AdValorem").checked = true;
} else {
document.getElementById("ValeurDeclaree").checked = true;
}
};
- if (rc.extRCCTPPC) { garantieRCCSelector.querySelector('option[value="tppc"]').selected = true; };
- if (rc.extRCCRegie) { garantieRCCSelector.querySelector('option[value="regie"]').selected = true; };
- if (rc.extRCCSansMontageDemontage) { garantieRCCSelector.querySelector('option[value="sans-montage-demontage"]').selected = true; };
+ if (projet && projet.extRCCTPPC) { garantieRCCSelector.querySelector('option[value="tppc"]').selected = true; };
+ if (projet && projet.extRCCRegie) { garantieRCCSelector.querySelector('option[value="regie"]').selected = true; };
+ if (projet && projet.extRCCSansMontageDemontage) { garantieRCCSelector.querySelector('option[value="sans-montage-demontage"]').selected = true; };
document.getElementById('garantieRCC-selector').dispatchEvent(new Event('change'));
- // Populate extensions de garantie RCC
- if (rc.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 (rc.extRCEBraDebra) { garantieRCESelector.querySelector('option[value="branchement-debranchement"]').selected = true; };
- if (rc.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 (rc.tempo) { document.getElementById(rc.tempo).checked = true };
- if (rc.dateEffet) { document.getElementById("dateEffet").value = rc.dateEffet };
- if (rc.dateEcheance) { document.getElementById("dateEcheance").value = rc.dateEcheance };
+ if (projet && projet.tempo) { document.getElementById(projet.tempo).checked = true };
+ if (projet && projet.dateEffet) { document.getElementById("dateEffet").value = projet.dateEffet };
+ if (projet && projet.dateEcheance) { document.getElementById("dateEcheance").value = projet.dateEcheance };
if (contrat.type == "TEMPORAIRE") { document.getElementById("rowDateFin").style.display = 'block'; }
- if (rc.dateFin) { document.getElementById("dateFin").value = rc.dateFin };
+ if (projet && projet.dateFin) { document.getElementById("dateFin").value = projet.dateFin };
- if (rc.programmeInternationale) { document.getElementById("programmeInternationale").checked = true; }
- if (rc.participationResultat) { document.getElementById("participationResultat").checked = true; }
+ if (projet && projet.programmeInternationale) { document.getElementById("programmeInternationale").checked = true; }
+ if (projet && projet.participationResultat) { document.getElementById("participationResultat").checked = true; }
- if (rc.pj) {
+ if (projet && projet.pj) {
document.getElementById("switchPJ").checked = true;
document.getElementById('PJ1').style.display = '';
document.getElementById('PJ2').style.display = '';
}
- // Populate Cotisation
- if (rc.typeCot) { document.getElementById(rc.typeCot).checked = true };
+ // Populate Cotisation - charger depuis RC principal si existe
+ const typeCotFromRC = rc?.typeCotisation || projet?.typeCot;
+ if (typeCotFromRC) {
+ const radioCot = document.getElementById(typeCotFromRC);
+ if (radioCot) radioCot.checked = true;
+ }
- if (rc.typeCot == "forfaitaire") {
+ // Populate CA depuis RC principal
+ const caFromRC = rc?.chiffreAffaires || projet?.ca;
+ if (caFromRC) {
+ document.getElementById("CA").value = caFromRC;
+ }
+
+ if ((typeCotFromRC || projet?.typeCot) == "forfaitaire") {
document.getElementById("checkVehicules").style.display = 'block';
document.getElementById("colTauxAjustement").style.display = 'none';
document.getElementById("colCotMini").style.display = 'none';
@@ -939,60 +2257,71 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
document.getElementById("colTypeCot").style.float = "left";
}
- if (rc.ca) { document.getElementById("CA").value = rc.ca };
- if (rc.cotIrreductible) { document.getElementById("cotisationIrreductible").value = rc.cotIrreductible };
- if (rc.tauxRCCHT) { document.getElementById("tauxRCCHT").value = rc.tauxRCCHT };
- if (rc.tauxRCCTTC) { document.getElementById("tauxRCCTTC").value = rc.tauxRCCTTC };
- if (rc.tauxRCEHT) { document.getElementById("tauxRCEHT").value = rc.tauxRCEHT };
- if (rc.tauxRCETTC) { document.getElementById("tauxRCETTC").value = rc.tauxRCETTC };
- if (rc.tauxTotalHT) { document.getElementById("tauxTotalHT").value = rc.tauxTotalHT };
- if (rc.tauxTotalTTC) { document.getElementById("tauxTotalTTC").value = rc.tauxTotalTTC };
- if (rc.cotRCCHT) { document.getElementById("cotRCCHT").value = rc.cotRCCHT };
- if (rc.cotRCCTTC) { document.getElementById("cotRCCTTC").value = rc.cotRCCTTC };
- if (rc.cotRCEHT) { document.getElementById("cotRCEHT").value = rc.cotRCEHT };
- if (rc.cotRCETTC) { document.getElementById("cotRCETTC").value = rc.cotRCETTC };
- if (rc.cotPJHT) { document.getElementById("cotPJHT").value = rc.cotPJHT };
- if (rc.cotPJTTC) { document.getElementById("cotPJTTC").value = rc.cotPJTTC };
- if (rc.cotTotalHT) { document.getElementById("cotTotalHT").value = rc.cotTotalHT };
- if (rc.cotTotalTTC) { document.getElementById("cotTotalTTC").value = rc.cotTotalTTC };
- if (rc.cotFraisHT) { document.getElementById("cotFraisHT").value = rc.cotFraisHT };
- if (rc.cotFraisTTC) { document.getElementById("cotFraisTTC").value = rc.cotFraisTTC };
+ if (projet && projet.ca) { document.getElementById("CA").value = projet.ca };
+ if (projet && projet.cotIrreductible) { document.getElementById("cotisationIrreductible").value = projet.cotIrreductible };
+ if (projet && projet.tauxRCCHT) { document.getElementById("tauxRCCHT").value = projet.tauxRCCHT };
+ if (projet && projet.tauxRCCTTC) { document.getElementById("tauxRCCTTC").value = projet.tauxRCCTTC };
+ if (projet && projet.tauxRCEHT) { document.getElementById("tauxRCEHT").value = projet.tauxRCEHT };
+ if (projet && projet.tauxRCETTC) { document.getElementById("tauxRCETTC").value = projet.tauxRCETTC };
+ if (projet && projet.tauxTotalHT) { document.getElementById("tauxTotalHT").value = projet.tauxTotalHT };
+ if (projet && projet.tauxTotalTTC) { document.getElementById("tauxTotalTTC").value = projet.tauxTotalTTC };
+ if (projet && projet.cotRCCHT) { document.getElementById("cotRCCHT").value = projet.cotRCCHT };
+ if (projet && projet.cotRCCTTC) { document.getElementById("cotRCCTTC").value = projet.cotRCCTTC };
+ if (projet && projet.cotRCEHT) { document.getElementById("cotRCEHT").value = projet.cotRCEHT };
+ if (projet && projet.cotRCETTC) { document.getElementById("cotRCETTC").value = projet.cotRCETTC };
+ if (projet && projet.cotPJHT) { document.getElementById("cotPJHT").value = projet.cotPJHT };
+ if (projet && projet.cotPJTTC) { document.getElementById("cotPJTTC").value = projet.cotPJTTC };
+ if (projet && projet.cotTotalHT) { document.getElementById("cotTotalHT").value = projet.cotTotalHT };
+ if (projet && projet.cotTotalTTC) { document.getElementById("cotTotalTTC").value = projet.cotTotalTTC };
+ if (projet && projet.cotFraisHT) { document.getElementById("cotFraisHT").value = projet.cotFraisHT };
+ if (projet && projet.cotFraisTTC) { document.getElementById("cotFraisTTC").value = projet.cotFraisTTC };
// Populate tableau vehicule
- if (!rc || !rc.designationVehicule || Object.keys(rc.designationVehicule).length === 0) {
+ if (!rc || !projet.designationVehicule || Object.keys(projet.designationVehicule).length === 0) {
console.log("Le JSON est vide, pas de véhicules à pré-remplir.");
} else {
- for (let i = 0; i < rc.designationVehicule.length; i++) {
- const row = rc.designationVehicule[i];
+ for (let i = 0; i < projet.designationVehicule.length; i++) {
+ const row = projet.designationVehicule[i];
addRowVehicule(row.marque, row.genre, row.type, row.immat, row.capital);
}
}
// Populate Grille Advalorem
- if (rc.actMultimodal) {
- if (rc.grilleAerien) {
- populateGrAdvalo(rc.grilleAerien, "tabAdvaloAerien");
+ hasSavedGrilleData = Boolean(
+ (projet?.grilleMultimodal && (Array.isArray(projet.grilleMultimodal) ? projet.grilleMultimodal.length : true)) ||
+ (projet?.grilleTerrestre && (Array.isArray(projet.grilleTerrestre) ? projet.grilleTerrestre.length : true)) ||
+ (projet?.grilleAerien && (Array.isArray(projet.grilleAerien) ? projet.grilleAerien.length : true))
+ );
+
+ const isMultimodal = Boolean(projet?.actMultimodal || rc?.actMultimodal);
+ if (isMultimodal) {
+ if (projet?.grilleAerien) {
+ 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 (rc.grilleTerrestre) {
- populateGrAdvalo(rc.grilleTerrestre, "tabAdvaloTerrestre");
+ if (projet?.grilleTerrestre) {
+ 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 (rc.grilleMultimodal) {
- populateGrAdvalo(rc.grilleMultimodal, "tabAdvaloMultimodal");
+ if (projet?.grilleMultimodal) {
+ 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 (rc.grilleTerrestre) {
- populateGrAdvalo(rc.grilleTerrestre, "tabAdvaloTerrestre");
+ if (projet?.grilleTerrestre) {
+ 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";
@@ -1002,20 +2331,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;
@@ -1078,10 +2422,10 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
for (let k = 1; k <= 8; k++) {
const element = document.getElementById(`${mode}Cat${k}Zone${zone}`);
const marPerissable = document.getElementById("perissable-temperature-dirigee-chip") || null;
- const marEngins = document.getElementById("engins-chantier-agricole-chip" || null);
- const marMobilier = document.getElementById("mobilier-usages-chip" || null);
- const marRoulantDem = document.getElementById("roulant-demenagement-chip" || null);
- const marRoulant = document.getElementById("roulant-chip" || null);
+ const marEngins = document.getElementById("engins-chantier-agricole-chip") || null;
+ const marMobilier = document.getElementById("mobilier-usages-chip") || null;
+ const marRoulantDem = document.getElementById("roulant-demenagement-chip") || null;
+ const marRoulant = document.getElementById("roulant-chip") || null;
let value = "Nous consulter"; // Par défaut
@@ -1108,6 +2452,10 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
value = categories[mode][`Cat${k}`][zone - 1];
}
}
+ // Si une grille enregistrée existe déjà, ne pas écraser les valeurs pré-remplies
+ if (hasSavedGrilleData && element && element.value && element.value.trim() !== '') {
+ continue;
+ }
element.value = value;
}
}
@@ -1154,21 +2502,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 = `
-
-
-
-
-
-
-
- `;
- activityFormsContainer.appendChild(activityDiv);
+ if (option.selected && option.value) {
+ const existingChip = document.getElementById(option.value + "-chip");
+ if (!existingChip) {
+ const activityName = option.textContent;
+ const activityDiv = document.createElement('div');
+ activityDiv.classList.add('activity-input', 'row');
+ activityDiv.style.marginBottom = '10px';
+ activityDiv.innerHTML = `
+
+
+
+
+
+
+
+ `;
+ activityFormsContainer.appendChild(activityDiv);
+ }
+ } else {
+ const existingChip = document.getElementById(option.value + "-chip");
+ if (existingChip) {
+ const activityDiv = existingChip.closest('.activity-input');
+ if (activityDiv) {
+ activityDiv.remove();
+ }
+ }
}
});
}
@@ -1229,22 +2588,33 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
const marchandiseFormsContainer = document.getElementById('selected-marchandises');
// Clear previous entries
- marchandiseFormsContainer.innerHTML = ''; // Clear any existing entries
+ marchandiseFormsContainer.innerHTML = '';
- // Iterate over each selected option
+ // Iterate over each option
Array.from(select.options).forEach(option => {
if (option.selected && option.value) {
- const marchandiseName = option.textContent;
- const marchandiseDiv = document.createElement('div');
- marchandiseDiv.classList.add('marchandise-input', 'row');
- marchandiseDiv.style.display = 'flex';
- marchandiseDiv.style.alignItems = 'center';
- marchandiseDiv.style.justifyContent = 'start';
- marchandiseDiv.style.marginBottom = '10px';
- marchandiseDiv.innerHTML = `
- ${marchandiseName}
- `;
- marchandiseFormsContainer.appendChild(marchandiseDiv);
+ const existingChip = document.getElementById(`${option.value}-chip`);
+ if (!existingChip) {
+ const marchandiseName = option.textContent;
+ const marchandiseDiv = document.createElement('div');
+ marchandiseDiv.classList.add('marchandise-input', 'row');
+ marchandiseDiv.style.display = 'flex';
+ marchandiseDiv.style.alignItems = 'center';
+ marchandiseDiv.style.justifyContent = 'start';
+ marchandiseDiv.style.marginBottom = '10px';
+ marchandiseDiv.innerHTML = `
+ ${marchandiseName}
+ `;
+ marchandiseFormsContainer.appendChild(marchandiseDiv);
+ }
+ } else {
+ const existingChip = document.getElementById(`${option.value}-chip`);
+ if (existingChip) {
+ const chipContainer = existingChip.closest('.marchandise-input');
+ if (chipContainer) {
+ chipContainer.remove();
+ }
+ }
}
});
}
@@ -1382,19 +2752,81 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
function extractGrilleAdvalo(tableID) {
var jsonData = [];
var table = document.getElementById(tableID);
- var zonesCount = table.rows[0].cells.length - 1;
-
- for (var i = 1; i < table.rows.length; i++) {
- var category = table.rows[i].cells[0].innerText.trim();
- var categoryData = { "name": category };
-
- for (var j = 1; j <= zonesCount; j++) {
- var zoneKey = "zone" + j;
- var zoneValue = table.rows[i].cells[j].querySelector("input[type='text']").value || "Nous consulter";
- categoryData[zoneKey] = zoneValue;
+ if (!table) {
+ return jsonData;
+ }
+
+ var parentDiv = table.closest('div');
+ var wasHidden = false;
+ var originalDisplay = '';
+ var originalVisibility = '';
+ var originalPosition = '';
+ var originalLeft = '';
+
+ if (parentDiv) {
+ originalDisplay = parentDiv.style.display || '';
+ originalVisibility = parentDiv.style.visibility || '';
+ originalPosition = parentDiv.style.position || '';
+ originalLeft = parentDiv.style.left || '';
+
+ if (parentDiv.style.display === 'none' || window.getComputedStyle(parentDiv).display === 'none') {
+ wasHidden = true;
+ parentDiv.style.display = 'block';
+ parentDiv.style.visibility = 'hidden';
+ parentDiv.style.position = 'absolute';
+ parentDiv.style.left = '-9999px';
+ }
+ }
+
+ try {
+ if (!table.rows || table.rows.length < 2) {
+ return jsonData;
+ }
+
+ var zonesCount = table.rows[0] ? table.rows[0].cells.length - 1 : 0;
+ if (zonesCount === 0) {
+ return jsonData;
}
- jsonData.push(categoryData);
+ for (var i = 1; i < table.rows.length; i++) {
+ var row = table.rows[i];
+ if (!row || !row.cells || row.cells.length === 0) continue;
+
+ var category = row.cells[0] ? (row.cells[0].innerText || row.cells[0].textContent || '').trim() : '';
+ if (!category) continue;
+
+ var categoryData = { "name": category };
+
+ for (var j = 1; j <= zonesCount && j < row.cells.length; j++) {
+ var zoneKey = "zone" + j;
+ var cell = row.cells[j];
+ if (!cell) {
+ categoryData[zoneKey] = "Nous consulter";
+ continue;
+ }
+
+ var input = cell.querySelector("input[type='text']");
+ if (input) {
+ var zoneValue = (input.value || '').trim();
+ categoryData[zoneKey] = zoneValue || "Nous consulter";
+ } else {
+ categoryData[zoneKey] = "Nous consulter";
+ }
+ }
+
+ if (Object.keys(categoryData).length > 1) {
+ jsonData.push(categoryData);
+ }
+ }
+ } catch (error) {
+ console.error('Erreur lors de l\'extraction de la grille Ad Valorem:', error);
+ } finally {
+ if (wasHidden && parentDiv) {
+ parentDiv.style.display = originalDisplay;
+ parentDiv.style.visibility = originalVisibility;
+ parentDiv.style.position = originalPosition;
+ parentDiv.style.left = originalLeft;
+ }
}
return jsonData;
@@ -1482,46 +2914,48 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
async function handleSubmitForm(event) {
event.preventDefault();
- // Création d'une nouvelle saisie dans la collection RC
- const responseRC = await fetch(`/rc/create`, {
- method: 'POST',
- body: JSON.stringify({
+ // Étape 1: Créer d'abord un enregistrement dans projetRC
+ const grilleMultimodal = extractGrilleAdvalo('tabAdvaloMultimodal');
+ const grilleTerrestre = extractGrilleAdvalo('tabAdvaloTerrestre');
+ const grilleAerien = extractGrilleAdvalo('tabAdvaloAerien');
+
+ const projetRCData = {
// Tableaux
"assureAdditionnel": extractAssureAdditionnel('empTableAdditionnel'),
"designationVehicule": extractDesignationVehicule('empTableVehicules'),
- "grilleMultimodal": extractGrilleAdvalo('tabAdvaloMultimodal'),
- "grilleTerrestre": extractGrilleAdvalo('tabAdvaloTerrestre'),
- "grilleAerien": extractGrilleAdvalo('tabAdvaloAerien'),
+ "grilleMultimodal": grilleMultimodal,
+ "grilleTerrestre": grilleTerrestre,
+ "grilleAerien": grilleAerien,
- // Activitées
+ // Activitées - avec gestion "Nous consulter"
"actVoiturier": document.getElementById("voiturier-chip") ? true : false,
- "valueActVoiturier": document.getElementById("voiturier-chip") ? document.getElementById("voiturier").value : false,
+ "valueActVoiturier": document.getElementById("voiturier-chip") ? getValueOrConsulter("voiturier") : false,
"actLoueur": document.getElementById("loueur-chip") ? true : false,
- "valueActLoueur": document.getElementById("loueur-chip") ? document.getElementById("loueur").value : false,
+ "valueActLoueur": document.getElementById("loueur-chip") ? getValueOrConsulter("loueur") : false,
"actMultimodal": document.getElementById("commissionnaire-multimodal-chip") ? true : false,
- "valueActMultimodal": document.getElementById("commissionnaire-multimodal-chip") ? document.getElementById("commissionnaire-multimodal").value : false,
+ "valueActMultimodal": document.getElementById("commissionnaire-multimodal-chip") ? getValueOrConsulter("commissionnaire-multimodal") : false,
"actDouane": document.getElementById("représentant-douane-chip") ? true : false,
- "valueActDouane": document.getElementById("représentant-douane-chip") ? document.getElementById("représentant-douane").value : false,
+ "valueActDouane": document.getElementById("représentant-douane-chip") ? getValueOrConsulter("représentant-douane") : false,
"actDemPar": document.getElementById("demenageur-particulier-chip") ? true : false,
- "valueActDemPar": document.getElementById("demenageur-particulier-chip") ? document.getElementById("demenageur-particulier").value : false,
+ "valueActDemPar": document.getElementById("demenageur-particulier-chip") ? getValueOrConsulter("demenageur-particulier") : false,
"actDemParDom": document.getElementById("demenageur-particulier-dommage-chip") ? true : false,
- "valueActDemParDom": document.getElementById("demenageur-particulier-dommage-chip") ? document.getElementById("demenageur-particulier-dommage").value : false,
+ "valueActDemParDom": document.getElementById("demenageur-particulier-dommage-chip") ? getValueOrConsulter("demenageur-particulier-dommage") : false,
"actDemParAdv": document.getElementById("demenageur-particulier-advalorem-chip") ? true : false,
- "valueActDemParAdv": document.getElementById("demenageur-particulier-advalorem-chip") ? document.getElementById("demenageur-particulier-advalorem").value : false,
+ "valueActDemParAdv": document.getElementById("demenageur-particulier-advalorem-chip") ? getValueOrConsulter("demenageur-particulier-advalorem") : false,
"actDemEntr": document.getElementById("demenageur-entreprise-chip") ? true : false,
- "valueActDemEntr": document.getElementById("demenageur-entreprise-chip") ? document.getElementById("demenageur-entreprise").value : false,
+ "valueActDemEntr": document.getElementById("demenageur-entreprise-chip") ? getValueOrConsulter("demenageur-entreprise") : false,
"actDemInterne": document.getElementById("demenageur-interne-chip") ? true : false,
- "valueActDemInterne": document.getElementById("demenageur-interne-chip") ? document.getElementById("demenageur-interne").value : false,
+ "valueActDemInterne": document.getElementById("demenageur-interne-chip") ? getValueOrConsulter("demenageur-interne") : false,
"actGardeMeuble": document.getElementById("garde-meubles-chip") ? true : false,
- "valueActGardeMeuble": document.getElementById("garde-meubles-chip") ? document.getElementById("garde-meubles").value : false,
+ "valueActGardeMeuble": document.getElementById("garde-meubles-chip") ? getValueOrConsulter("garde-meubles") : false,
"actEntDep": document.getElementById("entrepositaire-depositaire-chip") ? true : false,
- "valueActEntDep": document.getElementById("entrepositaire-depositaire-chip") ? document.getElementById("entrepositaire-depositaire").value : false,
+ "valueActEntDep": document.getElementById("entrepositaire-depositaire-chip") ? getValueOrConsulter("entrepositaire-depositaire") : false,
"actPrestaLog": document.getElementById("prestataire-logistique-chip") ? true : false,
- "valueActPrestaLog": document.getElementById("prestataire-logistique-chip") ? document.getElementById("prestataire-logistique").value : false,
+ "valueActPrestaLog": document.getElementById("prestataire-logistique-chip") ? getValueOrConsulter("prestataire-logistique") : false,
"actLevageur": document.getElementById("manutentionnaire-levageur-chip") ? true : false,
- "valueActLevageur": document.getElementById("manutentionnaire-levageur-chip") ? document.getElementById("manutentionnaire-levageur").value : false,
+ "valueActLevageur": document.getElementById("manutentionnaire-levageur-chip") ? getValueOrConsulter("manutentionnaire-levageur") : false,
"actTransitaire": document.getElementById("transitaire-chip") ? true : false,
- "valueActTransitaire": document.getElementById("transitaire-chip") ? document.getElementById("transitaire").value : false,
+ "valueActTransitaire": document.getElementById("transitaire-chip") ? getValueOrConsulter("transitaire") : false,
//Marchandises
"marOrdinaire": document.getElementById("ordinaire-chip") ? true : false,
@@ -1536,13 +2970,13 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
"marExceptionnels": document.getElementById("exceptionnels-chip") ? true : false,
"marVrac": document.getElementById("vrac-chip") ? true : false,
- // Territorialités
- "zone1": document.getElementById("zone1").checked ? true : false,
- "zone2": document.getElementById("zone2").checked ? true : false,
- "zone3": document.getElementById("zone3").checked ? true : false,
- "zone4": document.getElementById("zone4").checked ? true : false,
- "zone5": document.getElementById("zone5").checked ? true : false,
- "zone6": document.getElementById("zone6").checked ? true : false,
+ // Territorialités - vérifier checked même si disabled
+ "zone1": document.getElementById("zone1") && (document.getElementById("zone1").checked || document.getElementById("zone1").disabled) ? true : false,
+ "zone2": document.getElementById("zone2") && (document.getElementById("zone2").checked || document.getElementById("zone2").disabled) ? true : false,
+ "zone3": document.getElementById("zone3") && document.getElementById("zone3").checked ? true : false,
+ "zone4": document.getElementById("zone4") && document.getElementById("zone4").checked ? true : false,
+ "zone5": document.getElementById("zone5") && document.getElementById("zone5").checked ? true : false,
+ "zone6": document.getElementById("zone6") && document.getElementById("zone6").checked ? true : false,
// Extensions de garantie RCC
"extRCCModifCalArrim": document.getElementById("modif-calage-arrimage-chip") ? true : false,
@@ -1559,6 +2993,12 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
"extRCEBraDebra": document.getElementById("branchement-debranchement-chip") ? true : false,
"extRCEMontageDemontage": document.getElementById("montage-demontage-chip") ? true : false,
+ // Activités complémentaires
+ "activitesVoiturier": JSON.stringify(getActivitesComplFromForm('actComplVoiturier/Loueur')),
+ "activitesCommissionnaire": JSON.stringify(getActivitesComplFromForm('actComplCommissionnaire de Transport')),
+ "activitesDemenageur": JSON.stringify(getActivitesComplFromForm('actComplDéménageur')),
+ "activitesLogistique": JSON.stringify(getActivitesComplFromForm('actComplLogistique')),
+
// Temporalités
"tempo": extractTempo(),
"dateEffet": document.getElementById("dateEffet").value,
@@ -1568,39 +3008,108 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
"programmeInternationale": document.getElementById("programmeInternationale").checked ? true : false,
"participationResultat": document.getElementById("participationResultat").checked ? true : false,
- // Cotisations
+ // Cotisations - avec gestion "Nous consulter"
"typeCot": extractTypeCot(),
- "ca": document.getElementById("CA").value,
- "cotIrreductible": document.getElementById("cotisationIrreductible").value,
- "tauxRCCHT": document.getElementById("tauxRCCHT").value,
- "tauxRCCTTC": document.getElementById("tauxRCCTTC").value,
- "tauxRCEHT": document.getElementById("tauxRCEHT").value,
- "tauxRCETTC": document.getElementById("tauxRCETTC").value,
- "tauxTotalHT": document.getElementById("tauxTotalHT").value,
- "tauxTotalTTC": document.getElementById("tauxTotalTTC").value,
- "cotRCCHT": document.getElementById("cotRCCHT").value,
- "cotRCCTTC": document.getElementById("cotRCCTTC").value,
- "cotRCEHT": document.getElementById("cotRCEHT").value,
- "cotRCETTC": document.getElementById("cotRCETTC").value,
- "cotPJHT": document.getElementById("cotPJHT").value,
- "cotPJTTC": document.getElementById("cotPJTTC").value,
- "cotTotalHT": document.getElementById("cotTotalHT").value,
- "cotTotalTTC": document.getElementById("cotTotalTTC").value,
- "cotFraisHT": document.getElementById("cotFraisHT").value,
- "cotFraisTTC": document.getElementById("cotFraisTTC").value
+ "ca": getValueOrConsulter("CA"),
+ "cotIrreductible": getValueOrConsulter("cotisationIrreductible"),
+ "tauxRCCHT": getValueOrConsulter("tauxRCCHT"),
+ "tauxRCCTTC": getValueOrConsulter("tauxRCCTTC"),
+ "tauxRCEHT": getValueOrConsulter("tauxRCEHT"),
+ "tauxRCETTC": getValueOrConsulter("tauxRCETTC"),
+ "tauxTotalHT": getValueOrConsulter("tauxTotalHT"),
+ "tauxTotalTTC": getValueOrConsulter("tauxTotalTTC"),
+ "cotRCCHT": getValueOrConsulter("cotRCCHT"),
+ "cotRCCTTC": getValueOrConsulter("cotRCCTTC"),
+ "cotRCEHT": getValueOrConsulter("cotRCEHT"),
+ "cotRCETTC": getValueOrConsulter("cotRCETTC"),
+ "cotPJHT": getValueOrConsulter("cotPJHT"),
+ "cotPJTTC": getValueOrConsulter("cotPJTTC"),
+ "cotTotalHT": getValueOrConsulter("cotTotalHT"),
+ "cotTotalTTC": getValueOrConsulter("cotTotalTTC"),
+ "cotFraisHT": getValueOrConsulter("cotFraisHT"),
+ "cotFraisTTC": getValueOrConsulter("cotFraisTTC")
+ };
- // Vous pouvez ajouter d'autres données pour la saisie dans la collection RC ici
+ // Créer ou mettre à jour l'enregistrement projetRC
+ let idProjetRC;
+ if (projet && projet.id) {
+ // Mettre à jour l'enregistrement projetRC existant
+ const responseProjetRC = await fetch(`/rc/projet/update/${projet.id}`, {
+ method: 'POST',
+ body: JSON.stringify(projetRCData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const dataProjetRC = await responseProjetRC.json();
+ if (dataProjetRC.valid) {
+ idProjetRC = dataProjetRC.projetRc.id;
+ } else {
+ console.log('Échec lors de la mise à jour de l\'enregistrement ProjetRC :', dataProjetRC.message);
+ return;
+ }
+ } else {
+ // Créer un nouvel enregistrement projetRC
+ const responseProjetRC = await fetch(`/rc/projet/create`, {
+ method: 'POST',
+ body: JSON.stringify(projetRCData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const dataProjetRC = await responseProjetRC.json();
+ if (dataProjetRC.valid) {
+ idProjetRC = dataProjetRC.projetRc.id;
+ } else {
+ console.log('Échec lors de la création de l\'enregistrement ProjetRC :', dataProjetRC.message);
+ return;
+ }
+ }
+
+ if (idProjetRC) {
+
+ // Étape 2: Créer ou mettre à jour l'enregistrement RC principal
+ let idRC;
+ if (rc && rc.id) {
+ // Mettre à jour l'enregistrement RC existant avec la nouvelle référence projetRC
+ const responseRC = await fetch(`/rc/update/${rc.id}`, {
+ method: 'POST',
+ body: JSON.stringify({
+ projetRC: idProjetRC
}),
headers: {
'Content-Type': 'application/json',
},
});
const dataRC = await responseRC.json();
-
if (dataRC.valid) {
- const idRC = dataRC.rc.id;
+ idRC = dataRC.rc.id;
+ } else {
+ console.log('Échec lors de la mise à jour de l\'enregistrement RC :', dataRC.message);
+ return;
+ }
+ } else {
+ // Créer un nouvel enregistrement RC
+ const responseRC = await fetch(`/rc/create`, {
+ method: 'POST',
+ body: JSON.stringify({
+ projetRC: idProjetRC,
+ typeCotisation: extractTypeCot()
+ }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const dataRC = await responseRC.json();
+ if (dataRC.valid) {
+ idRC = dataRC.rc.id;
+ } else {
+ console.log('Échec lors de la création de l\'enregistrement RC :', dataRC.message);
+ return;
+ }
+ }
- // Mettre à jour le champ "enCours" dans le contrat avec l'ID de la nouvelle saisie RC
+ // Étape 3: Mettre à jour le champ "rc" dans le contrat avec l'ID de la saisie RC
const responseContratEnCours = await fetch(`/contrat/update/${contrat.produit}/${contrat.id}/${idRC}`, {
method: 'POST',
headers: {
@@ -1666,47 +3175,264 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
'Content-Type': 'application/json',
},
})
- .then(response => {
- if (!response.ok) {
- throw new Error('Erreur réseau ou serveur');
- }
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Erreur réseau ou serveur');
+ }
- const disposition = response.headers.get('content-disposition');
- filename = disposition.split(';')[1].trim().split('=')[1];
+ const disposition = response.headers.get('content-disposition');
+ filename = disposition.split(';')[1].trim().split('=')[1];
- return response.blob(); // On attend une réponse sous forme de blob pour un fichier
- })
- .then(blob => {
- // Crée un URL pour le blob
- const url = window.URL.createObjectURL(blob);
- // Crée un élément a temporaire pour simuler un clic pour téléchargement
- const a = document.createElement('a');
- a.href = url;
- a.download = filename; // Nomme le fichier téléchargé
- document.body.appendChild(a); // Ajoute l'élément au document
- a.click(); // Simule un clic sur l'élément pour déclencher le téléchargement
- window.URL.revokeObjectURL(url); // Nettoie l'URL objet
- a.remove(); // Supprime l'élément a du document
+ return response.blob(); // On attend une réponse sous forme de blob pour un fichier
+ })
+ .then(blob => {
+ // Crée un URL pour le blob
+ const url = window.URL.createObjectURL(blob);
+ // Crée un élément a temporaire pour simuler un clic pour téléchargement
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = filename; // Nomme le fichier téléchargé
+ document.body.appendChild(a); // Ajoute l'élément au document
+ a.click(); // Simule un clic sur l'élément pour déclencher le téléchargement
+ window.URL.revokeObjectURL(url); // Nettoie l'URL objet
+ a.remove(); // Supprime l'élément a du document
- window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=projet`;
- })
- .catch(error => console.error('Erreur lors de la génération du projet:', error));
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=projet`;
+ })
+ .catch(error => console.error('Erreur lors de la génération du projet 111:', error));
/// TODO FIN Génération fichier à l'enregistrement A RETIRER QUAND MODE CONTRAT
///////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO NE PAS OUBLIER LE HREF QUI EST DANS LE GEN ACTUELLEMENT
// window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=projet`;
} else {
- console.log('Echec lors de la mise à jour de l\'historique du contrat :', dataHistoriqueUpdate.message);
+ console.log('Échec lors de la mise à jour de l\'historique du contrat :', dataHistoriqueUpdate.message);
}
} else {
- console.log('Echec lors de la mise à jour du champ "enCours" dans le contrat :', dataContratEnCours.message);
+ console.log('Échec lors de la mise à jour du champ "rc" dans le contrat :', dataContratEnCours.message);
}
} else {
- console.log('Echec lors de la création de la saisie dans la collection RC :', dataRC.message);
+ console.log('Échec lors de la création de l\'enregistrement ProjetRC :', dataProjetRC.message);
}
}
- // Exposer init globalement pour y accéder depuis l'extérieur
+ // Fonction helper pour récupérer valeur ou "Nous consulter"
+ function getValueOrConsulter(id) {
+ const element = document.getElementById(id);
+ if (!element) return 'Nous consulter';
+ const value = element.value?.trim();
+ return value || 'Nous consulter';
+ }
+
+ // Fonction exposée pour sauvegarder le projet sans générer le document
+ async function saveProjetRC() {
+ try {
+ // Étape 1: Créer d'abord un enregistrement dans projetRC
+ const grilleMultimodal = extractGrilleAdvalo('tabAdvaloMultimodal');
+ const grilleTerrestre = extractGrilleAdvalo('tabAdvaloTerrestre');
+ const grilleAerien = extractGrilleAdvalo('tabAdvaloAerien');
+
+ const projetRCData = {
+ // Tableaux
+ "assureAdditionnel": extractAssureAdditionnel('empTableAdditionnel'),
+ "designationVehicule": extractDesignationVehicule('empTableVehicules'),
+ "grilleMultimodal": grilleMultimodal,
+ "grilleTerrestre": grilleTerrestre,
+ "grilleAerien": grilleAerien,
+
+ // Activitées
+ "actVoiturier": document.getElementById("voiturier-chip") ? true : false,
+ "valueActVoiturier": document.getElementById("voiturier-chip") ? getValueOrConsulter("voiturier") : false,
+ "actLoueur": document.getElementById("loueur-chip") ? true : false,
+ "valueActLoueur": document.getElementById("loueur-chip") ? document.getElementById("loueur").value : false,
+ "actMultimodal": document.getElementById("commissionnaire-multimodal-chip") ? true : false,
+ "valueActMultimodal": document.getElementById("commissionnaire-multimodal-chip") ? document.getElementById("commissionnaire-multimodal").value : false,
+ "actDouane": document.getElementById("représentant-douane-chip") ? true : false,
+ "valueActDouane": document.getElementById("représentant-douane-chip") ? document.getElementById("représentant-douane").value : false,
+ "actDemPar": document.getElementById("demenageur-particulier-chip") ? true : false,
+ "valueActDemPar": document.getElementById("demenageur-particulier-chip") ? document.getElementById("demenageur-particulier").value : false,
+ "actDemParDom": document.getElementById("demenageur-particulier-dommage-chip") ? true : false,
+ "valueActDemParDom": document.getElementById("demenageur-particulier-dommage-chip") ? document.getElementById("demenageur-particulier-dommage").value : false,
+ "actDemParAdv": document.getElementById("demenageur-particulier-advalorem-chip") ? true : false,
+ "valueActDemParAdv": document.getElementById("demenageur-particulier-advalorem-chip") ? document.getElementById("demenageur-particulier-advalorem").value : false,
+ "actDemEntr": document.getElementById("demenageur-entreprise-chip") ? true : false,
+ "valueActDemEntr": document.getElementById("demenageur-entreprise-chip") ? document.getElementById("demenageur-entreprise").value : false,
+ "actDemInterne": document.getElementById("demenageur-interne-chip") ? true : false,
+ "valueActDemInterne": document.getElementById("demenageur-interne-chip") ? document.getElementById("demenageur-interne").value : false,
+ "actGardeMeuble": document.getElementById("garde-meubles-chip") ? true : false,
+ "valueActGardeMeuble": document.getElementById("garde-meubles-chip") ? document.getElementById("garde-meubles").value : false,
+ "actEntDep": document.getElementById("entrepositaire-depositaire-chip") ? true : false,
+ "valueActEntDep": document.getElementById("entrepositaire-depositaire-chip") ? document.getElementById("entrepositaire-depositaire").value : false,
+ "actPrestaLog": document.getElementById("prestataire-logistique-chip") ? true : false,
+ "valueActPrestaLog": document.getElementById("prestataire-logistique-chip") ? document.getElementById("prestataire-logistique").value : false,
+ "actLevageur": document.getElementById("manutentionnaire-levageur-chip") ? true : false,
+ "valueActLevageur": document.getElementById("manutentionnaire-levageur-chip") ? document.getElementById("manutentionnaire-levageur").value : false,
+ "actTransitaire": document.getElementById("transitaire-chip") ? true : false,
+ "valueActTransitaire": document.getElementById("transitaire-chip") ? document.getElementById("transitaire").value : false,
+
+ //Marchandises
+ "marOrdinaire": document.getElementById("ordinaire-chip") ? true : false,
+ "marRoulant": document.getElementById("roulant-chip") ? true : false,
+ "marEngins": document.getElementById("engins-chantier-agricole-chip") ? true : false,
+ "marRoulantDem": document.getElementById("roulant-demenagement-chip") ? true : false,
+ "marMobilerUsag": document.getElementById("mobilier-usages-chip") ? true : false,
+ "marPerissable": document.getElementById("perissable-temperature-dirigee-chip") ? true : false,
+ "marAnimaux": document.getElementById("animaux-vivant-chip") ? true : false,
+ "marCiterne": document.getElementById("citerne-chip") ? true : false,
+ "marBeton": document.getElementById("beton-chip") ? true : false,
+ "marExceptionnels": document.getElementById("exceptionnels-chip") ? true : false,
+ "marVrac": document.getElementById("vrac-chip") ? true : false,
+
+ // Territorialités - vérifier checked même si disabled
+ "zone1": document.getElementById("zone1") && (document.getElementById("zone1").checked || document.getElementById("zone1").disabled) ? true : false,
+ "zone2": document.getElementById("zone2") && (document.getElementById("zone2").checked || document.getElementById("zone2").disabled) ? true : false,
+ "zone3": document.getElementById("zone3") && document.getElementById("zone3").checked ? true : false,
+ "zone4": document.getElementById("zone4") && document.getElementById("zone4").checked ? true : false,
+ "zone5": document.getElementById("zone5") && document.getElementById("zone5").checked ? true : false,
+ "zone6": document.getElementById("zone6") && document.getElementById("zone6").checked ? true : false,
+
+ // Extensions de garantie RCC
+ "extRCCModifCalArrim": document.getElementById("modif-calage-arrimage-chip") ? true : false,
+ "extRCCFerroutage": document.getElementById("ferroutage-chip") ? true : false,
+ "extRCCFraisRecons": document.getElementById("frais-reconstitution-chip") ? true : false,
+ "extRCCConfie": document.getElementById("contenant-confie-chip") ? true : false,
+ "typeExtConfies": document.getElementById("contenant-confie-chip") ? (document.getElementById('ValeurDeclaree').checked ? "VALEUR DECLAREE" : "ADVALOREM") : "",
+ "extRCCTPPC": document.getElementById("tppc-chip") ? true : false,
+ "extRCCRegie": document.getElementById("regie-chip") ? true : false,
+ "extRCCSansMontageDemontage": document.getElementById("sans-montage-demontage-chip") ? true : false,
+
+ // Extensions de garantie RCE
+ "autresRC": document.getElementById("choixRCE").checked ? true : false,
+ "extRCEBraDebra": document.getElementById("branchement-debranchement-chip") ? true : false,
+ "extRCEMontageDemontage": document.getElementById("montage-demontage-chip") ? true : false,
+
+ // Activités complémentaires
+ "activitesVoiturier": JSON.stringify(getActivitesComplFromForm('actComplVoiturier/Loueur')),
+ "activitesCommissionnaire": JSON.stringify(getActivitesComplFromForm('actComplCommissionnaire de Transport')),
+ "activitesDemenageur": JSON.stringify(getActivitesComplFromForm('actComplDéménageur')),
+ "activitesLogistique": JSON.stringify(getActivitesComplFromForm('actComplLogistique')),
+
+ // Temporalités
+ "tempo": extractTempo(),
+ "dateEffet": document.getElementById("dateEffet").value,
+ "dateEcheance": document.getElementById("dateEcheance").value,
+ "dateFin": document.getElementById("dateFin").value,
+ "pj": document.getElementById("switchPJ").checked ? true : false,
+ "programmeInternationale": document.getElementById("programmeInternationale").checked ? true : false,
+ "participationResultat": document.getElementById("participationResultat").checked ? true : false,
+
+ // Cotisations - avec gestion "Nous consulter"
+ "typeCot": extractTypeCot(),
+ "ca": getValueOrConsulter("CA"),
+ "cotIrreductible": getValueOrConsulter("cotisationIrreductible"),
+ "tauxRCCHT": getValueOrConsulter("tauxRCCHT"),
+ "tauxRCCTTC": getValueOrConsulter("tauxRCCTTC"),
+ "tauxRCEHT": getValueOrConsulter("tauxRCEHT"),
+ "tauxRCETTC": getValueOrConsulter("tauxRCETTC"),
+ "tauxTotalHT": getValueOrConsulter("tauxTotalHT"),
+ "tauxTotalTTC": getValueOrConsulter("tauxTotalTTC"),
+ "cotRCCHT": getValueOrConsulter("cotRCCHT"),
+ "cotRCCTTC": getValueOrConsulter("cotRCCTTC"),
+ "cotRCEHT": getValueOrConsulter("cotRCEHT"),
+ "cotRCETTC": getValueOrConsulter("cotRCETTC"),
+ "cotPJHT": getValueOrConsulter("cotPJHT"),
+ "cotPJTTC": getValueOrConsulter("cotPJTTC"),
+ "cotTotalHT": getValueOrConsulter("cotTotalHT"),
+ "cotTotalTTC": getValueOrConsulter("cotTotalTTC"),
+ "cotFraisHT": getValueOrConsulter("cotFraisHT"),
+ "cotFraisTTC": getValueOrConsulter("cotFraisTTC")
+ };
+
+ // Créer ou mettre à jour l'enregistrement projetRC
+ let idProjetRC;
+ if (projet && projet.id) {
+ // Mettre à jour l'enregistrement projetRC existant
+ const responseProjetRC = await fetch(`/rc/projet/update/${projet.id}`, {
+ method: 'POST',
+ body: JSON.stringify(projetRCData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const dataProjetRC = await responseProjetRC.json();
+ if (dataProjetRC.valid) {
+ idProjetRC = dataProjetRC.projetRc.id;
+ } else {
+ console.log('Échec lors de la mise à jour de l\'enregistrement ProjetRC :', dataProjetRC.message);
+ return { valid: false, message: 'Échec mise à jour ProjetRC' };
+ }
+ } else {
+ // Créer un nouvel enregistrement projetRC
+ const responseProjetRC = await fetch(`/rc/projet/create`, {
+ method: 'POST',
+ body: JSON.stringify(projetRCData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const dataProjetRC = await responseProjetRC.json();
+ if (dataProjetRC.valid) {
+ idProjetRC = dataProjetRC.projetRc.id;
+ } else {
+ console.log('Échec lors de la création de l\'enregistrement ProjetRC :', dataProjetRC.message);
+ return { valid: false, message: 'Échec création ProjetRC' };
+ }
+ }
+
+ if (idProjetRC) {
+
+ // Étape 2: Créer ou mettre à jour l'enregistrement RC principal
+ let idRC;
+
+ if (rc && rc.id) {
+ // Mettre à jour l'enregistrement RC existant
+ const responseRC = await fetch(`/rc/update/${rc.id}`, {
+ method: 'POST',
+ body: JSON.stringify({ projetRC: idProjetRC }),
+ headers: { 'Content-Type': 'application/json' },
+ });
+ const dataRC = await responseRC.json();
+ if (dataRC.valid) {
+ idRC = dataRC.rc.id;
+ } else {
+ return { valid: false, message: 'Échec mise à jour RC' };
+ }
+ } else {
+ // Créer un nouvel enregistrement RC
+ const responseRC = await fetch(`/rc/create`, {
+ method: 'POST',
+ body: JSON.stringify({
+ projetRC: idProjetRC,
+ typeCotisation: extractTypeCot()
+ }),
+ headers: { 'Content-Type': 'application/json' },
+ });
+ const dataRC = await responseRC.json();
+ if (dataRC.valid) {
+ idRC = dataRC.rc.id;
+ } else {
+ return { valid: false, message: 'Échec création RC' };
+ }
+ }
+
+ // Étape 3: Mettre à jour le contrat
+ const responseContrat = await fetch(`/contrat/update/${contrat.produit}/${contrat.id}/${idRC}`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ });
+ const dataContrat = await responseContrat.json();
+
+ return { valid: dataContrat.valid, idRC, idProjetRC };
+ } else {
+ return { valid: false, message: 'Échec création ProjetRC' };
+ }
+ } catch (error) {
+ console.error('Erreur lors de la sauvegarde:', error);
+ return { valid: false, message: error.message };
+ }
+ }
+
+ // Exposer les fonctions globalement pour y accéder depuis l'extérieur
window.initSubmenuForm = init;
+ window.saveProjetRC = saveProjetRC;
})();
\ No newline at end of file
diff --git a/ecole/public/js/rc-data-manager.js b/ecole/public/js/rc-data-manager.js
new file mode 100644
index 00000000..283e2f54
--- /dev/null
+++ b/ecole/public/js/rc-data-manager.js
@@ -0,0 +1,647 @@
+/**
+ * ═══════════════════════════════════════════════════════════════════════════
+ * RC DATA MANAGER
+ * ═══════════════════════════════════════════════════════════════════════════
+ *
+ * Ce module gère la collecte, la sauvegarde et le pré-remplissage des données
+ * RC entre les formulaires Tarif et Projet.
+ *
+ * @requires rc-sync-utils.js
+ * @author AXA Transport Team
+ * @version 2.0.0
+ * @since 2026-02-17
+ */
+
+(function(window) {
+ 'use strict';
+
+ const { toNumber, getValue, setValue, getElementByIdFlexible } = window.RCSync;
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // MAPPING DES CHAMPS TARIF ↔ PROJET
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Mapping complet des champs entre Tarif et Projet.
+ * Permet la synchronisation bidirectionnelle.
+ *
+ * Structure: { tarifFieldId: projetFieldId }
+ */
+ const FIELD_MAPPING = {
+ // Informations générales
+ 'CA': 'CA',
+ 'chiffreAffaire': 'CA',
+ 'nbVehicules': 'nombreVehicules',
+ 'nbrVehicule': 'nombreVehicules',
+
+ // Type de cotisation
+ 'cotisation': 'typeCot',
+
+ // Activités RCC - Voiturier
+ 'checkVoiturier': 'actVoiturier',
+ 'capitalVoiturier': 'valueActVoiturier',
+
+ // Activités RCC - Commissionnaire (Multimodal)
+ 'checkCommissionnaire': 'actMultimodal',
+ 'capitalCommissionnaire': 'valueActMultimodal',
+
+ // Activités RCC - Déménageur
+ 'checkDemenageur': 'actDemEntr',
+ 'capitalDemenageur': 'valueActDemEntr',
+
+ // Activités RCC - Logistique
+ 'checkLogistique': 'actPrestaLog',
+ 'capitalLogistique': 'valueActPrestaLog',
+
+ // RCE
+ 'checkRCE': 'autresRC',
+
+ // Zones géographiques
+ 'zone1': 'zone1',
+ 'zone2': 'zone2',
+ 'zone3': 'zone3',
+ 'zone4': 'zone4',
+ 'zone5': 'zone5',
+ 'zone6': 'zone6',
+
+ // Protection Juridique
+ 'checkPJ': 'pj',
+
+ // Garanties additionnelles - Engagements complémentaires
+ 'checkDomImmat': 'extRCCConfie', // Simplifié
+ 'checkContConf': 'extRCCConfie',
+ 'checkTPPC': 'extRCCTPPC',
+
+ // Extensions RCC
+ 'checkStationLavage': 'extRCCModifCalArrim',
+
+ // Extensions RCE
+ // (géré séparément car structure différente)
+
+ // Sinistralité
+ 'sinistre': 'nbSinistres3ans'
+ };
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // COLLECTE DES DONNÉES COMPLÈTES
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Collecte toutes les données du formulaire Tarif RC.
+ * Cette fonction est exhaustive et capture TOUS les champs nécessaires.
+ *
+ * @returns {Object} Objet contenant toutes les données du tarif
+ *
+ * @example
+ * const tarifData = collectAllTarifData();
+ * console.log(tarifData.ca, tarifData.zones, tarifData.marchandises);
+ */
+ function collectAllTarifData() {
+ // Références flexibles aux éléments
+ const getEl = getElementByIdFlexible;
+
+ const data = {
+ // ═══ INFORMATIONS GÉNÉRALES ═══
+ typeCotisation: document.querySelector('input[name="cotisation"]:checked')?.value || null,
+ ca: toNumber(getValue('CA') || getValue('chiffreAffaire')),
+ nombreVehicules: Math.max(0, Math.round(toNumber(getValue('nbVehicules') || getValue('nbrVehicule')))),
+
+ // ═══ ACTIVITÉS RCC ═══
+ activites: {
+ voiturier: {
+ checked: getValue('checkVoiturier') || false,
+ capital: toNumber(getValue('capitalVoiturier')),
+ pourcentage: toNumber(getValue('pourcent_voiturier') || getValue('pourcentVoiturier/Loueur')),
+ isSet: Boolean(getValue('pourcent_voiturier')?.trim())
+ },
+ commissionnaire: {
+ checked: getValue('checkCommissionnaire') || false,
+ capital: toNumber(getValue('capitalCommissionnaire')),
+ pourcentage: toNumber(getValue('pourcent_commissionnaire')),
+ isSet: Boolean(getValue('pourcent_commissionnaire')?.trim())
+ },
+ demenageur: {
+ checked: getValue('checkDemenageur') || false,
+ capital: toNumber(getValue('capitalDemenageur')),
+ pourcentage: toNumber(getValue('pourcent_demenageur')),
+ isSet: Boolean(getValue('pourcent_demenageur')?.trim())
+ },
+ logistique: {
+ checked: getValue('checkLogistique') || false,
+ capital: toNumber(getValue('capitalLogistique')),
+ pourcentage: toNumber(getValue('pourcent_logistique')),
+ isSet: Boolean(getValue('pourcent_logistique')?.trim())
+ },
+ autocariste: {
+ checked: getValue('checkAutocariste') || false,
+ capital: toNumber(getValue('capitalAutocariste')),
+ pourcentage: toNumber(getValue('pourcent_autocariste')),
+ isSet: Boolean(getValue('pourcent_autocariste')?.trim())
+ },
+ autres: {
+ checked: getValue('checkAutres') || false,
+ capital: toNumber(getValue('capitalAutres')),
+ pourcentage: toNumber(getValue('pourcent_autres')),
+ isSet: Boolean(getValue('pourcent_autres')?.trim())
+ }
+ },
+
+ // ═══ RCE ═══
+ rce: {
+ checked: getValue('checkRCE') || false
+ },
+
+ // ═══ ACTIVITÉS COMPLÉMENTAIRES (JSON) ═══
+ activitesComplementaires: {
+ voiturier: collectActivitesComplJSON('voiturier'),
+ commissionnaire: collectActivitesComplJSON('commissionnaire'),
+ demenageur: collectActivitesComplJSON('demenageur'),
+ logistique: collectActivitesComplJSON('logistique')
+ },
+
+ // ═══ MARCHANDISES (JSON) ═══
+ marchandises: {
+ voiturier: collectMarchandisesJSON('voiturier'),
+ commissionnaire: collectMarchandisesJSON('commissionnaire'),
+ demenageur: collectMarchandisesJSON('demenageur'),
+ logistique: collectMarchandisesJSON('logistique'),
+ autocariste: collectMarchandisesJSON('autocariste'),
+ autres: collectMarchandisesJSON('autres')
+ },
+
+ // ═══ ZONES GÉOGRAPHIQUES ═══
+ zones: {
+ zone1: getValue('zone1') || false,
+ zone2: getValue('zone2') || false,
+ zone3: getValue('zone3') || false,
+ zone4: getValue('zone4') || false,
+ zone5: getValue('zone5') || false,
+ zone6: getValue('zone6') || false
+ },
+
+ // ═══ ENGAGEMENTS COMPLÉMENTAIRES ═══
+ engagementsComplementaires: {
+ domicileImmatriculation: {
+ checked: getValue('checkDomImmat') || false,
+ capital: toNumber(getValue('inputDomImmat'))
+ },
+ contenantConfie: {
+ checked: getValue('checkContConf') || false,
+ capital: toNumber(getValue('inputContConf'))
+ },
+ differenceInventaire: {
+ checked: getValue('checkDiffInv') || false,
+ capital: toNumber(getValue('inputDiffInv'))
+ }
+ },
+
+ // ═══ GARANTIES ADDITIONNELLES ═══
+ garantiesAdditionnelles: {
+ stationLavage: getValue('checkStationLavage') || false,
+ garageInterne: getValue('checkGarageInterne') || false,
+ cse: getValue('checkCSE') || false,
+ tppc: {
+ checked: getValue('checkTPPC') || false,
+ capital: toNumber(getValue('selTPPCcapital')),
+ vehicules: Math.max(0, Math.round(toNumber(getValue('selTPPCveh'))))
+ },
+ pj: getValue('checkPJ') || false
+ },
+
+ // ═══ SINISTRALITÉ ═══
+ sinistralite: {
+ nombre3ans: toNumber(getValue('sinistre')),
+ montant3ans: 0 // TODO: ajouter si champ existe
+ },
+
+ // ═══ RÉSULTATS DE CALCUL ═══
+ resultats: {
+ // Franchise 250
+ fr250: {
+ primeRCC: toNumber(getEl('rccFr250')?.textContent),
+ primeRCE: toNumber(getEl('rceFr250')?.textContent),
+ primePJ: toNumber(getEl('pjFr250')?.textContent),
+ primeTotal: toNumber(getEl('priceFr250')?.textContent),
+ tauxRCC: toNumber(getEl('tauxRccFr250')?.textContent),
+ tauxRCE: toNumber(getEl('tauxRceFr250')?.textContent),
+ tauxGlobal: toNumber(getEl('tauxGlobalFr250')?.textContent)
+ },
+ // Franchise 400
+ fr400: {
+ primeRCC: toNumber(getEl('rccFr400')?.textContent),
+ primeRCE: toNumber(getEl('rceFr400')?.textContent),
+ primePJ: toNumber(getEl('pjFr400')?.textContent),
+ primeTotal: toNumber(getEl('priceFr400')?.textContent),
+ tauxRCC: toNumber(getEl('tauxRccFr400')?.textContent),
+ tauxRCE: toNumber(getEl('tauxRceFr400')?.textContent),
+ tauxGlobal: toNumber(getEl('tauxGlobalFr400')?.textContent)
+ },
+ // Franchise 2000
+ fr2000: {
+ primeRCC: toNumber(getEl('rccFr2000')?.textContent),
+ primeRCE: toNumber(getEl('rceFr2000')?.textContent),
+ primePJ: toNumber(getEl('pjFr2000')?.textContent),
+ primeTotal: toNumber(getEl('priceFr2000')?.textContent),
+ tauxRCC: toNumber(getEl('tauxRccFr2000')?.textContent),
+ tauxRCE: toNumber(getEl('tauxRceFr2000')?.textContent),
+ tauxGlobal: toNumber(getEl('tauxGlobalFr2000')?.textContent)
+ },
+ franchiseChoisie: window.franchiseChoisie || null,
+ tarifCommercial: toNumber(getValue('tarifCom'))
+ },
+
+ // ═══ COMMENTAIRE ═══
+ commentaire: getValue('commentaire') || ''
+ };
+
+ console.log('📊 Données Tarif collectées:', data);
+ return data;
+ }
+
+ /**
+ * Fonction helper pour collecter les activités complémentaires depuis le formulaire.
+ *
+ * @param {string} typeActivite - Type d'activité ('voiturier', 'commissionnaire', etc.)
+ * @returns {string} JSON array des activités cochées
+ * @private
+ */
+ function collectActivitesComplJSON(typeActivite) {
+ let name;
+ switch(typeActivite.toLowerCase()) {
+ case 'voiturier':
+ name = 'actComplVoiturier/Loueur';
+ break;
+ case 'commissionnaire':
+ name = 'actComplCommissionnaire de Transport';
+ break;
+ case 'demenageur':
+ name = 'actComplDéménageur';
+ break;
+ case 'logistique':
+ name = 'actComplLogistique';
+ break;
+ default:
+ return JSON.stringify([]);
+ }
+
+ const checkboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]:checked`);
+ const activites = [];
+ checkboxes.forEach(cb => {
+ const text = cb.nextElementSibling ? cb.nextElementSibling.textContent.trim() : cb.value;
+ activites.push(text);
+ });
+ return JSON.stringify(activites);
+ }
+
+ /**
+ * Fonction helper pour collecter les marchandises depuis le formulaire.
+ *
+ * @param {string} typeActivite - Type d'activité
+ * @returns {string} JSON array des marchandises cochées
+ * @private
+ */
+ function collectMarchandisesJSON(typeActivite) {
+ let name;
+ switch(typeActivite.toLowerCase()) {
+ case 'voiturier':
+ name = 'marVoiturier/Loueur';
+ break;
+ case 'commissionnaire':
+ name = 'marCommissionnaire de Transport';
+ break;
+ case 'demenageur':
+ name = 'marDéménageur';
+ break;
+ case 'logistique':
+ name = 'marLogistique';
+ break;
+ case 'autocariste':
+ name = 'marAutocariste';
+ break;
+ case 'autres':
+ name = 'marAutres activites';
+ break;
+ default:
+ return JSON.stringify([]);
+ }
+
+ const checkboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]:checked`);
+ const marchandises = [];
+ checkboxes.forEach(cb => {
+ const text = cb.nextElementSibling ? cb.nextElementSibling.textContent.trim() : cb.value;
+ marchandises.push(text);
+ });
+ return JSON.stringify(marchandises);
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // PRÉ-REMPLISSAGE TARIF → PROJET
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Pré-remplit le formulaire Projet avec les données du Tarif.
+ * Cette fonction est appelée quand l'utilisateur passe du Tarif au Projet.
+ *
+ * @param {Object} tarifData - Données complètes du tarif (de collectAllTarifData)
+ *
+ * @example
+ * const tarifData = collectAllTarifData();
+ * prefillProjetFromTarif(tarifData);
+ */
+ function prefillProjetFromTarif(tarifData) {
+ if (!tarifData) {
+ console.warn('Pas de données tarif à pré-remplir');
+ return;
+ }
+
+ console.log('📝 Pré-remplissage Projet depuis Tarif...');
+
+ try {
+ // ═══ INFORMATIONS GÉNÉRALES ═══
+
+ // CA
+ if (tarifData.ca) {
+ setValue('CA', tarifData.ca);
+ console.log(' ✓ CA:', tarifData.ca);
+ }
+
+ // Type de cotisation
+ if (tarifData.typeCotisation) {
+ const radio = document.querySelector(`input[name="typeCot"][value="${tarifData.typeCotisation}"]`);
+ if (radio) {
+ radio.checked = true;
+ console.log(' ✓ Type cotisation:', tarifData.typeCotisation);
+ }
+ }
+
+ // Nombre de véhicules
+ if (tarifData.nombreVehicules) {
+ setValue('nombreVehicules', tarifData.nombreVehicules);
+ console.log(' ✓ Véhicules:', tarifData.nombreVehicules);
+ }
+
+ // ═══ ACTIVITÉS ═══
+
+ const activitySelector = document.getElementById('activity-selector');
+ if (activitySelector && tarifData.activites) {
+ const activitesToAdd = [];
+
+ if (tarifData.activites.voiturier?.checked) {
+ activitesToAdd.push('Voiturier/Loueur');
+ }
+ if (tarifData.activites.commissionnaire?.checked) {
+ activitesToAdd.push('Commissionnaire de Transport');
+ }
+ if (tarifData.activites.demenageur?.checked) {
+ activitesToAdd.push('Déménageur d\'entreprises');
+ }
+ if (tarifData.activites.logistique?.checked) {
+ activitesToAdd.push('Prestataire logistique');
+ }
+ if (tarifData.activites.autocariste?.checked) {
+ activitesToAdd.push('Autocariste');
+ }
+ if (tarifData.activites.autres?.checked) {
+ activitesToAdd.push('Autres activités');
+ }
+
+ // Sélectionner les options dans le select
+ Array.from(activitySelector.options).forEach(option => {
+ if (activitesToAdd.includes(option.value)) {
+ option.selected = true;
+ }
+ });
+
+ // Trigger change pour créer les chips Materialize
+ const event = new Event('change', { bubbles: true });
+ activitySelector.dispatchEvent(event);
+
+ console.log(' ✓ Activités:', activitesToAdd.length);
+ }
+
+ // ═══ MARCHANDISES ═══
+
+ const marchandiseSelector = document.getElementById('marchandise-selector');
+ if (marchandiseSelector && tarifData.marchandises) {
+ const marchandisesToSelect = [];
+
+ // Parser les marchandises de chaque type
+ ['voiturier', 'commissionnaire', 'demenageur', 'logistique', 'autocariste', 'autres'].forEach(type => {
+ const marchArray = tarifData.marchandises[type];
+ if (Array.isArray(marchArray)) {
+ marchArray.forEach(m => marchandisesToSelect.push(m));
+ }
+ });
+
+ // Sélectionner dans le select
+ Array.from(marchandiseSelector.options).forEach(option => {
+ if (marchandisesToSelect.includes(option.text) || marchandisesToSelect.includes(option.value)) {
+ option.selected = true;
+ }
+ });
+
+ const event = new Event('change', { bubbles: true });
+ marchandiseSelector.dispatchEvent(event);
+
+ console.log(' ✓ Marchandises:', marchandisesToSelect.length);
+ }
+
+ // ═══ ZONES GÉOGRAPHIQUES ═══
+
+ if (tarifData.zones) {
+ let zonesCount = 0;
+ Object.keys(tarifData.zones).forEach(zoneKey => {
+ const checkbox = document.getElementById(zoneKey);
+ if (checkbox && tarifData.zones[zoneKey]) {
+ checkbox.checked = true;
+ zonesCount++;
+ }
+ });
+ console.log(' ✓ Zones:', zonesCount);
+ }
+
+ // ═══ PROTECTION JURIDIQUE ═══
+
+ if (tarifData.garantiesAdditionnelles?.pj) {
+ const switchPJ = document.getElementById('switchPJ');
+ if (switchPJ) {
+ switchPJ.checked = true;
+ console.log(' ✓ PJ activée');
+
+ // Afficher la section PJ
+ const pjSection = document.getElementById('pj-section');
+ if (pjSection) pjSection.style.display = 'block';
+ }
+ }
+
+ // ═══ RCE ═══
+
+ if (tarifData.rce?.checked) {
+ const choixRCE = document.getElementById('choixRCE');
+ if (choixRCE) {
+ choixRCE.checked = true;
+ console.log(' ✓ RCE activée');
+
+ // Afficher la section RCE
+ const rceSection = document.getElementById('section-rce');
+ if (rceSection) rceSection.style.display = 'block';
+ }
+ }
+
+ // ═══ TPPC ═══
+
+ if (tarifData.garantiesAdditionnelles?.tppc?.checked) {
+ const checkTPPC = document.getElementById('checkTPPC');
+ if (checkTPPC) {
+ checkTPPC.checked = true;
+
+ if (tarifData.garantiesAdditionnelles.tppc.capital) {
+ setValue('capitalTPPC', tarifData.garantiesAdditionnelles.tppc.capital);
+ }
+ if (tarifData.garantiesAdditionnelles.tppc.vehicules) {
+ setValue('vehiculesTPPC', tarifData.garantiesAdditionnelles.tppc.vehicules);
+ }
+
+ console.log(' ✓ TPPC');
+ }
+ }
+
+ // ═══ ENGAGEMENTS COMPLÉMENTAIRES ═══
+
+ const engagements = tarifData.engagementsComplementaires;
+ if (engagements) {
+ if (engagements.domicileImmatriculation?.checked) {
+ setValue('checkDomImmat', true);
+ console.log(' ✓ Domicile immatriculation');
+ }
+ if (engagements.contenantConfie?.checked) {
+ setValue('checkContConf', true);
+ console.log(' ✓ Contenant confié');
+ }
+ }
+
+ // ═══ SINISTRALITÉ ═══
+
+ if (tarifData.sinistralite) {
+ if (tarifData.sinistralite.nombre3ans) {
+ setValue('nbSinistres3ans', tarifData.sinistralite.nombre3ans);
+ }
+ if (tarifData.sinistralite.montant3ans) {
+ setValue('montantSinistres3ans', tarifData.sinistralite.montant3ans);
+ }
+ console.log(' ✓ Sinistralité');
+ }
+
+ // ═══ RÉSULTATS TARIFAIRES ═══
+
+ if (tarifData.resultats) {
+ const res = tarifData.resultats;
+
+ // Taux
+ if (res.tauxRCCHT) setValue('tauxRCCHT', res.tauxRCCHT);
+ if (res.tauxRCCTTC) setValue('tauxRCCTTC', res.tauxRCCTTC);
+ if (res.tauxRCEHT) setValue('tauxRCEHT', res.tauxRCEHT);
+ if (res.tauxRCETTC) setValue('tauxRCETTC', res.tauxRCETTC);
+ if (res.tauxTotalHT) setValue('tauxTotalHT', res.tauxTotalHT);
+ if (res.tauxTotalTTC) setValue('tauxTotalTTC', res.tauxTotalTTC);
+
+ // Cotisations
+ if (res.cotRCCHT) setValue('cotRCCHT', res.cotRCCHT);
+ if (res.cotRCCTTC) setValue('cotRCCTTC', res.cotRCCTTC);
+ if (res.cotRCEHT) setValue('cotRCEHT', res.cotRCEHT);
+ if (res.cotRCETTC) setValue('cotRCETTC', res.cotRCETTC);
+ if (res.cotPJHT) setValue('cotPJHT', res.cotPJHT);
+ if (res.cotPJTTC) setValue('cotPJTTC', res.cotPJTTC);
+ if (res.cotTotalHT) setValue('cotTotalHT', res.cotTotalHT);
+ if (res.cotTotalTTC) setValue('cotTotalTTC', res.cotTotalTTC);
+
+ console.log(' ✓ Résultats tarifaires');
+ }
+
+ // Forcer la mise à jour des éléments Materialize
+ if (window.M && window.M.FormSelect) {
+ const selects = document.querySelectorAll('select');
+ window.M.FormSelect.init(selects);
+ }
+ if (window.M && window.M.updateTextFields) {
+ window.M.updateTextFields();
+ }
+
+ console.log('✅ Pré-remplissage Projet terminé');
+
+ } catch (error) {
+ console.error('❌ Erreur lors du pré-remplissage Projet:', error);
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // PRÉ-REMPLISSAGE PROJET → TARIF
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Pré-remplit le formulaire Tarif avec les données du Projet.
+ * Cette fonction est appelée quand l'utilisateur passe du Projet au Tarif.
+ *
+ * @param {Object} projetData - Données complètes du projet
+ *
+ * @example
+ * prefillTarifFromProjet(projetData);
+ */
+ function prefillTarifFromProjet(projetData) {
+ if (!projetData) {
+ console.warn('Pas de données projet à pré-remplir');
+ return;
+ }
+
+ console.log('📝 Pré-remplissage Tarif depuis Projet...');
+
+ try {
+ // CA
+ if (projetData.ca) {
+ setValue('CA', projetData.ca);
+ }
+
+ // Type de cotisation
+ if (projetData.typeCot) {
+ const radio = document.querySelector(`input[name="cotisation"][value="${projetData.typeCot}"]`);
+ if (radio) radio.checked = true;
+ }
+
+ // Zones géographiques
+ ['zone1', 'zone2', 'zone3', 'zone4', 'zone5', 'zone6'].forEach(zone => {
+ if (projetData[zone]) {
+ setValue(zone, true);
+ }
+ });
+
+ // PJ
+ if (projetData.pj) {
+ setValue('checkPJ', true);
+ }
+
+ // RCE
+ if (projetData.autresRC) {
+ setValue('checkRCE', true);
+ }
+
+ console.log('✅ Pré-remplissage Tarif terminé');
+
+ } catch (error) {
+ console.error('❌ Erreur lors du pré-remplissage Tarif:', error);
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // EXPORT PUBLIC
+ // ═══════════════════════════════════════════════════════════════════════
+
+ window.RCDataManager = {
+ collectAllTarifData,
+ prefillProjetFromTarif,
+ prefillTarifFromProjet,
+ FIELD_MAPPING
+ };
+
+ console.log('✅ RC Data Manager loaded');
+
+})(window);
diff --git a/ecole/public/js/rc-orchestrator.js b/ecole/public/js/rc-orchestrator.js
new file mode 100644
index 00000000..43d54242
--- /dev/null
+++ b/ecole/public/js/rc-orchestrator.js
@@ -0,0 +1,388 @@
+/**
+ * ═══════════════════════════════════════════════════════════════════════════
+ * RC SYNC ORCHESTRATOR
+ * ═══════════════════════════════════════════════════════════════════════════
+ *
+ * Ce module orchestre la synchronisation entre Tarif RC et Projet RC.
+ * Il s'intègre avec les formulaires existants sans les modifier.
+ *
+ * @requires rc-sync-utils.js
+ * @requires rc-data-manager.js
+ * @author AXA Transport Team
+ * @version 2.0.0
+ * @since 2026-02-17
+ */
+
+(function(window) {
+ 'use strict';
+
+ // Attendre que les dépendances soient chargées
+ if (!window.RCSync || !window.RCDataManager) {
+ console.error('❌ Dépendances RC Sync manquantes');
+ return;
+ }
+
+ const { isChangeImpactingTarif, showReturnToTarifModal } = window.RCSync;
+ const { collectAllTarifData, prefillProjetFromTarif, prefillTarifFromProjet } = window.RCDataManager;
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // CONFIGURATION
+ // ═══════════════════════════════════════════════════════════════════════
+
+ const SESSION_STORAGE_KEYS = {
+ TARIF_DATA: 'rc_tarif_validated_data',
+ PROJET_DATA: 'rc_projet_data',
+ TARIF_ORIGINAL: 'rc_tarif_original_for_comparison'
+ };
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // DÉTECTION DE LA PAGE ACTIVE
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Détecte la page active (tarif ou projet) depuis l'URL.
+ *
+ * @returns {'tarif'|'projet'|null} Page active ou null
+ */
+ function detectActivePage() {
+ const params = new URLSearchParams(window.location.search);
+ const submenu = params.get('submenu');
+
+ if (submenu === 'tarif' || submenu === 'tarifrc') {
+ return 'tarif';
+ } else if (submenu === 'projet' || submenu === 'projetrc') {
+ return 'projet';
+ }
+
+ return null;
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // GESTION SESSIONSTORAGE
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Sauvegarde les données du tarif validé dans sessionStorage.
+ *
+ * @param {Object} tarifData - Données complètes du tarif
+ */
+ function saveTarifDataToSession(tarifData) {
+ try {
+ sessionStorage.setItem(SESSION_STORAGE_KEYS.TARIF_DATA, JSON.stringify(tarifData));
+ sessionStorage.setItem(SESSION_STORAGE_KEYS.TARIF_ORIGINAL, JSON.stringify(tarifData));
+ console.log('✅ Données tarif sauvegardées en session');
+ } catch (error) {
+ console.error('❌ Erreur sauvegarde session:', error);
+ }
+ }
+
+ /**
+ * Récupère les données du tarif depuis sessionStorage.
+ *
+ * @returns {Object|null} Données du tarif ou null
+ */
+ function getTarifDataFromSession() {
+ try {
+ const data = sessionStorage.getItem(SESSION_STORAGE_KEYS.TARIF_DATA);
+ return data ? JSON.parse(data) : null;
+ } catch (error) {
+ console.error('❌ Erreur lecture session:', error);
+ return null;
+ }
+ }
+
+ /**
+ * Récupère les données originales du tarif pour comparaison.
+ *
+ * @returns {Object|null} Données originales du tarif
+ */
+ function getTarifOriginalDataFromSession() {
+ try {
+ const data = sessionStorage.getItem(SESSION_STORAGE_KEYS.TARIF_ORIGINAL);
+ return data ? JSON.parse(data) : null;
+ } catch (error) {
+ return null;
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // HOOK: APRÈS VALIDATION TARIF
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Hook appelé après la validation du tarif commercial.
+ * Collecte toutes les données et les sauvegarde en session.
+ *
+ * Cette fonction doit être appelée juste avant la redirection vers le projet.
+ */
+ function onTarifValidated() {
+ console.log('🎯 Hook: Tarif validé, collecte des données...');
+
+ try {
+ // Collecter toutes les données du tarif
+ const tarifData = collectAllTarifData();
+
+ // Sauvegarder en session pour le pré-remplissage projet
+ saveTarifDataToSession(tarifData);
+
+ console.log('✅ Données tarif prêtes pour le projet');
+ } catch (error) {
+ console.error('❌ Erreur hook tarif validé:', error);
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // INITIALISATION PAGE PROJET
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Initialise le formulaire projet au chargement.
+ * Configure UNIQUEMENT la détection des changements impactants.
+ * Le pré-remplissage est géré par prefillFromTarif() existant dans projet-form-RC.js
+ */
+ function initProjetPage() {
+ console.log('🚀 Initialisation RC Orchestrator pour page Projet...');
+
+ // Les données rc/tarif/projet sont DÉJÀ chargées depuis la base
+ // par le code existant dans projet-form-RC.js
+ // On configure juste la détection des changements
+
+ setTimeout(() => {
+ setupProjetChangeDetection();
+ }, 1000); // Attendre que prefillFromTarif() ait fini
+ }
+
+ /**
+ * Configure la détection des changements impactants dans le projet.
+ * Affiche un modal si l'utilisateur modifie un champ qui impacte le tarif.
+ * Utilise les variables globales rc/tarif depuis projet-form-RC.js
+ */
+ function setupProjetChangeDetection() {
+ // Les données originales sont dans les variables globales window.tarif et window.rc
+ // définies par projet-form-RC.js
+ const tarifOriginal = window.tarif;
+ const rcOriginal = window.rc;
+
+ if (!tarifOriginal && !rcOriginal) {
+ console.log('ℹ️ Pas de tarif/rc, pas de détection');
+ return;
+ }
+
+ console.log('👁️ Configuration détection changements...');
+ console.log('📋 Données originales:', { tarif: tarifOriginal, rc: rcOriginal });
+
+ // Liste COMPLÈTE des éléments à surveiller (tous les champs impactants)
+ const elementsToWatch = [
+ // CA et infos générales
+ 'CA', 'chiffreAffaire', 'nombreVehicules', 'nbrVehicule',
+
+ // Zones géographiques
+ 'zone1', 'zone2', 'zone3', 'zone4', 'zone5', 'zone6',
+
+ // Protection Juridique
+ 'switchPJ', 'checkPJ',
+
+ // RCE
+ 'choixRCE', 'checkRCE',
+
+ // TPPC
+ 'checkTPPC', 'capitalTPPC', 'vehiculesTPPC',
+
+ // Engagements complémentaires
+ 'checkDomImmat', 'checkContConf', 'checkDiffInv',
+
+ // Garanties additionnelles
+ 'checkStationLavage', 'checkGarageInterne', 'checkCSE',
+
+ // Sinistralité
+ 'nbSinistres3ans', 'montantSinistres3ans',
+
+ // Autres
+ 'programmeInternationale', 'participationResultat'
+ ];
+
+ // Ajouter des listeners sur tous les éléments surveillés
+ elementsToWatch.forEach(elementId => {
+ const element = document.getElementById(elementId);
+ if (!element) return;
+
+ const eventType = element.type === 'checkbox' ? 'change' : 'blur';
+
+ element.addEventListener(eventType, function(e) {
+ const fieldName = this.id;
+ const newValue = this.type === 'checkbox' ? this.checked : this.value;
+
+ console.log(`🔍 Changement détecté: ${fieldName} = ${newValue}`);
+
+ // Vérifier si c'est un champ impactant
+ if (isFieldImpactingTarif(fieldName)) {
+ console.warn(`⚠️ "${fieldName}" impacte le tarif !`);
+ showReturnToTarifModal(fieldName);
+ } else {
+ console.log(`ℹ️ "${fieldName}" n'impacte pas le tarif`);
+ }
+ });
+ });
+
+ // Surveiller les radio buttons (type de cotisation)
+ const radioTypeCot = document.querySelectorAll('input[name="typeCot"]');
+ radioTypeCot.forEach(radio => {
+ radio.addEventListener('change', function() {
+ console.log(`🔍 Changement type cotisation: ${this.value}`);
+ console.warn(`⚠️ Type de cotisation impacte le tarif !`);
+ showReturnToTarifModal('Type de cotisation');
+ });
+ });
+
+ // Surveiller le select activités
+ const activitySelector = document.getElementById('activity-selector');
+ if (activitySelector) {
+ activitySelector.addEventListener('change', function() {
+ const selectedValues = Array.from(this.selectedOptions).map(opt => opt.value);
+ console.log(`🔍 Changement activités:`, selectedValues);
+ console.warn(`⚠️ Activités impactent le tarif !`);
+ showReturnToTarifModal('Activités');
+ });
+ }
+
+ // Surveiller le select marchandises
+ const marchandiseSelector = document.getElementById('marchandise-selector');
+ if (marchandiseSelector) {
+ marchandiseSelector.addEventListener('change', function() {
+ const selectedValues = Array.from(this.selectedOptions).map(opt => opt.value);
+ console.log(`🔍 Changement marchandises:`, selectedValues);
+ console.warn(`⚠️ Marchandises impactent le tarif !`);
+ showReturnToTarifModal('Marchandises');
+ });
+ }
+
+ // Surveiller les boutons d'action sur les zones (Monde entier / Reset)
+ ['btnMondeEntier', 'btnReset'].forEach(btnId => {
+ const btn = document.getElementById(btnId);
+ if (!btn) return;
+ btn.addEventListener('click', () => {
+ console.log(`🔍 Changement zones via ${btnId}`);
+ console.warn('⚠️ Zones géographiques impactent le tarif !');
+ showReturnToTarifModal('Zones géographiques');
+ });
+ });
+
+ console.log('✅ Détection changements configurée sur tous les champs impactants');
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // INITIALISATION PAGE TARIF
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Initialise le formulaire tarif au chargement.
+ * Pré-remplit depuis le projet si l'utilisateur vient du projet.
+ */
+ function initTarifPage() {
+ console.log('🚀 Initialisation page Tarif...');
+
+ // Vérifier si on vient du projet
+ const projetData = JSON.parse(sessionStorage.getItem(SESSION_STORAGE_KEYS.PROJET_DATA) || 'null');
+
+ if (projetData && !getTarifDataFromSession()) {
+ // On a des données projet mais pas de tarif validé
+ // = L'utilisateur a commencé par le projet
+ console.log('📥 Pré-remplissage depuis projet...');
+
+ setTimeout(() => {
+ prefillTarifFromProjet(projetData);
+ }, 500);
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // INTERCEPTION DES FONCTIONS EXISTANTES
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Intercepte la fonction de validation du tarif commercial existante.
+ * Ajoute notre hook avant la redirection.
+ */
+ function interceptTarifValidation() {
+ // Attendre que la fonction window.saveTarifRC soit disponible
+ const checkInterval = setInterval(() => {
+ if (window.saveTarifRC) {
+ clearInterval(checkInterval);
+
+ // Sauvegarder la fonction originale
+ const originalSaveTarifRC = window.saveTarifRC;
+
+ // Remplacer par notre version wrappée
+ window.saveTarifRC = async function(...args) {
+ console.log('🎯 Interception saveTarifRC...');
+
+ // Appeler la fonction originale
+ const result = await originalSaveTarifRC.apply(this, args);
+
+ // Si succès, appeler notre hook
+ if (result && result.valid) {
+ onTarifValidated();
+ }
+
+ return result;
+ };
+
+ console.log('✅ saveTarifRC intercepté');
+ }
+ }, 100);
+
+ // Timeout après 5 secondes
+ setTimeout(() => clearInterval(checkInterval), 5000);
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // DÉMARRAGE AUTOMATIQUE
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Initialise l'orchestrateur au chargement de la page.
+ */
+ function init() {
+ console.log('🎼 RC Sync Orchestrator: Démarrage...');
+
+ const activePage = detectActivePage();
+ console.log(`📄 Page active détectée: ${activePage || 'aucune'}`);
+
+ if (activePage === 'tarif') {
+ interceptTarifValidation();
+
+ // Attendre que le formulaire soit initialisé
+ setTimeout(() => {
+ initTarifPage();
+ }, 1000);
+
+ } else if (activePage === 'projet') {
+ // Attendre que le formulaire soit initialisé
+ setTimeout(() => {
+ initProjetPage();
+ }, 1000);
+ }
+ }
+
+ // Démarrage au chargement du DOM
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // EXPORT PUBLIC
+ // ═══════════════════════════════════════════════════════════════════════
+
+ window.RCOrchestrator = {
+ onTarifValidated,
+ initProjetPage,
+ initTarifPage,
+ saveTarifDataToSession,
+ getTarifDataFromSession
+ };
+
+ console.log('✅ RC Sync Orchestrator loaded');
+
+})(window);
diff --git a/ecole/public/js/rc-sync-utils.js b/ecole/public/js/rc-sync-utils.js
new file mode 100644
index 00000000..0939ba32
--- /dev/null
+++ b/ecole/public/js/rc-sync-utils.js
@@ -0,0 +1,464 @@
+/**
+ * ═══════════════════════════════════════════════════════════════════════════
+ * RC SYNCHRONIZATION UTILITIES
+ * ═══════════════════════════════════════════════════════════════════════════
+ *
+ * Ce module contient toutes les fonctions utilitaires pour la synchronisation
+ * bidirectionnelle entre les formulaires Tarif RC et Projet RC.
+ *
+ * @author AXA Transport Team
+ * @version 2.0.0
+ * @since 2026-02-17
+ */
+
+(function(window) {
+ 'use strict';
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // CONSTANTES
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Liste exhaustive des champs qui impactent le calcul du tarif.
+ * Si l'un de ces champs est modifié dans le projet, un modal
+ * demandera à l'utilisateur de retourner au tarif.
+ *
+ * @constant {Array}
+ */
+ const TARIF_IMPACTING_FIELDS = [
+ // Chiffre d'affaires et type de contrat
+ 'ca', 'chiffreAffaires', 'CA',
+ 'typeCotisation', 'cotisation',
+ 'nombreVehicules', 'nbVehicules',
+
+ // Activités RCC
+ 'checkVoiturier', 'capitalVoiturier', 'actVoiturier',
+ 'checkCommissionnaire', 'capitalCommissionnaire', 'actMultimodal',
+ 'checkDemenageur', 'capitalDemenageur',
+ 'checkLogistique', 'capitalLogistique',
+ 'checkAutocariste', 'capitalAutocariste',
+ 'checkAutres', 'capitalAutres',
+
+ // RCE
+ 'checkRCE', 'autresRC',
+
+ // Activités complémentaires
+ 'actComplVoiturier', 'actComplCommissionnaire', 'actComplDemenageur', 'actComplLogistique',
+ 'activitesVoiturier', 'activitesCommissionnaire', 'activitesDemenageur', 'activitesLogistique',
+
+ // Marchandises
+ 'marchandisesVoiturier', 'marchandisesCommissionnaire', 'marchandisesDemenageur',
+ 'marchandisesLogistique', 'marchandisesAutocariste', 'marchandisesAutres',
+ 'marOrdinaire', 'marRoulant', 'marEngins', 'marRoulantDem', 'marMobilerUsag',
+ 'marPerissable', 'marAnimaux', 'marCiterne', 'marBeton', 'marExceptionnels', 'marVrac',
+
+ // Zones géographiques
+ 'zone1', 'zone2', 'zone3', 'zone4', 'zone5', 'zone6',
+
+ // Extensions de garantie RCC
+ 'extRCCModifCalArrim', 'extRCCFerroutage', 'extRCCFraisRecons',
+ 'extRCCConfie', 'typeExtConfies', 'extRCCTPPC', 'extRCCRegie', 'extRCCSansMontageDemontage',
+ 'checkDomImmat', 'capitalDomImmat', 'checkContConf', 'capitalContConf',
+ 'checkDiffInv', 'capitalDiffInv', 'checkTPPC', 'capitalTPPC', 'vehiculesTPPC',
+
+ // Extensions de garantie RCE
+ 'extRCEBraDebra', 'extRCEMontageDemontage',
+
+ // Garanties additionnelles
+ 'checkStationLavage', 'checkGarageInterne', 'checkCSE', 'checkPJ', 'pj',
+
+ // Sinistralité
+ 'sinistre', 'nbSinistres3ans', 'montantSinistres3ans'
+ ];
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // HELPERS - MANIPULATION DE VALEURS
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Convertit une valeur en nombre en gérant les formats français et internationaux.
+ * Gère les espaces, virgules, points, et valeurs nulles/undefined.
+ *
+ * @param {string|number|null|undefined} x - Valeur à convertir
+ * @returns {number} Nombre converti ou 0 si impossible
+ *
+ * @example
+ * toNumber("1 234,56") // 1234.56
+ * toNumber("1.234,56") // 1234.56
+ * toNumber("1,234.56") // 1234.56
+ * toNumber(null) // 0
+ */
+ function toNumber(x) {
+ if (x == null) return 0;
+
+ let value = String(x).trim();
+ if (!value) return 0;
+
+ value = value
+ .replace(/\s/g, '')
+ .replace(/[^\d.,-]/g, '');
+
+ if (!value) return 0;
+
+ const isNegative = value.startsWith('-');
+ value = value.replace(/-/g, '');
+ if (isNegative && value) {
+ value = '-' + value;
+ }
+
+ const hasComma = value.includes(',');
+ const hasDot = value.includes('.');
+
+ if (hasComma) {
+ value = value.replace(/\./g, '').replace(/,/g, '.');
+ } else if (hasDot) {
+ const dotMatches = value.match(/\./g);
+ const dotCount = dotMatches ? dotMatches.length : 0;
+ if (dotCount > 1) {
+ const parts = value.split('.');
+ const lastSegment = parts[parts.length - 1];
+ if (lastSegment.length === 3) {
+ value = parts.join('');
+ } else {
+ value = parts.slice(0, -1).join('') + '.' + lastSegment;
+ }
+ }
+ }
+
+ const parsed = Number(value);
+ return Number.isFinite(parsed) ? parsed : 0;
+ }
+
+ /**
+ * Récupère la valeur d'un élément par son ID de manière flexible.
+ * Gère les différents types d'éléments (input, select, textarea, etc.)
+ * et les cas où l'ID contient des caractères spéciaux.
+ *
+ * @param {string} id - ID de l'élément
+ * @returns {HTMLElement|null} Élément trouvé ou null
+ *
+ * @example
+ * const element = getElementByIdFlexible("my-element");
+ */
+ function getElementByIdFlexible(id) {
+ if (!id) return null;
+ const direct = document.getElementById(id);
+ if (direct) return direct;
+ try {
+ return document.querySelector(`[id="${id.replace(/"/g, '\\"')}"]`);
+ } catch (err) {
+ return null;
+ }
+ }
+
+ /**
+ * Récupère la valeur d'un champ de formulaire de manière sécurisée.
+ * Gère les inputs, selects, textareas, checkboxes, et contenus textuels.
+ *
+ * @param {string} elementId - ID de l'élément
+ * @returns {string|number|boolean|null} Valeur du champ
+ *
+ * @example
+ * getValue("ca") // "100000"
+ * getValue("checkPJ") // true
+ */
+ function getValue(elementId) {
+ const element = getElementByIdFlexible(elementId);
+ if (!element) return null;
+
+ if (element.type === 'checkbox') {
+ return element.checked;
+ } else if (element.type === 'radio') {
+ const checked = document.querySelector(`input[name="${element.name}"]:checked`);
+ return checked ? checked.value : null;
+ } else if (element.tagName === 'SELECT') {
+ return element.value;
+ } else if (element.value !== undefined) {
+ return element.value;
+ } else {
+ return element.textContent || element.innerText || null;
+ }
+ }
+
+ /**
+ * Définit la valeur d'un champ de formulaire.
+ * Gère automatiquement le type de champ et met à jour l'interface.
+ *
+ * @param {string} elementId - ID de l'élément
+ * @param {any} value - Valeur à définir
+ *
+ * @example
+ * setValue("ca", 100000);
+ * setValue("checkPJ", true);
+ */
+ function setValue(elementId, value) {
+ const element = getElementByIdFlexible(elementId);
+ if (!element) {
+ console.warn(`Élément non trouvé: ${elementId}`);
+ return;
+ }
+
+ if (element.type === 'checkbox') {
+ element.checked = Boolean(value);
+ } else if (element.type === 'radio') {
+ const radio = document.querySelector(`input[name="${element.name}"][value="${value}"]`);
+ if (radio) radio.checked = true;
+ } else if (element.tagName === 'SELECT') {
+ element.value = value;
+ // Réinitialiser Materialize select si présent
+ if (window.M && window.M.FormSelect) {
+ const instance = window.M.FormSelect.getInstance(element);
+ if (instance) instance.destroy();
+ window.M.FormSelect.init(element);
+ }
+ } else if (element.value !== undefined) {
+ element.value = value;
+ } else {
+ element.textContent = value;
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // COMPARAISON DE DONNÉES
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Compare deux tableaux pour vérifier leur égalité.
+ * Effectue une comparaison profonde élément par élément.
+ *
+ * @param {Array} arr1 - Premier tableau
+ * @param {Array} arr2 - Deuxième tableau
+ * @returns {boolean} true si les tableaux sont égaux
+ *
+ * @example
+ * arraysEqual([1,2,3], [1,2,3]) // true
+ * arraysEqual([1,2], [1,2,3]) // false
+ */
+ function arraysEqual(arr1, arr2) {
+ if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false;
+ if (arr1.length !== arr2.length) return false;
+
+ const sorted1 = [...arr1].sort();
+ const sorted2 = [...arr2].sort();
+
+ return sorted1.every((val, idx) => val === sorted2[idx]);
+ }
+
+ /**
+ * Compare deux valeurs en tenant compte de leur type.
+ * Gère les tableaux, objets, null, undefined, et valeurs primitives.
+ *
+ * @param {any} value1 - Première valeur
+ * @param {any} value2 - Deuxième valeur
+ * @returns {boolean} true si les valeurs sont égales
+ *
+ * @example
+ * valuesEqual([1,2], [2,1]) // true (ordre indépendant)
+ * valuesEqual(null, undefined) // true
+ * valuesEqual(100, "100") // true (conversion automatique)
+ */
+ function valuesEqual(value1, value2) {
+ // Normaliser null et undefined
+ if (value1 == null && value2 == null) return true;
+ if (value1 == null || value2 == null) return false;
+
+ // Comparer les tableaux
+ if (Array.isArray(value1) && Array.isArray(value2)) {
+ return arraysEqual(value1, value2);
+ }
+
+ // Comparer les objets
+ if (typeof value1 === 'object' && typeof value2 === 'object') {
+ return JSON.stringify(value1) === JSON.stringify(value2);
+ }
+
+ // Comparer les nombres (avec conversion)
+ if (!isNaN(value1) && !isNaN(value2)) {
+ return toNumber(value1) === toNumber(value2);
+ }
+
+ // Comparaison standard
+ return value1 === value2;
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // DÉTECTION DE CHANGEMENTS IMPACTANTS
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Vérifie si un champ donné impacte le calcul du tarif.
+ * Se base sur la liste TARIF_IMPACTING_FIELDS.
+ *
+ * @param {string} fieldName - Nom du champ
+ * @returns {boolean} true si le champ impacte le tarif
+ *
+ * @example
+ * isFieldImpactingTarif("ca") // true
+ * isFieldImpactingTarif("dateEffet") // false
+ */
+ function isFieldImpactingTarif(fieldName) {
+ return TARIF_IMPACTING_FIELDS.some(field =>
+ fieldName.includes(field) || field.includes(fieldName)
+ );
+ }
+
+ /**
+ * Vérifie si un changement de valeur impacte le tarif.
+ * Compare la nouvelle valeur avec les données originales du tarif.
+ *
+ * @param {string} fieldName - Nom du champ modifié
+ * @param {any} newValue - Nouvelle valeur
+ * @param {Object} tarifOriginalData - Données originales du tarif
+ * @returns {boolean} true si le changement impacte le tarif
+ *
+ * @example
+ * const impacted = isChangeImpactingTarif("ca", 200000, tarifData);
+ * if (impacted) showReturnToTarifModal();
+ */
+ function isChangeImpactingTarif(fieldName, newValue, tarifOriginalData) {
+ // Vérifier si le champ est dans la liste des champs impactants
+ if (!isFieldImpactingTarif(fieldName)) {
+ return false;
+ }
+
+ // Si pas de données originales, pas d'impact possible
+ if (!tarifOriginalData) {
+ return false;
+ }
+
+ // Récupérer la valeur originale
+ const originalValue = tarifOriginalData[fieldName];
+
+ // Comparer les valeurs
+ return !valuesEqual(newValue, originalValue);
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // MODAL DE RETOUR AU TARIF
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * Affiche le modal demandant à l'utilisateur de retourner au tarif.
+ * Ce modal s'affiche quand une modification dans le projet impacte
+ * le calcul du tarif.
+ *
+ * @param {string} [fieldName] - Nom du champ modifié (optionnel, pour info)
+ *
+ * @example
+ * showReturnToTarifModal("ca");
+ */
+ function showReturnToTarifModal(fieldName) {
+ const modalId = 'modalRetourTarif';
+ let modal = document.getElementById(modalId);
+
+ // Créer le modal s'il n'existe pas
+ if (!modal) {
+ modal = createReturnToTarifModal();
+ document.body.appendChild(modal);
+ }
+
+ // Mettre à jour le message si un champ est spécifié
+ if (fieldName) {
+ const messageEl = modal.querySelector('#modalRetourTarifMessage');
+ if (messageEl) {
+ messageEl.innerHTML = `
+ Vous avez modifié "${fieldName}" qui impacte le calcul du tarif.
+
+ Vous devez retourner sur le formulaire Tarif pour recalculer et valider le nouveau tarif.
+ `;
+ }
+ }
+
+ // Ouvrir le modal
+ if (window.M && window.M.Modal) {
+ const instance = window.M.Modal.getInstance(modal) || window.M.Modal.init(modal);
+ instance.open();
+ }
+ }
+
+ /**
+ * Crée l'élément DOM du modal de retour au tarif.
+ *
+ * @returns {HTMLElement} Élément modal créé
+ * @private
+ */
+ function createReturnToTarifModal() {
+ const modal = document.createElement('div');
+ modal.id = 'modalRetourTarif';
+ modal.className = 'modal';
+
+ modal.innerHTML = `
+
+
⚠️ Modification impactant le tarif
+
+ Vous avez modifié une donnée qui impacte le calcul du tarif.
+
+ Vous devez retourner sur le formulaire Tarif pour recalculer et valider le nouveau tarif.
+
+
+
+ `;
+
+ return modal;
+ }
+
+ /**
+ * Navigate vers l'onglet Tarif depuis le Projet.
+ *
+ * @example
+ * navigateToTarif();
+ */
+ function navigateToTarif() {
+ // Fermer le modal
+ const modal = document.getElementById('modalRetourTarif');
+ if (modal && window.M) {
+ const instance = window.M.Modal.getInstance(modal);
+ if (instance) instance.close();
+ }
+
+ // Naviguer vers le tarif
+ const numParcours = new URLSearchParams(window.location.search).get('numParcours');
+ if (numParcours) {
+ window.location.href = `/navParcours?numParcours=${numParcours}&submenu=tarif`;
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════
+ // EXPORT PUBLIC
+ // ═══════════════════════════════════════════════════════════════════════
+
+ /**
+ * API publique du module RC Sync.
+ * Toutes les fonctions exportées ici sont accessibles via window.RCSync.
+ */
+ window.RCSync = {
+ // Helpers
+ toNumber,
+ getValue,
+ setValue,
+ getElementByIdFlexible,
+
+ // Comparaison
+ arraysEqual,
+ valuesEqual,
+
+ // Détection changements
+ isFieldImpactingTarif,
+ isChangeImpactingTarif,
+
+ // Modal
+ showReturnToTarifModal,
+ navigateToTarif,
+
+ // Constantes
+ TARIF_IMPACTING_FIELDS
+ };
+
+ console.log('✅ RC Sync Utils loaded');
+
+})(window);
diff --git a/ecole/public/js/tarif-form-rc.js b/ecole/public/js/tarif-form-rc.js
new file mode 100644
index 00000000..aa29160e
--- /dev/null
+++ b/ecole/public/js/tarif-form-rc.js
@@ -0,0 +1,3376 @@
+function initSubmenuForm() {
+ // Accéder aux informations stockées du parcours
+ const parcours = JSON.parse(sessionStorage.getItem('parcours'));
+}
+
+function toNumber(x) {
+ if (x == null) return 0;
+
+ let value = String(x).trim();
+ if (!value) return 0;
+
+ value = value
+ .replace(/\s/g, '')
+ .replace(/[^\d.,-]/g, '');
+
+ if (!value) return 0;
+
+ const isNegative = value.startsWith('-');
+ value = value.replace(/-/g, '');
+ if (isNegative && value) {
+ value = '-' + value;
+ }
+
+ const hasComma = value.includes(',');
+ const hasDot = value.includes('.');
+
+ if (hasComma) {
+ value = value.replace(/\./g, '').replace(/,/g, '.');
+ } else if (hasDot) {
+ const dotMatches = value.match(/\./g);
+ const dotCount = dotMatches ? dotMatches.length : 0;
+ if (dotCount > 1) {
+ const parts = value.split('.');
+ const lastSegment = parts[parts.length - 1];
+ if (lastSegment.length === 3) {
+ value = parts.join('');
+ } else {
+ value = parts.slice(0, -1).join('') + '.' + lastSegment;
+ }
+ }
+ }
+
+ const parsed = Number(value);
+ return Number.isFinite(parsed) ? parsed : 0;
+}
+
+// Fonction pour formater un nombre avec X décimales max (sans décimales si entier)
+function formatNumber(num, decimals = 2) {
+ if (!num || isNaN(num)) return '0.' + '0'.repeat(decimals);
+ const factor = Math.pow(10, decimals);
+ const rounded = Math.round(num * factor) / factor;
+ // Si c'est un nombre entier, ne pas afficher les décimales
+ if (Number.isInteger(rounded)) {
+ return rounded.toString();
+ }
+ return rounded.toFixed(decimals);
+}
+
+function getElementByIdFlexible(id) {
+ if (!id) return null;
+ const direct = document.getElementById(id);
+ if (direct) return direct;
+ try {
+ return document.querySelector(`[id="${id.replace(/"/g, '\\"')}"]`);
+ } catch (err) {
+ return null;
+ }
+}
+
+// Exposer initSubmenuForm globalement pour y accéder depuis l'extérieur
+window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollution de l'espace global
+(function () {
+ // Variables globales du module
+ let parcours, contrat, client, intermediaire, rc, projet, tarif;
+
+ //Variables modulos et liste
+ let modRCCA, modRCActRCC, modRCActRCE, modRCActCompl, modRCMar, modRCZone, modRCEngagCompl, modRCGarAdd, modRCSinistre, modRCFranchise, modRCPrimeMini
+
+ // ═══════════════════════════════════════════════════════════════
+ // FONCTIONS HELPERS
+ // ═══════════════════════════════════════════════════════════════
+
+ // Fonction helper : trouver la tranche la plus proche
+ function findClosestTranche(val, tranches) {
+ if (val <= tranches[0]) return tranches[0];
+ if (val >= tranches[tranches.length - 1]) return tranches[tranches.length - 1];
+
+ for (let i = 0; i < tranches.length - 1; i++) {
+ if (val >= tranches[i] && val < tranches[i + 1]) {
+ return tranches[i];
+ }
+ }
+ return tranches[tranches.length - 1];
+ }
+
+ // Fonction pour afficher un avertissement visuel de dépassement %
+ function showPercentageWarning(excess) {
+ let warningDiv = document.getElementById('percentageWarning');
+ if (!warningDiv) {
+ warningDiv = document.createElement('div');
+ warningDiv.id = 'percentageWarning';
+ warningDiv.style.cssText = `
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ background: #f44336;
+ color: white;
+ padding: 15px 25px;
+ border-radius: 5px;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.3);
+ z-index: 9999;
+ font-weight: bold;
+ `;
+ document.body.appendChild(warningDiv);
+ }
+
+ warningDiv.innerHTML = `Plafonnement à 100% (vous dépassiez de ${excess.toFixed(1)}%)`;
+ warningDiv.style.display = 'block';
+
+ setTimeout(() => {
+ warningDiv.style.display = 'none';
+ }, 3000);
+ }
+
+ // Fonction pour masquer toutes les primes (quand % invalide)
+ function hideAllPrimes() {
+ const primeElements = [
+ 'primeChapActRCC', 'primeChapActRCE',
+ 'primeChapActComplRCC', 'primeChapActComplRCE',
+ 'primeChapMarchRCC', 'primeChapMarchRCE',
+ 'primeChapZonesRCC', 'primeChapZonesRCE',
+ 'primeEngValue', 'primeChapGarAddRCC', 'primeChapGarAddRCE',
+ 'priceFr250', 'priceFr400', 'priceFr2000'
+ ];
+
+ primeElements.forEach(id => {
+ const el = document.getElementById(id);
+ if (el) {
+ el.innerHTML = ' % invalide (> 100%)';
+ }
+ });
+ }
+
+ // Fonction pour mettre à jour l'indicateur visuel du total des pourcentages
+ function updatePercentageIndicator(total) {
+ const indicator = document.getElementById('pourcentageTotal');
+ if (!indicator) return;
+
+ const displayTotal = total.toFixed(1);
+ indicator.textContent = `Total : ${displayTotal}%`;
+
+ if (total > 100) {
+ indicator.style.background = '#f44336';
+ indicator.style.color = 'white';
+ indicator.style.border = '3px solid #c62828';
+ } else if (total === 100 || Math.abs(total - 100) < 0.1) {
+ indicator.style.background = '#4caf50';
+ indicator.style.color = 'white';
+ indicator.style.border = '3px solid #2e7d32';
+ } else if (total >= 95) {
+ indicator.style.background = '#ff9800';
+ indicator.style.color = 'white';
+ indicator.style.border = '3px solid #ef6c00';
+ } else {
+ indicator.style.background = 'white';
+ indicator.style.color = 'darkblue';
+ indicator.style.border = '2px solid darkblue';
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════
+
+ // Initialisation du formulaire et des données
+ function init() {
+ // Materialize init select
+ var select = document.querySelectorAll('select');
+ M.FormSelect.init(select);
+
+ // Materialize init Modal
+ var modals = document.querySelectorAll('.modal');
+ M.Modal.init(modals);
+
+ // Initialiser les modals spécifiques
+ window.modalAnimauxVivants = M.Modal.getInstance(document.getElementById('modalAnimauxVivants'));
+ window.modalTransportBeton = M.Modal.getInstance(document.getElementById('modalTransportBeton'));
+ window.modalAutocaristeRCE = M.Modal.getInstance(document.getElementById('modalAutocaristeRCE'));
+ window.modalTarifCom = M.Modal.getInstance(document.getElementById('modalTarifCom'));
+
+ // Accéder aux informations stockées du parcours
+ parcours = JSON.parse(sessionStorage.getItem('parcours'));
+ contrat = JSON.parse(sessionStorage.getItem('contrat'));
+ client = contrat?.["@expand"]?.client || null;
+ intermediaire = contrat?.["@expand"]?.intermediaire || null;
+
+ // Récupérer les données RC depuis la nouvelle structure (EXACTEMENT comme TPPC)
+ rc = contrat?.["@expand"]?.enCours || null; // RC principal
+ projet = rc?.["@expand"]?.projetRC || null; // Données projetRC
+ tarif = rc?.["@expand"]?.tarifRC || null; // Données tarifRC
+
+ console.log("Initialisation pour formulaire tarif :", parcours);
+
+ constantsJSON().then(() => {
+ //TODO à virer après les tests
+ console.log("--- Initialisation modulateur RC ---"
+ , "\nCA : ", modRCCA
+ , "\nactRCC : ", modRCActRCC
+ , "\nactRCE : ", modRCActRCE
+ , "\nactCompl : ", modRCActCompl
+ , "\nmar : ", modRCMar
+ , "\nengagComple : ", modRCEngagCompl
+ , "\nfranchise : ", modRCFranchise
+ , "\ngarAdd : ", modRCGarAdd
+ , "\nprimeMini : ", modRCPrimeMini
+ , "\nzone : ", modRCZone
+ , "\nantecedantSinistre: ", modRCSinistre
+ );
+
+ // Appel des différentes fonctions d'initialisation
+ setupEventListeners();
+ setupTarifetteButtons();
+ populateFormData();
+ updatePercentageIndicator(100); // Initialiser à 100%
+ calcGlobal();
+ })
+ }
+
+ // Configuration des listeners d'événements
+ function setupEventListeners() {
+ // Empêcher la soumission du formulaire avec la touche Enter
+ const form = document.getElementById('projetForm');
+ if (form) {
+ form.addEventListener('keydown', function(e) {
+ // Si Enter est pressée et que ce n'est pas sur un bouton submit
+ if (e.key === 'Enter' && e.target.type !== 'submit' && e.target.tagName !== 'BUTTON') {
+ // Si c'est un input de pourcentage, on passe au suivant
+ if (e.target.classList.contains('input-pourcent')) {
+ e.preventDefault();
+ // Déclencher l'événement input pour forcer le calcul
+ e.target.dispatchEvent(new Event('input', { bubbles: true }));
+ // Passer au champ suivant
+ const inputs = Array.from(document.querySelectorAll('.input-pourcent')).filter(inp => inp.offsetParent !== null);
+ const currentIndex = inputs.indexOf(e.target);
+ if (currentIndex >= 0 && currentIndex < inputs.length - 1) {
+ inputs[currentIndex + 1].focus();
+ inputs[currentIndex + 1].select();
+ }
+ } else {
+ // Pour les autres inputs, empêcher le submit mais permettre la navigation
+ e.preventDefault();
+ }
+ }
+ });
+ }
+
+ document.getElementById('loadHistoriqueBtn').addEventListener('click', function () {
+ handleLoadHistoriqueBtn();
+ });
+
+ resetInputs();
+
+ var radioButtonsCot = document.getElementsByName('cotisation');
+ for (var i = 0; i < radioButtonsCot.length; i++) {
+ radioButtonsCot[i].addEventListener('change', function () {
+ if (this.value == "forfaitaire") {
+ document.getElementById("rowNbrVehicule").style.display = "block";
+ document.getElementById("labelVoiturier").style.display = "block";
+ document.getElementById("labelCommissionnaire").style.display = "none";
+ document.getElementById("labelDemenageur").style.display = "block";
+ document.getElementById("labelLogistique").style.display = "none";
+ document.getElementById("labelAutocariste").style.display = "block";
+ document.getElementById("labelAutres").style.display = "none";
+
+ document.getElementById("nbrVehicule").value = null;
+
+ // Lancement du calcul forfaitaire
+ calcForfaitaire();
+ } else if (this.value == "revisable") {
+ document.getElementById("rowNbrVehicule").style.display = "none";
+ document.getElementById("labelVoiturier").style.display = "block";
+ document.getElementById("labelCommissionnaire").style.display = "block";
+ document.getElementById("labelDemenageur").style.display = "block";
+ document.getElementById("labelLogistique").style.display = "block";
+ document.getElementById("labelAutocariste").style.display = "none";
+ document.getElementById("labelAutres").style.display = "block";
+
+ // Lancement du calcul revisable
+ calcRevisable();
+ }
+ });
+ };
+
+ document.getElementById('chiffreAffaire').addEventListener('input', function () {
+ const cot = document.querySelector('input[name="cotisation"]:checked')?.value;
+
+ if (document.getElementById('chiffreAffaire').value.trim() == '') {
+ document.getElementById("modCA").style.display = "none";
+ } else {
+ // Masquer modCA en forfaitaire car il n'est pas utilisé
+ if (cot === 'forfaitaire') {
+ document.getElementById("modCA").style.display = "none";
+ } else {
+ document.getElementById("modCA").style.display = "block";
+ }
+ }
+
+ calcGlobal();
+ // Validation conditionnelle : CA obligatoire seulement en revisable
+ if (typeof validateField === 'function') {
+ if (cot === 'revisable') {
+ validateField('chiffreAffaire', true);
+ } else {
+ // En forfaitaire, CA optionnel
+ validateField('chiffreAffaire', false);
+ }
+ }
+ if (document.getElementById('projetForm')) {
+ updateSubmitButtonState('projetForm');
+ }
+ });
+
+ document.getElementById('nbrVehicule').addEventListener('input', function () {
+ // Validation : forcer entre 1 et 2 véhicules (comme ancienne plateforme)
+ let nbVeh = parseInt(this.value);
+ if (nbVeh < 1) {
+ this.value = 1;
+ } else if (nbVeh > 2) {
+ this.value = 2;
+ } else if (isNaN(nbVeh)) {
+ this.value = 1;
+ }
+
+ calcGlobal();
+ validateField('nbrVehicule', true);
+ if (document.getElementById('projetForm')) {
+ updateSubmitButtonState('projetForm');
+ }
+ });
+
+ document.getElementById('sinistre').addEventListener('input', function () {
+ if (document.getElementById('sinistre').value.trim() == '') {
+ document.getElementById("modSinistre").style.display = "none";
+ } else {
+ document.getElementById("modSinistre").style.display = "block";
+ }
+ });
+
+ document.getElementById('checkRCE').addEventListener('click', function () {
+ var RCE = document.querySelectorAll('[name="RCE"]');
+
+ if (document.getElementById('checkRCE').checked == true) {
+ for (var i = 0; i < RCE.length; i++) {
+ RCE[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < RCE.length; i++) {
+ RCE[i].style.display = "none";
+ }
+ }
+
+ calcGlobal();
+ });
+
+ // Ajouter des styles dynamiques pour améliorer le feedback visuel
+ const style = document.createElement('style');
+ style.textContent = `
+ .input-pourcent:focus {
+ border-color: #1976d2 !important;
+ box-shadow: 0 0 8px rgba(25, 118, 210, 0.5) !important;
+ outline: none;
+ transform: scale(1.05);
+ transition: all 0.2s ease;
+ }
+ .input-pourcent:hover {
+ border-color: #5c6bc0 !important;
+ transition: all 0.2s ease;
+ }
+ .input-pourcent.set {
+ background-color: #e8f5e9 !important;
+ border-color: #4caf50 !important;
+ }
+ `;
+ document.head.appendChild(style);
+
+ // Ajout d'un écouteur d'événement à chaque champ pourcentage
+ document.querySelectorAll('.input-pourcent').forEach(input => {
+ // Sélectionner automatiquement le contenu au focus pour faciliter la saisie
+ input.addEventListener('focus', function() {
+ this.select();
+ });
+
+ // Validation automatique lors de la perte de focus (clic ailleurs)
+ input.addEventListener('blur', function() {
+ // Déclencher le recalcul si la valeur a changé
+ if (this.value !== this.defaultValue) {
+ this.dispatchEvent(new Event('input', { bubbles: true }));
+ }
+ });
+
+ input.addEventListener('input', function() {
+ // Récupérer l'ID de l'input modifié pour accéder à son isSet
+ const isSetInputId = 'isSet' + input.id.replace('pourcent', '');
+ const isSetInput = document.getElementById(isSetInputId);
+
+ // Mettre à jour isSet correspondant à true si l'input a une valeur
+ if (input.value != '') {
+ isSetInput.value = 'true';
+ input.classList.add('set'); // Changer le fond
+ } else {
+ isSetInput.value = 'false'; // Réinitialiser isSet si l'input est vide
+ input.classList.remove('set'); // Remettre le fond d'origine
+ }
+
+ // Réinitialiser les inputs non set à vide avant de recalculer
+ document.querySelectorAll('.input-pourcent').forEach(p => {
+ const correspondingIsSetInput = document.getElementById('isSet' + p.id.replace('pourcent', ''));
+ if (correspondingIsSetInput.value == 'false') {
+ p.value = ''; // Réinitialiser la valeur
+ }
+ });
+
+ // Calcul de la somme des pourcentages des champs actuellement modifiés
+ let totalPourcent = 0;
+ document.querySelectorAll('.input-pourcent').forEach(pourcentInput => {
+ if (pourcentInput.value != '' && pourcentInput.offsetParent != null) {
+ totalPourcent += toNumber(pourcentInput.value);
+ }
+ });
+
+ // PLAFONNEMENT STRICT À 100%
+ if (totalPourcent > 100) {
+ const excess = totalPourcent - 100;
+
+ // Plafonnement : empêcher de dépasser
+ // Réduire la valeur qui vient d'être modifiée
+ const currentInputVal = toNumber(input.value);
+ const maxPossible = currentInputVal - excess;
+
+ if (maxPossible >= 0) {
+ // Plafonner la valeur actuelle
+ input.value = maxPossible.toFixed(2);
+ totalPourcent = 100;
+ } else {
+ // La valeur est trop grande, la limiter au restant
+ const otherTotal = totalPourcent - currentInputVal;
+ input.value = (100 - otherTotal).toFixed(2);
+ totalPourcent = 100;
+ }
+
+ // Afficher message d'avertissement visuel
+ showPercentageWarning(excess);
+
+ // Masquer les primes pour montrer que c'est invalide
+ const allInputs = document.querySelectorAll('.input-pourcent');
+ let finalTotal = 0;
+ allInputs.forEach(p => {
+ if (p.offsetParent != null) {
+ finalTotal += toNumber(p.value);
+ }
+ });
+
+ if (finalTotal > 100.01) { // Tolérance de 0.01 pour les arrondis
+ // BLOQUER les calculs - afficher erreur
+ hideAllPrimes();
+ return;
+ }
+ }
+
+ // Calcul de la différence à répartir
+ const remainingPourcent = 100 - totalPourcent;
+
+ // Répartition de la différence sur les champs restants non marqués isSet
+ const nonModifiedInputs = Array.from(document.querySelectorAll('.input-pourcent')).filter(p => {
+ const correspondingIsSetInput = document.getElementById('isSet' + p.id.replace('pourcent', ''));
+ return p.value == '' && correspondingIsSetInput.value == 'false' && p.offsetParent != null;
+ });
+
+ // Vérifier si nous avons des inputs non modifiés pour répartir le pourcentage restant
+ if (remainingPourcent > 0 && nonModifiedInputs.length > 0) {
+ const pourcentToAdd = remainingPourcent / nonModifiedInputs.length;
+
+ nonModifiedInputs.forEach(p => {
+ p.value = pourcentToAdd.toFixed(2);
+ });
+ } else if (remainingPourcent > 0 && nonModifiedInputs.length === 0) {
+ // Tous les champs sont remplis mais total < 100
+ // Trouver le dernier champ non-set et lui ajouter le restant
+ const allInputs = Array.from(document.querySelectorAll('.input-pourcent')).filter(p => p.offsetParent != null);
+ const lastNonSet = allInputs.filter(p => {
+ const correspondingIsSetInput = document.getElementById('isSet' + p.id.replace('pourcent', ''));
+ return correspondingIsSetInput.value == 'false';
+ }).pop();
+
+ if (lastNonSet) {
+ const currentVal = toNumber(lastNonSet.value);
+ lastNonSet.value = (currentVal + remainingPourcent).toFixed(2);
+ }
+ }
+
+ // Mettre à jour l'indicateur visuel du total
+ updatePercentageIndicator(totalPourcent);
+
+ calcGlobal();
+ });
+ });
+
+ // Bouton reset de l'équilibrage pourcentage
+ document.getElementById('resetPourcent').addEventListener('click', function() {
+ resetInputs();
+ updatePercentageIndicator(100); // Après reset = 100%
+ calcGlobal();
+ });
+
+ document.getElementById('checkVoiturier').addEventListener('click', function () {
+ var actVoiturier = document.querySelectorAll('[name="actVoiturier/Loueur"]');
+ var actComplVoiturier = document.querySelectorAll('[name="actComplVoiturier/Loueur"]');
+ var marVoiturier = document.querySelectorAll('[name="marVoiturier/Loueur"]');
+
+ if (document.getElementById('checkVoiturier').checked == true) {
+ for (var i = 0; i < actVoiturier.length; i++) {
+ actVoiturier[i].style.display = "block";
+ actComplVoiturier[i].style.display = "block";
+ marVoiturier[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < actVoiturier.length; i++) {
+ actVoiturier[i].style.display = "none";
+ actComplVoiturier[i].style.display = "none";
+ marVoiturier[i].style.display = "none";
+ }
+ }
+
+ // Reset de l'équilibrage pourcentage
+ resetInputs();
+ updatePercentageIndicator(100);
+ calcGlobal();
+ });
+
+ document.getElementById('checkCommissionnaire').addEventListener('click', function () {
+ var actCommissionnaire = document.querySelectorAll('[name="actCommissionnaire de Transport"]');
+ var actComplCommissionnaire = document.querySelectorAll('[name="actComplCommissionnaire de Transport"]');
+ var marCommissionnaire = document.querySelectorAll('[name="marCommissionnaire de Transport"]');
+
+ if (document.getElementById('checkCommissionnaire').checked == true) {
+ for (var i = 0; i < actCommissionnaire.length; i++) {
+ actCommissionnaire[i].style.display = "block";
+ actComplCommissionnaire[i].style.display = "block";
+ marCommissionnaire[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < actCommissionnaire.length; i++) {
+ actCommissionnaire[i].style.display = "none";
+ actComplCommissionnaire[i].style.display = "none";
+ marCommissionnaire[i].style.display = "none";
+ }
+ }
+
+ // Reset de l'équilibrage pourcentage
+ resetInputs();
+ updatePercentageIndicator(100);
+ calcGlobal();
+ });
+
+ document.getElementById('checkDemenageur').addEventListener('click', function () {
+ var actDemenageur = document.querySelectorAll('[name="actDéménageur"]');
+ var actComplDemenageur = document.querySelectorAll('[name="actComplDéménageur"]');
+ var marDemenageur = document.querySelectorAll('[name="marDéménageur"]');
+
+ if (document.getElementById('checkDemenageur').checked == true) {
+ for (var i = 0; i < actDemenageur.length; i++) {
+ actDemenageur[i].style.display = "block";
+ actComplDemenageur[i].style.display = "block";
+ marDemenageur[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < actDemenageur.length; i++) {
+ actDemenageur[i].style.display = "none";
+ actComplDemenageur[i].style.display = "none";
+ marDemenageur[i].style.display = "none";
+ }
+ }
+
+ // Reset de l'équilibrage pourcentage
+ resetInputs();
+ updatePercentageIndicator(100);
+ calcGlobal();
+ });
+
+ document.getElementById('checkLogistique').addEventListener('click', function () {
+ var actLogistique = document.querySelectorAll('[name="actLogistique"]');
+ var actComplLogistique = document.querySelectorAll('[name="actComplLogistique"]');
+ var marLogistique = document.querySelectorAll('[name="marLogistique"]');
+
+ if (document.getElementById('checkLogistique').checked == true) {
+ for (var i = 0; i < actLogistique.length; i++) {
+ actLogistique[i].style.display = "block";
+ actComplLogistique[i].style.display = "block";
+ marLogistique[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < actLogistique.length; i++) {
+ actLogistique[i].style.display = "none";
+ actComplLogistique[i].style.display = "none";
+ marLogistique[i].style.display = "none";
+ }
+ }
+
+ // Reset de l'équilibrage pourcentage
+ resetInputs();
+ updatePercentageIndicator(100);
+ calcGlobal();
+ });
+
+ document.getElementById('checkAutocariste').addEventListener('click', function () {
+ var actAutocariste = document.querySelectorAll('[name="actAutocariste"]');
+ var marAutocariste = document.querySelectorAll('[name="marAutocariste"]');
+
+ if (document.getElementById('checkAutocariste').checked == true) {
+ for (var i = 0; i < actAutocariste.length; i++) {
+ actAutocariste[i].style.display = "block";
+ marAutocariste[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < actAutocariste.length; i++) {
+ actAutocariste[i].style.display = "none";
+ marAutocariste[i].style.display = "none";
+ }
+ }
+
+ // Reset de l'équilibrage pourcentage
+ resetInputs();
+ updatePercentageIndicator(100);
+ calcGlobal();
+ });
+
+ document.getElementById('checkAutres').addEventListener('click', function () {
+ var actAutres = document.querySelectorAll('[name="actAutres activites"]');
+ var marAutres = document.querySelectorAll('[name="marAutres activites"]');
+
+ if (document.getElementById('checkAutres').checked == true) {
+ for (var i = 0; i < actAutres.length; i++) {
+ actAutres[i].style.display = "block";
+ marAutres[i].style.display = "block";
+ }
+ } else {
+ for (var i = 0; i < actAutres.length; i++) {
+ actAutres[i].style.display = "none";
+ marAutres[i].style.display = "none";
+ }
+ }
+
+ // Reset de l'équilibrage pourcentage
+ resetInputs();
+ updatePercentageIndicator(100);
+ calcGlobal();
+ });
+
+ // Event listeners pour les inputs capital (au lieu de selects)
+ const capitalInputs = [
+ 'selectActVoiturier/Loueur',
+ 'selectActCommissionnaire de Transport',
+ 'selectActDéménageur',
+ 'selectActLogistique',
+ 'selectActAutocariste',
+ 'selectActAutres activites'
+ ];
+
+ capitalInputs.forEach(name => {
+ const el = document.getElementsByName(name)[0];
+ if (el) {
+ el.addEventListener('input', function() {
+ calcGlobal();
+ });
+ }
+ });
+
+ const checkboxesActComplVoiturier = document.querySelectorAll('div[name="actComplVoiturier/Loueur"] input[type="checkbox"]');
+ checkboxesActComplVoiturier.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesActCompltComDeTransport = document.querySelectorAll('div[name="actComplCommissionnaire de Transport"] input[type="checkbox"]');
+ checkboxesActCompltComDeTransport.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesActComplDem = document.querySelectorAll('div[name="actComplDéménageur"] input[type="checkbox"]');
+ checkboxesActComplDem.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesActComplLogistique = document.querySelectorAll('div[name="actComplLogistique"] input[type="checkbox"]');
+ checkboxesActComplLogistique.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesMarVoiturier = document.querySelectorAll('div[name="marVoiturier/Loueur"] input[type="checkbox"]');
+ checkboxesMarVoiturier.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesMarComDeTransport = document.querySelectorAll('div[name="marCommissionnaire de Transport"] input[type="checkbox"]');
+ checkboxesMarComDeTransport.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesMarDem = document.querySelectorAll('div[name="marDéménageur"] input[type="checkbox"]');
+ checkboxesMarDem.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesMarLogistique = document.querySelectorAll('div[name="marLogistique"] input[type="checkbox"]');
+ checkboxesMarLogistique.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ const checkboxesMarAutres = document.querySelectorAll('div[name="marAutres activites"] input[type="checkbox"]');
+ checkboxesMarAutres.forEach(checkbox => {
+ checkbox.addEventListener('change', function () {
+ calcGlobal();
+ });
+ });
+
+ document.getElementById('btnMondeEntier').addEventListener('click', function () {
+ document.getElementById('zone1').checked = true;
+ document.getElementById('zone1').disabled = true;
+ document.getElementById('zone2').checked = true;
+ document.getElementById('zone2').disabled = true;
+ document.getElementById('zone3').checked = true;
+ document.getElementById('zone4').checked = true;
+ document.getElementById('zone5').checked = true;
+ document.getElementById('zone6').checked = true;
+ });
+
+ document.getElementById('btnReset').addEventListener('click', function () {
+ document.getElementById('zone1').checked = false;
+ document.getElementById('zone1').disabled = false;
+ document.getElementById('zone2').checked = false;
+ document.getElementById('zone2').disabled = false;
+ document.getElementById('zone3').checked = false;
+ document.getElementById('zone4').checked = false;
+ document.getElementById('zone5').checked = false;
+ document.getElementById('zone6').checked = false;
+ });
+
+ document.getElementById('btnZone1').addEventListener('click', function () {
+ const elem = document.getElementById('modalZone1');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('btnZone2').addEventListener('click', function () {
+ const elem = document.getElementById('modalZone2');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('btnZone3').addEventListener('click', function () {
+ const elem = document.getElementById('modalZone3');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('btnZone4').addEventListener('click', function () {
+ const elem = document.getElementById('modalZone4');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('btnZone5').addEventListener('click', function () {
+ const elem = document.getElementById('modalZone5');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('btnZone6').addEventListener('click', function () {
+ const elem = document.getElementById('modalZone6');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('btnZone7').addEventListener('click', function () {
+ const elem = document.getElementById('modalZoneExclus');
+ const instance = M.Modal.getInstance(elem);
+ instance.open();
+ });
+
+ document.getElementById('zone2').addEventListener('click', function () {
+ if (document.getElementById('zone2').checked == true) {
+ document.getElementById('zone1').checked = true;
+ document.getElementById('zone1').disabled = true;
+ } else if (document.getElementById('zone2').checked == false) {
+ document.getElementById('zone1').checked = true;
+ document.getElementById('zone1').disabled = false;
+ }
+ });
+
+ document.getElementById('zone3').addEventListener('click', function () {
+ if (document.getElementById('zone3').checked == true) {
+ document.getElementById('zone2').checked = true;
+ document.getElementById('zone1').checked = true;
+ document.getElementById('zone2').disabled = true;
+ document.getElementById('zone1').disabled = true;
+ } else if (document.getElementById('zone3').checked == false) {
+ document.getElementById('zone1').checked = true;
+ document.getElementById('zone1').disabled = true;
+ document.getElementById('zone2').checked = true;
+ document.getElementById('zone2').disabled = false;
+ }
+ });
+
+ // === Brancher toutes les cases zones sur calcGlobal ===
+ document.querySelectorAll('input[id^="zone"]').forEach(cb => {
+ cb.addEventListener('change', calcGlobal);
+ });
+
+ // Dommages immatériels
+ document.getElementById('checkDomImmat').addEventListener('click', function () {
+ document.getElementById('selectDomImmat').style.display = this.checked ? "block" : "none";
+ calcGlobal();
+ });
+ const inputDomImmat = document.getElementById('inputDomImmat');
+ if (inputDomImmat) inputDomImmat.addEventListener('input', calcGlobal);
+
+ // Contenants confiés
+ document.getElementById('checkContConf').addEventListener('click', function () {
+ document.getElementById('selectContConf').style.display = this.checked ? "block" : "none";
+ calcGlobal();
+ });
+ const inputContConf = document.getElementById('inputContConf');
+ if (inputContConf) inputContConf.addEventListener('input', calcGlobal);
+
+ // Différence inventaire
+ document.getElementById('checkDiffInv').addEventListener('click', function () {
+ document.getElementById('selectDiffInv').style.display = this.checked ? "block" : "none";
+ calcGlobal();
+ });
+ const inputDiffInv = document.getElementById('inputDiffInv');
+ if (inputDiffInv) inputDiffInv.addEventListener('input', calcGlobal);
+
+ // TPPC show/hide + recalc
+ const checkTPPC = document.getElementById('checkTPPC');
+ const selectTPPC = document.getElementById('selectTPPC');
+
+
+
+ if (checkTPPC && selectTPPC) {
+ checkTPPC.addEventListener('click', function () {
+ console.log('TPPC checkbox clicked:', this.checked);
+ selectTPPC.style.display = this.checked ? "block" : "none";
+
+ if (!this.checked) {
+ // reset des valeurs si décoché
+ const cap = document.getElementById('selTPPCcapital');
+ const veh = document.getElementById('selTPPCveh');
+ if (cap) cap.value = "";
+ if (veh) veh.value = "";
+ }
+
+ calcGlobal();
+ });
+ } else {
+ console.error('TPPC elements not found!', { checkTPPC, selectTPPC });
+ }
+
+ const inputTPPCcap = document.getElementById('selTPPCcapital');
+ const inputTPPCveh = document.getElementById('selTPPCveh');
+ if (inputTPPCcap) {
+ inputTPPCcap.addEventListener('input', calcGlobal);
+ console.log('TPPC capital input listener attached');
+ }
+ if (inputTPPCveh) {
+ inputTPPCveh.addEventListener('input', calcGlobal);
+ console.log('TPPC véhicules input listener attached');
+ }
+
+ // Protection juridique
+ document.getElementById('checkPJ').addEventListener('click', calcGlobal);
+
+ // RCE
+ document.getElementById('checkStationLavage').addEventListener('click', calcGlobal);
+ document.getElementById('checkGarageInterne').addEventListener('click', calcGlobal);
+ document.getElementById('checkCSE').addEventListener('click', calcGlobal);
+ // Dès que l’utilisateur tape ou modifie le champ sinistre, on recalcule
+ const elSin = document.getElementById('sinistre');
+ if (elSin) {
+ elSin.addEventListener('input', () => {
+ console.log('[event] valeur sinistre modifiée =', elSin.value);
+ calcGlobal();
+ });
+ elSin.addEventListener('change', () => {
+ console.log('[event] valeur sinistre validée =', elSin.value);
+ calcGlobal();
+ });
+ }
+
+ document.querySelectorAll('.franchise-card .btn').forEach(btn => {
+ btn.addEventListener('click', () => {
+ const selectedFr = btn.getAttribute('name'); // "250", "400", "mini300"
+ window.franchiseChoisie = selectedFr;
+ console.log('[tarifette] franchise choisie =', selectedFr);
+ document.querySelectorAll('.franchise-card').forEach(c => c.classList.remove('selected'));
+ btn.closest('.franchise-card').classList.add('selected');
+ });
+ });
+
+ // Event listeners pour les modals d'alerte
+ setupMarchandiseAlerts();
+ setupActiviteAlerts();
+
+ // Event listener pour le bouton Valider du modal tarif commercial
+ document.getElementById('comm-OK').addEventListener('click', handleValidateTarifCom);
+
+ // Le bouton Annuler ferme automatiquement le modal grâce à la classe "modal-close"
+ }
+
+ // Peupler le formulaire avec les données
+ function populateFormData() {
+ //Poupulate select historique
+ if (!contrat.historique) {
+ document.getElementById('historiqueDiv').style.display = "none";
+ } else {
+ document.getElementById('historiqueDiv').style.display = "block";
+
+ const idSelect = document.getElementById('idSelect');
+
+ contrat.historique.forEach(function (item) {
+ var option = document.createElement('option');
+ option.value = item.id;
+ option.textContent = item.type + " " + item.produit + " - " + item.date + " - " + item.heure;
+
+ if (item.nom != undefined && item.prenom != undefined) {
+ option.textContent += " - " + item.nom + " " + item.prenom;
+ }
+
+ idSelect.appendChild(option);
+ });
+
+ M.FormSelect.init(idSelect);
+ }
+
+ // ===== PRÉ-REMPLIR LE FORMULAIRE AVEC LES DONNÉES RC DE LA BASE =====
+ if (!rc) {
+ console.log('Aucune donnée RC à pré-remplir');
+ return;
+ }
+
+ console.log('🔄 Pré-remplissage du formulaire tarif avec les données RC:', rc);
+
+ // Type de cotisation
+ if (rc.typeCotisation) {
+ const radioBtn = document.getElementById(rc.typeCotisation);
+ if (radioBtn) {
+ radioBtn.checked = true;
+ radioBtn.dispatchEvent(new Event('change'));
+ }
+ }
+
+ // Chiffre d'affaires et nombre de véhicules
+ const caField = getElementByIdFlexible('CA') || getElementByIdFlexible('chiffreAffaire');
+ if (rc.chiffreAffaires && caField) caField.value = rc.chiffreAffaires;
+
+ const nbVehiculeField = getElementByIdFlexible('nbVehicules') || getElementByIdFlexible('nbrVehicule');
+ if (rc.nombreVehicules && nbVehiculeField) nbVehiculeField.value = rc.nombreVehicules;
+
+ // Sinistralité (depuis tarifRC)
+ if (tarif && tarif.sinistre) {
+ document.getElementById('sinistre').value = tarif.sinistre;
+ }
+
+ // Checkbox RCE
+ if (rc.checkRCE !== undefined) {
+ document.getElementById('checkRCE').checked = rc.checkRCE;
+ document.getElementById('checkRCE').dispatchEvent(new Event('click'));
+ }
+
+ // Activité Voiturier/Loueur
+ if (rc.checkVoiturier !== undefined) {
+ const checkVoiturierEl = getElementByIdFlexible('checkVoiturier');
+ if (checkVoiturierEl) {
+ checkVoiturierEl.checked = rc.checkVoiturier;
+ const capitalVoiturierEl = getElementByIdFlexible('capitalVoiturier') || document.querySelector('input[name="selectActVoiturier/Loueur"]');
+ if (rc.capitalVoiturier && capitalVoiturierEl) capitalVoiturierEl.value = rc.capitalVoiturier;
+ checkVoiturierEl.dispatchEvent(new Event('click'));
+ }
+ }
+
+ // Activité Commissionnaire
+ if (rc.checkCommissionnaire !== undefined) {
+ const checkCommissionnaireEl = getElementByIdFlexible('checkCommissionnaire');
+ if (checkCommissionnaireEl) {
+ checkCommissionnaireEl.checked = rc.checkCommissionnaire;
+ const capitalCommissionnaireEl = getElementByIdFlexible('capitalCommissionnaire') || document.querySelector('input[name="selectActCommissionnaire de Transport"]') || document.querySelector('input[name="selectActCommissionnaireDeTransport"]');
+ if (rc.capitalCommissionnaire && capitalCommissionnaireEl) capitalCommissionnaireEl.value = rc.capitalCommissionnaire;
+ checkCommissionnaireEl.dispatchEvent(new Event('click'));
+ }
+ }
+
+ // Activité Déménageur
+ if (rc.checkDemenageur !== undefined) {
+ const checkDemenageurEl = getElementByIdFlexible('checkDemenageur');
+ if (checkDemenageurEl) {
+ checkDemenageurEl.checked = rc.checkDemenageur;
+ const capitalDemenageurEl = getElementByIdFlexible('capitalDemenageur') || document.querySelector('input[name="selectActDéménageur"]') || document.querySelector('input[name="selectActDemenageur"]');
+ if (rc.capitalDemenageur && capitalDemenageurEl) capitalDemenageurEl.value = rc.capitalDemenageur;
+ checkDemenageurEl.dispatchEvent(new Event('click'));
+ }
+ }
+
+ // Activité Logistique
+ if (rc.checkLogistique !== undefined) {
+ const checkLogistiqueEl = getElementByIdFlexible('checkLogistique');
+ if (checkLogistiqueEl) {
+ checkLogistiqueEl.checked = rc.checkLogistique;
+ const capitalLogistiqueEl = getElementByIdFlexible('capitalLogistique') || document.querySelector('input[name="selectActLogistique"]');
+ if (rc.capitalLogistique && capitalLogistiqueEl) capitalLogistiqueEl.value = rc.capitalLogistique;
+ checkLogistiqueEl.dispatchEvent(new Event('click'));
+ }
+ }
+
+ // Activité Autocariste
+ if (rc.checkAutocariste !== undefined) {
+ const checkAutocaristeEl = getElementByIdFlexible('checkAutocariste');
+ if (checkAutocaristeEl) {
+ checkAutocaristeEl.checked = rc.checkAutocariste;
+ const capitalAutocaristeEl = getElementByIdFlexible('capitalAutocariste') || document.querySelector('input[name="selectActAutocariste"]');
+ if (rc.capitalAutocariste && capitalAutocaristeEl) capitalAutocaristeEl.value = rc.capitalAutocariste;
+ checkAutocaristeEl.dispatchEvent(new Event('click'));
+ }
+ }
+
+ // Activité Autres
+ if (rc.checkAutres !== undefined) {
+ const checkAutresEl = getElementByIdFlexible('checkAutres');
+ if (checkAutresEl) {
+ checkAutresEl.checked = rc.checkAutres;
+ const capitalAutresEl = getElementByIdFlexible('capitalAutres') || document.querySelector('input[name="selectActAutres activites"]') || document.querySelector('input[name="selectActAutresActivites"]');
+ if (rc.capitalAutres && capitalAutresEl) capitalAutresEl.value = rc.capitalAutres;
+ checkAutresEl.dispatchEvent(new Event('click'));
+ }
+ }
+
+ // Zones géographiques
+ if (rc.zone1) document.getElementById('zone1').checked = rc.zone1;
+ if (rc.zone2) document.getElementById('zone2').checked = rc.zone2;
+ if (rc.zone3) document.getElementById('zone3').checked = rc.zone3;
+ if (rc.zone4) document.getElementById('zone4').checked = rc.zone4;
+ if (rc.zone5) document.getElementById('zone5').checked = rc.zone5;
+ if (rc.zone6) document.getElementById('zone6').checked = rc.zone6;
+
+ // Pré-remplir les activités complémentaires (JSON) pour TOUTES les activités
+ const activitiesTypes = [
+ { field: 'actComplVoiturier', name: 'actComplVoiturier/Loueur' },
+ { field: 'actComplCommissionnaire', name: 'actComplCommissionnaire de Transport' },
+ { field: 'actComplDemenageur', name: 'actComplDéménageur' },
+ { field: 'actComplLogistique', name: 'actComplLogistique' }
+ ];
+
+ console.log('🔄 Pré-remplissage des activités complémentaires...');
+ activitiesTypes.forEach(({ field, name }) => {
+ // D'abord DÉCOCHER toutes les checkboxes de cette activité
+ const allCheckboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]`);
+ allCheckboxes.forEach(cb => cb.checked = false);
+
+ if (rc[field]) {
+ try {
+ // PocketBase parse automatiquement les champs JSON, donc rc[field] est déjà un array
+ const activites = Array.isArray(rc[field]) ? rc[field] : JSON.parse(rc[field]);
+ console.log(` ✓ ${field}:`, activites);
+ activites.forEach(actText => {
+ // Chercher la checkbox dont le span adjacent contient ce texte
+ allCheckboxes.forEach(cb => {
+ const label = cb.nextElementSibling?.textContent.trim();
+ if (label === actText) {
+ cb.checked = true;
+ console.log(` ✓ Coché: ${actText}`);
+ }
+ });
+ });
+ } catch (e) { console.error(`❌ Erreur parsing ${field}:`, e); }
+ }
+ });
+
+ // Pré-remplir les marchandises (JSON) pour TOUTES les activités
+ const marchandisesTypes = [
+ { field: 'marchandisesVoiturier', name: 'marVoiturier/Loueur' },
+ { field: 'marchandisesCommissionnaire', name: 'marCommissionnaire de Transport' },
+ { field: 'marchandisesDemenageur', name: 'marDéménageur' },
+ { field: 'marchandisesLogistique', name: 'marLogistique' },
+ { field: 'marchandisesAutocariste', name: 'marAutocariste' },
+ { field: 'marchandisesAutres', name: 'marAutres activites' }
+ ];
+
+ console.log('🔄 Pré-remplissage des marchandises...');
+ marchandisesTypes.forEach(({ field, name }) => {
+ // D'abord DÉCOCHER toutes les checkboxes de cette marchandise
+ const allCheckboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]`);
+ allCheckboxes.forEach(cb => cb.checked = false);
+
+ if (rc[field]) {
+ try {
+ // PocketBase parse automatiquement les champs JSON, donc rc[field] est déjà un array
+ const marchandises = Array.isArray(rc[field]) ? rc[field] : JSON.parse(rc[field]);
+ console.log(` ✓ ${field}:`, marchandises);
+ marchandises.forEach(marText => {
+ // Chercher la checkbox dont le span adjacent contient ce texte
+ allCheckboxes.forEach(cb => {
+ const label = cb.nextElementSibling?.textContent.trim();
+ if (label === marText) {
+ cb.checked = true;
+ console.log(` ✓ Coché: ${marText}`);
+ }
+ });
+ });
+ } catch (e) { console.error(`❌ Erreur parsing ${field}:`, e); }
+ }
+ });
+
+ // Pré-remplir les pourcentages (depuis tarifRC)
+ // Préférer l'objet tarif si présent, sinon retomber sur l'expansion RC
+ const tarifSource = tarif || rc?.["@expand"]?.tarifRC || rc?.tarifRC || rc || null;
+ // Fallback ultime : données de session (hook RC orchestrator) si tout est vide
+ let sessionTarifData = null;
+ try {
+ const stored = sessionStorage.getItem('rc_tarif_validated_data');
+ sessionTarifData = stored ? JSON.parse(stored) : null;
+ } catch (e) {
+ sessionTarifData = null;
+ }
+ if (tarifSource || sessionTarifData) {
+ const pctVoiturierEl = getElementByIdFlexible('pourcent_voiturier') || getElementByIdFlexible('pourcentVoiturier/Loueur');
+ if (tarifSource?.pourcentageVoiturier && pctVoiturierEl) pctVoiturierEl.value = tarifSource.pourcentageVoiturier;
+
+ const pctCommissionnaireEl = getElementByIdFlexible('pourcent_commissionnaire') || getElementByIdFlexible('pourcentCommissionnaire de Transport') || getElementByIdFlexible('pourcentCommissionnaireDeTransport');
+ if (tarifSource?.pourcentageCommissionnaire && pctCommissionnaireEl) pctCommissionnaireEl.value = tarifSource.pourcentageCommissionnaire;
+
+ const pctDemenageurEl = getElementByIdFlexible('pourcent_demenageur') || getElementByIdFlexible('pourcentDéménageur') || getElementByIdFlexible('pourcentDemenageur');
+ if (tarifSource?.pourcentageDemenageur && pctDemenageurEl) pctDemenageurEl.value = tarifSource.pourcentageDemenageur;
+
+ const pctLogistiqueEl = getElementByIdFlexible('pourcent_logistique') || getElementByIdFlexible('pourcentLogistique');
+ if (tarifSource?.pourcentageLogistique && pctLogistiqueEl) pctLogistiqueEl.value = tarifSource.pourcentageLogistique;
+
+ const pctAutocaristeEl = getElementByIdFlexible('pourcent_autocariste') || getElementByIdFlexible('pourcentAutocariste');
+ if (tarifSource?.pourcentageAutocariste && pctAutocaristeEl) pctAutocaristeEl.value = tarifSource.pourcentageAutocariste;
+
+ const pctAutresEl = getElementByIdFlexible('pourcent_autres') || getElementByIdFlexible('pourcentAutres activites') || getElementByIdFlexible('pourcentAutresActivites');
+ if (tarifSource?.pourcentageAutres && pctAutresEl) pctAutresEl.value = tarifSource.pourcentageAutres;
+
+ // ===== ENGAGEMENTS COMPLÉMENTAIRES (depuis tarifRC) =====
+ // Dommages immatériels
+ const engagementSrc = tarifSource || sessionTarifData?.engagementsComplementaires;
+ if (tarifSource?.checkDomImmat || engagementSrc?.domicileImmatriculation?.checked) {
+ document.getElementById('checkDomImmat').checked = true;
+ document.getElementById('selectDomImmat').style.display = 'block';
+ const cap = tarifSource?.capitalDomImmat ?? engagementSrc?.domicileImmatriculation?.capital;
+ if (cap) {
+ document.getElementById('inputDomImmat').value = cap;
+ }
+ }
+
+ // Contenants confiés
+ if (tarifSource?.checkContConf || engagementSrc?.contenantConfie?.checked) {
+ document.getElementById('checkContConf').checked = true;
+ document.getElementById('selectContConf').style.display = 'block';
+ const cap = tarifSource?.capitalContConf ?? engagementSrc?.contenantConfie?.capital;
+ if (cap) {
+ document.getElementById('inputContConf').value = cap;
+ }
+ }
+
+ // Différence inventaire
+ if (tarifSource?.checkDiffInv || engagementSrc?.differenceInventaire?.checked) {
+ document.getElementById('checkDiffInv').checked = true;
+ document.getElementById('selectDiffInv').style.display = 'block';
+ const cap = tarifSource?.capitalDiffInv ?? engagementSrc?.differenceInventaire?.capital;
+ if (cap) {
+ document.getElementById('inputDiffInv').value = cap;
+ }
+ }
+
+ // ===== GARANTIES ADDITIONNELLES (depuis tarifRC) =====
+ // TPPC
+ const garantiesSrc = tarifSource || sessionTarifData?.garantiesAdditionnelles;
+ if (tarifSource?.checkTPPC || garantiesSrc?.tppc?.checked) {
+ document.getElementById('checkTPPC').checked = true;
+ document.getElementById('selectTPPC').style.display = 'block';
+ const cap = tarifSource?.capitalTPPC ?? garantiesSrc?.tppc?.capital;
+ if (cap) {
+ document.getElementById('selTPPCcapital').value = cap;
+ }
+ const veh = tarifSource?.vehiculesTPPC ?? garantiesSrc?.tppc?.vehicules;
+ if (veh) {
+ document.getElementById('selTPPCveh').value = veh;
+ }
+ }
+
+ // Protection juridique
+ if (tarifSource?.checkPJ || garantiesSrc?.pj) {
+ document.getElementById('checkPJ').checked = true;
+ }
+
+ // RCE - Station lavage
+ if (tarifSource?.checkStationLavage || garantiesSrc?.stationLavage) {
+ document.getElementById('checkStationLavage').checked = true;
+ }
+
+ // RCE - Garage interne
+ if (tarifSource?.checkGarageInterne || garantiesSrc?.garageInterne) {
+ document.getElementById('checkGarageInterne').checked = true;
+ }
+
+ // RCE - CSE
+ if (tarifSource?.checkCSE || garantiesSrc?.cse) {
+ document.getElementById('checkCSE').checked = true;
+ }
+
+ // ===== FRANCHISE CHOISIE =====
+ if (tarifSource?.franchiseChoisie) {
+ window.franchiseChoisie = tarifSource.franchiseChoisie;
+ // Mettre en surbrillance la carte sélectionnée
+ const selectedButton = document.querySelector(`.franchise-card button[name="${tarifSource.franchiseChoisie}"]`);
+ if (selectedButton) {
+ selectedButton.closest('.franchise-card').classList.add('selected');
+ }
+ }
+ }
+
+ console.log('✅ Formulaire tarif pré-rempli avec succès');
+
+ // Recalculer après pré-remplissage
+ setTimeout(() => {
+ calcGlobal();
+ }, 500);
+ }
+
+ function calcModCA(caRaw){
+ const ca = Number(String(caRaw || '').replace(/\s/g,'').replace(',','.')) || 0;
+ const thresholds = Object.keys(modRCCA).map(n => Number(n)).sort((a,b)=>a-b);
+ for (const t of thresholds) if (ca < t) return modRCCA[t];
+ return modRCCA[thresholds.at(-1)] ?? 1;
+ }
+
+ function calcModMarchandises(data, activityName, type, cot) {
+ let m = 1;
+
+ // On cible le bloc correspondant à l'activité
+ const container = document.querySelector(`[name="mar${activityName}"]`);
+ if (!container) return 1;
+
+ // On récupère toutes les cases à cocher de ce bloc
+ const checkboxes = container.querySelectorAll('input[type="checkbox"]');
+
+ checkboxes.forEach(cb => {
+ if (cb.checked) {
+ // Le libellé affiché est dans le juste après l'input
+ const label = cb.nextElementSibling?.innerText.trim();
+
+ // On simplifie le libellé pour matcher les clés du JSON
+ let key = null;
+ if (label.includes("ordinaires")) key = "Marchandises ordinaires";
+ else if (label.includes("Véhicules roulants")) key = "Véhicules roulants";
+ else if (label.includes("Engins de chantier")) key = "Engins de chantier";
+ else if (label.includes("Mobiliers")) key = "Mobiliers en déménagement";
+ else if (label.includes("périssables")) key = "Marchandises périssables";
+ else if (label.includes("citerne")) key = "Marchandises en citerne";
+ else if (label.includes("Animaux")) key = "Animaux vivants";
+ else if (label.includes("benne")) key = "Marchandises en benne";
+ else if (label.includes("béton")) key = "Transport de béton";
+
+ if (key) {
+ const v = data?.[cot]?.[activityName]?.[key]?.[`mod${type}`];
+ if (typeof v === "number") {
+ m *= v;
+ } else {
+ console.warn(`Pas de mod trouvé pour activité=${activityName}, clé=${key}, type=${type}, cot=${cot}`);
+ }
+ } else {
+ console.warn(`Libellé non reconnu: "${label}"`);
+ }
+ }
+ });
+
+ return m;
+ }
+
+ function getZoneMods(data) {
+ let mRCC = 1;
+ let mRCE = 1;
+
+ // On parcourt toutes les cases à cocher de zones
+ for (let i = 1; i <= 6; i++) {
+ const cb = document.getElementById(`zone${i}`);
+ if (cb && cb.checked) {
+ // Récupérer le libellé affiché
+ const label = document.getElementById(`zone${i}-text`).innerText.trim();
+
+ // Trouver la clé correspondante dans le JSON
+ let key = null;
+ if (label.includes("France Métropolitaine")) key = "France Métropolitaine et pays limitrophes";
+ else if (label.includes("Union Européenne")) key = "Union Européenne";
+ else if (label.includes("Autres pays européens")) key = "Autres pays européens sauf Russie et Ukraine (y compris UK et Norvège)";
+ else if (label.includes("Maghreb") || label.includes("Amérique du Nord")) key = "Pays du Maghreb et Amérique du Nord ( USA / Canada / Mexique )";
+ else if (label.includes("Amérique Centrale") || label.includes("Asie") || label.includes("Océanie")) key = "Amérique Centrale et Sud / Caraïbes, Asie et Océanie";
+ else if (label.includes("Afrique") || label.includes("Moyen Orient")) key = "Afrique Hors Maghreb / Proche Orient / Moyen Orient";
+
+ if (key && data[key]) {
+ const zone = data[key];
+ if (typeof zone.modRCC === "number") mRCC = Math.max(mRCC, zone.modRCC);
+ if (typeof zone.modRCE === "number") mRCE = Math.max(mRCE, zone.modRCE);
+ }
+ }
+ }
+
+ return { mRCC, mRCE };
+}
+
+ function calcModActCompl(data, activityName, type, cot) {
+ let m = 1;
+ const current = getSelectedActivities().find(a => a.typeActivite === activityName);
+ if (!current) return 1;
+ const table = data?.[cot]?.[activityName] || {};
+ (current.listActComplChecked||[]).forEach(name => {
+ const v = table[name]?.[`mod${type}`];
+ if (typeof v === "number") m *= v;
+ });
+ return m;
+ }
+
+ function calcEngagCompl(data, primeRCC) {
+ let prime = primeRCC;
+ let surPrime = 0;
+ let modDommImmat = 1;
+ let infos = [];
+
+ function writeToCard(inputId, message) {
+ const inputEl = document.getElementById(inputId);
+ if (!inputEl) return;
+
+ const cardContent = inputEl.closest('.card-content');
+ if (!cardContent) return;
+
+ // Supprime l’ancien wrapper pour cet input
+ cardContent.querySelectorAll(`div.chip[data-for="${inputId}"]`).forEach(el => el.remove());
+
+ if (!message) return;
+
+ // Wrapper
+ const wrapper = document.createElement("div");
+ wrapper.classList.add("chip"); // uniquement "chip"
+ wrapper.dataset.for = inputId;
+
+ // Message
+ const p = document.createElement("p");
+ p.dataset.for = inputId;
+ p.classList.add("helper-text", "red-text");
+ p.style.display = "block"; // override helper-text { display: none; }
+ p.textContent = message;
+
+ wrapper.appendChild(p);
+ cardContent.appendChild(wrapper);
+ }
+
+
+
+
+
+
+
+ // === Contenants confiés ===
+ const checkContConf = document.getElementById('checkContConf');
+ const inputContConf = document.getElementById('inputContConf');
+ if (checkContConf?.checked) {
+ const val = toNumber(inputContConf?.value);
+ if (val > 0) {
+ const tranches = Object.keys(data.modRCC["Contenants confiés"]).map(Number).sort((a,b)=>a-b);
+ const tranche = findClosestTranche(val, tranches);
+ const add = data.modRCC["Contenants confiés"][tranche];
+ if (typeof add === "number") {
+ surPrime += add;
+ const msg = `Prime RCC : +${add.toLocaleString('fr-FR',{style:'currency',currency:'EUR'})}`;
+ //infos.push(msg); pour ajouter le message dans la div "Prime RCC"
+ writeToCard('inputContConf', msg);
+ }
+ }
+ } else {
+ writeToCard('inputContConf', null); // supprime si décoché
+ }
+
+ // === Différence inventaire ===
+ const checkDiffInv = document.getElementById('checkDiffInv');
+ const inputDiffInv = document.getElementById('inputDiffInv');
+ if (checkDiffInv?.checked) {
+ const val = toNumber(inputDiffInv?.value);
+ if (val > 0) {
+ const tranches = Object.keys(data.modRCC["Différence inventaire"]).map(Number).sort((a,b)=>a-b);
+ const tranche = findClosestTranche(val, tranches);
+ const add = data.modRCC["Différence inventaire"][tranche];
+ if (typeof add === "number") {
+ surPrime += add;
+ const msg = `Prime RCC : +${add.toLocaleString('fr-FR',{style:'currency',currency:'EUR'})}`;
+ //infos.push(msg); pour ajouter le message dans la div "Prime RCC"
+ writeToCard('inputDiffInv', msg);
+ }
+ }
+ } else {
+ writeToCard('inputDiffInv', null);
+ }
+
+ // === Dommages immatériels ===
+ const checkDomImmat = document.getElementById('checkDomImmat');
+ const inputDomImmat = document.getElementById('inputDomImmat');
+ if (checkDomImmat?.checked) {
+ const val = toNumber(inputDomImmat?.value);
+ if (val > 0) {
+ const tranches = Object.keys(data.modRCC["Dommages immatériels"]).map(Number).sort((a,b)=>a-b);
+ const tranche = findClosestTranche(val, tranches);
+ const mod = data.modRCC["Dommages immatériels"][tranche];
+ if (typeof mod === "number") {
+ modDommImmat = mod;
+ const msg = `Mod Taux RCC : ×${mod}`;
+ //infos.push(msg); pour ajouter le message dans la div "Prime RCC"
+ writeToCard('inputDomImmat', msg);
+ }
+ }
+ } else {
+ writeToCard('inputDomImmat', null);
+ }
+
+ // === Totaux ===
+ prime += surPrime;
+ prime *= modDommImmat;
+
+ return { prime, surPrime, infos };
+ }
+
+ // Fonction helper : trouver la tranche la plus proche
+ function findClosestTranche(val, tranches) {
+ if (val <= tranches[0]) return tranches[0];
+ if (val >= tranches[tranches.length - 1]) return tranches[tranches.length - 1];
+
+ for (let i = 0; i < tranches.length - 1; i++) {
+ if (val >= tranches[i] && val < tranches[i + 1]) {
+ // Prendre la tranche inférieure ou égale
+ return tranches[i];
+ }
+ }
+ return tranches[tranches.length - 1];
+ }
+
+ // Fonction pour afficher un avertissement visuel de dépassement %
+ function showPercentageWarning(excess) {
+ // Créer ou récupérer le div d'avertissement
+ let warningDiv = document.getElementById('percentageWarning');
+ if (!warningDiv) {
+ warningDiv = document.createElement('div');
+ warningDiv.id = 'percentageWarning';
+ warningDiv.style.cssText = `
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ background: #f44336;
+ color: white;
+ padding: 15px 25px;
+ border-radius: 5px;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.3);
+ z-index: 9999;
+ font-weight: bold;
+ animation: slideIn 0.3s ease;
+ `;
+ document.body.appendChild(warningDiv);
+ }
+
+ warningDiv.innerHTML = `Vous dépassez 100% (vous dépassiez de ${excess.toFixed(1)}%)`;
+ warningDiv.style.display = 'block';
+
+ // Masquer après 3 secondes
+ setTimeout(() => {
+ warningDiv.style.display = 'none';
+ }, 3000);
+ }
+
+ // Fonction pour masquer toutes les primes (quand % invalide)
+ function hideAllPrimes() {
+ const primeElements = [
+ 'primeChapActRCC', 'primeChapActRCE',
+ 'primeChapActComplRCC', 'primeChapActComplRCE',
+ 'primeChapMarchRCC', 'primeChapMarchRCE',
+ 'primeChapZonesRCC', 'primeChapZonesRCE',
+ 'primeEngValue', 'primeChapGarAddRCC', 'primeChapGarAddRCE',
+ 'priceFr250', 'priceFr400', 'priceFr2000'
+ ];
+
+ primeElements.forEach(id => {
+ const el = document.getElementById(id);
+ if (el) {
+ el.innerHTML = ' % invalide (> 100%)';
+ }
+ });
+ }
+
+ // Fonction pour afficher toutes les primes (quand % valide)
+ function showAllPrimes() {
+ }
+
+ // Fonction pour mettre à jour l'indicateur visuel du total des pourcentages
+ function updatePercentageIndicator(total) {
+ const indicator = document.getElementById('pourcentageTotal');
+ if (!indicator) return;
+
+ const displayTotal = total.toFixed(1);
+ indicator.textContent = `Total : ${displayTotal}%`;
+
+ // Changer la couleur selon le total
+ if (total > 100) {
+ // ROUGE : Dépassement - INVALIDE
+ indicator.style.background = '#f44336';
+ indicator.style.color = 'white';
+ indicator.style.border = '3px solid #c62828';
+ indicator.style.animation = 'pulse 1s infinite';
+ } else if (total === 100 || Math.abs(total - 100) < 0.1) {
+ // VERT : Parfait - 100%
+ indicator.style.background = '#4caf50';
+ indicator.style.color = 'white';
+ indicator.style.border = '3px solid #2e7d32';
+ indicator.style.animation = 'none';
+ } else if (total >= 95) {
+ // ORANGE : Proche de 100%
+ indicator.style.background = '#ff9800';
+ indicator.style.color = 'white';
+ indicator.style.border = '3px solid #ef6c00';
+ indicator.style.animation = 'none';
+ } else {
+ // BLEU : En cours de saisie
+ indicator.style.background = 'white';
+ indicator.style.color = 'darkblue';
+ indicator.style.border = '2px solid darkblue';
+ indicator.style.animation = 'none';
+ }
+ }
+
+ function calcGarAdd(data, primeRCC, primeRCE) {
+ let primeRCCres = Number(primeRCC) || 0;
+ let primeRCEres = Number(primeRCE) || 0;
+ let surPrimeRCE = 0;
+ const infosRCC = [];
+ const infosRCE = [];
+
+ function writeToCard(inputId, message) {
+ const inputEl = document.getElementById(inputId);
+ if (!inputEl) return;
+
+ const cardContent = inputEl.closest('.card-content');
+ if (!cardContent) return;
+
+ // Supprime l’ancien wrapper pour cet input
+ cardContent.querySelectorAll(`div.chip[data-for="${inputId}"]`).forEach(el => el.remove());
+
+ if (!message) return;
+
+ // Wrapper
+ const wrapper = document.createElement("div");
+ wrapper.classList.add("chip");
+ wrapper.dataset.for = inputId;
+
+ // Style : occupe sa propre ligne mais largeur adaptée au contenu
+ wrapper.style.display = "table"; // se comporte comme un bloc centré sur son contenu
+ wrapper.style.margin = "8px auto"; // centre horizontalement
+
+ // Message
+ const p = document.createElement("p");
+ p.dataset.for = inputId;
+ p.classList.add("helper-text", "red-text");
+ p.style.display = "block"; // override helper-text { display: none; }
+ p.textContent = message;
+
+ wrapper.appendChild(p);
+ cardContent.appendChild(wrapper);
+ }
+
+
+
+
+
+
+ // === Station de lavage (RCE forfait) ===
+ const checkStation = document.getElementById('checkStationLavage');
+ if (checkStation?.checked) {
+ const add = data.modRCE["Station de lavage"];
+ if (typeof add === "number") {
+ surPrimeRCE += add;
+ const msg = `Prime RCE : +${add.toLocaleString('fr-FR', { style:'currency', currency:'EUR' })}`;
+ //infosRCE.push(msg);
+ writeToCard('checkStationLavage', msg);
+ }
+ } else {
+ writeToCard('checkStationLavage', null);
+ }
+
+ // === Garage interne (RCE forfait) ===
+ const checkGarage = document.getElementById('checkGarageInterne');
+ if (checkGarage?.checked) {
+ const add = data.modRCE["Garage interne"];
+ if (typeof add === "number") {
+ surPrimeRCE += add;
+ const msg = `Prime RCE : +${add.toLocaleString('fr-FR', { style:'currency', currency:'EUR' })}`;
+ //infosRCE.push(msg);
+ writeToCard('checkGarageInterne', msg);
+ }
+ } else {
+ writeToCard('checkGarageInterne', null);
+ }
+
+ // === Comité Social et Economique (RCE forfait) ===
+ const checkCSE = document.getElementById('checkCSE');
+ if (checkCSE?.checked) {
+ const add = data.modRCE["Comité Social et Economique"];
+ if (typeof add === "number") {
+ surPrimeRCE += add;
+ const msg = `Prime RCE : +${add.toLocaleString('fr-FR', { style:'currency', currency:'EUR' })}`;
+ //infosRCE.push(msg);
+ writeToCard('checkCSE', msg);
+ }
+ } else {
+ writeToCard('checkCSE', null);
+ }
+
+ // === Addition des garanties RCE ===
+ primeRCEres += surPrimeRCE;
+
+ return { primeRCC: primeRCCres, primeRCE: primeRCEres, surPrimeRCE, infosRCC, infosRCE };
+ }
+
+
+
+ function calcSinistre(data, primeRCC, primeRCE) {
+ console.log('[calcSinistre] start', { primeRCC, primeRCE });
+
+ let primeRCCres = Number(primeRCC) || 0;
+ let primeRCEres = Number(primeRCE) || 0;
+ let mod = 1;
+
+ const elSin = document.getElementById('sinistre');
+ const elCA = document.getElementById('chiffreAffaire');
+ const chip = document.getElementById('modSinistre');
+
+ if (!elSin || !elCA) {
+ console.warn('[calcSinistre] Missing #sinistre or #chiffreAffaire');
+ } else {
+ const sinistreVal = toNumber(elSin.value);
+ const CA = toNumber(elCA.value);
+
+ console.log('[calcSinistre] inputs', { sinistreVal, CA });
+
+ if (CA > 0 && sinistreVal >= 0) {
+ const ratio = sinistreVal / CA;
+ let key = 0.4;
+ if (ratio <= 0.4) key = 0.4;
+ else if (ratio <= 0.7) key = 0.7;
+ else key = 1;
+
+ mod = data[key];
+ console.log('[calcSinistre] ratio=', ratio.toFixed(3), 'key=', key, 'mod=', mod);
+ } else {
+ console.log('[calcSinistre] CA <= 0 or sinistre < 0 -> mod=1');
+ }
+ }
+
+ // Apply modulation to both RCC and RCE
+ primeRCCres *= mod;
+ primeRCEres *= mod;
+
+ if (chip) {
+ chip.style.display = 'block';
+ chip.innerHTML = 'Modulation sinistre :
x ' + mod.toLocaleString('fr-FR', { minimumFractionDigits: 2 });
+ } else {
+ console.warn('[calcSinistre] #modSinistre not found');
+ }
+
+ console.log('[calcSinistre] result', { primeRCC: primeRCCres, primeRCE: primeRCEres, mod });
+ return { primeRCC: primeRCCres, primeRCE: primeRCEres, mod };
+ }
+
+
+ // --- Fonctions utilitaires ---
+
+ function getMaxMiniRCC(activites, cot) {
+ let maxMini = 0;
+ activites.forEach(act => {
+ // Récupérer l'input/select pour cette activité
+ const inputEl = document.querySelector(`input[name="selectAct${act}"], select[name="selectAct${act}"]`);
+ if (!inputEl) return;
+
+ const capitalSaisi = toNumber(inputEl.value);
+ if (capitalSaisi <= 0) return;
+
+ // Déterminer le type de cotisation
+ const cotType = cot === 'revisable' ? 'revisable' : 'forfaitaire';
+
+ // Trouver la tranche la plus proche
+ const grilleAct = modRCPrimeMini?.[cotType]?.[act];
+ if (grilleAct) {
+ const tranches = Object.keys(grilleAct).map(Number).sort((a,b)=>a-b);
+ const tranche = findClosestTranche(capitalSaisi, tranches);
+ const miniData = grilleAct[tranche];
+
+ if (miniData && typeof miniData.miniRCC === 'number') {
+ maxMini = Math.max(maxMini, miniData.miniRCC);
+ }
+ }
+ });
+ return maxMini;
+ }
+
+ function getMaxMiniRCE(activites, cot) {
+ let maxMini = 0;
+ activites.forEach(act => {
+ // Récupérer l'input/select pour cette activité
+ const inputEl = document.querySelector(`input[name="selectAct${act}"], select[name="selectAct${act}"]`);
+ if (!inputEl) return;
+
+ const capitalSaisi = toNumber(inputEl.value);
+ if (capitalSaisi <= 0) return;
+
+ // Déterminer le type de cotisation
+ const cotType = cot === 'revisable' ? 'revisable' : 'forfaitaire';
+
+ // Trouver la tranche la plus proche
+ const grilleAct = modRCPrimeMini?.[cotType]?.[act];
+ if (grilleAct) {
+ const tranches = Object.keys(grilleAct).map(Number).sort((a,b)=>a-b);
+ const tranche = findClosestTranche(capitalSaisi, tranches);
+ const miniData = grilleAct[tranche];
+
+ if (miniData && typeof miniData.miniRCE === 'number') {
+ maxMini = Math.max(maxMini, miniData.miniRCE);
+ }
+ }
+ });
+ return maxMini;
+ }
+
+
+ function calcTarifRCC({
+ CA,
+ primeRCCbase,
+ primeRCEbase,
+ capitalTPPC,
+ nbVehicules,
+ coefTPPC,
+ franchiseCoef,
+ primeMini
+ }) {
+ // --- Prime RCC avec franchise ---
+ let primeFranchiseRCC = Number(primeRCCbase) * Number(franchiseCoef.modRCC || 1);
+ let primeFranchiseRCE = Number(primeRCEbase) * Number(franchiseCoef.modRCE || 1);
+
+ // --- Ajout TPPC APRÈS franchise ---
+ const primeTPPC = capitalTPPC * nbVehicules * coefTPPC;
+ primeFranchiseRCC = primeFranchiseRCC + primeTPPC;
+
+ // --- Calcul taux AVANT minima ---
+ let tauxRCC = CA > 0 ? (primeFranchiseRCC * 100 / CA).toFixed(2) : "0.00";
+ let tauxRCE = CA > 0 ? (primeFranchiseRCE * 100 / CA).toFixed(2) : "0.00";
+
+ // --- Application des minima ---
+ let isMiniRCC = false;
+ let isMiniRCE = false;
+
+ if (primeFranchiseRCC < primeMini[0]) {
+ tauxRCC = (primeFranchiseRCC * 100 / CA).toFixed(2); // Garder le taux avant mini
+ primeFranchiseRCC = primeMini[0];
+ isMiniRCC = true;
+ }
+
+ if (primeFranchiseRCE < primeMini[1]) {
+ tauxRCE = (primeFranchiseRCE * 100 / CA).toFixed(2); // Garder le taux avant mini
+ primeFranchiseRCE = primeMini[1];
+ isMiniRCE = true;
+ }
+
+ // --- Recalculer taux si PAS mini ---
+ if (!isMiniRCC && CA > 0) {
+ tauxRCC = (primeFranchiseRCC * 100 / CA).toFixed(2);
+ }
+ if (!isMiniRCE && CA > 0) {
+ tauxRCE = (primeFranchiseRCE * 100 / CA).toFixed(2);
+ }
+
+ // --- Prime totale ---
+ const primeTotale = primeFranchiseRCC + primeFranchiseRCE;
+
+ // --- Taux global ---
+ const tauxGlobal = CA > 0 ? ((primeTotale * 100 / CA).toFixed(2)) : "0.00";
+
+ return {
+ primeRCC: primeFranchiseRCC.toString(),
+ tauxRCC,
+ primeRCE: primeFranchiseRCE.toString(),
+ tauxRCE,
+ primeTotale: primeTotale.toString(),
+ tauxGlobal,
+ isMiniRCC,
+ isMiniRCE
+ };
+ }
+
+
+ function calcTarifettes(primePJ, CA, activites, capitalTPPC, nbVehicules, coefTPPC, primeRCCbase, primeRCEbase) {
+ const cards = [
+ { key: "250", priceId: "priceFr250", rccId: "rccFr250", rceId: "rceFr250", pjId: "pjFr250", txRccId: "tauxRccFr250", txRceId: "tauxRceFr250", txGlobId: "tauxGlobalFr250" },
+ { key: "400", priceId: "priceFr400", rccId: "rccFr400", rceId: "rceFr400", pjId: "pjFr400", txRccId: "tauxRccFr400", txRceId: "tauxRceFr400", txGlobId: "tauxGlobalFr400" },
+ { key: "10% avec mini 300 € et maxi 2000", priceId: "priceFr2000", rccId: "rccFr2000", rceId: "rceFr2000", pjId: "pjFr2000", txRccId: "tauxRccFr2000", txRceId: "tauxRceFr2000", txGlobId: "tauxGlobalFr2000" },
+ ];
+
+ // Déterminer le type de cotisation
+ const cot = document.querySelector('input[name="cotisation"]:checked')?.value || 'revisable';
+ const checkRCE = document.getElementById('checkRCE')?.checked || false;
+ const checkPJ = document.getElementById('checkPJ')?.checked || false;
+
+ const primeMini = [
+ getMaxMiniRCC(activites, cot),
+ getMaxMiniRCE(activites, cot)
+ ];
+
+ cards.forEach(card => {
+ const mods = modRCFranchise[card.key] || { modRCC: 1, modRCE: 1 };
+
+ const result = calcTarifRCC({
+ CA,
+ primeRCCbase,
+ primeRCEbase,
+ capitalTPPC,
+ nbVehicules,
+ coefTPPC,
+ franchiseCoef: mods,
+ primeMini
+ });
+
+ // Calculer la PJ en fonction de la prime totale RCC+RCE
+ let primePJcalc = 0;
+ if (checkPJ) {
+ const primeTotaleAvantPJ = Number(result.primeRCC) + (checkRCE ? Number(result.primeRCE) : 0);
+ primePJcalc = calcPJ(primeTotaleAvantPJ);
+ }
+
+ // Prime totale finale avec PJ
+ const primeTotaleFinale = Number(result.primeRCC) + (checkRCE ? Number(result.primeRCE) : 0) + primePJcalc;
+ const tauxGlobalFinal = CA > 0 ? formatNumber((Number(result.primeRCC) + (checkRCE ? Number(result.primeRCE) : 0)) * 100 / CA, 2) : "0.000";
+
+ // Récupérer les éléments du DOM
+ const elPrice = document.getElementById(card.priceId);
+ const elRCC = document.getElementById(card.rccId);
+ const elRCE = document.getElementById(card.rceId);
+ const elPJ = document.getElementById(card.pjId);
+ const elTxRCC = document.getElementById(card.txRccId);
+ const elTxRCE = document.getElementById(card.txRceId);
+ const elTxGlob = document.getElementById(card.txGlobId);
+
+ // Récupérer les lignes parent pour masquer/afficher
+ const rowRCE = elRCE?.closest('p');
+ const rowTxRCE = elTxRCE?.closest('p');
+ const rowPJ = elPJ?.closest('p');
+ const rowTxGlob = elTxGlob?.closest('p');
+
+ // Afficher le prix total
+ if (elPrice) elPrice.innerText = formatNumber(primeTotaleFinale, 2) + ' €';
+
+ // Afficher Prime RCC (toujours visible)
+ if (elRCC) {
+ elRCC.innerText = formatNumber(result.primeRCC, 2) + " €" + (result.isMiniRCC ? " (Mini)" : "");
+ }
+
+ // Afficher Prime RCE uniquement si cochée ET > 0
+ if (rowRCE) {
+ if (checkRCE && result.primeRCE > 0) {
+ rowRCE.style.display = 'block';
+ if (elRCE) {
+ elRCE.innerText = formatNumber(result.primeRCE, 2) + " €" + (result.isMiniRCE ? " (Mini)" : "");
+ }
+ } else {
+ rowRCE.style.display = 'none';
+ }
+ }
+
+ // Afficher Prime PJ uniquement si cochée ET > 0
+ if (rowPJ) {
+ if (checkPJ && primePJcalc > 0) {
+ rowPJ.style.display = 'block';
+ if (elPJ) {
+ elPJ.innerText = formatNumber(primePJcalc, 2) + " €";
+ }
+ } else {
+ rowPJ.style.display = 'none';
+ }
+ }
+
+ // En forfaitaire, ne pas afficher les taux (uniquement des primes fixes)
+ if (cot === 'forfaitaire') {
+ // Masquer tous les taux en forfaitaire
+ if (elTxRCC?.closest('p')) elTxRCC.closest('p').style.display = 'none';
+ if (rowTxRCE) rowTxRCE.style.display = 'none';
+ if (rowTxGlob) rowTxGlob.style.display = 'none';
+ } else {
+ // En revisable, afficher les taux
+ if (elTxRCC?.closest('p')) {
+ elTxRCC.closest('p').style.display = 'block';
+ elTxRCC.innerText = formatNumber(result.tauxRCC, 2) + " %";
+ }
+
+ if (rowTxRCE) {
+ if (checkRCE && result.primeRCE > 0) {
+ rowTxRCE.style.display = 'block';
+ if (elTxRCE) {
+ elTxRCE.innerText = formatNumber(result.tauxRCE, 2) + " %";
+ }
+ } else {
+ rowTxRCE.style.display = 'none';
+ }
+ }
+
+ if (rowTxGlob && CA > 0) {
+ rowTxGlob.style.display = 'block';
+ if (elTxGlob) {
+ elTxGlob.innerText = tauxGlobalFinal + " %";
+ }
+ }
+ }
+ });
+ }
+
+ // Fonction pour calculer la PJ selon la prime totale
+ function calcPJ(primeTotale) {
+ let primePJ = 0;
+ const tablePJ = modRCGarAdd?.modRCC?.["Protection juridique"];
+ if (!tablePJ) return 0;
+
+ // Parcourir les tranches de PJ et prendre la plus grande tranche inférieure à la prime totale
+ const tranches = Object.keys(tablePJ).map(Number).sort((a, b) => a - b);
+ for (const tranche of tranches) {
+ if (primeTotale >= tranche) {
+ primePJ = tablePJ[tranche];
+ } else {
+ break;
+ }
+ }
+ return primePJ;
+ }
+
+
+
+ function calcGlobal() {
+ // Vérification des pourcentages AVANT calcul
+ const allPourcentInputs = Array.from(document.querySelectorAll('.input-pourcent')).filter(p => p.offsetParent != null);
+ let totalPourcentCheck = 0;
+ allPourcentInputs.forEach(p => {
+ totalPourcentCheck += toNumber(p.value);
+ });
+
+ if (totalPourcentCheck > 100.01) {
+ // Total > 100% : BLOQUER tous les calculs
+ hideAllPrimes();
+ return;
+ }
+
+ const cot = document.querySelector('input[name="cotisation"]:checked')?.value;
+ let result = (cot === 'revisable') ? calcRevisable() : calcForfaitaire();
+
+ if (result) {
+ const capitalTPPCsaisi = toNumber(document.getElementById("selTPPCcapital")?.value);
+ const nbVehicules = toNumber(document.getElementById("selTPPCveh")?.value);
+
+ // Trouver la tranche TPPC la plus proche
+ let capitalTPPC = 0;
+ let coefTPPC = 0;
+ if (capitalTPPCsaisi > 0 && modRCGarAdd?.modRCC?.["TPPC"]) {
+ const tranches = Object.keys(modRCGarAdd.modRCC.TPPC).map(Number).sort((a,b)=>a-b);
+ capitalTPPC = findClosestTranche(capitalTPPCsaisi, tranches);
+ coefTPPC = modRCGarAdd.modRCC.TPPC[capitalTPPC] || 0;
+ }
+
+ calcTarifettes(result.primePJ, result.CA, result.activites, capitalTPPC, nbVehicules, coefTPPC, result.primeRCCbase, result.primeRCEbase);
+ }
+ }
+
+ function calcRevisable() {
+ // ========= Variables centrales (déclarées au début) =========
+ const capitalTPPCEl = document.getElementById("capital_TPPC");
+ const vehiculeTPPCEl = document.getElementById("vehicule_TPPC");
+ const coefTPPCEl = document.getElementById("garantie_prime_TPPC");
+
+ const capitalTPPC = toNumber(capitalTPPCEl?.value);
+ const nbVehicules = toNumber(vehiculeTPPCEl?.value);
+ const coefTPPC = toNumber(coefTPPCEl?.value) || 0.01;
+ let primeBaseRCC = 0;
+ let tauxBaseRCC = 0.000;
+ let primeRCC = 0;
+ let tauxRCC = 0.000;
+ let primeBaseRCE = 0;
+ let tauxBaseRCE = 0.000;
+ let primeRCE = 0;
+ let tauxRCE = 0.000;
+ let primePJ = 0;
+ let primeGlobal = 0;
+ let tauxGlobal = 0;
+
+ // Tableaux de travail par activité
+ let primeBaseRCCparAct = [];
+ let primeBaseRCEparAct = [];
+
+ // ========= Étape CA =========
+ const modCA = calcModCA(document.getElementById('chiffreAffaire').value);
+ document.getElementById('modCA').innerHTML =
+ 'Mod. CA test :
x ' + modCA.toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
+
+ // ========= Étape Activités (taux base) =========
+ tauxBaseRCC = get_taux_base_RCC(modRCActRCC, "revisable");
+ if (document.getElementById('checkRCE').checked === true) {
+ tauxBaseRCE = get_taux_base_RCE(modRCActRCE, "revisable");
+ }
+
+ const CA = toNumber(document.getElementById("chiffreAffaire").value);
+
+ // ========= Calcul primes de base RCC =========
+ for (let i = 0; i < tauxBaseRCC.length; i++) {
+ const pourcentInput = toNumber(document.getElementById("pourcent" + tauxBaseRCC[i].typeActivite)?.value);
+ const primeBase = (tauxBaseRCC[i].tauxBase / 100 * pourcentInput / 100 * CA);
+ primeBaseRCCparAct.push({
+ typeActivite: tauxBaseRCC[i].typeActivite,
+ primeBase: primeBase
+ });
+ }
+
+ // ========= Calcul primes de base RCE si coché =========
+ if (document.getElementById('checkRCE').checked) {
+ for (let i = 0; i < tauxBaseRCE.length; i++) {
+ const pourcentInput = toNumber(document.getElementById("pourcent" + tauxBaseRCE[i].typeActivite)?.value);
+ const primeBase = (tauxBaseRCE[i].tauxBase / 100 * pourcentInput / 100 * CA);
+ primeBaseRCEparAct.push({
+ typeActivite: tauxBaseRCE[i].typeActivite,
+ primeBase: primeBase
+ });
+ }
+ }
+
+ // Sommes des primes de base (SANS mod CA)
+ primeBaseRCC = primeBaseRCCparAct.reduce((total, item) => total + item.primeBase, 0);
+ primeBaseRCE = primeBaseRCEparAct.reduce((total, item) => total + item.primeBase, 0);
+
+ // UI (affichage sans mod CA)
+ document.getElementById('primeChapActRCC').innerHTML =
+ 'Prime de base RCC : ' + primeBaseRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+
+ document.getElementById('primeChapActRCE').innerHTML =
+ 'Prime de base RCE : ' + primeBaseRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+
+ // ========= Étape Activités complémentaires =========
+ for (let i = 0; i < primeBaseRCCparAct.length; i++) {
+ primeBaseRCCparAct[i].primeBase *= calcModActCompl(modRCActCompl, primeBaseRCCparAct[i].typeActivite, "RCC", "revisable");
+ }
+
+ if (document.getElementById('checkRCE').checked) {
+ for (let i = 0; i < primeBaseRCEparAct.length; i++) {
+ primeBaseRCEparAct[i].primeBase *= calcModActCompl(
+ modRCActCompl,
+ primeBaseRCEparAct[i].typeActivite,
+ "RCE",
+ "revisable"
+ );
+ }
+ }
+
+ // Re-sommes (toujours sans mod CA)
+ primeBaseRCC = primeBaseRCCparAct.reduce((total, item) => total + item.primeBase, 0);
+ primeBaseRCE = primeBaseRCEparAct.reduce((total, item) => total + item.primeBase, 0);
+
+ document.getElementById('primeChapActComplRCC').innerHTML =
+ 'Prime RCC : ' + primeBaseRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+ document.getElementById('primeChapActComplRCE').innerHTML =
+ 'Prime RCE : ' + primeBaseRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ // ========= Étape Marchandises (× par activité) + Mod CA =========
+ const selections = getSelectedActivities();
+
+ for (let i = 0; i < primeBaseRCCparAct.length; i++) {
+ const actName = primeBaseRCCparAct[i].typeActivite;
+ const modMar = calcModMarchandises(modRCMar, actName, "RCC", "revisable");
+ // Appliquer marchandises ET CA ensemble
+ primeBaseRCCparAct[i].primeBase = primeBaseRCCparAct[i].primeBase * modMar * modCA;
+ }
+
+ if (document.getElementById('checkRCE').checked) {
+ for (let i = 0; i < primeBaseRCEparAct.length; i++) {
+ const actName = primeBaseRCEparAct[i].typeActivite;
+ const modMar = calcModMarchandises(modRCMar, actName, "RCE", "revisable");
+ // Appliquer marchandises ET CA ensemble
+ primeBaseRCEparAct[i].primeBase = primeBaseRCEparAct[i].primeBase * modMar * modCA;
+ }
+ }
+
+ // Recalcule totaux apres mods marchandises + CA
+ primeBaseRCC = primeBaseRCCparAct.reduce((total, item) => total + item.primeBase, 0);
+ primeBaseRCE = primeBaseRCEparAct.reduce((total, item) => total + item.primeBase, 0);
+
+ // Maintenant primeRCC et primeRCE incluent déjà le mod CA
+ primeRCC = primeBaseRCC;
+ primeRCE = primeBaseRCE;
+
+ // UI marchandises
+ document.getElementById('primeChapMarchRCC').innerHTML =
+ 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+ document.getElementById('primeChapMarchRCE').innerHTML =
+ 'Prime RCE : ' + primeRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ // ========= Étape Zones (× max RCC / × max RCE) =========
+ const { mRCC, mRCE } = getZoneMods(modRCZone);
+ primeRCC *= mRCC;
+ primeRCE *= mRCE;
+
+ // UI zones
+ document.getElementById('primeChapZonesRCC').innerHTML =
+ 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+ document.getElementById('primeChapZonesRCE').innerHTML =
+ 'Prime RCE : ' + primeRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ // ========= Étape Engagements complémentaires (×) =========
+ const result = calcEngagCompl(modRCEngagCompl, primeRCC);
+ primeRCC = result.prime;
+
+ // UI engagements
+ document.getElementById('primeEngValue').innerText =
+ 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ const infoContainer = document.getElementById('primeEngInfos');
+ infoContainer.innerHTML = "";
+ result.infos.forEach(msg => {
+ const p = document.createElement("p");
+ p.style.color = "#e53935";
+ p.style.fontWeight = "300";
+ p.style.fontSize = "0.85em";
+ p.style.marginTop = "5px";
+ p.style.fontStyle = "italic";
+ p.innerText = msg;
+ infoContainer.appendChild(p);
+ }); // non necessaire, mais garder si utile, car fonctionne a 100%
+
+ // ========= Étape Garanties additionnelles (RCE uniquement) =========
+ const garAdd = calcGarAdd(modRCGarAdd, primeRCC, primeRCE);
+ // primeRCC reste inchangée (TPPC appliquée plus tard)
+ primeRCE = garAdd.primeRCE; // RCE avec Station lavage, Garage, CSE
+
+ // UI RCC
+ const blocRCC = document.getElementById('primeChapGarAddRCC');
+ blocRCC.innerHTML = 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+ garAdd.infosRCC.forEach(msg => {
+ const p = document.createElement("p");
+ p.style.color = "#e53935";
+ p.style.fontWeight = "300";
+ p.style.fontSize = "0.85em";
+ p.style.marginTop = "5px";
+ p.style.fontStyle = "italic";
+ p.innerText = msg;
+ blocRCC.appendChild(p);
+ });// toujours inutile, pas necessaire
+
+ // UI RCE
+ const blocRCE = document.getElementById('primeChapGarAddRCE');
+ blocRCE.innerHTML = 'Prime RCE : ' + primeRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+ garAdd.infosRCE.forEach(msg => {
+ const p = document.createElement("p");
+ p.style.color = "#e53935";
+ p.style.fontWeight = "300";
+ p.style.fontSize = "0.85em";
+ p.style.marginTop = "5px";
+ p.style.fontStyle = "italic";
+ p.innerText = msg;
+ blocRCE.appendChild(p);
+ }); // toujours inutile, pas necessaire
+
+ // ========= Étape Sinistres =========
+ const sin = calcSinistre(modRCSinistre, primeRCC, primeRCE);
+ primeRCC = sin.primeRCC;
+ primeRCE = sin.primeRCE;
+
+ // ========= Sauvegarder les primes BASE pour les tarifettes (après sinistre, avant franchise) =========
+ const primeRCCavantFranchise = primeRCC;
+ const primeRCEavantFranchise = primeRCE;
+
+ // Les totaux RCC et RCE sont maintenant prêts pour les franchises
+ const totalRCC = primeRCC;
+ const totalRCE = primeRCE;
+
+ // PJ (calculée dans calcTarifettes selon prime totale)
+ primePJ = 0;
+
+ primeGlobal = totalRCC + totalRCE + primePJ;
+
+ // UI
+ document.getElementById('modCA').innerHTML =
+ 'Modulation CA :
x ' + modCA.toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
+
+ const activiteMap = {
+ "Voiturier / Loueur": "Voiturier/Loueur",
+ "Commissionnaire de Transport": "Commissionnaire de Transport",
+ "Déménageur": "Déménageur",
+ "Logistique": "Logistique",
+ "Autocariste": "Autocariste",
+ "Autres activites": "Autres activites"
+ };
+
+ function getSelectedActivites() {
+ const activites = [];
+ document.querySelectorAll('label input[type="checkbox"]:checked').forEach(cb => {
+ const span = cb.parentElement.querySelector('span');
+ if (span) {
+ const labelText = span.textContent.trim();
+ if (activiteMap[labelText]) {
+ activites.push(activiteMap[labelText]);
+ }
+ }
+ });
+ return activites;
+ }
+
+
+ const activites = getSelectedActivites();
+
+ return {
+ CA,
+ activites,
+ primeRCC: totalRCC,
+ primeRCE: totalRCE,
+ primeRCCbase: primeRCCavantFranchise,
+ primeRCEbase: primeRCEavantFranchise,
+ primePJ,
+ primeGlobal
+ };
+ }
+
+ function calcForfaitaire() {
+ // ========= Variables centrales =========
+ let primeBaseRCC = 0;
+ let primeBaseRCE = 0;
+ let primeRCC = 0;
+ let primeRCE = 0;
+ let primePJ = 0;
+ let primeGlobal = 0;
+
+ // Tableaux de travail par activité
+ let primeBaseRCCparAct = [];
+ let primeBaseRCEparAct = [];
+
+ // ========= Récupération du nombre de véhicules =========
+ const nbrVehicule = toNumber(document.getElementById('nbrVehicule')?.value);
+ // Déterminer si c'est 1 ou 2 véhicules (par défaut 1)
+ const nbVehiculeKey = (nbrVehicule === 2) ? "deuxVehicules" : "unVehicule";
+
+ // ========= Étape Activités (primes forfaitaires de base) =========
+ const selections = getSelectedActivities();
+
+ selections.forEach(activity => {
+ const typeActivite = activity.typeActivite;
+ const inputElement = document.querySelector(
+ `input[name="selectAct${typeActivite}"], select[name="selectAct${typeActivite}"]`
+ );
+
+ if (inputElement) {
+ const capitalSaisi = toNumber(inputElement.value);
+
+ if (capitalSaisi <= 0) {
+ return; // Skip cette activité
+ }
+
+ // Récupération de la prime forfaitaire RCC
+ const grilleActRCC = modRCActRCC.forfaitaire[typeActivite];
+ if (grilleActRCC) {
+ const tranches = Object.keys(grilleActRCC).map(Number).sort((a, b) => a - b);
+ const tranche = findClosestTranche(capitalSaisi, tranches);
+ const primeData = grilleActRCC[tranche];
+
+ if (primeData && typeof primeData[nbVehiculeKey] === 'number') {
+ const primeBase = primeData[nbVehiculeKey];
+ primeBaseRCCparAct.push({
+ typeActivite: typeActivite,
+ primeBase: primeBase
+ });
+
+ // Affichage du taux (ici c'est une prime fixe)
+ const rccDiv = document.getElementById("tauxBaseRCCact" + typeActivite);
+ if (rccDiv) {
+ rccDiv.innerText = "RCC : " + primeBase.toFixed(2) + " €";
+ }
+
+ // Info tranche si différente
+ if (capitalSaisi !== tranche) {
+ const rowDiv = inputElement.closest('.row');
+ if (rowDiv) {
+ const oldInfo = rowDiv.querySelector('.info-tranche');
+ if (oldInfo) oldInfo.remove();
+
+ const infoSpan = document.createElement('span');
+ infoSpan.className = 'info-tranche';
+ infoSpan.style.color = '#e53935';
+ infoSpan.style.fontSize = '0.8em';
+ infoSpan.style.fontStyle = 'italic';
+ infoSpan.innerText = `(tranche ${tranche.toLocaleString('fr-FR')} €)`;
+
+ rowDiv.appendChild(infoSpan);
+ }
+ }
+ }
+ }
+
+ // Récupération de la prime forfaitaire RCE si coché
+ if (document.getElementById('checkRCE')?.checked) {
+ const grilleActRCE = modRCActRCE.forfaitaire[typeActivite];
+ if (grilleActRCE && grilleActRCE[nbVehiculeKey]) {
+ const primeBaseRCE_val = grilleActRCE[nbVehiculeKey].optimale || 0;
+ primeBaseRCEparAct.push({
+ typeActivite: typeActivite,
+ primeBase: primeBaseRCE_val
+ });
+
+ // Affichage
+ const rceDiv = document.getElementById("tauxBaseRCEact" + typeActivite);
+ if (rceDiv) {
+ rceDiv.innerText = "RCE : " + primeBaseRCE_val.toFixed(2) + " €";
+ }
+ }
+ }
+ }
+ });
+
+ // Sommes des primes de base
+ primeBaseRCC = primeBaseRCCparAct.reduce((total, item) => total + item.primeBase, 0);
+ primeBaseRCE = primeBaseRCEparAct.reduce((total, item) => total + item.primeBase, 0);
+
+ // UI (affichage)
+ document.getElementById('primeChapActRCC').innerHTML =
+ 'Prime de base RCC : ' + primeBaseRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+
+ document.getElementById('primeChapActRCE').innerHTML =
+ 'Prime de base RCE : ' + primeBaseRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+
+ // ========= Étape Activités complémentaires =========
+ for (let i = 0; i < primeBaseRCCparAct.length; i++) {
+ primeBaseRCCparAct[i].primeBase *= calcModActCompl(modRCActCompl, primeBaseRCCparAct[i].typeActivite, "RCC", "forfaitaire");
+ }
+
+ if (document.getElementById('checkRCE')?.checked) {
+ for (let i = 0; i < primeBaseRCEparAct.length; i++) {
+ primeBaseRCEparAct[i].primeBase *= calcModActCompl(
+ modRCActCompl,
+ primeBaseRCEparAct[i].typeActivite,
+ "RCE",
+ "forfaitaire"
+ );
+ }
+ }
+
+ // Re-sommes
+ primeBaseRCC = primeBaseRCCparAct.reduce((total, item) => total + item.primeBase, 0);
+ primeBaseRCE = primeBaseRCEparAct.reduce((total, item) => total + item.primeBase, 0);
+
+ document.getElementById('primeChapActComplRCC').innerHTML =
+ 'Prime RCC : ' + primeBaseRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+ document.getElementById('primeChapActComplRCE').innerHTML =
+ 'Prime RCE : ' + primeBaseRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ // ========= Étape Marchandises (× par activité) =========
+ for (let i = 0; i < primeBaseRCCparAct.length; i++) {
+ const actName = primeBaseRCCparAct[i].typeActivite;
+ const modMar = calcModMarchandises(modRCMar, actName, "RCC", "forfaitaire");
+ primeBaseRCCparAct[i].primeBase = primeBaseRCCparAct[i].primeBase * modMar;
+ }
+
+ if (document.getElementById('checkRCE')?.checked) {
+ for (let i = 0; i < primeBaseRCEparAct.length; i++) {
+ const actName = primeBaseRCEparAct[i].typeActivite;
+ const modMar = calcModMarchandises(modRCMar, actName, "RCE", "forfaitaire");
+ primeBaseRCEparAct[i].primeBase = primeBaseRCEparAct[i].primeBase * modMar;
+ }
+ }
+
+ // Recalcule totaux après mods marchandises
+ primeBaseRCC = primeBaseRCCparAct.reduce((total, item) => total + item.primeBase, 0);
+ primeBaseRCE = primeBaseRCEparAct.reduce((total, item) => total + item.primeBase, 0);
+
+ primeRCC = primeBaseRCC;
+ primeRCE = primeBaseRCE;
+
+ // UI marchandises
+ document.getElementById('primeChapMarchRCC').innerHTML =
+ 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+ document.getElementById('primeChapMarchRCE').innerHTML =
+ 'Prime RCE : ' + primeRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ // ========= Étape Zones (× max RCC / × max RCE) =========
+ const { mRCC, mRCE } = getZoneMods(modRCZone);
+ primeRCC *= mRCC;
+ primeRCE *= mRCE;
+
+ // UI zones
+ document.getElementById('primeChapZonesRCC').innerHTML =
+ 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+ document.getElementById('primeChapZonesRCE').innerHTML =
+ 'Prime RCE : ' + primeRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ // ========= Étape Engagements complémentaires (×) =========
+ const result = calcEngagCompl(modRCEngagCompl, primeRCC);
+ primeRCC = result.prime;
+
+ // UI engagements
+ document.getElementById('primeEngValue').innerText =
+ 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' });
+
+ const infoContainer = document.getElementById('primeEngInfos');
+ infoContainer.innerHTML = "";
+ result.infos.forEach(msg => {
+ const p = document.createElement("p");
+ p.style.color = "#e53935";
+ p.style.fontWeight = "300";
+ p.style.fontSize = "0.85em";
+ p.style.marginTop = "5px";
+ p.style.fontStyle = "italic";
+ p.innerText = msg;
+ infoContainer.appendChild(p);
+ });
+
+ // ========= Étape Garanties additionnelles (RCE uniquement) =========
+ const garAdd = calcGarAdd(modRCGarAdd, primeRCC, primeRCE);
+ primeRCE = garAdd.primeRCE;
+
+ // UI RCC
+ const blocRCC = document.getElementById('primeChapGarAddRCC');
+ blocRCC.innerHTML = 'Prime RCC : ' + primeRCC.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+ garAdd.infosRCC.forEach(msg => {
+ const p = document.createElement("p");
+ p.style.color = "#e53935";
+ p.style.fontWeight = "300";
+ p.style.fontSize = "0.85em";
+ p.style.marginTop = "5px";
+ p.style.fontStyle = "italic";
+ p.innerText = msg;
+ blocRCC.appendChild(p);
+ });
+
+ // UI RCE
+ const blocRCE = document.getElementById('primeChapGarAddRCE');
+ blocRCE.innerHTML = 'Prime RCE : ' + primeRCE.toLocaleString('fr-FR', { style: 'currency', currency: 'EUR' }) + '';
+ garAdd.infosRCE.forEach(msg => {
+ const p = document.createElement("p");
+ p.style.color = "#e53935";
+ p.style.fontWeight = "300";
+ p.style.fontSize = "0.85em";
+ p.style.marginTop = "5px";
+ p.style.fontStyle = "italic";
+ p.innerText = msg;
+ blocRCE.appendChild(p);
+ });
+
+ // ========= Étape Sinistres (OPTIONNEL en forfaitaire - basé sur CA) =========
+ // Note: En forfaitaire, normalement pas de sinistre car pas de CA
+ // Mais on garde la logique au cas où il y aurait un CA saisi
+ const CA = toNumber(document.getElementById("chiffreAffaire")?.value);
+ if (CA > 0) {
+ const sin = calcSinistre(modRCSinistre, primeRCC, primeRCE);
+ primeRCC = sin.primeRCC;
+ primeRCE = sin.primeRCE;
+ }
+
+ // ========= Sauvegarder les primes BASE pour les tarifettes =========
+ const primeRCCavantFranchise = primeRCC;
+ const primeRCEavantFranchise = primeRCE;
+
+ // Les totaux RCC et RCE sont maintenant prêts
+ const totalRCC = primeRCC;
+ const totalRCE = primeRCE;
+
+ // PJ (calculée dans calcTarifettes selon prime totale)
+ primePJ = 0;
+
+ primeGlobal = totalRCC + totalRCE + primePJ;
+
+ const activiteMap = {
+ "Voiturier / Loueur": "Voiturier/Loueur",
+ "Commissionnaire de Transport": "Commissionnaire de Transport",
+ "Déménageur": "Déménageur",
+ "Logistique": "Logistique",
+ "Autocariste": "Autocariste",
+ "Autres activites": "Autres activites"
+ };
+
+ function getSelectedActivites() {
+ const activites = [];
+ document.querySelectorAll('label input[type="checkbox"]:checked').forEach(cb => {
+ const span = cb.parentElement.querySelector('span');
+ if (span) {
+ const labelText = span.textContent.trim();
+ if (activiteMap[labelText]) {
+ activites.push(activiteMap[labelText]);
+ }
+ }
+ });
+ return activites;
+ }
+
+ const activites = getSelectedActivites();
+
+ return {
+ CA: CA || 0,
+ activites,
+ primeRCC: totalRCC,
+ primeRCE: totalRCE,
+ primeRCCbase: primeRCCavantFranchise,
+ primeRCEbase: primeRCEavantFranchise,
+ primePJ,
+ primeGlobal
+ };
+ }
+
+ function getZoneMods(modRCZone) {
+ const zones = [
+ { id: 'zone1', label: 'France Métropolitaine et pays limitrophes' },
+ { id: 'zone2', label: 'Union Européenne' },
+ { id: 'zone3', label: 'Autres pays européens sauf Russie et Ukraine (y compris UK et Norvège)' },
+ { id: 'zone4', label: 'Pays du Maghreb et Amérique du Nord ( USA / Canada / Mexique )' },
+ { id: 'zone5', label: 'Amérique Centrale et Sud / Caraïbes, Asie et Océanie' },
+ { id: 'zone6', label: 'Afrique Hors Maghreb / Proche Orient / Moyen Orient' }
+ ];
+ let mRCC = 1, mRCE = 1;
+ zones.forEach(z => {
+ const cb = document.getElementById(z.id);
+ if (cb && cb.checked) {
+ const m = modRCZone[z.label];
+ if (m) {
+ if (typeof m.modRCC === 'number') mRCC = Math.max(mRCC, m.modRCC);
+ if (typeof m.modRCE === 'number') mRCE = Math.max(mRCE, m.modRCE);
+ }
+ }
+ });
+ return { mRCC, mRCE };
+ }
+
+
+ function handleLoadHistoriqueBtn() {
+ var selectedId = document.getElementById('idSelect').value;
+
+ if (selectedId != "") {
+ fetch(`/contrat/update/${contrat.produit}/${contrat.id}/${selectedId}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.valid) {
+ window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=projet`;
+ } else {
+ console.log('Echec lors de la mise à jour de la relation id contrat - id client :', data);
+ }
+ });
+ }
+ }
+
+ //Appel pour recevoir les constantes
+ async function constantsJSON() {
+ try {
+ const responsesJSON = await Promise.all([
+ fetch('/rc/modulo/CARC'),
+ fetch('/rc/modulo/activiteRCC'),
+ fetch('/rc/modulo/activiteRCE'),
+ fetch('/rc/modulo/activiteComplRC'),
+ fetch('/rc/modulo/marchandiseRC'),
+ fetch('/rc/modulo/zoneRC'),
+ fetch('/rc/modulo/engagComplRC'),
+ fetch('/rc/modulo/garAdditionelRC'),
+ fetch('/rc/modulo/sinistreRC'),
+ fetch('/rc/modulo/franchiseRC'),
+ fetch('/rc/modulo/primeMiniRC')
+ ]);
+ const jsonResponses = await Promise.all(responsesJSON.map(r => r.json())); // Récupérer toutes les réponses JSON
+
+ // Extraire la valeur objRetourne de chaque réponse
+ [
+ modRCCA,
+ modRCActRCC,
+ modRCActRCE,
+ modRCActCompl,
+ modRCMar,
+ modRCZone,
+ modRCEngagCompl,
+ modRCGarAdd,
+ modRCSinistre,
+ modRCFranchise,
+ modRCPrimeMini
+ ] = jsonResponses.map(response => response.objRetourne); // Adapter pour extraire objRetourne
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ function resetInputs() {
+ // Sélection des éléments input pourcentage
+ const pourcentInputs = document.querySelectorAll('.input-pourcent');
+ // Calculer le nombre d'inputs visibles
+ const visibleInputs = Array.from(pourcentInputs).filter(input => input.offsetParent != null);
+
+ // Vérifier s'il y a des inputs visibles
+ if (visibleInputs.length > 0) {
+ // Réinitialiser les valeurs
+ visibleInputs.forEach(p => {
+ p.value = ''; // Réinitialiser la valeur
+ const correspondingIsSetInput = document.getElementById('isSet' + p.id.replace('pourcent', ''));
+ correspondingIsSetInput.value = 'false'; // Réinitialiser isSet
+ p.classList.remove('set'); // Remettre le fond d'origine
+ });
+
+ // Calculer le pourcentage à répartir
+ const pourcentToAdd = (100 / visibleInputs.length).toFixed(2);
+
+ // Répartir le pourcentage entre les inputs visibles
+ visibleInputs.forEach(p => {
+ p.value = pourcentToAdd; // Assigner la valeur calculée
+ // Ne pas changer isSet à true ici
+ // correspondingIsSetInput.value reste 'false'
+ });
+
+ // Mettre à jour l'indicateur
+ updatePercentageIndicator(100);
+ }
+ }
+
+ function get_taux_base_RCC(grille_mod_RCC, cot) {
+ const tauxOptimaux = [];
+ const selections = getSelectedActivities();
+
+ selections.forEach(activity => {
+ const typeActivite = activity.typeActivite;
+ const inputElement = document.querySelector(
+ `input[name="selectAct${typeActivite}"], select[name="selectAct${typeActivite}"]`
+ );
+
+ if (inputElement) {
+ const capitalSaisi = toNumber(inputElement.value);
+
+ if (capitalSaisi <= 0) {
+ return;
+ }
+
+ if (cot === 'revisable') {
+ const grilleAct = grille_mod_RCC.revisable[typeActivite];
+ if (grilleAct) {
+ const tranches = Object.keys(grilleAct).map(Number).sort((a, b) => a - b);
+ const tranche = findClosestTranche(capitalSaisi, tranches);
+ const tauxBase = grilleAct[tranche];
+
+ if (typeof tauxBase === 'number') {
+ // 1. Mettre à jour la div RCC avec uniquement le texte principal
+ const rccDiv = document.getElementById("tauxBaseRCCact" + typeActivite);
+ if (rccDiv) {
+ rccDiv.innerText = "RCC : " + tauxBase.toFixed(3) + " %";
+ }
+ if (capitalSaisi !== tranche) {
+ const rowDiv = inputElement.closest('.row');
+ if (rowDiv) {
+ const oldInfo = rowDiv.querySelector('.info-tranche');
+ if (oldInfo) oldInfo.remove();
+
+ const infoSpan = document.createElement('span');
+ infoSpan.className = 'info-tranche';
+ infoSpan.style.color = '#e53935';
+ infoSpan.style.fontSize = '0.8em';
+ infoSpan.style.fontStyle = 'italic';
+ infoSpan.innerText = `(tranche ${tranche.toLocaleString('fr-FR')} €)`;
+
+ rowDiv.appendChild(infoSpan);
+ }
+ }
+
+ tauxOptimaux.push({ typeActivite, capital: tranche, tauxBase });
+ }
+ }
+ } else if (cot === 'forfaitaire') {
+ console.log("TODO FORFAITAIRE");
+ }
+ }
+ });
+
+ return tauxOptimaux;
+ }
+
+
+ function get_taux_base_RCE(grille_mod_RCE, cot) {
+ const tauxOptimaux = [];
+ const selections = getSelectedActivities();
+
+ selections.forEach(activity => {
+ const typeActivite = activity.typeActivite;
+ const inputElement = document.querySelector(`input[name="selectAct${typeActivite}"], select[name="selectAct${typeActivite}"]`);
+
+ if (inputElement) {
+ const capitalSaisi = toNumber(inputElement.value);
+
+ // Si rien n'est saisi ou invalide, ignorer
+ if (capitalSaisi <= 0) {
+ return;
+ }
+
+ // Traitement selon le type de cotisation
+ if (cot == 'revisable') {
+ if (grille_mod_RCE.revisable[typeActivite]) {
+ const tauxBase = grille_mod_RCE.revisable[typeActivite]["optimale"];
+ document.getElementById("tauxBaseRCEact" + typeActivite).innerHTML = "RCE : " + tauxBase.toFixed(3) + " %"
+ tauxOptimaux.push({ typeActivite, tauxBase });
+ }
+ } else if (cot == 'forfaitaire') {
+ console.log("TODO FORFAITAIRE"); // ehhh
+ }
+ }
+ });
+
+ return tauxOptimaux;
+ }
+
+ function getSelectedActivities() {
+ const selections = [];
+
+ // Récupérer le nombre de véhicules depuis l'input
+ const nombreVehicules = document.getElementById('nbrVehicule').value || null; // Valeur par défaut à null si vide
+
+ if (document.getElementById('checkVoiturier').checked) {
+ const listActComplChecked = [];
+ const listMarChecked = [];
+
+ // Récupérer les activités complémentaires
+ const actComplCheckboxes = document.querySelectorAll('[name="actComplVoiturier/Loueur"] input[type="checkbox"]:checked');
+ actComplCheckboxes.forEach(checkbox => {
+ listActComplChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ // Récupérer les marchandises
+ const marComplCheckboxes = document.querySelectorAll('[name="marVoiturier/Loueur"] input[type="checkbox"]:checked');
+ marComplCheckboxes.forEach(checkbox => {
+ listMarChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ selections.push({
+ typeActivite: "Voiturier/Loueur",
+ nombreVehicules: nombreVehicules,
+ listActComplChecked: listActComplChecked,
+ listMarChecked: listMarChecked
+ });
+ }
+
+ if (document.getElementById('checkCommissionnaire').checked) {
+ const listActComplChecked = [];
+ const listMarChecked = [];
+
+ // Récupérer les activités complémentaires
+ const actComplCheckboxes = document.querySelectorAll('[name="actComplCommissionnaire de Transport"] input[type="checkbox"]:checked');
+ actComplCheckboxes.forEach(checkbox => {
+ listActComplChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ // Récupérer les marchandises
+ const marComplCheckboxes = document.querySelectorAll('[name="marCommissionnaire de Transport"] input[type="checkbox"]:checked');
+ marComplCheckboxes.forEach(checkbox => {
+ listMarChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ selections.push({
+ typeActivite: "Commissionnaire de Transport",
+ nombreVehicules: null,
+ listActComplChecked: listActComplChecked,
+ listMarChecked: listMarChecked
+ });
+ }
+
+ if (document.getElementById('checkDemenageur').checked) {
+ const listActComplChecked = [];
+ const listMarChecked = [];
+
+ // Récupérer les activités complémentaires
+ const actComplCheckboxes = document.querySelectorAll('[name="actComplDéménageur"] input[type="checkbox"]:checked');
+ actComplCheckboxes.forEach(checkbox => {
+ listActComplChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ // Récupérer les marchandises
+ const marComplCheckboxes = document.querySelectorAll('[name="marDéménageur"] input[type="checkbox"]:checked');
+ marComplCheckboxes.forEach(checkbox => {
+ listMarChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ selections.push({
+ typeActivite: "Déménageur",
+ nombreVehicules: nombreVehicules,
+ listActComplChecked: listActComplChecked,
+ listMarChecked: listMarChecked
+ });
+ }
+
+ if (document.getElementById('checkLogistique').checked) {
+ const listActComplChecked = [];
+ const listMarChecked = [];
+
+ // Récupérer les activités complémentaires
+ const actComplCheckboxes = document.querySelectorAll('[name="actComplLogistique"] input[type="checkbox"]:checked');
+ actComplCheckboxes.forEach(checkbox => {
+ listActComplChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ // Récupérer les marchandises
+ const marComplCheckboxes = document.querySelectorAll('[name="marLogistique"] input[type="checkbox"]:checked');
+ marComplCheckboxes.forEach(checkbox => {
+ listMarChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ selections.push({
+ typeActivite: "Logistique",
+ nombreVehicules: null,
+ listActComplChecked: listActComplChecked,
+ listMarChecked: listMarChecked
+ });
+ }
+
+ if (document.getElementById('checkAutres').checked) {
+ const listActComplChecked = [];
+ const listMarChecked = [];
+
+ // Récupérer les activités complémentaires
+ const actComplCheckboxes = document.querySelectorAll('[name="actComplAutres activites"] input[type="checkbox"]:checked');
+ actComplCheckboxes.forEach(checkbox => {
+ listActComplChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ // Récupérer les marchandises
+ const marComplCheckboxes = document.querySelectorAll('[name="marAutres activites"] input[type="checkbox"]:checked');
+ marComplCheckboxes.forEach(checkbox => {
+ listMarChecked.push(checkbox.nextElementSibling.textContent.trim());
+ });
+
+ selections.push({
+ typeActivite: "Autres activites",
+ nombreVehicules: nombreVehicules,
+ listActComplChecked: listActComplChecked,
+ listMarChecked: listMarChecked
+ });
+ }
+ // Ajoutez d'autres cas si nécessaire
+
+ return selections;
+ }
+
+ // Fonction pour sauvegarder les données tarifRC dans la base
+ async function saveTarifRC() {
+ if (!rc || !contrat) {
+ console.error('Données manquantes pour sauvegarder le tarif RC');
+ return { valid: false, message: 'Données manquantes' };
+ }
+
+ // Préparer les références aux champs selon les différents templates possibles
+ const caInput = getElementByIdFlexible('CA') || getElementByIdFlexible('chiffreAffaire');
+ const nbVehInput = getElementByIdFlexible('nbVehicules') || getElementByIdFlexible('nbrVehicule');
+
+ const capitalVoiturierInput = getElementByIdFlexible('capitalVoiturier') || document.querySelector('input[name="selectActVoiturier/Loueur"]');
+ const capitalCommissionnaireInput = getElementByIdFlexible('capitalCommissionnaire') || document.querySelector('input[name="selectActCommissionnaire de Transport"]') || document.querySelector('input[name="selectActCommissionnaireDeTransport"]');
+ const capitalDemenageurInput = getElementByIdFlexible('capitalDemenageur') || document.querySelector('input[name="selectActDéménageur"]') || document.querySelector('input[name="selectActDemenageur"]');
+ const capitalLogistiqueInput = getElementByIdFlexible('capitalLogistique') || document.querySelector('input[name="selectActLogistique"]');
+ const capitalAutocaristeInput = getElementByIdFlexible('capitalAutocariste') || document.querySelector('input[name="selectActAutocariste"]');
+ const capitalAutresInput = getElementByIdFlexible('capitalAutres') || document.querySelector('input[name="selectActAutres activites"]') || document.querySelector('input[name="selectActAutresActivites"]');
+
+ const pctVoiturierInput = getElementByIdFlexible('pourcent_voiturier') || getElementByIdFlexible('pourcentVoiturier/Loueur');
+ const pctCommissionnaireInput = getElementByIdFlexible('pourcent_commissionnaire') || getElementByIdFlexible('pourcentCommissionnaire de Transport') || getElementByIdFlexible('pourcentCommissionnaireDeTransport');
+ const pctDemenageurInput = getElementByIdFlexible('pourcent_demenageur') || getElementByIdFlexible('pourcentDéménageur') || getElementByIdFlexible('pourcentDemenageur');
+ const pctLogistiqueInput = getElementByIdFlexible('pourcent_logistique') || getElementByIdFlexible('pourcentLogistique');
+ const pctAutocaristeInput = getElementByIdFlexible('pourcent_autocariste') || getElementByIdFlexible('pourcentAutocariste');
+ const pctAutresInput = getElementByIdFlexible('pourcent_autres') || getElementByIdFlexible('pourcentAutres activites') || getElementByIdFlexible('pourcentAutresActivites');
+
+ // ===== ÉTAPE 1: Collecter les données communes à sauvegarder dans RC principal =====
+ const rcMainData = {
+ typeCotisation: document.querySelector('input[name="cotisation"]:checked')?.value,
+ chiffreAffaires: toNumber(caInput?.value ?? caInput?.textContent),
+ nombreVehicules: Math.max(0, Math.round(toNumber(nbVehInput?.value ?? nbVehInput?.textContent))),
+ checkRCE: document.getElementById('checkRCE')?.checked || false,
+ checkVoiturier: document.getElementById('checkVoiturier')?.checked || false,
+ capitalVoiturier: toNumber(capitalVoiturierInput?.value ?? capitalVoiturierInput?.textContent),
+ checkCommissionnaire: document.getElementById('checkCommissionnaire')?.checked || false,
+ capitalCommissionnaire: toNumber(capitalCommissionnaireInput?.value ?? capitalCommissionnaireInput?.textContent),
+ checkDemenageur: document.getElementById('checkDemenageur')?.checked || false,
+ capitalDemenageur: toNumber(capitalDemenageurInput?.value ?? capitalDemenageurInput?.textContent),
+ checkLogistique: document.getElementById('checkLogistique')?.checked || false,
+ capitalLogistique: toNumber(capitalLogistiqueInput?.value ?? capitalLogistiqueInput?.textContent),
+ checkAutocariste: document.getElementById('checkAutocariste')?.checked || false,
+ capitalAutocariste: toNumber(capitalAutocaristeInput?.value ?? capitalAutocaristeInput?.textContent),
+ checkAutres: document.getElementById('checkAutres')?.checked || false,
+ capitalAutres: toNumber(capitalAutresInput?.value ?? capitalAutresInput?.textContent),
+
+ // Activités complémentaires (JSON) - collectées avec les bons noms
+ actComplVoiturier: collectActivitesComplJSON('voiturier'),
+ actComplCommissionnaire: collectActivitesComplJSON('commissionnaire'),
+ actComplDemenageur: collectActivitesComplJSON('demenageur'),
+ actComplLogistique: collectActivitesComplJSON('logistique'),
+
+ // Marchandises (JSON) - collectées avec les bons noms
+ marchandisesVoiturier: collectMarchandisesJSON('voiturier'),
+ marchandisesCommissionnaire: collectMarchandisesJSON('commissionnaire'),
+ marchandisesDemenageur: collectMarchandisesJSON('demenageur'),
+ marchandisesLogistique: collectMarchandisesJSON('logistique'),
+ marchandisesAutocariste: collectMarchandisesJSON('autocariste'),
+ marchandisesAutres: collectMarchandisesJSON('autres'),
+
+ // Zones
+ zone1: document.getElementById('zone1')?.checked || false,
+ zone2: document.getElementById('zone2')?.checked || false,
+ zone3: document.getElementById('zone3')?.checked || false,
+ zone4: document.getElementById('zone4')?.checked || false,
+ zone5: document.getElementById('zone5')?.checked || false,
+ zone6: document.getElementById('zone6')?.checked || false,
+
+ //commentaire
+ commentaire: document.getElementById('commentaire')?.value,
+ };
+
+ // ===== LOGS DE DÉBOGAGE =====
+ console.log('📊 === DÉBUT SAUVEGARDE TARIF RC ===');
+ console.log('🔍 rcMainData:', rcMainData);
+
+ // ===== ÉTAPE 2: Collecter les résultats de calculs pour tarifRC =====
+ const tarifRCData = {
+ sinistre: toNumber(document.getElementById('sinistre')?.value),
+ pourcentageVoiturier: toNumber(pctVoiturierInput?.value ?? pctVoiturierInput?.textContent),
+ isSetVoiturier: Boolean(pctVoiturierInput?.value?.trim()),
+ pourcentageCommissionnaire: toNumber(pctCommissionnaireInput?.value ?? pctCommissionnaireInput?.textContent),
+ isSetCommissionnaire: Boolean(pctCommissionnaireInput?.value?.trim()),
+ pourcentageDemenageur: toNumber(pctDemenageurInput?.value ?? pctDemenageurInput?.textContent),
+ isSetDemenageur: Boolean(pctDemenageurInput?.value?.trim()),
+ pourcentageLogistique: toNumber(pctLogistiqueInput?.value ?? pctLogistiqueInput?.textContent),
+ isSetLogistique: Boolean(pctLogistiqueInput?.value?.trim()),
+ pourcentageAutocariste: toNumber(pctAutocaristeInput?.value ?? pctAutocaristeInput?.textContent),
+ isSetAutocariste: Boolean(pctAutocaristeInput?.value?.trim()),
+ pourcentageAutres: toNumber(pctAutresInput?.value ?? pctAutresInput?.textContent),
+ isSetAutres: Boolean(pctAutresInput?.value?.trim()),
+
+ // Tarifs pour franchise 250
+ primeRCC_250: toNumber(document.getElementById('rccFr250')?.textContent),
+ primeRCE_250: toNumber(document.getElementById('rceFr250')?.textContent),
+ primePJ_250: toNumber(document.getElementById('pjFr250')?.textContent),
+ primeTotal_250: toNumber(document.getElementById('priceFr250')?.textContent),
+ tauxRCC_250: toNumber(document.getElementById('tauxRccFr250')?.textContent),
+ tauxRCE_250: toNumber(document.getElementById('tauxRceFr250')?.textContent),
+ tauxGlobal_250: toNumber(document.getElementById('tauxGlobalFr250')?.textContent),
+
+ // Tarifs pour franchise 400
+ primeRCC_400: toNumber(document.getElementById('rccFr400')?.textContent),
+ primeRCE_400: toNumber(document.getElementById('rceFr400')?.textContent),
+ primePJ_400: toNumber(document.getElementById('pjFr400')?.textContent),
+ primeTotal_400: toNumber(document.getElementById('priceFr400')?.textContent),
+ tauxRCC_400: toNumber(document.getElementById('tauxRccFr400')?.textContent),
+ tauxRCE_400: toNumber(document.getElementById('tauxRceFr400')?.textContent),
+ tauxGlobal_400: toNumber(document.getElementById('tauxGlobalFr400')?.textContent),
+
+ // Tarifs pour franchise 2000
+ primeRCC_2000: toNumber(document.getElementById('rccFr2000')?.textContent),
+ primeRCE_2000: toNumber(document.getElementById('rceFr2000')?.textContent),
+ primePJ_2000: toNumber(document.getElementById('pjFr2000')?.textContent),
+ primeTotal_2000: toNumber(document.getElementById('priceFr2000')?.textContent),
+ tauxRCC_2000: toNumber(document.getElementById('tauxRccFr2000')?.textContent),
+ tauxRCE_2000: toNumber(document.getElementById('tauxRceFr2000')?.textContent),
+ tauxGlobal_2000: toNumber(document.getElementById('tauxGlobalFr2000')?.textContent),
+
+ // Franchise choisie
+ franchiseChoisie: window.franchiseChoisie || null,
+
+ // Engagements complémentaires (dans tarifRC, pas dans rc!)
+ checkDomImmat: document.getElementById('checkDomImmat')?.checked || false,
+ capitalDomImmat: toNumber(document.getElementById('inputDomImmat')?.value),
+ checkContConf: document.getElementById('checkContConf')?.checked || false,
+ capitalContConf: toNumber(document.getElementById('inputContConf')?.value),
+ checkDiffInv: document.getElementById('checkDiffInv')?.checked || false,
+ capitalDiffInv: toNumber(document.getElementById('inputDiffInv')?.value),
+
+ // Garanties additionnelles (dans tarifRC, pas dans rc!)
+ checkStationLavage: document.getElementById('checkStationLavage')?.checked || false,
+ checkGarageInterne: document.getElementById('checkGarageInterne')?.checked || false,
+ checkCSE: document.getElementById('checkCSE')?.checked || false,
+ checkTPPC: document.getElementById('checkTPPC')?.checked || false,
+ capitalTPPC: toNumber(document.getElementById('selTPPCcapital')?.value),
+ vehiculesTPPC: Math.max(0, Math.round(toNumber(document.getElementById('selTPPCveh')?.value))),
+ checkPJ: document.getElementById('checkPJ')?.checked || false,
+
+ tarifcommercial: toNumber(document.getElementById('tarifCom')?.value),
+ };
+
+ console.log('tarifRCData:', tarifRCData);
+
+ try {
+ let idTarifRC;
+ let rcId = rc?.id;
+
+ // ===== VÉRIFIER SI RC EXISTE, SINON LE CRÉER =====
+ if (!rcId) {
+ console.log('RC n\'existe pas encore, création en cours...');
+ const createRCResponse = await fetch(`/rc/create`, {
+ method: 'POST',
+ body: JSON.stringify({ typeCotisation: rcMainData.typeCotisation }),
+ headers: { 'Content-Type': 'application/json' },
+ });
+ const createRCData = await createRCResponse.json();
+
+ if (createRCData.valid) {
+ rcId = createRCData.rc.id;
+ // Mettre à jour le contrat avec le nouvel ID RC
+ await fetch(`/contrat/update/${contrat.produit}/${contrat.id}/${rcId}`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ });
+ } else {
+ console.error('Échec de la création de RC:', createRCData.message);
+ return { valid: false, message: 'Échec création RC' };
+ }
+ }
+
+ // ===== ÉTAPE 3: Sauvegarder/Mettre à jour tarifRC =====
+ if (tarif && tarif.id) {
+ // Mettre à jour un enregistrement tarifRC existant
+ console.log(`📝 Mise à jour tarifRC existant (ID: ${tarif.id})`);
+ const response = await fetch(`/rc/tarif/update/${tarif.id}`, {
+ method: 'POST',
+ body: JSON.stringify(tarifRCData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const data = await response.json();
+ console.log('📥 Réponse serveur tarifRC update:', data);
+ if (data.valid) {
+ idTarifRC = data.tarifRc.id;
+ } else {
+ console.error('❌ Échec de la mise à jour de tarifRC:', data.message);
+ return { valid: false, message: data.message };
+ }
+ } else {
+ // Créer un nouvel enregistrement tarifRC
+ console.log('📝 Création nouveau tarifRC');
+ const response = await fetch(`/rc/tarif/create`, {
+ method: 'POST',
+ body: JSON.stringify(tarifRCData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const data = await response.json();
+ console.log('📥 Réponse serveur tarifRC create:', data);
+ if (data.valid) {
+ idTarifRC = data.tarifRc.id;
+ } else {
+ console.error('❌ Échec de la création de tarifRC:', data.message);
+ return { valid: false, message: data.message };
+ }
+ }
+
+ // ===== ÉTAPE 4: Mettre à jour RC principal avec les données communes ET la référence tarifRC =====
+ rcMainData.tarifRC = idTarifRC; // Ajouter la référence à tarifRC
+
+ console.log(`📝 Mise à jour RC principal (ID: ${rcId}) avec référence tarifRC: ${idTarifRC}`);
+ console.log('🔍 Données envoyées pour RC:', rcMainData);
+
+ const updateRCResponse = await fetch(`/rc/update/${rcId}`, {
+ method: 'POST',
+ body: JSON.stringify(rcMainData),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const updateRCData = await updateRCResponse.json();
+ console.log('📥 Réponse serveur RC update:', updateRCData);
+
+ if (!updateRCData.valid) {
+ console.error('❌ Échec de la mise à jour de RC principal:', updateRCData.message);
+ return { valid: false, message: 'Échec mise à jour RC principal' };
+ }
+
+ console.log('✅ === TARIF RC SAUVEGARDÉ AVEC SUCCÈS ===');
+ console.log('✅ RC ID:', rcId, '| TarifRC ID:', idTarifRC);
+ return { valid: true, idTarifRC, idRC: rcId };
+ } catch (error) {
+ console.error('Erreur lors de la sauvegarde de tarifRC:', error);
+ return { valid: false, message: error.message };
+ }
+ }
+
+ // Fonction helper pour collecter les activités complémentaires
+ function collectActivitesComplJSON(typeActivite) {
+ let name;
+ switch(typeActivite.toLowerCase()) {
+ case 'voiturier':
+ name = 'actComplVoiturier/Loueur';
+ break;
+ case 'commissionnaire':
+ name = 'actComplCommissionnaire de Transport';
+ break;
+ case 'demenageur':
+ name = 'actComplDéménageur';
+ break;
+ case 'logistique':
+ name = 'actComplLogistique';
+ break;
+ default:
+ return JSON.stringify([]);
+ }
+
+ const checkboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]:checked`);
+ const activites = [];
+ checkboxes.forEach(cb => {
+ const text = cb.nextElementSibling ? cb.nextElementSibling.textContent.trim() : cb.value;
+ activites.push(text);
+ });
+ return JSON.stringify(activites);
+ }
+
+ // Fonction helper pour collecter les marchandises
+ function collectMarchandisesJSON(typeActivite) {
+ let name;
+ switch(typeActivite.toLowerCase()) {
+ case 'voiturier':
+ name = 'marVoiturier/Loueur';
+ break;
+ case 'commissionnaire':
+ name = 'marCommissionnaire de Transport';
+ break;
+ case 'demenageur':
+ name = 'marDéménageur';
+ break;
+ case 'logistique':
+ name = 'marLogistique';
+ break;
+ case 'autocariste':
+ name = 'marAutocariste';
+ break;
+ case 'autres':
+ name = 'marAutres activites';
+ break;
+ default:
+ return JSON.stringify([]);
+ }
+
+ const checkboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]:checked`);
+ const marchandises = [];
+ checkboxes.forEach(cb => {
+ const text = cb.nextElementSibling ? cb.nextElementSibling.textContent.trim() : cb.value;
+ marchandises.push(text);
+ });
+ return JSON.stringify(marchandises);
+ }
+
+ // Fonction pour gérer les clics sur les boutons de tariffettes
+ function setupTarifetteButtons() {
+ const tarifetteButtons = document.querySelectorAll('.franchise-card button[name]');
+ tarifetteButtons.forEach(button => {
+ button.addEventListener('click', async function(e) {
+ e.preventDefault();
+ const franchiseValue = this.getAttribute('name');
+
+ // Mettre à jour la variable globale et l'UI
+ window.franchiseChoisie = franchiseValue;
+ console.log(`Tariffette sélectionnée: ${franchiseValue}€`);
+
+ // Mettre en surbrillance la carte sélectionnée
+ document.querySelectorAll('.franchise-card').forEach(c => c.classList.remove('selected'));
+ this.closest('.franchise-card').classList.add('selected');
+
+ // Ouvrir le modal de tarif commercial
+ openModalTarifCom(franchiseValue);
+ });
+ });
+ }
+
+ // Fonction pour configurer les alertes de marchandises
+ function setupMarchandiseAlerts() {
+ // Alerte pour Animaux Vivants
+ document.querySelectorAll('[name^="mar"] input[type="checkbox"]').forEach(cb => {
+ cb.addEventListener('change', function() {
+ const label = this.nextElementSibling?.textContent.trim();
+ if (label && label.includes('Animaux vivants') && this.checked) {
+ window.modalAnimauxVivants.open();
+ }
+ if (label && label.includes('Transport de béton') && this.checked) {
+ window.modalTransportBeton.open();
+ }
+ });
+ });
+ }
+
+ // Fonction pour configurer les alertes d'activités
+ function setupActiviteAlerts() {
+ // Alerte pour Autocariste + RCE
+ const checkAutocariste = document.getElementById('checkAutocariste');
+ const checkRCE = document.getElementById('checkRCE');
+
+ const checkBothAutocariste = () => {
+ if (checkAutocariste?.checked && checkRCE?.checked) {
+ window.modalAutocaristeRCE.open();
+ }
+ };
+
+ if (checkAutocariste) checkAutocariste.addEventListener('change', checkBothAutocariste);
+ if (checkRCE) checkRCE.addEventListener('change', checkBothAutocariste);
+ }
+
+ // Seuil de différence acceptable (5%)
+ const seuil = 5;
+
+ // Fonction pour ouvrir le modal de tarif commercial
+ function openModalTarifCom(franchiseValue) {
+ // Récupérer le tarif de référence selon la franchise
+ let tarifRef = 0;
+ if (franchiseValue === '250') {
+ tarifRef = toNumber(document.getElementById('priceFr250')?.textContent);
+ } else if (franchiseValue === '400') {
+ tarifRef = toNumber(document.getElementById('priceFr400')?.textContent);
+ } else if (franchiseValue === 'mini300') {
+ tarifRef = toNumber(document.getElementById('priceFr2000')?.textContent);
+ }
+
+ // Réinitialiser le modal
+ document.getElementById('tarifRefText').innerText = `Tarif de Référence : ${formatNumber(tarifRef, 2)} €`;
+ document.getElementById('tarifCom').value = '';
+ document.getElementById('commentaire').value = '';
+ document.getElementById('comm-OK').disabled = false;
+ document.getElementById('tarifCom-error').style.display = 'none';
+ document.getElementById('col-commentaire').style.display = 'none';
+ document.getElementById('qualiteDiv').style.display = 'none';
+ document.getElementById('comm-OK').setAttribute('data-franchise', franchiseValue);
+ document.getElementById('comm-OK').setAttribute('data-tarif-ref', tarifRef);
+
+ // Event listener pour le champ tarif commercial
+ const tarifComInput = document.getElementById('tarifCom');
+ tarifComInput.removeEventListener('input', handleTarifComInput);
+ tarifComInput.addEventListener('input', handleTarifComInput);
+
+ // Event listener pour le commentaire
+ const commentaireInput = document.getElementById('commentaire');
+ commentaireInput.removeEventListener('input', handleCommentaireInput);
+ commentaireInput.addEventListener('input', handleCommentaireInput);
+
+ // Ouvrir le modal
+ window.modalTarifCom.open();
+ }
+
+ // Fonction pour gérer l'input du tarif commercial
+ function handleTarifComInput(e) {
+ const tarifCom = parseFloat(e.target.value);
+ const tarifRef = parseFloat(document.getElementById('comm-OK').getAttribute('data-tarif-ref'));
+
+ if (!tarifCom || tarifCom <= 0) {
+ document.getElementById('qualiteDiv').style.display = 'none';
+ return;
+ }
+
+ const diff = 100 * (tarifCom / tarifRef);
+ let qualitePrime = '';
+ let emoji = '';
+ let showComment = false;
+
+ if (diff < (100 + seuil) && diff > (100 - seuil)) {
+ emoji = 'mood';
+ showComment = false;
+
+ if (diff > 100) {
+ qualitePrime = `Tarif correct (+${(diff - 100).toFixed(2)}%)`;
+ } else if (diff < 100) {
+ qualitePrime = `Tarif correct (-${(100 - diff).toFixed(2)}%)`;
+ } else {
+ qualitePrime = 'Le juste prix';
+ emoji = 'thumb_up_alt';
+ }
+ } else {
+ emoji = 'mood_bad';
+ showComment = true;
+
+ if (diff > (100 + seuil)) {
+ qualitePrime = `Tarif trop élevé (+${(diff - 100).toFixed(2)}%)`;
+ } else if (diff < (100 - seuil)) {
+ qualitePrime = `Tarif trop bas (-${(100 - diff).toFixed(2)}%)`;
+ }
+ }
+
+ document.getElementById('qualiteDiv').style.display = 'block';
+ document.getElementById('qualitePrime').innerText = qualitePrime;
+ document.getElementById('modalTarifCom-icon').innerText = emoji;
+ document.getElementById('modalTarifCom-icon').style.color = (emoji === 'mood_bad') ? 'red' : 'green';
+
+ if (showComment) {
+ document.getElementById('tarifCom-error').style.display = 'flex';
+ document.getElementById('col-commentaire').style.display = 'flex';
+ if (!document.getElementById('commentaire').value.trim()) {
+ document.getElementById('comm-OK').disabled = true;
+ }
+ } else {
+ document.getElementById('comm-OK').disabled = false;
+ document.getElementById('tarifCom-error').style.display = 'none';
+ document.getElementById('col-commentaire').style.display = 'none';
+ }
+ }
+
+ // Fonction pour gérer l'input du commentaire
+ function handleCommentaireInput(e) {
+ const commentaire = e.target.value.trim();
+ const tarifComError = document.getElementById('tarifCom-error').style.display !== 'none';
+
+ if (tarifComError) {
+ document.getElementById('comm-OK').disabled = !commentaire;
+ }
+ }
+
+ // Fonction pour gérer la validation du tarif commercial
+ async function handleValidateTarifCom() {
+ const tarifCom = parseFloat(document.getElementById('tarifCom').value);
+ const commentaire = document.getElementById('commentaire').value.trim();
+ const franchiseValue = document.getElementById('comm-OK').getAttribute('data-franchise');
+
+ if (!tarifCom || tarifCom <= 0) {
+ M.toast({html: 'Veuillez saisir un tarif commercial valide', classes: 'red'});
+ return;
+ }
+
+
+ // Fermer le modal
+ window.modalTarifCom.close();
+
+ // Afficher un loader
+ M.toast({html: '⏳ Sauvegarde en cours...', classes: 'blue'});
+
+ // Sauvegarder le tarif
+ const saveResult = await saveTarifRC();
+
+ if (saveResult && saveResult.valid) {
+ M.toast({html: `Tarif sauvegardé avec succès !`, classes: 'green'});
+
+ // Rediriger vers la page projet après un court délai
+ setTimeout(() => {
+ console.log('🚀 Redirection vers projet...');
+ // Construire l'URL de redirection vers projet
+ const numParcours = parcours?.numParcours;
+ if (numParcours) {
+ window.location.href = `navParcours?numParcours=${numParcours}&submenu=projet`;
+ } else {
+ M.toast({html: 'Erreur: impossible de rediriger', classes: 'red'});
+ }
+ }, 1000);
+ } else {
+ M.toast({html: '❌ Erreur lors de la sauvegarde du tarif', classes: 'red'});
+ }
+ }
+
+ // Exposer les fonctions globalement pour y accéder depuis l'extérieur
+ window.initSubmenuForm = init;
+ window.saveTarifRC = saveTarifRC;
+})();
\ No newline at end of file
diff --git a/ecole/src/constantes/json-modulateur-rc.js b/ecole/src/constantes/json-modulateur-rc.js
new file mode 100644
index 00000000..4550c440
--- /dev/null
+++ b/ecole/src/constantes/json-modulateur-rc.js
@@ -0,0 +1,1434 @@
+const modRCCA = {
+ // max CA : Modulation CA
+ 400000: 1.00,
+ 500000: 0.85,
+ 800000: 0.80,
+ 1000000: 0.70,
+ 1600000: 0.64,
+ 2000000: 0.51,
+ 2400000: 0.44,
+ 3000000: 0.38,
+ 3200000: 0.30,
+ 4000000: 0.28,
+ 5000000: 0.22,
+ 1234567890123456789: 0.20
+};
+
+const modRCActRCC = {
+ revisable: {
+ // Capital:TauxBase
+ "Voiturier/Loueur": {
+ 5000: 0.16,
+ 10000: 0.16,
+ 15000: 0.16,
+ 20000: 0.16,
+ 25000: 0.17,
+ 30000: 0.17,
+ 50000: 0.17,
+ 60000: 0.18,
+ 100000: 0.19,
+ 150000: 0.20,
+ 200000: 0.21,
+ 300000: 0.22,
+ 400000: 0.23
+ },
+ "Commissionnaire de Transport": {
+ 100000: 0.08,
+ 150000: 0.10,
+ 200000: 0.11,
+ 300000: 0.12,
+ 400000: 0.13,
+ },
+ "Déménageur": {
+ 5000: 0.32,
+ 10000: 0.32,
+ 15000: 0.32,
+ 20000: 0.32,
+ 25000: 0.34,
+ 30000: 0.34,
+ 50000: 0.34,
+ 60000: 0.36,
+ 100000: 0.38,
+ 150000: 0.40,
+ 200000: 0.42,
+ 300000: 0.44,
+ 400000: 0.46
+ },
+ "Logistique": {
+ 5000: 0.057,
+ 10000: 0.057,
+ 15000: 0.057,
+ 20000: 0.057,
+ 25000: 0.057,
+ 30000: 0.057,
+ 50000: 0.057,
+ 60000: 0.21,
+ 100000: 0.271,
+ 150000: 0.271,
+ 200000: 0.271,
+ 300000: 0.2,
+ 400000: 0.25
+ },
+ "Autres activites": {
+ 5000: 0.16,
+ 10000: 0.16,
+ 15000: 0.16,
+ 20000: 0.16,
+ 25000: 0.17,
+ 30000: 0.17,
+ 50000: 0.17,
+ 60000: 0.18,
+ 100000: 0.19,
+ 150000: 0.20,
+ 200000: 0.21,
+ 300000: 0.22,
+ 400000: 0.23
+ }
+ },
+ forfaitaire: {
+ // Capital : prime forfaitaire {1veh, 2veh}
+ "Voiturier/Loueur": {
+ 5000: {
+ unVehicule: 130,
+ deuxVehicules: 220
+ },
+ 10000: {
+ unVehicule: 160,
+ deuxVehicules: 270
+ },
+ 15000: {
+ unVehicule: 180,
+ deuxVehicules: 300
+ },
+ 20000: {
+ unVehicule: 190,
+ deuxVehicules: 320
+ },
+ 25000: {
+ unVehicule: 205,
+ deuxVehicules: 345
+ },
+ 30000: {
+ unVehicule: 205,
+ deuxVehicules: 345
+ },
+ 50000: {
+ unVehicule: 260,
+ deuxVehicules: 425
+ },
+ 60000: {
+ unVehicule: 295,
+ deuxVehicules: 480
+ },
+ 100000: {
+ unVehicule: 330,
+ deuxVehicules: 495
+ },
+ 150000: {
+ unVehicule: 370,
+ deuxVehicules: 555
+ },
+ 200000: {
+ unVehicule: 410,
+ deuxVehicules: 600
+ },
+ 300000: {
+ unVehicule: 490,
+ deuxVehicules: 730
+ },
+ 400000: {
+ unVehicule: 550,
+ deuxVehicules: 820
+ }
+ },
+ "Déménageur": {
+ 5000: {
+ unVehicule: 260,
+ deuxVehicules: 440
+ },
+ 10000: {
+ unVehicule: 320,
+ deuxVehicules: 540
+ },
+ 15000: {
+ unVehicule: 360,
+ deuxVehicules: 600
+ },
+ 20000: {
+ unVehicule: 380,
+ deuxVehicules: 640
+ },
+ 25000: {
+ unVehicule: 410,
+ deuxVehicules: 690
+ },
+ 30000: {
+ unVehicule: 450,
+ deuxVehicules: 750
+ },
+ 50000: {
+ unVehicule: 520,
+ deuxVehicules: 850
+ },
+ 60000: {
+ unVehicule: 590,
+ deuxVehicules: 960
+ },
+ 100000: {
+ unVehicule: 660,
+ deuxVehicules: 990
+ },
+ 150000: {
+ unVehicule: 740,
+ deuxVehicules: 1110
+ },
+ 200000: {
+ unVehicule: 820,
+ deuxVehicules: 1200
+ },
+ 300000: {
+ unVehicule: 980,
+ deuxVehicules: 1460
+ },
+ 400000: {
+ unVehicule: 1100,
+ deuxVehicules: 1640
+ }
+ },
+ "Autocariste": {
+ 25000: {
+ unVehicule: 114,
+ deuxVehicules: 228
+ },
+ 50000: {
+ unVehicule: 204,
+ deuxVehicules: 408
+ },
+ 75000: {
+ unVehicule: 294,
+ deuxVehicules: 588
+ },
+ 100000: {
+ unVehicule: 384,
+ deuxVehicules: 768
+ },
+ 125000: {
+ unVehicule: 474,
+ deuxVehicules: 948
+ },
+ 150000: {
+ unVehicule: 564,
+ deuxVehicules: 1128
+ }
+ }
+ }
+};
+
+const modRCActRCE = {
+ revisable: {
+ "Voiturier/Loueur": {
+ mini: 0.06,
+ optimale: 0.08,
+ maxi: 0.1
+ },
+ "Commissionnaire de Transport": {
+ mini: 0.045,
+ optimale: 0.05,
+ maxi: 0.055
+ },
+ "Déménageur": {
+ mini: 0.12,
+ optimale: 0.16,
+ maxi: 0.2
+ },
+ "Logistique": {
+ mini: 0.06,
+ optimale: 0.08,
+ maxi: 0.1
+ },
+ "Autres activites": {
+ mini: 0.06,
+ optimale: 0.08,
+ maxi: 0.1
+ }
+ },
+ forfaitaire: {
+ "Voiturier/Loueur": {
+ unVehicule: {
+ mini: 105,
+ optimale: 115,
+ maxi: 125
+ },
+ deuxVehicules: {
+ mini: 140,
+ optimale: 150,
+ maxi: 160
+ }
+ },
+ "Déménageur": {
+ unVehicule: {
+ mini: 0,
+ optimale: 115,
+ maxi: 0
+ },
+ deuxVehicules: {
+ mini: 0,
+ optimale: 150,
+ maxi: 0
+ }
+ },
+ "Autocariste": {
+ unVehicule: {
+ mini: 0,
+ optimale: 0,
+ maxi: 0
+ },
+ deuxVehicules: {
+ mini: 0,
+ optimale: 0,
+ maxi: 0
+ }
+ }
+ }
+};
+
+const modRCActCompl = {
+ revisable: {
+ "Voiturier/Loueur": {
+ "Voiturier y compris sous-traitance temporaire": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Loueur de véhicule industriel avec conducteur": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Coursier en 2 ou 3 roues": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Montage de meuble, électroménager, branchement": {
+ modRCC: 1,
+ modRCE: 3
+ },
+ "Manutentionnaire - levageur / Loueur de matériel de levage avec opérateur": {
+ modRCC: 1,
+ modRCE: 3
+ },
+ "Accompagnement de transport exceptionnel": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ },
+ "Commissionnaire de Transport": {
+ "Commissionnaire de transport multimodal - zone UE": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Commissionnaire de transport multimodal": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Transitaire": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Représentant en Douane Enregistré": {
+ modRCC: 1.5,
+ modRCE: 1
+ }
+ },
+ "Déménageur": {
+ "Déménageur de particuliers par voie terrestre": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Déménageur de particuliers par voie terrestre - garantie dommage": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Déménageur d'entreprises": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Déménageur interne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Garde-meubles": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ },
+ "Logistique": {
+ "Entrepositaire - dépositaire": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Gestion de stocks - préparation de commande": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Empoteur": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ },
+ "Autres activites": {
+ }
+ },
+ forfaitaire: {
+ "Voiturier/Loueur": {
+ "Coursier en 2 ou 3 roues": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Montage de meuble, électroménager, branchement": {
+ modRCC: 3,
+ modRCE: 3
+ },
+ "Manutentionnaire": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Accompagnement de transport exceptionnel": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ },
+ "Déménageur": {
+ "Garde Meuble": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ },
+ "Autocariste": {
+ }
+ }
+};
+
+const modRCMar = {
+ revisable: {
+ "Voiturier/Loueur": {
+ "Marchandises ordinaires": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Véhicules roulants": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Engins de chantier": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Objets indivisibles": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises périssables": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises en citerne": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ },
+ "Animaux vivants": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Transport de béton": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ }
+ },
+ "Commissionnaire de Transport": {
+ "Marchandises ordinaires": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Véhicules roulants": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Engins de chantier": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Objets indivisibles": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises périssables": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises en citerne": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ },
+ "Animaux vivants": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Transport de béton": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ }
+ },
+ "Déménageur": {
+ "Mobiliers en déménagement": {
+ modRCC: 3,
+ modRCE: 2
+ }
+ },
+ "Logistique": {
+ "Marchandises ordinaires": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Véhicules roulants": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Engins de chantier": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Objets indivisibles": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises périssables": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises en citerne": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ },
+ "Animaux vivants": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Transport de béton": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ }
+ },
+ "Autres activites": {
+ "Marchandises ordinaires": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Véhicules roulants": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Engins de chantier": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Objets indivisibles": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises périssables": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises en citerne": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ },
+ "Animaux vivants": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Transport de béton": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ }
+ }
+ },
+ forfaitaire: {
+ "Voiturier/Loueur": {
+ "Marchandises ordinaires": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Véhicules roulants": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Engins de chantier": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Objets indivisibles": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises périssables": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises en citerne": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ },
+ "Animaux vivants": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Transport de béton": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ },
+ "Déménageur": {
+ "Mobiliers en déménagement": {
+ modRCC: 3,
+ modRCE: 2
+ }
+ },
+ "Autocariste": {
+ "Marchandises ordinaires": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Véhicules roulants": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Engins de chantier": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Objets indivisibles": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises périssables": {
+ modRCC: 1.2,
+ modRCE: 1
+ },
+ "Marchandises en citerne": {
+ modRCC: 0.7,
+ modRCE: 1.5
+ },
+ "Animaux vivants": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Marchandises en benne": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Transport de béton": {
+ modRCC: 1,
+ modRCE: 1
+ }
+ }
+ }
+};
+
+const modRCZone = {
+ "France Métropolitaine et pays limitrophes": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "Union Européenne": {
+ modRCC: 1.1,
+ modRCE: 1
+ },
+ "Autres pays européens sauf Russie et Ukraine (y compris UK et Norvège)": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Pays du Maghreb et Amérique du Nord ( USA / Canada / Mexique )": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Amérique Centrale et Sud / Caraïbes, Asie et Océanie": {
+ modRCC: 1.3,
+ modRCE: 1
+ },
+ "Afrique Hors Maghreb / Proche Orient / Moyen Orient": {
+ modRCC: 1.3,
+ modRCE: 1
+ }
+};
+
+const modRCEngagCompl = {
+ modRCC: {
+ // Tranche:Modulation
+ "Dommages immatériels": {
+ 15000: 1,
+ 50000: 1.025,
+ 100000: 1.05,
+ 150000: 1.08,
+ 300000: 1.10,
+ 400000: 1.13,
+ 500000: 1.15
+ },
+ "Contenants confiés": {
+ 25000: 0,
+ 50000: 500,
+ 100000: 1000
+ },
+ "Différence inventaire": {
+ 15000: 0,
+ 30000: 1000,
+ 50000: 3000
+ }
+ }
+};
+
+const modRCGarAdd = {
+ modRCC: {
+ // Tranche:Modulation
+ "TPPC": {
+ 5000: 0,
+ 10000: 0.01,
+ 15000: 0.01,
+ 30000: 0.01
+ },
+ "Protection juridique": {
+ 0: 49.38,
+ 500: 80.25,
+ 1000: 119.93,
+ 2000: 209.88,
+ 3000: 320.11,
+ 5000: 509.70,
+ 7000: 720.46,
+ 10000: 990.30,
+ 15000: 1489.42,
+ 25000: 2389.77,
+ 40000: 2389.77
+ }
+ },
+ modRCE: {
+ "Station de lavage": 1000,
+ "Garage interne": 1500,
+ "Comité Social et Economique": 100
+ }
+};
+
+const modRCSinistre = {
+ // pourcentage:modulation
+ 0.4: 1,
+ 0.7: 1.3,
+ 1: 1.5
+};
+
+const modRCFranchise = {
+ "250": {
+ modRCC: 1,
+ modRCE: 1
+ },
+ "400": {
+ modRCC: 0.9,
+ modRCE: 0.9
+ },
+ "10% avec mini 300 € et maxi 2000": {
+ modRCC: 0.8,
+ modRCE: 0.8
+ }
+};
+
+const modRCPrimeMini = {
+ revisable: {
+ //Tranche:Modulation
+ "Voiturier/Loueur": {
+ 5000: {
+ miniRCC: 330,
+ miniRCE: 330
+ },
+ 10000: {
+ miniRCC: 374,
+ miniRCE: 330
+ },
+ 15000: {
+ miniRCC: 396,
+ miniRCE: 330
+ },
+ 20000: {
+ miniRCC: 418,
+ miniRCE: 330
+ },
+ 25000: {
+ miniRCC: 462,
+ miniRCE: 330
+ },
+ 30000: {
+ miniRCC: 484,
+ miniRCE: 330
+ },
+ 50000: {
+ miniRCC: 550,
+ miniRCE: 330
+ },
+ 60000: {
+ miniRCC: 616,
+ miniRCE: 330
+ },
+ 100000: {
+ miniRCC: 660,
+ miniRCE: 330
+ },
+ 150000: {
+ miniRCC: 770,
+ miniRCE: 330
+ },
+ 200000: {
+ miniRCC: 880,
+ miniRCE: 330
+ },
+ 300000: {
+ miniRCC: 1100,
+ miniRCE: 330
+ },
+ 400000: {
+ miniRCC: 1320,
+ miniRCE: 330
+ }
+ },
+ "Commissionnaire de Transport": {
+ 5000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 10000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 15000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 20000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 25000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 30000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 50000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 60000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 100000: {
+ miniRCC: 1200,
+ miniRCE: 150
+ },
+ 150000: {
+ miniRCC: 1300,
+ miniRCE: 150
+ },
+ 200000: {
+ miniRCC: 1300,
+ miniRCE: 150
+ },
+ 300000: {
+ miniRCC: 1600,
+ miniRCE: 150
+ },
+ 400000: {
+ miniRCC: 1800,
+ miniRCE: 150
+ }
+ },
+ "Déménageur": {
+ 5000: {
+ miniRCC: 594,
+ miniRCE: 660
+ },
+ 10000: {
+ miniRCC: 673,
+ miniRCE: 660
+ },
+ 15000: {
+ miniRCC: 713,
+ miniRCE: 660
+ },
+ 20000: {
+ miniRCC: 752,
+ miniRCE: 660
+ },
+ 25000: {
+ miniRCC: 832,
+ miniRCE: 660
+ },
+ 30000: {
+ miniRCC: 871,
+ miniRCE: 660
+ },
+ 50000: {
+ miniRCC: 990,
+ miniRCE: 660
+ },
+ 60000: {
+ miniRCC: 1109,
+ miniRCE: 660
+ },
+ 100000: {
+ miniRCC: 1188,
+ miniRCE: 660
+ },
+ 150000: {
+ miniRCC: 1386,
+ miniRCE: 660
+ },
+ 200000: {
+ miniRCC: 1584,
+ miniRCE: 660
+ },
+ 300000: {
+ miniRCC: 1980,
+ miniRCE: 660
+ },
+ 400000: {
+ miniRCC: 2376,
+ miniRCE: 660
+ }
+ },
+ "Logistique": {
+ 5000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 10000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 15000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 20000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 25000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 30000: {
+ miniRCC: 557,
+ miniRCE: 150
+ },
+ 50000: {
+ miniRCC: 633,
+ miniRCE: 150
+ },
+ 60000: {
+ miniRCC: 708,
+ miniRCE: 150
+ },
+ 100000: {
+ miniRCC: 759,
+ miniRCE: 150
+ },
+ 150000: {
+ miniRCC: 886,
+ miniRCE: 150
+ },
+ 200000: {
+ miniRCC: 1012,
+ miniRCE: 150
+ },
+ 300000: {
+ miniRCC: 1265,
+ miniRCE: 150
+ },
+ 400000: {
+ miniRCC: 1518,
+ miniRCE: 150
+ }
+ },
+ "Autocariste": {
+ 5000: {
+ miniRCC: 500,
+ miniRCE: 150
+ },
+ 10000: {
+ miniRCC: 500,
+ miniRCE: 150
+ },
+ 15000: {
+ miniRCC: 550,
+ miniRCE: 150
+ },
+ 20000: {
+ miniRCC: 550,
+ miniRCE: 150
+ },
+ 25000: {
+ miniRCC: 620,
+ miniRCE: 150
+ },
+ 30000: {
+ miniRCC: 620,
+ miniRCE: 150
+ },
+ 50000: {
+ miniRCC: 660,
+ miniRCE: 150
+ },
+ 60000: {
+ miniRCC: 660,
+ miniRCE: 150
+ },
+ 100000: {
+ miniRCC: 700,
+ miniRCE: 150
+ },
+ 150000: {
+ miniRCC: 700,
+ miniRCE: 150
+ },
+ 200000: {
+ miniRCC: 750,
+ miniRCE: 150
+ },
+ 300000: {
+ miniRCC: 850,
+ miniRCE: 150
+ },
+ 400000: {
+ miniRCC: 850,
+ miniRCE: 150
+ }
+ },
+ "Autres activites": {
+ 5000: {
+ miniRCC: 500,
+ miniRCE: 150
+ },
+ 10000: {
+ miniRCC: 500,
+ miniRCE: 150
+ },
+ 15000: {
+ miniRCC: 550,
+ miniRCE: 150
+ },
+ 20000: {
+ miniRCC: 550,
+ miniRCE: 150
+ },
+ 25000: {
+ miniRCC: 620,
+ miniRCE: 150
+ },
+ 30000: {
+ miniRCC: 620,
+ miniRCE: 150
+ },
+ 50000: {
+ miniRCC: 660,
+ miniRCE: 150
+ },
+ 60000: {
+ miniRCC: 660,
+ miniRCE: 150
+ },
+ 100000: {
+ miniRCC: 700,
+ miniRCE: 150
+ },
+ 150000: {
+ miniRCC: 700,
+ miniRCE: 150
+ },
+ 200000: {
+ miniRCC: 750,
+ miniRCE: 150
+ },
+ 300000: {
+ miniRCC: 850,
+ miniRCE: 150
+ },
+ 400000: {
+ miniRCC: 850,
+ miniRCE: 150
+ }
+ }
+ },
+ forfaitaire: {
+ //Tranche:Value Mini
+ "Voiturier/Loueur": {
+ 5000: {
+ miniRCC: 150,
+ miniRCE: 150
+ },
+ 10000: {
+ miniRCC: 170,
+ miniRCE: 150
+ },
+ 15000: {
+ miniRCC: 180,
+ miniRCE: 150
+ },
+ 20000: {
+ miniRCC: 190,
+ miniRCE: 150
+ },
+ 25000: {
+ miniRCC: 210,
+ miniRCE: 150
+ },
+ 30000: {
+ miniRCC: 220,
+ miniRCE: 150
+ },
+ 50000: {
+ miniRCC: 250,
+ miniRCE: 150
+ },
+ 60000: {
+ miniRCC: 280,
+ miniRCE: 150
+ },
+ 100000: {
+ miniRCC: 300,
+ miniRCE: 150
+ },
+ 150000: {
+ miniRCC: 350,
+ miniRCE: 150
+ },
+ 200000: {
+ miniRCC: 400,
+ miniRCE: 150
+ },
+ 300000: {
+ miniRCC: 500,
+ miniRCE: 150
+ },
+ 400000: {
+ miniRCC: 600,
+ miniRCE: 150
+ }
+ },
+ "Commissionnaire de Transport": {
+ 5000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 10000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 15000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 20000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 25000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 30000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 50000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 60000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 100000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 150000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 200000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 300000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 400000: {
+ miniRCC: 0,
+ miniRCE: 0
+ }
+ },
+ "Déménageur": {
+ 5000: {
+ miniRCC: 270,
+ miniRCE: 300
+ },
+ 10000: {
+ miniRCC: 306,
+ miniRCE: 300
+ },
+ 15000: {
+ miniRCC: 324,
+ miniRCE: 300
+ },
+ 20000: {
+ miniRCC: 342,
+ miniRCE: 300
+ },
+ 25000: {
+ miniRCC: 378,
+ miniRCE: 300
+ },
+ 30000: {
+ miniRCC: 396,
+ miniRCE: 300
+ },
+ 50000: {
+ miniRCC: 450,
+ miniRCE: 300
+ },
+ 60000: {
+ miniRCC: 504,
+ miniRCE: 300
+ },
+ 100000: {
+ miniRCC: 540,
+ miniRCE: 300
+ },
+ 150000: {
+ miniRCC: 630,
+ miniRCE: 300
+ },
+ 200000: {
+ miniRCC: 720,
+ miniRCE: 300
+ },
+ 300000: {
+ miniRCC: 900,
+ miniRCE: 300
+ },
+ 400000: {
+ miniRCC: 1080,
+ miniRCE: 300
+ }
+ },
+ "Logistique": {
+ 5000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 10000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 15000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 20000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 25000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 30000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 50000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 60000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 100000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 150000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 200000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 300000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 400000: {
+ miniRCC: 0,
+ miniRCE: 0
+ }
+ },
+ "Autocariste": {
+ 5000: {
+ miniRCC: 270,
+ miniRCE: 300
+ },
+ 10000: {
+ miniRCC: 306,
+ miniRCE: 300
+ },
+ 15000: {
+ miniRCC: 324,
+ miniRCE: 300
+ },
+ 20000: {
+ miniRCC: 342,
+ miniRCE: 300
+ },
+ 25000: {
+ miniRCC: 378,
+ miniRCE: 300
+ },
+ 30000: {
+ miniRCC: 396,
+ miniRCE: 300
+ },
+ 50000: {
+ miniRCC: 450,
+ miniRCE: 300
+ },
+ 60000: {
+ miniRCC: 504,
+ miniRCE: 300
+ },
+ 100000: {
+ miniRCC: 540,
+ miniRCE: 300
+ },
+ 150000: {
+ miniRCC: 630,
+ miniRCE: 300
+ },
+ 200000: {
+ miniRCC: 720,
+ miniRCE: 300
+ },
+ 300000: {
+ miniRCC: 900,
+ miniRCE: 300
+ },
+ 400000: {
+ miniRCC: 1080,
+ miniRCE: 300
+ }
+ },
+ "Autres activites": {
+ 5000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 10000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 15000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 20000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 25000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 30000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 50000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 60000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 100000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 150000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 200000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 300000: {
+ miniRCC: 0,
+ miniRCE: 0
+ },
+ 400000: {
+ miniRCC: 0,
+ miniRCE: 0
+ }
+ }
+ }
+};
+
+module.exports = {
+ modRCCA,
+ modRCActRCC,
+ modRCActRCE,
+ modRCActCompl,
+ modRCMar,
+ modRCZone,
+ modRCEngagCompl,
+ modRCGarAdd,
+ modRCSinistre,
+ modRCFranchise,
+ modRCPrimeMini
+};
\ No newline at end of file
diff --git a/ecole/src/controllers/generateRcController.js b/ecole/src/controllers/generateRcController.js
index 47a4a468..a4d09fe3 100644
--- a/ecole/src/controllers/generateRcController.js
+++ b/ecole/src/controllers/generateRcController.js
@@ -8,157 +8,196 @@ const path = require("path");
const moment = require("moment");
const parcoursService = require("../services/parcoursService");
const contratService = require("../services/contratService");
+const userService = require("../services/userService");
const globalService = require("../services/globalService");
+//const projetformrc = require("../../public/js/projet-form-rc");
+//const moduloRC = require("../constantes/json-modulateur-rc"); useless pour le moment ?
require("moment/locale/fr");
moment.locale("fr");
+// Fonctions helper pour récupérer les valeurs selon la franchise choisie
+function getSelectedTarifReference(tarifRC) {
+ const franchise = tarifRC.franchiseChoisie;
+ if (franchise === '250') return tarifRC.primeTotal_250;
+ if (franchise === '400') return tarifRC.primeTotal_400;
+ if (franchise === 'mini300') return tarifRC.primeTotal_2000;
+ return null;
+}
+
+function getSelectedPrime(tarifRC, type) {
+ const franchise = tarifRC.franchiseChoisie;
+ if (!franchise) return 0;
+
+ const suffix = franchise === 'mini300' ? '2000' : franchise;
+ const fieldName = `prime${type}_${suffix}`;
+ return tarifRC[fieldName] || 0;
+}
+
+function getSelectedTaux(tarifRC, type) {
+ const franchise = tarifRC.franchiseChoisie;
+ if (!franchise) return 0;
+
+ const suffix = franchise === 'mini300' ? '2000' : franchise;
+ const fieldName = `taux${type}_${suffix}`;
+ return tarifRC[fieldName] || 0;
+}
+
router.post("/rc/projet/:numParcours", async (req, res) => {
- const content = fs.readFileSync(
- path.resolve("src/templates/template-projet-rc.docx"),
- "binary"
- );
-
- const zip = new PizZip(content);
- const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
- const numParcours = req.params.numParcours.toUpperCase();
-
- const parcours = await parcoursService.getParcoursByNumParcours(numParcours);
- const contrat = await contratService.getContratById(parcours.contrat);
- const client = contrat?.["@expand"]?.client || {};
- const intermediaire = contrat?.["@expand"]?.intermediaire || {};
- const rc = contrat?.["@expand"]?.enCours || {};
-
- const listAssAdd = [];
-
try {
- rc.assureAdditionnel.forEach((objet) => {
- listAssAdd.push(
- objet.nom +
+ const content = fs.readFileSync(
+ path.resolve("src/templates/template-projet-rc.docx"),
+ "binary"
+ );
+
+ const zip = new PizZip(content);
+ const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
+ const numParcours = req.params.numParcours.toUpperCase();
+
+ const parcours = await parcoursService.getParcoursByNumParcours(numParcours);
+ const contrat = await contratService.getContratById(parcours.contrat);
+ const client = contrat?.["@expand"]?.client || {};
+ const intermediaire = contrat?.["@expand"]?.intermediaire || {};
+
+ // Récupérer la collection rc avec ses relations (APRÈS placerDansEnCours, c'est dans enCours)
+ const rcFull = contrat?.["@expand"]?.enCours;
+ if (!rcFull) {
+ logger.log('error', 'No RC found for contrat:', contrat.id);
+ return res.status(404).send("Aucune donnée RC trouvée pour ce contrat");
+ }
+
+ // Les données sont déjà expandées par contratService
+ const rc = rcFull?.["@expand"]?.projetRC || {};
+
+ const listAssAdd = [];
+
+ // Traiter les assurés additionnels s'ils existent
+ if (rc.assureAdditionnel && Array.isArray(rc.assureAdditionnel)) {
+ rc.assureAdditionnel.forEach((objet) => {
+ listAssAdd.push(
+ objet.nom +
" - Adresse : " +
objet.adresse +
" - Siret : " +
objet.siret
- );
- });
- } catch (error) { }
-
- // Conditions zone
- hasMondeEntier = false;
- hasZone1 = false;
- hasZone2 = false;
- hasZone3 = false;
- hasZone4 = false;
- hasZone5 = false;
- hasZone6 = false;
- hasActiviteButNotMultimodal = false; // Attention trick pour les zones géographiques dans le cas de multimodal
- hasZone456 = false;
-
- // Cas monde entier
- if (
- rc.zone1 &&
- rc.zone2 &&
- rc.zone3 &&
- rc.zone4 &&
- rc.zone5 &&
- rc.zone6 &&
- (rc.actVoiturier ||
- rc.actLoueur ||
- rc.actDouane ||
- rc.actDemPar ||
- rc.actDemParDom ||
- rc.actDemParAdv ||
- rc.actDemEntr ||
- rc.actDemInterne ||
- rc.actGardeMeuble ||
- rc.actEntDep ||
- rc.actPrestaLog ||
- rc.actLevageur)
- ) {
- hasMondeEntier = true;
- }
-
- // Cas date du jour d'édition
- let dateNow;
-
- dateNow = moment().format("DD MMMM YYYY");
-
- // Cas une ou plusieurs zone(s) spécifique(s) + cas zone456
- if (hasMondeEntier == false && (rc.actVoiturier || rc.actLoueur || rc.actDouane || rc.actDemPar || rc.actDemParDom || rc.actDemParAct || rc.actDemEntr || rc.actDemInterne || rc.actGardeMeuble || rc.actEntDep || rc.actPrestaLog || rc.actLevageur || rc.actDemParAdv)) {
- if (rc.zone1) {
- hasZone1 = true;
+ );
+ });
}
- if (rc.zone2) {
- hasZone2 = true;
+
+ // Conditions zone
+ let hasMondeEntier = false;
+ let hasZone1 = false;
+ let hasZone2 = false;
+ let hasZone3 = false;
+ let hasZone4 = false;
+ let hasZone5 = false;
+ let hasZone6 = false;
+ let hasActiviteButNotMultimodal = false; // Attention trick pour les zones géographiques dans le cas de multimodal
+ let hasZone456 = false;
+
+ // Cas monde entier
+ if (
+ rc.zone1 &&
+ rc.zone2 &&
+ rc.zone3 &&
+ rc.zone4 &&
+ rc.zone5 &&
+ rc.zone6 &&
+ (rc.actVoiturier ||
+ rc.actLoueur ||
+ rc.actDouane ||
+ rc.actDemPar ||
+ rc.actDemParDom ||
+ rc.actDemParAdv ||
+ rc.actDemEntr ||
+ rc.actDemInterne ||
+ rc.actGardeMeuble ||
+ rc.actEntDep ||
+ rc.actPrestaLog ||
+ rc.actLevageur)
+ ) {
+ hasMondeEntier = true;
}
- if (rc.zone3) {
- hasZone3 = true;
+
+ // Cas date du jour d'édition
+ let dateNow = moment().format("DD MMMM YYYY");
+
+ // Cas une ou plusieurs zone(s) spécifique(s) + cas zone456
+ if (hasMondeEntier == false && (rc.actVoiturier || rc.actLoueur || rc.actDouane || rc.actDemPar || rc.actDemParDom || rc.actDemParAct || rc.actDemEntr || rc.actDemInterne || rc.actGardeMeuble || rc.actEntDep || rc.actPrestaLog || rc.actLevageur || rc.actDemParAdv)) {
+ if (rc.zone1) {
+ hasZone1 = true;
+ }
+ if (rc.zone2) {
+ hasZone2 = true;
+ }
+ if (rc.zone3) {
+ hasZone3 = true;
+ }
+ if (rc.zone4) {
+ hasZone4 = true;
+ hasZone456 = true;
+ }
+ if (rc.zone5) {
+ hasZone5 = true;
+ hasZone456 = true;
+ }
+ if (rc.zone6) {
+ hasZone6 = true;
+ hasZone456 = true;
+ }
}
- if (rc.zone4) {
- hasZone4 = true;
- hasZone456 = true;
+
+ // Cas Activité multimodal + Au minimum une zone
+ if (rc.actMultimodal) {
+ if (hasZone1 || hasZone2 || hasZone3 || hasZone456 || hasMondeEntier) {
+ hasActiviteButNotMultimodal = true;
+ }
}
- if (rc.zone5) {
- hasZone5 = true;
- hasZone456 = true;
+
+ let hasMondeEntierOrMultimodal, hasNotMondeEntierOrMultimodal;
+ if (rc.actMultimodal || hasMondeEntier) {
+ hasMondeEntierOrMultimodal = true;
+ hasNotMondeEntierOrMultimodal = false;
+ } else {
+ hasMondeEntierOrMultimodal = false;
+ hasNotMondeEntierOrMultimodal = true;
}
- if (rc.zone6) {
- hasZone6 = true;
- hasZone456 = true;
+
+ // Conditions Extensions RCC
+ let extRCC = false;
+
+ if ( rc.extRCCModifCalArrim == true || rc.extRCCFerroutage == true || rc.extRCCFraisRecons == true || rc.extRCCConfie == true || rc.extRCCTPPC == true || rc.extRCCRegie == true || rc.extRCCSansMontageDemontage == true ) {
+ extRCC = true;
}
- }
- // Cas Activité multimodal + Au minimum une zone
- if (rc.actMultimodal) {
- if (hasZone1 || hasZone2 || hasZone3 || hasZone456 || hasMondeEntier) {
- hasActiviteButNotMultimodal = true;
+ // Conditions Extensions RCE
+ let extRCE = false;
+
+ if (rc.extRCEMontageDemontage == true || rc.extRCEBraDebra == true) {
+ extRCE = true;
}
- }
- if (rc.actMultimodal || hasMondeEntier) {
- hasMondeEntierOrMultimodal = true;
- hasNotMondeEntierOrMultimodal = false;
- } else {
- hasMondeEntierOrMultimodal = false;
- hasNotMondeEntierOrMultimodal = true;
- }
+ // Conditions Activitées
+ let hasActiviteDemenageurGardeMeuble = false;
+ if ( rc.actDemPar == true || rc.actDemEntr == true || rc.actDemParDom == true || rc.actDemParAdv == true || rc.actDemInterne) {
+ hasActiviteDemenageurGardeMeuble = true;
+ }
- // Conditions Extensions RCC
- let extRCC = false;
+ let oneOfActiviteDemenageurParticulier = false;
+ if ( rc.actDemPar == true || rc.actDemParDom == true || rc.actDemParAdv == true ) {
+ oneOfActiviteDemenageurParticulier = true;
+ }
- if ( rc.extRCCModifCalArrim == true || rc.extRCCFerroutage == true || rc.extRCCFraisRecons == true || rc.extRCCConfie == true || rc.extRCCTPPC == true || rc.extRCCRegie == true || rc.extRCCSansMontageDemontage == true ) {
- extRCC = true;
- }
+ let coorDem = "";
+ if ( (rc.actDemPar == true || rc.actDemParDom == true || rc.actDemParAdv == true) && (rc.actDemEntr == true || rc.actDemInterne == true) && rc.actGardeMeuble == true) {
+ coorDem = ",";
+ } else if ( (rc.actDemPar == true || rc.actDemParDom == true || rc.actDemParAdv == true) && (rc.actDemEntr == true || rc.actDemInterne == true) && rc.actGardeMeuble == false ) {
+ coorDem = " et";
+ }
- // Conditions Extensions RCC
- let extRCE = false;
+ // Variables numériques
+ const franchiseTarif = "250";
- if ( rc.extRCEMontageDemontage == true || rc.extRCEBraDebra == true) {
- extRCE = true;
- }
-
- // Conditions Activitées
- let hasActiviteDemenageurGardeMeuble = false;
- if ( rc.actDemPar == true || rc.actDemEntr == true || rc.actDemParDom == true || rc.actDemParAdv == true || rc.actDemInterne) {
- hasActiviteDemenageurGardeMeuble = true;
- }
-
- let oneOfActiviteDemenageurParticulier = false;
- if ( rc.actDemPar == true || rc.actDemParDom == true || rc.actDemParAdv == true ) {
- oneOfActiviteDemenageurParticulier = true;
- }
-
- let coorDem = "";
- if ( (rc.actDemPar == true || rc.actDemParDom == true || rc.actDemParAdv == true) && (rc.actDemEntr == true || rc.actDemInterne == true) && rc.actGardeMeuble == true) {
- coorDem = ",";
- } else if ( (rc.actDemPar == true || rc.actDemParDom == true || rc.actDemParAdv == true) && (rc.actDemEntr == true || rc.actDemInterne == true) && rc.actGardeMeuble == false ) {
- coorDem = " et";
- }
-
- // Variables numériques
- const franchiseTarif = "250";
-
- try {
doc.render({
// Client
nomClient: client.nom,
@@ -303,51 +342,310 @@ router.post("/rc/projet/:numParcours", async (req, res) => {
fraisRepFraction: globalService.customFormatNumber(rc.cotFraisTTC, true),
ca: globalService.customFormatNumber(rc.ca, true),
});
+
+ const buf = doc.getZip().generate({ type: "nodebuffer" });
+
+ const currentDate = new Date();
+
+ // Formatage de la date au format "JJ-MM-AAAA-HH-MM-SS"
+ const day = String(currentDate.getDate()).padStart(2, "0");
+ const month = String(currentDate.getMonth() + 1).padStart(2, "0");
+ const year = currentDate.getFullYear();
+ const hours = String(currentDate.getHours()).padStart(2, "0");
+ const minutes = String(currentDate.getMinutes()).padStart(2, "0");
+ const seconds = String(currentDate.getSeconds()).padStart(2, "0");
+ const formattedDate = `${day}-${month}-${year}-${hours}-${minutes}-${seconds}`;
+
+ // Génération du nom de fichier
+ const sanitizedClientNom = client.nom
+ .replace(/[^\w\s.-]/gi, "")
+ .replace(/\s+/g, "-");
+ const filename = `Projet-${contrat.produit}-${parcours.numParcours}-${sanitizedClientNom}-${formattedDate}`;
+
+ // Définit le type de contenu et un nom de fichier par défaut pour le téléchargement
+ res.setHeader(
+ "Content-Type",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+ );
+
+ res.setHeader(
+ "Content-Disposition",
+ "attachment; filename=" + filename + ".docx"
+ );
+
+ // Envoie le buffer au client, déclenchant le téléchargement
+ res.send(buf);
} catch (error) {
- const e = {
- message: error.message,
- name: error.name,
- stack: error.stack,
- properties: error.properties,
- };
- logger.log('error', JSON.stringify({ error: e }));
-
- // Envoyez une réponse d'erreur si le rendu échoue
- return res.status(500).send("Erreur lors de la génération du document");
+ logger.log('error', 'Error in RC projet generation:', error);
+ return res.status(500).send("Erreur lors de la génération du projet RC");
}
-
- const buf = doc.getZip().generate({ type: "nodebuffer" });
-
- const currentDate = new Date();
-
- // Formatage de la date au format "JJ-MM-AAAA-HH-MM-SS"
- const day = String(currentDate.getDate()).padStart(2, "0");
- const month = String(currentDate.getMonth() + 1).padStart(2, "0");
- const year = currentDate.getFullYear();
- const hours = String(currentDate.getHours()).padStart(2, "0");
- const minutes = String(currentDate.getMinutes()).padStart(2, "0");
- const seconds = String(currentDate.getSeconds()).padStart(2, "0");
- const formattedDate = `${day}-${month}-${year}-${hours}-${minutes}-${seconds}`;
-
- // Génération du nom de fichier
- const sanitizedClientNom = client.nom
- .replace(/[^\w\s.-]/gi, "")
- .replace(/\s+/g, "-");
- const filename = `Projet-${contrat.produit}-${parcours.numParcours}-${sanitizedClientNom}-${formattedDate}`;
-
- // Définit le type de contenu et un nom de fichier par défaut pour le téléchargement
- res.setHeader(
- "Content-Type",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
- );
-
- res.setHeader(
- "Content-Disposition",
- "attachment; filename=" + filename + ".docx"
- );
-
- // Envoie le buffer au client, déclenchant le téléchargement
- res.send(buf);
});
-module.exports = router;
+router.post("/rc/tarif/:numParcours", async (req, res) => {
+ try {
+ const content = fs.readFileSync(
+ path.resolve("src/templates/template-declinaison-tarifaire-rc.docx"),
+ "binary"
+ );
+
+ const zip = new PizZip(content);
+ const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
+
+ const numParcours = req.params.numParcours.toUpperCase();
+ const parcours = await parcoursService.getParcoursByNumParcours(numParcours);
+ const contrat = await contratService.getContratById(parcours.contrat);
+ const client = contrat?.["@expand"]?.client || {};
+ const user = await userService.getUserById(parcours.dernierUtilisateur);
+
+ // Récupérer la collection rc avec ses relations (APRÈS placerDansEnCours, c'est dans enCours)
+ const rcFull = contrat?.["@expand"]?.enCours;
+ if (!rcFull) {
+ logger.log('error', 'No RC found for contrat:', contrat.id);
+ return res.status(404).send("Aucune donnée RC trouvée pour ce contrat");
+ }
+
+ // Les données sont déjà expandées par contratService
+ const rc = rcFull?.["@expand"]?.tarifRC || {};
+ const rcMain = rcFull || {};
+
+ // Formatage des taux avec maximum 2 décimales
+ function formatTaux(taux) {
+ if (!taux) return 0;
+ return parseFloat(taux).toFixed(2);
+ }
+
+ // Préparer les données des activités avec leurs marchandises et activités complémentaires
+ const activites = [];
+
+ // Voiturier/Loueur
+ if (rcMain.checkVoiturier || rcMain.checkLoueur) {
+ activites.push({
+ type: 'Voiturier/Loueur',
+ capital: rcMain.capitalVoiturier || 0,
+ pourcentage: rc.pourcentageVoiturier || 0,
+ marchandises: rcMain.marchandisesVoiturier || [],
+ activitesCompl: rcMain.activitesVoiturier || []
+ });
+ }
+
+ // Commissionnaire de Transport
+ if (rcMain.checkCommissionnaire) {
+ activites.push({
+ type: 'Commissionnaire de Transport',
+ capital: rcMain.capitalCommissionnaire || 0,
+ pourcentage: rc.pourcentageCommissionnaire || 0,
+ marchandises: rcMain.marchandisesCommissionnaire || [],
+ activitesCompl: rcMain.activitesCommissionnaire || []
+ });
+ }
+
+ // Déménageur
+ if (rcMain.checkDemenageur) {
+ activites.push({
+ type: 'Déménageur',
+ capital: rcMain.capitalDemenageur || 0,
+ pourcentage: rc.pourcentageDemenageur || 0,
+ marchandises: rcMain.marchandisesDemenageur || [],
+ activitesCompl: rcMain.activitesDemenageur || []
+ });
+ }
+
+ // Logistique
+ if (rcMain.checkLogistique) {
+ activites.push({
+ type: 'Logistique',
+ capital: rcMain.capitalLogistique || 0,
+ pourcentage: rc.pourcentageLogistique || 0,
+ marchandises: rcMain.marchandisesLogistique || [],
+ activitesCompl: rcMain.activitesLogistique || []
+ });
+ }
+
+ // Autocariste
+ if (rcMain.checkAutocariste) {
+ activites.push({
+ type: 'Autocariste',
+ capital: rcMain.capitalAutocariste || 0,
+ pourcentage: rc.pourcentageAutocariste || 0,
+ marchandises: rcMain.marchandisesAutocariste || [],
+ activitesCompl: rcMain.activitesAutocariste || []
+ });
+ }
+
+ // Autres activités
+ if (rcMain.checkAutres) {
+ activites.push({
+ type: 'Autres activités',
+ capital: rcMain.capitalAutres || 0,
+ pourcentage: rc.pourcentageAutres || 0,
+ marchandises: rcMain.marchandisesAutres || [],
+ activitesCompl: rcMain.activitesAutres || []
+ });
+ }
+
+ // Préparer les zones
+ const zones = [];
+ if (rcMain.zone1) zones.push("Zone 1");
+ if (rcMain.zone2) zones.push("Zone 2");
+ if (rcMain.zone3) zones.push("Zone 3");
+ if (rcMain.zone4) zones.push("Zone 4");
+ if (rcMain.zone5) zones.push("Zone 5");
+ if (rcMain.zone6) zones.push("Zone 6");
+
+ // Préparer les garanties additionnelles
+ const garantiesAdditionnelles = [];
+ if (rc.checkStationLavage) garantiesAdditionnelles.push("Station de lavage");
+ if (rc.checkGarageInterne) garantiesAdditionnelles.push("Garage interne");
+ if (rc.checkCSE) garantiesAdditionnelles.push("CSE");
+ if (rc.checkTPPC) garantiesAdditionnelles.push(`TPPC (Capital: ${rc.capitalTPPC || 0}€, Véhicules: ${rc.vehiculesTPPC || 0})`);
+ if (rc.checkPJ) garantiesAdditionnelles.push("Protection Juridique");
+
+ // Préparer les engagements complémentaires
+ const engagements = [];
+ if (rc.checkDomImmat) engagements.push(`Dommages immatériels (Capital: ${rc.capitalDomImmat || 0}€)`);
+ if (rc.checkContConf) engagements.push(`Contenu confié (Capital: ${rc.capitalContConf || 0}€)`);
+ if (rc.checkDiffInv) engagements.push(`Différence d'inventaire (Capital: ${rc.capitalDiffInv || 0}€)`);
+
+ let dateNow = moment().format("DD MMMM YYYY");
+
+ doc.render({
+ // Infos générales
+ matricule: user.matricule,
+ date: dateNow,
+ typeCotisation: rcMain.typeCotisation || "Non défini",
+ hasforfaitaire: !(rcMain.typeCotisation === "forfaitaire" || (!rcMain.chiffreAffaires || rcMain.chiffreAffaires === 0)),
+ hasRCE: rcMain.checkRCE || false,
+ hasContrat: !!contrat.numContrat,
+ numContrat: contrat.numContrat,
+ hasSaisine: !!contrat.numSaisine,
+ numSaisine: contrat.numSaisine,
+ numeroCS: contrat.numSaisine || contrat.numContrat,
+ nomAssure: client.nom,
+ ca: rcMain.chiffreAffaires || 0,
+ hasNbVehicule: (rcMain.nombreVehicules || 0) > 0,
+ nbVehicule: rcMain.nombreVehicules || 0,
+
+ // Activités principales
+ hasVoiturierLoueur: rcMain.checkVoiturier || rcMain.checkLoueur,
+ capitalAssureVoiturierLoueur: rcMain.capitalVoiturier || 0,
+ pourcentageVoiturierLoueur: rc.pourcentageVoiturier || 0,
+ marchandiseVoiturierLoueur: rcMain.marchandisesVoiturier || [],
+ activiteVoiturierLoueur: rcMain.actComplVoiturier || [],
+
+ hasComTransport: rcMain.checkCommissionnaire || false,
+ capitalAssureComTransport: rcMain.capitalCommissionnaire || 0,
+ pourcentageComTransport: rc.pourcentageCommissionnaire || 0,
+ marchandiseComTransport: rcMain.marchandisesCommissionnaire || [],
+ activiteComTransport: rcMain.actComplCommissionnaire || [],
+
+ hasDemenageur: rcMain.checkDemenageur || false,
+ capitalAssureDemenageur: rcMain.capitalDemenageur || 0,
+ pourcentageDemenageur: rc.pourcentageDemenageur || 0,
+ marchandiseDemenageur: rcMain.marchandisesDemenageur || [],
+ activiteDemenageur: rcMain.actComplDemenageur || [],
+
+ hasLogistique: rcMain.checkLogistique || false,
+ capitalAssureLogistique: rcMain.capitalLogistique || 0,
+ pourcentageLogistique: rc.pourcentageLogistique || 0,
+ marchandiseLogistique: rcMain.marchandisesLogistique || [],
+ activiteLogistique: rcMain.actComplLogistique || [],
+
+ hasAutocariste: rcMain.checkAutocariste || false,
+ capitalAssureAutocariste: rcMain.capitalAutocariste || 0,
+ pourcentageAutocariste: rc.pourcentageAutocariste || 0,
+ marchandiseAutocariste: rcMain.marchandisesAutocariste || [],
+ activiteAutocariste: rcMain.activitesAutocariste || [],
+
+ hasAutre: rcMain.checkAutres || false,
+ capitalAssureAutre: rcMain.capitalAutres || 0,
+ pourcentageAutre: rc.pourcentageAutres || 0,
+ marchandiseAutre: rcMain.marchandisesAutres || [],
+ //activiteAutre: rcMain.activitesAutres || [], existe pas dans ejs
+
+ // Zones géographiques
+ zones: zones,
+
+ // Garanties additionnelles
+ hasGarantieAdd: garantiesAdditionnelles.length > 0,
+ garantieAdd: garantiesAdditionnelles,
+
+ // Engagements complémentaires
+ hasEngagement: engagements.length > 0,
+ engagement: engagements,
+
+ // Tarifs sélectionnés
+ franchise: rc.franchiseChoisie || rc.franchiseSelectionnee,
+ tarifReference: getSelectedTarifReference(rc),
+ tarifCommercial: rc.tarifcommercial,
+ primeRCC: getSelectedPrime(rc, 'RCC'),
+ tauxRCC: formatTaux(getSelectedTaux(rc, 'RCC')),
+ hasRCE: rcMain.checkRCE,
+ primeRCE: getSelectedPrime(rc, 'RCE'),
+ tauxRCE: formatTaux(getSelectedTaux(rc, 'RCE')),
+ hasPrimePJ: rc.checkPJ && getSelectedPrime(rc, 'PJ') > 0,
+ primePJ: getSelectedPrime(rc, 'PJ'),
+ tauxGlobal: formatTaux(getSelectedTaux(rc, 'Global')),
+
+
+ // Propositions franchise 250
+ tarifRefP1: rc.primeTotal_250 || 0,
+ pRCCP1: rc.primeRCC_250 || 0,
+ tRCCP1: formatTaux(rc.tauxRCC_250),
+ pRCEP1: rc.primeRCE_250 || 0,
+ tRCEP1: formatTaux(rc.tauxRCE_250),
+ primePJP1: rc.primePJ_250 || 0,
+ tauxGlobalP1: formatTaux(rc.tauxGlobal_250),
+
+ // Propositions franchise 400
+ tarifRefP2: rc.primeTotal_400 || 0,
+ pRCCP2: rc.primeRCC_400 || 0,
+ tRCCP2: formatTaux(rc.tauxRCC_400),
+ pRCEP2: rc.primeRCE_400 || 0,
+ tRCEP2: formatTaux(rc.tauxRCE_400),
+ primePJP2: rc.primePJ_400 || 0,
+ tauxGlobalP2: formatTaux(rc.tauxGlobal_400),
+
+ // Propositions franchise 2000
+ tarifRefP3: rc.primeTotal_2000 || 0,
+ pRCCP3: rc.primeRCC_2000 || 0,
+ tRCCP3: formatTaux(rc.tauxRCC_2000),
+ pRCEP3: rc.primeRCE_2000 || 0,
+ tRCEP3: formatTaux(rc.tauxRCE_2000),
+ primePJP3: rc.primePJ_2000 || 0,
+ tauxGlobalP3: formatTaux(rc.tauxGlobal_2000),
+ });
+
+ const buf = doc.getZip().generate({ type: "nodebuffer" });
+
+ const currentDate = new Date();
+
+ // Formatage de la date au format "JJ-MM-AAAA-HH-MM-SS"
+ const day = String(currentDate.getDate()).padStart(2, "0");
+ const month = String(currentDate.getMonth() + 1).padStart(2, "0");
+ const year = currentDate.getFullYear();
+ const hours = String(currentDate.getHours()).padStart(2, "0");
+ const minutes = String(currentDate.getMinutes()).padStart(2, "0");
+ const seconds = String(currentDate.getSeconds()).padStart(2, "0");
+ const formattedDate = `${day}-${month}-${year}-${hours}-${minutes}-${seconds}`;
+
+ const sanitizedClientNom = client.nom
+ .replace(/[^\w\s.-]/gi, "")
+ .replace(/\s+/g, "-");
+
+ const filename = `Tarif-RC-${parcours.numParcours}-${sanitizedClientNom}-${formattedDate}`;
+
+ res.setHeader(
+ "Content-Type",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+ );
+ res.setHeader("Content-Disposition", "attachment; filename=" + filename + ".docx");
+ res.send(buf);
+ } catch (error) {
+ logger.log("error", 'Error in RC tarif generation:', error);
+ return res.status(500).send("Erreur lors de la génération du tarif RC");
+ }
+});
+
+
+
+module.exports = router;
\ No newline at end of file
diff --git a/ecole/src/controllers/navParcoursController.js b/ecole/src/controllers/navParcoursController.js
index 7957d553..62cf03e5 100644
--- a/ecole/src/controllers/navParcoursController.js
+++ b/ecole/src/controllers/navParcoursController.js
@@ -22,7 +22,7 @@ router.get('/contrat', async (req, res) => {
});
router.get('/tarifrc', async (req, res) => {
- renderPage('dev.ejs', res, {}, true);
+ renderPage('tarifformrc.ejs', res, {}, true);
});
router.get('/tariffac', async (req, res) => {
diff --git a/ecole/src/controllers/rcController.js b/ecole/src/controllers/rcController.js
index 5eb55239..cc863d6e 100644
--- a/ecole/src/controllers/rcController.js
+++ b/ecole/src/controllers/rcController.js
@@ -1,12 +1,152 @@
const express = require('express');
const router = express.Router();
const rcService = require('../services/rcService');
+const constantesJSON = require("../constantes/json-modulateur-rc");
+const logger = require('../utils/logger');
+// ===== Routes RC principale =====
router.post('/create', async (req, res) => {
- const data = req.body;
- const rc = await rcService.createRc(data);
+ try {
+ const data = req.body;
+ const rc = await rcService.createRc(data);
+ res.json({ valid: Boolean(rc), rc });
+ } catch (error) {
+ logger.log("error", "Error creating RC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
- res.json({ valid: Boolean(rc), rc });
+router.get('/:id', async (req, res) => {
+ try {
+ const rc = await rcService.getRcById(req.params.id);
+ res.json({ valid: Boolean(rc), rc });
+ } catch (error) {
+ logger.log("error", "Error getting RC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+router.post('/update/:id', async (req, res) => {
+ try {
+ const rc = await rcService.updateRc(req.params.id, req.body);
+ res.json({ valid: Boolean(rc), rc });
+ } catch (error) {
+ logger.log("error", "Error updating RC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+// ===== Routes TarifRC =====
+router.post('/tarif/create', async (req, res) => {
+ try {
+ const data = req.body;
+ const tarifRc = await rcService.createTarifRc(data);
+ res.json({ valid: Boolean(tarifRc), tarifRc });
+ } catch (error) {
+ logger.log("error", "Error creating TarifRC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+router.get('/tarif/:id', async (req, res) => {
+ try {
+ const tarifRc = await rcService.getTarifRcById(req.params.id);
+ res.json({ valid: Boolean(tarifRc), tarifRc });
+ } catch (error) {
+ logger.log("error", "Error getting TarifRC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+router.post('/tarif/update/:id', async (req, res) => {
+ try {
+ const tarifRc = await rcService.updateTarifRc(req.params.id, req.body);
+ res.json({ valid: Boolean(tarifRc), tarifRc });
+ } catch (error) {
+ logger.log("error", "Error updating TarifRC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+// ===== Routes ProjetRC =====
+router.post('/projet/create', async (req, res) => {
+ try {
+ const data = req.body;
+ const projetRc = await rcService.createProjetRc(data);
+ res.json({ valid: Boolean(projetRc), projetRc });
+ } catch (error) {
+ logger.log("error", "Error creating ProjetRC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+router.get('/projet/:id', async (req, res) => {
+ try {
+ const projetRc = await rcService.getProjetRcById(req.params.id);
+ res.json({ valid: Boolean(projetRc), projetRc });
+ } catch (error) {
+ logger.log("error", "Error getting ProjetRC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+router.post('/projet/update/:id', async (req, res) => {
+ try {
+ const projetRc = await rcService.updateProjetRc(req.params.id, req.body);
+ res.json({ valid: Boolean(projetRc), projetRc });
+ } catch (error) {
+ logger.log("error", "Error updating ProjetRC:", error);
+ res.status(500).json({ valid: false, error: "Internal Server Error" });
+ }
+});
+
+// ===== Routes Modulateurs =====
+router.get("/modulo/:objDemande", async (req, res) => {
+ const objDemande = req.params.objDemande;
+ var objRetourne
+
+ switch (objDemande) {
+ case "CARC":
+ objRetourne = constantesJSON.modRCCA;
+ break;
+ case "activiteRCC":
+ objRetourne = constantesJSON.modRCActRCC;
+ break;
+ case "activiteRCE":
+ objRetourne = constantesJSON.modRCActRCE;
+ break;
+ case "activiteComplRC":
+ objRetourne = constantesJSON.modRCActCompl;
+ break;
+ case "marchandiseRC":
+ objRetourne = constantesJSON.modRCMar;
+ break;
+ case "zoneRC":
+ objRetourne = constantesJSON.modRCZone;
+ break;
+ case "engagComplRC":
+ objRetourne = constantesJSON.modRCEngagCompl;
+ break;
+ case "garAdditionelRC":
+ objRetourne = constantesJSON.modRCGarAdd ;
+ break;
+ case "sinistreRC":
+ objRetourne = constantesJSON.modRCSinistre;
+ break;
+ case "franchiseRC":
+ objRetourne = constantesJSON.modRCFranchise;
+ break;
+ case "primeMiniRC":
+ objRetourne = constantesJSON.modRCPrimeMini;
+ break;
+ }
+
+ try {
+ res.json({valid: Boolean(objRetourne), objRetourne});
+ } catch (error) {
+ logger.log("error", `Error finding constant ${objDemande}:`, error);
+ res.status(500).json({valid: false, error: "Internal Server Error"});
+ }
});
module.exports = router;
\ No newline at end of file
diff --git a/ecole/src/db/pb_data/data.db b/ecole/src/db/pb_data/data.db
index c7402141..8a065ea0 100644
Binary files a/ecole/src/db/pb_data/data.db and b/ecole/src/db/pb_data/data.db differ
diff --git a/ecole/src/db/pb_data/data.db-shm b/ecole/src/db/pb_data/data.db-shm
index fe9ac284..19889b16 100644
Binary files a/ecole/src/db/pb_data/data.db-shm and b/ecole/src/db/pb_data/data.db-shm differ
diff --git a/ecole/src/db/pb_data/data.db-wal b/ecole/src/db/pb_data/data.db-wal
index e69de29b..01d6ba37 100644
Binary files a/ecole/src/db/pb_data/data.db-wal and b/ecole/src/db/pb_data/data.db-wal differ
diff --git a/ecole/src/db/pb_data/logs.db b/ecole/src/db/pb_data/logs.db
index de9bbfb3..a9c46b80 100644
Binary files a/ecole/src/db/pb_data/logs.db and b/ecole/src/db/pb_data/logs.db differ
diff --git a/ecole/src/db/pb_data/logs.db-shm b/ecole/src/db/pb_data/logs.db-shm
index fdfdf0ac..85ce056d 100644
Binary files a/ecole/src/db/pb_data/logs.db-shm and b/ecole/src/db/pb_data/logs.db-shm differ
diff --git a/ecole/src/db/pb_data/logs.db-wal b/ecole/src/db/pb_data/logs.db-wal
index e6bc7706..df2eb83a 100644
Binary files a/ecole/src/db/pb_data/logs.db-wal and b/ecole/src/db/pb_data/logs.db-wal differ
diff --git a/ecole/src/services/contratService.js b/ecole/src/services/contratService.js
index e8f692ac..5fe56a10 100644
--- a/ecole/src/services/contratService.js
+++ b/ecole/src/services/contratService.js
@@ -45,14 +45,33 @@ async function createContrat() {
async function expandProjetTarif(resultat) {
const produit = resultat?.['produit'].toLowerCase()
- const idProjet = resultat?.['@expand']?.[produit]?.['projet'] || undefined
- const idTarif = resultat?.['@expand']?.[produit]?.['tarif'] || undefined
-
- const expand = {
- projet: (idProjet) ? await db.records.getOne(produit + "projet", idProjet) : null,
- tarif: (idTarif) ? await db.records.getOne(produit + "tarif", idTarif) : null
- }
+ // RC utilise tarifRC/projetRC, les autres produits utilisent tarif/projet
+ let idProjet, idTarif, collectionProjet, collectionTarif;
+ if (produit === 'rc') {
+ idProjet = resultat?.['@expand']?.[produit]?.['projetRC'] || undefined
+ idTarif = resultat?.['@expand']?.[produit]?.['tarifRC'] || undefined
+ collectionProjet = 'projetRC'; // Nom de collection RC
+ collectionTarif = 'tarifRC'; // Nom de collection RC
+ } else {
+ idProjet = resultat?.['@expand']?.[produit]?.['projet'] || undefined
+ idTarif = resultat?.['@expand']?.[produit]?.['tarif'] || undefined
+ collectionProjet = produit + "projet"; // tppcprojet, facprojet
+ collectionTarif = produit + "tarif"; // tppctarif, factarif (n'existe pas mais bon)
+ }
+
+ // Pour RC, inclure à la fois les clés RC spécifiques (tarifRC/projetRC) et les clés génériques (tarif/projet)
+ // afin de rester compatible avec l'ancien front qui lisait `tarif`/`projet`.
+ const expand = {
+ projet: idProjet ? await db.records.getOne(collectionProjet, idProjet) : null,
+ tarif: idTarif ? await db.records.getOne(collectionTarif, idTarif) : null,
+ };
+
+ if (produit === 'rc') {
+ expand.projetRC = expand.projet;
+ expand.tarifRC = expand.tarif;
+ }
+
resultat['@expand'][produit] = {...resultat['@expand'][produit], '@expand': expand}
return resultat
}
diff --git a/ecole/src/services/rcService.js b/ecole/src/services/rcService.js
index 736df79a..21171b96 100644
--- a/ecole/src/services/rcService.js
+++ b/ecole/src/services/rcService.js
@@ -1,10 +1,55 @@
const { db } = require('../db/db-connect');
const logger = require('../utils/logger');
+// ===== Collection RC principale =====
async function createRc(data) {
return await db.records.create('rc', data);
}
+async function getRcById(id) {
+ return await db.records.getOne('rc', id, {
+ expand: 'tarifRC,projetRC'
+ });
+}
+
+async function updateRc(id, data) {
+ return await db.records.update('rc', id, data);
+}
+
+// ===== Collection TarifRC =====
+async function createTarifRc(data) {
+ return await db.records.create('tarifRC', data);
+}
+
+async function getTarifRcById(id) {
+ return await db.records.getOne('tarifRC', id);
+}
+
+async function updateTarifRc(id, data) {
+ return await db.records.update('tarifRC', id, data);
+}
+
+// ===== Collection ProjetRC =====
+async function createProjetRc(data) {
+ return await db.records.create('projetRC', data);
+}
+
+async function getProjetRcById(id) {
+ return await db.records.getOne('projetRC', id);
+}
+
+async function updateProjetRc(id, data) {
+ return await db.records.update('projetRC', id, data);
+}
+
module.exports = {
- createRc
+ createRc,
+ getRcById,
+ updateRc,
+ createTarifRc,
+ getTarifRcById,
+ updateTarifRc,
+ createProjetRc,
+ getProjetRcById,
+ updateProjetRc
};
\ No newline at end of file
diff --git a/ecole/src/templates/template-declinaison-tarifaire-rc.docx b/ecole/src/templates/template-declinaison-tarifaire-rc.docx
new file mode 100644
index 00000000..64ad83ee
Binary files /dev/null and b/ecole/src/templates/template-declinaison-tarifaire-rc.docx differ
diff --git a/ecole/src/templates/template-projet-rc.docx b/ecole/src/templates/template-projet-rc.docx
index dc3031e5..f6b360ce 100644
Binary files a/ecole/src/templates/template-projet-rc.docx and b/ecole/src/templates/template-projet-rc.docx differ
diff --git a/ecole/views/layout.ejs b/ecole/views/layout.ejs
index 54099ed9..0ea299c6 100644
--- a/ecole/views/layout.ejs
+++ b/ecole/views/layout.ejs
@@ -63,6 +63,12 @@
+
+
+
+
+
+