chore(rc): push complet sync tarif/projet et donnees locales
This commit is contained in:
parent
cc7d3d9e08
commit
bb695a820e
|
|
@ -115,23 +115,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.src = scriptSrc
|
script.src = scriptSrc
|
||||||
script.className = 'dynamic-script';
|
script.className = 'dynamic-script';
|
||||||
document.body.appendChild(script);
|
script.onload = async function() {
|
||||||
|
|
||||||
if (submenu === "tarif" || submenu == "projet") {
|
if (submenu === "tarif" || submenu == "projet") {
|
||||||
//RELOAD PARCOURS & CONTRAT
|
try {
|
||||||
loadParcours(numParcours);
|
// Recharger les donnees avant d'initialiser le script du formulaire.
|
||||||
const parcours = JSON.parse(sessionStorage.getItem('parcours'));
|
await loadParcours(numParcours);
|
||||||
if (parcours) {
|
const latestParcours = JSON.parse(sessionStorage.getItem('parcours'));
|
||||||
const contratId = parcours?.["@expand"]?.contrat?.id || null;
|
const contratId = latestParcours?.["@expand"]?.contrat?.id || null;
|
||||||
loadContrat(contratId);
|
if (contratId) {
|
||||||
|
await loadContrat(contratId);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du rafraichissement parcours/contrat:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
script.onload = function() {
|
|
||||||
if (typeof window.initSubmenuForm === 'function') {
|
if (typeof window.initSubmenuForm === 'function') {
|
||||||
window.initSubmenuForm();
|
window.initSubmenuForm();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
document.body.appendChild(script);
|
||||||
|
|
||||||
document.querySelectorAll('input').forEach((input) => {
|
document.querySelectorAll('input').forEach((input) => {
|
||||||
input.addEventListener('input', function () {
|
input.addEventListener('input', function () {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,15 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* ═══════════════════════════════════════════════════════════════════════════
|
* Utilitaires de synchro RC (collecte + pré-remplissage Tarif/Projet).
|
||||||
* 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) {
|
(function(window) {
|
||||||
|
|
@ -22,10 +12,8 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping complet des champs entre Tarif et Projet.
|
* Mapping des champs Tarif <-> Projet.
|
||||||
* Permet la synchronisation bidirectionnelle.
|
* Format: { idTarif: idProjet }.
|
||||||
*
|
|
||||||
* Structure: { tarifFieldId: projetFieldId }
|
|
||||||
*/
|
*/
|
||||||
const FIELD_MAPPING = {
|
const FIELD_MAPPING = {
|
||||||
// Informations générales
|
// Informations générales
|
||||||
|
|
@ -87,14 +75,7 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collecte toutes les données du formulaire Tarif RC.
|
* Lit l'ensemble des champs utiles depuis le formulaire tarif.
|
||||||
* 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() {
|
function collectAllTarifData() {
|
||||||
// Références flexibles aux éléments
|
// Références flexibles aux éléments
|
||||||
|
|
@ -211,7 +192,8 @@
|
||||||
// ═══ SINISTRALITÉ ═══
|
// ═══ SINISTRALITÉ ═══
|
||||||
sinistralite: {
|
sinistralite: {
|
||||||
nombre3ans: toNumber(getValue('sinistre')),
|
nombre3ans: toNumber(getValue('sinistre')),
|
||||||
montant3ans: 0 // TODO: ajouter si champ existe
|
// Pas de champ montant dans le formulaire actuel.
|
||||||
|
montant3ans: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
// ═══ RÉSULTATS DE CALCUL ═══
|
// ═══ RÉSULTATS DE CALCUL ═══
|
||||||
|
|
@ -254,16 +236,12 @@
|
||||||
commentaire: getValue('commentaire') || ''
|
commentaire: getValue('commentaire') || ''
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('📊 Données Tarif collectées:', data);
|
console.log('Donnees tarif collectees:', data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fonction helper pour collecter les activités complémentaires depuis le formulaire.
|
* Récupère les activités complémentaires cochées pour un type d'activité.
|
||||||
*
|
|
||||||
* @param {string} typeActivite - Type d'activité ('voiturier', 'commissionnaire', etc.)
|
|
||||||
* @returns {string} JSON array des activités cochées
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
function collectActivitesComplJSON(typeActivite) {
|
function collectActivitesComplJSON(typeActivite) {
|
||||||
let name;
|
let name;
|
||||||
|
|
@ -354,7 +332,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('📝 Pré-remplissage Projet depuis Tarif...');
|
console.log('Pre-remplissage Projet depuis Tarif...');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// ═══ INFORMATIONS GÉNÉRALES ═══
|
// ═══ INFORMATIONS GÉNÉRALES ═══
|
||||||
|
|
@ -362,7 +340,7 @@
|
||||||
// CA
|
// CA
|
||||||
if (tarifData.ca) {
|
if (tarifData.ca) {
|
||||||
setValue('CA', tarifData.ca);
|
setValue('CA', tarifData.ca);
|
||||||
console.log(' ✓ CA:', tarifData.ca);
|
console.log(' CA:', tarifData.ca);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type de cotisation
|
// Type de cotisation
|
||||||
|
|
@ -370,14 +348,14 @@
|
||||||
const radio = document.querySelector(`input[name="typeCot"][value="${tarifData.typeCotisation}"]`);
|
const radio = document.querySelector(`input[name="typeCot"][value="${tarifData.typeCotisation}"]`);
|
||||||
if (radio) {
|
if (radio) {
|
||||||
radio.checked = true;
|
radio.checked = true;
|
||||||
console.log(' ✓ Type cotisation:', tarifData.typeCotisation);
|
console.log(' Type cotisation:', tarifData.typeCotisation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nombre de véhicules
|
// Nombre de véhicules
|
||||||
if (tarifData.nombreVehicules) {
|
if (tarifData.nombreVehicules) {
|
||||||
setValue('nombreVehicules', tarifData.nombreVehicules);
|
setValue('nombreVehicules', tarifData.nombreVehicules);
|
||||||
console.log(' ✓ Véhicules:', tarifData.nombreVehicules);
|
console.log(' Vehicules:', tarifData.nombreVehicules);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ ACTIVITÉS ═══
|
// ═══ ACTIVITÉS ═══
|
||||||
|
|
@ -416,7 +394,7 @@
|
||||||
const event = new Event('change', { bubbles: true });
|
const event = new Event('change', { bubbles: true });
|
||||||
activitySelector.dispatchEvent(event);
|
activitySelector.dispatchEvent(event);
|
||||||
|
|
||||||
console.log(' ✓ Activités:', activitesToAdd.length);
|
console.log(' Activites:', activitesToAdd.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ MARCHANDISES ═══
|
// ═══ MARCHANDISES ═══
|
||||||
|
|
@ -443,7 +421,7 @@
|
||||||
const event = new Event('change', { bubbles: true });
|
const event = new Event('change', { bubbles: true });
|
||||||
marchandiseSelector.dispatchEvent(event);
|
marchandiseSelector.dispatchEvent(event);
|
||||||
|
|
||||||
console.log(' ✓ Marchandises:', marchandisesToSelect.length);
|
console.log(' Marchandises:', marchandisesToSelect.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ ZONES GÉOGRAPHIQUES ═══
|
// ═══ ZONES GÉOGRAPHIQUES ═══
|
||||||
|
|
@ -457,7 +435,7 @@
|
||||||
zonesCount++;
|
zonesCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(' ✓ Zones:', zonesCount);
|
console.log(' Zones:', zonesCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ PROTECTION JURIDIQUE ═══
|
// ═══ PROTECTION JURIDIQUE ═══
|
||||||
|
|
@ -466,7 +444,7 @@
|
||||||
const switchPJ = document.getElementById('switchPJ');
|
const switchPJ = document.getElementById('switchPJ');
|
||||||
if (switchPJ) {
|
if (switchPJ) {
|
||||||
switchPJ.checked = true;
|
switchPJ.checked = true;
|
||||||
console.log(' ✓ PJ activée');
|
console.log(' PJ activee');
|
||||||
|
|
||||||
// Afficher la section PJ
|
// Afficher la section PJ
|
||||||
const pjSection = document.getElementById('pj-section');
|
const pjSection = document.getElementById('pj-section');
|
||||||
|
|
@ -480,7 +458,7 @@
|
||||||
const choixRCE = document.getElementById('choixRCE');
|
const choixRCE = document.getElementById('choixRCE');
|
||||||
if (choixRCE) {
|
if (choixRCE) {
|
||||||
choixRCE.checked = true;
|
choixRCE.checked = true;
|
||||||
console.log(' ✓ RCE activée');
|
console.log(' RCE activee');
|
||||||
|
|
||||||
// Afficher la section RCE
|
// Afficher la section RCE
|
||||||
const rceSection = document.getElementById('section-rce');
|
const rceSection = document.getElementById('section-rce');
|
||||||
|
|
@ -502,7 +480,7 @@
|
||||||
setValue('vehiculesTPPC', tarifData.garantiesAdditionnelles.tppc.vehicules);
|
setValue('vehiculesTPPC', tarifData.garantiesAdditionnelles.tppc.vehicules);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(' ✓ TPPC');
|
console.log(' TPPC');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -512,11 +490,11 @@
|
||||||
if (engagements) {
|
if (engagements) {
|
||||||
if (engagements.domicileImmatriculation?.checked) {
|
if (engagements.domicileImmatriculation?.checked) {
|
||||||
setValue('checkDomImmat', true);
|
setValue('checkDomImmat', true);
|
||||||
console.log(' ✓ Domicile immatriculation');
|
console.log(' Domicile immatriculation');
|
||||||
}
|
}
|
||||||
if (engagements.contenantConfie?.checked) {
|
if (engagements.contenantConfie?.checked) {
|
||||||
setValue('checkContConf', true);
|
setValue('checkContConf', true);
|
||||||
console.log(' ✓ Contenant confié');
|
console.log(' Contenant confie');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -529,7 +507,7 @@
|
||||||
if (tarifData.sinistralite.montant3ans) {
|
if (tarifData.sinistralite.montant3ans) {
|
||||||
setValue('montantSinistres3ans', tarifData.sinistralite.montant3ans);
|
setValue('montantSinistres3ans', tarifData.sinistralite.montant3ans);
|
||||||
}
|
}
|
||||||
console.log(' ✓ Sinistralité');
|
console.log(' Sinistralite');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ RÉSULTATS TARIFAIRES ═══
|
// ═══ RÉSULTATS TARIFAIRES ═══
|
||||||
|
|
@ -555,7 +533,7 @@
|
||||||
if (res.cotTotalHT) setValue('cotTotalHT', res.cotTotalHT);
|
if (res.cotTotalHT) setValue('cotTotalHT', res.cotTotalHT);
|
||||||
if (res.cotTotalTTC) setValue('cotTotalTTC', res.cotTotalTTC);
|
if (res.cotTotalTTC) setValue('cotTotalTTC', res.cotTotalTTC);
|
||||||
|
|
||||||
console.log(' ✓ Résultats tarifaires');
|
console.log(' Resultats tarifaires');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forcer la mise à jour des éléments Materialize
|
// Forcer la mise à jour des éléments Materialize
|
||||||
|
|
@ -567,10 +545,10 @@
|
||||||
window.M.updateTextFields();
|
window.M.updateTextFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Pré-remplissage Projet terminé');
|
console.log('Pre-remplissage Projet termine');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Erreur lors du pré-remplissage Projet:', error);
|
console.error('Erreur lors du pre-remplissage Projet:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -593,7 +571,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('📝 Pré-remplissage Tarif depuis Projet...');
|
console.log('Pre-remplissage Tarif depuis Projet...');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// CA
|
// CA
|
||||||
|
|
@ -624,10 +602,10 @@
|
||||||
setValue('checkRCE', true);
|
setValue('checkRCE', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Pré-remplissage Tarif terminé');
|
console.log('Pre-remplissage Tarif termine');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Erreur lors du pré-remplissage Tarif:', error);
|
console.error('Erreur lors du pre-remplissage Tarif:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -642,6 +620,6 @@
|
||||||
FIELD_MAPPING
|
FIELD_MAPPING
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('✅ RC Data Manager loaded');
|
console.log('RC Data Manager loaded');
|
||||||
|
|
||||||
})(window);
|
})(window);
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* ═══════════════════════════════════════════════════════════════════════════
|
* Orchestrateur de synchro RC entre les écrans Tarif et Projet.
|
||||||
* 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) {
|
(function(window) {
|
||||||
|
|
@ -18,12 +7,12 @@
|
||||||
|
|
||||||
// Attendre que les dépendances soient chargées
|
// Attendre que les dépendances soient chargées
|
||||||
if (!window.RCSync || !window.RCDataManager) {
|
if (!window.RCSync || !window.RCDataManager) {
|
||||||
console.error('❌ Dépendances RC Sync manquantes');
|
console.error('Dependances RC Sync manquantes');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isChangeImpactingTarif, showReturnToTarifModal } = window.RCSync;
|
const { isFieldImpactingTarif, showReturnToTarifModal } = window.RCSync;
|
||||||
const { collectAllTarifData, prefillProjetFromTarif, prefillTarifFromProjet } = window.RCDataManager;
|
const { collectAllTarifData, prefillTarifFromProjet } = window.RCDataManager;
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
// CONFIGURATION
|
// CONFIGURATION
|
||||||
|
|
@ -40,9 +29,7 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Détecte la page active (tarif ou projet) depuis l'URL.
|
* Détecte si on est sur la page tarif ou projet.
|
||||||
*
|
|
||||||
* @returns {'tarif'|'projet'|null} Page active ou null
|
|
||||||
*/
|
*/
|
||||||
function detectActivePage() {
|
function detectActivePage() {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
|
@ -57,50 +44,52 @@
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Détecte le produit courant à partir de la session.
|
||||||
|
*
|
||||||
|
* @returns {string|null} Code produit en minuscule
|
||||||
|
*/
|
||||||
|
function detectCurrentProduct() {
|
||||||
|
try {
|
||||||
|
const contrat = JSON.parse(sessionStorage.getItem('contrat') || 'null');
|
||||||
|
const fromContrat = contrat?.produit;
|
||||||
|
if (fromContrat) return String(fromContrat).toLowerCase();
|
||||||
|
|
||||||
|
const parcours = JSON.parse(sessionStorage.getItem('parcours') || 'null');
|
||||||
|
const fromParcours = parcours?.["@expand"]?.contrat?.produit;
|
||||||
|
return fromParcours ? String(fromParcours).toLowerCase() : null;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Impossible de lire le produit courant:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
// GESTION SESSIONSTORAGE
|
// GESTION SESSIONSTORAGE
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sauvegarde les données du tarif validé dans sessionStorage.
|
* Sauvegarde le snapshot du tarif validé en sessionStorage.
|
||||||
*
|
|
||||||
* @param {Object} tarifData - Données complètes du tarif
|
|
||||||
*/
|
*/
|
||||||
function saveTarifDataToSession(tarifData) {
|
function saveTarifDataToSession(tarifData) {
|
||||||
try {
|
try {
|
||||||
sessionStorage.setItem(SESSION_STORAGE_KEYS.TARIF_DATA, JSON.stringify(tarifData));
|
sessionStorage.setItem(SESSION_STORAGE_KEYS.TARIF_DATA, JSON.stringify(tarifData));
|
||||||
sessionStorage.setItem(SESSION_STORAGE_KEYS.TARIF_ORIGINAL, JSON.stringify(tarifData));
|
sessionStorage.setItem(SESSION_STORAGE_KEYS.TARIF_ORIGINAL, JSON.stringify(tarifData));
|
||||||
console.log('✅ Données tarif sauvegardées en session');
|
console.log('Donnees tarif sauvegardees en session');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Erreur sauvegarde session:', error);
|
console.error('Erreur sauvegarde session:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Récupère les données du tarif depuis sessionStorage.
|
* Lit les données tarif sauvegardées en sessionStorage.
|
||||||
*
|
|
||||||
* @returns {Object|null} Données du tarif ou null
|
|
||||||
*/
|
*/
|
||||||
function getTarifDataFromSession() {
|
function getTarifDataFromSession() {
|
||||||
try {
|
try {
|
||||||
const data = sessionStorage.getItem(SESSION_STORAGE_KEYS.TARIF_DATA);
|
const data = sessionStorage.getItem(SESSION_STORAGE_KEYS.TARIF_DATA);
|
||||||
return data ? JSON.parse(data) : null;
|
return data ? JSON.parse(data) : null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Erreur lecture session:', 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;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,13 +99,10 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook appelé après la validation du tarif commercial.
|
* Hook appelé après validation tarif pour garder l'état en session.
|
||||||
* 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() {
|
function onTarifValidated() {
|
||||||
console.log('🎯 Hook: Tarif validé, collecte des données...');
|
console.log('Hook tarif valide: collecte des donnees');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Collecter toutes les données du tarif
|
// Collecter toutes les données du tarif
|
||||||
|
|
@ -125,9 +111,9 @@
|
||||||
// Sauvegarder en session pour le pré-remplissage projet
|
// Sauvegarder en session pour le pré-remplissage projet
|
||||||
saveTarifDataToSession(tarifData);
|
saveTarifDataToSession(tarifData);
|
||||||
|
|
||||||
console.log('✅ Données tarif prêtes pour le projet');
|
console.log('Donnees tarif pretes pour le projet');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Erreur hook tarif validé:', error);
|
console.error('Erreur hook tarif valide:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,12 +122,17 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise le formulaire projet au chargement.
|
* Initialisation côté projet.
|
||||||
* Configure UNIQUEMENT la détection des changements impactants.
|
* Le pré-remplissage reste géré dans projet-form-rc.js.
|
||||||
* Le pré-remplissage est géré par prefillFromTarif() existant dans projet-form-RC.js
|
|
||||||
*/
|
*/
|
||||||
function initProjetPage() {
|
function initProjetPage() {
|
||||||
console.log('🚀 Initialisation RC Orchestrator pour page Projet...');
|
console.log('Initialisation RC Orchestrator pour la page Projet');
|
||||||
|
|
||||||
|
const currentProduct = detectCurrentProduct();
|
||||||
|
if (currentProduct === 'rc') {
|
||||||
|
console.log('Projet RC detecte: la gestion modal est deja faite dans projet-form-rc.js');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Les données rc/tarif/projet sont DÉJÀ chargées depuis la base
|
// Les données rc/tarif/projet sont DÉJÀ chargées depuis la base
|
||||||
// par le code existant dans projet-form-RC.js
|
// par le code existant dans projet-form-RC.js
|
||||||
|
|
@ -153,9 +144,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure la détection des changements impactants dans le projet.
|
* Fallback générique de détection d'impact sur la page 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() {
|
function setupProjetChangeDetection() {
|
||||||
// Les données originales sont dans les variables globales window.tarif et window.rc
|
// Les données originales sont dans les variables globales window.tarif et window.rc
|
||||||
|
|
@ -164,12 +153,12 @@
|
||||||
const rcOriginal = window.rc;
|
const rcOriginal = window.rc;
|
||||||
|
|
||||||
if (!tarifOriginal && !rcOriginal) {
|
if (!tarifOriginal && !rcOriginal) {
|
||||||
console.log('ℹ️ Pas de tarif/rc, pas de détection');
|
console.log('Pas de tarif/rc, pas de detection');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('👁️ Configuration détection changements...');
|
console.log('Configuration de la detection des changements');
|
||||||
console.log('📋 Données originales:', { tarif: tarifOriginal, rc: rcOriginal });
|
console.log('Donnees originales:', { tarif: tarifOriginal, rc: rcOriginal });
|
||||||
|
|
||||||
// Liste COMPLÈTE des éléments à surveiller (tous les champs impactants)
|
// Liste COMPLÈTE des éléments à surveiller (tous les champs impactants)
|
||||||
const elementsToWatch = [
|
const elementsToWatch = [
|
||||||
|
|
@ -212,14 +201,14 @@
|
||||||
const fieldName = this.id;
|
const fieldName = this.id;
|
||||||
const newValue = this.type === 'checkbox' ? this.checked : this.value;
|
const newValue = this.type === 'checkbox' ? this.checked : this.value;
|
||||||
|
|
||||||
console.log(`🔍 Changement détecté: ${fieldName} = ${newValue}`);
|
console.log(`Changement detecte: ${fieldName} = ${newValue}`);
|
||||||
|
|
||||||
// Vérifier si c'est un champ impactant
|
// Vérifier si c'est un champ impactant
|
||||||
if (isFieldImpactingTarif(fieldName)) {
|
if (isFieldImpactingTarif(fieldName)) {
|
||||||
console.warn(`⚠️ "${fieldName}" impacte le tarif !`);
|
console.warn(`"${fieldName}" impacte le tarif`);
|
||||||
showReturnToTarifModal(fieldName);
|
showReturnToTarifModal(fieldName);
|
||||||
} else {
|
} else {
|
||||||
console.log(`ℹ️ "${fieldName}" n'impacte pas le tarif`);
|
console.log(`"${fieldName}" n'impacte pas le tarif`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -228,8 +217,8 @@
|
||||||
const radioTypeCot = document.querySelectorAll('input[name="typeCot"]');
|
const radioTypeCot = document.querySelectorAll('input[name="typeCot"]');
|
||||||
radioTypeCot.forEach(radio => {
|
radioTypeCot.forEach(radio => {
|
||||||
radio.addEventListener('change', function() {
|
radio.addEventListener('change', function() {
|
||||||
console.log(`🔍 Changement type cotisation: ${this.value}`);
|
console.log(`Changement type cotisation: ${this.value}`);
|
||||||
console.warn(`⚠️ Type de cotisation impacte le tarif !`);
|
console.warn('Type de cotisation impacte le tarif');
|
||||||
showReturnToTarifModal('Type de cotisation');
|
showReturnToTarifModal('Type de cotisation');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -239,8 +228,8 @@
|
||||||
if (activitySelector) {
|
if (activitySelector) {
|
||||||
activitySelector.addEventListener('change', function() {
|
activitySelector.addEventListener('change', function() {
|
||||||
const selectedValues = Array.from(this.selectedOptions).map(opt => opt.value);
|
const selectedValues = Array.from(this.selectedOptions).map(opt => opt.value);
|
||||||
console.log(`🔍 Changement activités:`, selectedValues);
|
console.log('Changement activites:', selectedValues);
|
||||||
console.warn(`⚠️ Activités impactent le tarif !`);
|
console.warn('Activites impactent le tarif');
|
||||||
showReturnToTarifModal('Activités');
|
showReturnToTarifModal('Activités');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -250,8 +239,8 @@
|
||||||
if (marchandiseSelector) {
|
if (marchandiseSelector) {
|
||||||
marchandiseSelector.addEventListener('change', function() {
|
marchandiseSelector.addEventListener('change', function() {
|
||||||
const selectedValues = Array.from(this.selectedOptions).map(opt => opt.value);
|
const selectedValues = Array.from(this.selectedOptions).map(opt => opt.value);
|
||||||
console.log(`🔍 Changement marchandises:`, selectedValues);
|
console.log('Changement marchandises:', selectedValues);
|
||||||
console.warn(`⚠️ Marchandises impactent le tarif !`);
|
console.warn('Marchandises impactent le tarif');
|
||||||
showReturnToTarifModal('Marchandises');
|
showReturnToTarifModal('Marchandises');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -261,13 +250,13 @@
|
||||||
const btn = document.getElementById(btnId);
|
const btn = document.getElementById(btnId);
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
console.log(`🔍 Changement zones via ${btnId}`);
|
console.log(`Changement zones via ${btnId}`);
|
||||||
console.warn('⚠️ Zones géographiques impactent le tarif !');
|
console.warn('Zones geographiques impactent le tarif');
|
||||||
showReturnToTarifModal('Zones géographiques');
|
showReturnToTarifModal('Zones géographiques');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ Détection changements configurée sur tous les champs impactants');
|
console.log('Detection des changements configuree');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
@ -279,7 +268,7 @@
|
||||||
* Pré-remplit depuis le projet si l'utilisateur vient du projet.
|
* Pré-remplit depuis le projet si l'utilisateur vient du projet.
|
||||||
*/
|
*/
|
||||||
function initTarifPage() {
|
function initTarifPage() {
|
||||||
console.log('🚀 Initialisation page Tarif...');
|
console.log('Initialisation page Tarif');
|
||||||
|
|
||||||
// Vérifier si on vient du projet
|
// Vérifier si on vient du projet
|
||||||
const projetData = JSON.parse(sessionStorage.getItem(SESSION_STORAGE_KEYS.PROJET_DATA) || 'null');
|
const projetData = JSON.parse(sessionStorage.getItem(SESSION_STORAGE_KEYS.PROJET_DATA) || 'null');
|
||||||
|
|
@ -287,7 +276,7 @@
|
||||||
if (projetData && !getTarifDataFromSession()) {
|
if (projetData && !getTarifDataFromSession()) {
|
||||||
// On a des données projet mais pas de tarif validé
|
// On a des données projet mais pas de tarif validé
|
||||||
// = L'utilisateur a commencé par le projet
|
// = L'utilisateur a commencé par le projet
|
||||||
console.log('📥 Pré-remplissage depuis projet...');
|
console.log('Pre-remplissage depuis projet');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
prefillTarifFromProjet(projetData);
|
prefillTarifFromProjet(projetData);
|
||||||
|
|
@ -314,7 +303,7 @@
|
||||||
|
|
||||||
// Remplacer par notre version wrappée
|
// Remplacer par notre version wrappée
|
||||||
window.saveTarifRC = async function(...args) {
|
window.saveTarifRC = async function(...args) {
|
||||||
console.log('🎯 Interception saveTarifRC...');
|
console.log('Interception de saveTarifRC');
|
||||||
|
|
||||||
// Appeler la fonction originale
|
// Appeler la fonction originale
|
||||||
const result = await originalSaveTarifRC.apply(this, args);
|
const result = await originalSaveTarifRC.apply(this, args);
|
||||||
|
|
@ -327,7 +316,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('✅ saveTarifRC intercepté');
|
console.log('saveTarifRC intercepte');
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
|
@ -343,10 +332,10 @@
|
||||||
* Initialise l'orchestrateur au chargement de la page.
|
* Initialise l'orchestrateur au chargement de la page.
|
||||||
*/
|
*/
|
||||||
function init() {
|
function init() {
|
||||||
console.log('🎼 RC Sync Orchestrator: Démarrage...');
|
console.log('RC Sync Orchestrator: demarrage');
|
||||||
|
|
||||||
const activePage = detectActivePage();
|
const activePage = detectActivePage();
|
||||||
console.log(`📄 Page active détectée: ${activePage || 'aucune'}`);
|
console.log(`Page active detectee: ${activePage || 'aucune'}`);
|
||||||
|
|
||||||
if (activePage === 'tarif') {
|
if (activePage === 'tarif') {
|
||||||
interceptTarifValidation();
|
interceptTarifValidation();
|
||||||
|
|
@ -383,6 +372,6 @@
|
||||||
getTarifDataFromSession
|
getTarifDataFromSession
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('✅ RC Sync Orchestrator loaded');
|
console.log('RC Sync Orchestrator loaded');
|
||||||
|
|
||||||
})(window);
|
})(window);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* ═══════════════════════════════════════════════════════════════════════════
|
* Fonctions utilitaires partagées entre les écrans RC Tarif et Projet.
|
||||||
* 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) {
|
(function(window) {
|
||||||
|
|
@ -19,11 +10,8 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Liste exhaustive des champs qui impactent le calcul du tarif.
|
* Champs qui influencent le calcul du tarif.
|
||||||
* Si l'un de ces champs est modifié dans le projet, un modal
|
* On s'en sert pour savoir quand proposer un retour vers l'onglet Tarif.
|
||||||
* demandera à l'utilisateur de retourner au tarif.
|
|
||||||
*
|
|
||||||
* @constant {Array<string>}
|
|
||||||
*/
|
*/
|
||||||
const TARIF_IMPACTING_FIELDS = [
|
const TARIF_IMPACTING_FIELDS = [
|
||||||
// Chiffre d'affaires et type de contrat
|
// Chiffre d'affaires et type de contrat
|
||||||
|
|
@ -76,17 +64,8 @@
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convertit une valeur en nombre en gérant les formats français et internationaux.
|
* Convertit une valeur texte/nombre en nombre JS.
|
||||||
* Gère les espaces, virgules, points, et valeurs nulles/undefined.
|
* Accepte les formats FR/EN (espaces, virgules, points).
|
||||||
*
|
|
||||||
* @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) {
|
function toNumber(x) {
|
||||||
if (x == null) return 0;
|
if (x == null) return 0;
|
||||||
|
|
@ -130,15 +109,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Récupère la valeur d'un élément par son ID de manière flexible.
|
* Récupère un élément par id, avec fallback querySelector.
|
||||||
* 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) {
|
function getElementByIdFlexible(id) {
|
||||||
if (!id) return null;
|
if (!id) return null;
|
||||||
|
|
@ -152,15 +123,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Récupère la valeur d'un champ de formulaire de manière sécurisée.
|
* Lit la valeur d'un champ de formulaire selon son type.
|
||||||
* 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) {
|
function getValue(elementId) {
|
||||||
const element = getElementByIdFlexible(elementId);
|
const element = getElementByIdFlexible(elementId);
|
||||||
|
|
@ -181,15 +144,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Définit la valeur d'un champ de formulaire.
|
* Ecrit une valeur dans un champ de formulaire selon son type.
|
||||||
* 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) {
|
function setValue(elementId, value) {
|
||||||
const element = getElementByIdFlexible(elementId);
|
const element = getElementByIdFlexible(elementId);
|
||||||
|
|
@ -218,83 +173,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
|
||||||
// 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
|
// DÉTECTION DE CHANGEMENTS IMPACTANTS
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vérifie si un champ donné impacte le calcul du tarif.
|
* Dit si un nom de champ fait partie des champs qui influencent le 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) {
|
function isFieldImpactingTarif(fieldName) {
|
||||||
return TARIF_IMPACTING_FIELDS.some(field =>
|
return TARIF_IMPACTING_FIELDS.some(field =>
|
||||||
|
|
@ -302,74 +186,43 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
// MODAL DE RETOUR AU TARIF
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Affiche le modal demandant à l'utilisateur de retourner au tarif.
|
* Ouvre le modal "modif tarif" déjà présent dans la vue projet.
|
||||||
* 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) {
|
function showReturnToTarifModal(fieldName) {
|
||||||
const modalId = 'modalRetourTarif';
|
const modal = document.getElementById('modalModif');
|
||||||
let modal = document.getElementById(modalId);
|
|
||||||
|
|
||||||
// Créer le modal s'il n'existe pas
|
|
||||||
if (!modal) {
|
if (!modal) {
|
||||||
modal = createReturnToTarifModal();
|
console.warn('Modal "modalModif" introuvable');
|
||||||
document.body.appendChild(modal);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mettre à jour le message si un champ est spécifié
|
|
||||||
if (fieldName) {
|
if (fieldName) {
|
||||||
const messageEl = modal.querySelector('#modalRetourTarifMessage');
|
console.warn(`Modification impactant le tarif: ${fieldName}`);
|
||||||
if (messageEl) {
|
}
|
||||||
messageEl.innerHTML = `
|
|
||||||
Vous avez modifié <strong>"${fieldName}"</strong> qui impacte le calcul du tarif.
|
const okBtn = document.getElementById('modif-OK');
|
||||||
<br><br>
|
const noBtn = document.getElementById('modif-NO');
|
||||||
Vous devez retourner sur le formulaire Tarif pour recalculer et valider le nouveau tarif.
|
|
||||||
`;
|
if (okBtn) {
|
||||||
}
|
okBtn.onclick = (event) => {
|
||||||
|
event?.preventDefault?.();
|
||||||
|
navigateToTarif();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noBtn) {
|
||||||
|
noBtn.onclick = (event) => {
|
||||||
|
event?.preventDefault?.();
|
||||||
|
if (!window.M || !window.M.Modal) return;
|
||||||
|
const instance = window.M.Modal.getInstance(modal);
|
||||||
|
if (instance) instance.close();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ouvrir le modal
|
|
||||||
if (window.M && window.M.Modal) {
|
if (window.M && window.M.Modal) {
|
||||||
const instance = window.M.Modal.getInstance(modal) || window.M.Modal.init(modal);
|
const instance = window.M.Modal.getInstance(modal) || window.M.Modal.init(modal);
|
||||||
instance.open();
|
instance.open();
|
||||||
|
|
@ -377,50 +230,29 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crée l'élément DOM du modal de retour au tarif.
|
* Redirige vers l'onglet Tarif depuis le Projet.
|
||||||
*
|
|
||||||
* @returns {HTMLElement} Élément modal créé
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function createReturnToTarifModal() {
|
|
||||||
const modal = document.createElement('div');
|
|
||||||
modal.id = 'modalRetourTarif';
|
|
||||||
modal.className = 'modal';
|
|
||||||
|
|
||||||
modal.innerHTML = `
|
|
||||||
<div class="modal-content">
|
|
||||||
<h5>⚠️ Modification impactant le tarif</h5>
|
|
||||||
<p id="modalRetourTarifMessage">
|
|
||||||
Vous avez modifié une donnée qui impacte le calcul du tarif.
|
|
||||||
<br><br>
|
|
||||||
<strong>Vous devez retourner sur le formulaire Tarif pour recalculer et valider le nouveau tarif.</strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<a href="#!" class="modal-close waves-effect waves-red btn-flat">Annuler</a>
|
|
||||||
<a href="#!" class="waves-effect waves-green btn" onclick="window.RCSync.navigateToTarif()">
|
|
||||||
Aller au Tarif
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
return modal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigate vers l'onglet Tarif depuis le Projet.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* navigateToTarif();
|
|
||||||
*/
|
*/
|
||||||
function navigateToTarif() {
|
function navigateToTarif() {
|
||||||
// Fermer le modal
|
// Fermer le modal
|
||||||
const modal = document.getElementById('modalRetourTarif');
|
const modal = document.getElementById('modalModif');
|
||||||
if (modal && window.M) {
|
if (modal && window.M) {
|
||||||
const instance = window.M.Modal.getInstance(modal);
|
const instance = window.M.Modal.getInstance(modal);
|
||||||
if (instance) instance.close();
|
if (instance) instance.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Si on est sur le formulaire projet, on garde un snapshot local
|
||||||
|
// pour pré-remplir le tarif juste après la navigation.
|
||||||
|
try {
|
||||||
|
if (typeof window.collectProjetDataForTarifPrefill === 'function') {
|
||||||
|
const projetData = window.collectProjetDataForTarifPrefill();
|
||||||
|
if (projetData) {
|
||||||
|
sessionStorage.setItem('rc_projet_data', JSON.stringify(projetData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Impossible de stocker les donnees projet avant redirection:', error);
|
||||||
|
}
|
||||||
|
|
||||||
// Naviguer vers le tarif
|
// Naviguer vers le tarif
|
||||||
const numParcours = new URLSearchParams(window.location.search).get('numParcours');
|
const numParcours = new URLSearchParams(window.location.search).get('numParcours');
|
||||||
if (numParcours) {
|
if (numParcours) {
|
||||||
|
|
@ -434,7 +266,6 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API publique du module RC Sync.
|
* API publique du module RC Sync.
|
||||||
* Toutes les fonctions exportées ici sont accessibles via window.RCSync.
|
|
||||||
*/
|
*/
|
||||||
window.RCSync = {
|
window.RCSync = {
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
@ -443,13 +274,8 @@
|
||||||
setValue,
|
setValue,
|
||||||
getElementByIdFlexible,
|
getElementByIdFlexible,
|
||||||
|
|
||||||
// Comparaison
|
|
||||||
arraysEqual,
|
|
||||||
valuesEqual,
|
|
||||||
|
|
||||||
// Détection changements
|
// Détection changements
|
||||||
isFieldImpactingTarif,
|
isFieldImpactingTarif,
|
||||||
isChangeImpactingTarif,
|
|
||||||
|
|
||||||
// Modal
|
// Modal
|
||||||
showReturnToTarifModal,
|
showReturnToTarifModal,
|
||||||
|
|
@ -459,6 +285,6 @@
|
||||||
TARIF_IMPACTING_FIELDS
|
TARIF_IMPACTING_FIELDS
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('✅ RC Sync Utils loaded');
|
console.log('RC Sync Utils loaded');
|
||||||
|
|
||||||
})(window);
|
})(window);
|
||||||
|
|
|
||||||
|
|
@ -929,6 +929,327 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
// Le bouton Annuler ferme automatiquement le modal grâce à la classe "modal-close"
|
// Le bouton Annuler ferme automatiquement le modal grâce à la classe "modal-close"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parsePrefillArray(value) {
|
||||||
|
if (Array.isArray(value)) return value;
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
return Array.isArray(parsed) ? parsed : [];
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizePrefillValue(value) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value
|
||||||
|
.map((item) => normalizePrefillValue(item))
|
||||||
|
.sort((a, b) => String(a).localeCompare(String(b), 'fr'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
const normalized = {};
|
||||||
|
Object.keys(value).sort().forEach((key) => {
|
||||||
|
normalized[key] = normalizePrefillValue(value[key]);
|
||||||
|
});
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (!trimmed) return '';
|
||||||
|
const numeric = toNumber(trimmed);
|
||||||
|
if (!Number.isNaN(numeric) && trimmed.match(/^-?[\d\s,\.]+$/)) {
|
||||||
|
return numeric;
|
||||||
|
}
|
||||||
|
return trimmed.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) return null;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildProjetPrefillDelta(snapshot, baseline) {
|
||||||
|
if (!snapshot || typeof snapshot !== 'object') return null;
|
||||||
|
if (!baseline || typeof baseline !== 'object') return snapshot;
|
||||||
|
|
||||||
|
const delta = {};
|
||||||
|
Object.keys(snapshot).forEach((key) => {
|
||||||
|
const currentValue = normalizePrefillValue(snapshot[key]);
|
||||||
|
const baselineValue = normalizePrefillValue(baseline[key]);
|
||||||
|
|
||||||
|
if (JSON.stringify(currentValue) !== JSON.stringify(baselineValue)) {
|
||||||
|
delta[key] = snapshot[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.keys(delta).length > 0 ? delta : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyProjetDataToTarif(projetSource) {
|
||||||
|
if (!projetSource || typeof projetSource !== 'object') return;
|
||||||
|
|
||||||
|
const hasOwn = (key) => Object.prototype.hasOwnProperty.call(projetSource, key);
|
||||||
|
const hasAny = (keys) => keys.some(hasOwn);
|
||||||
|
const normalize = (value) => String(value || '')
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '')
|
||||||
|
.toLowerCase()
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
const toProjetNumber = (value) => {
|
||||||
|
if (value == null) return null;
|
||||||
|
const raw = String(value).trim();
|
||||||
|
if (!raw || raw.toLowerCase() === 'nous consulter') return null;
|
||||||
|
const parsed = toNumber(raw);
|
||||||
|
return Number.isFinite(parsed) ? parsed : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pickNumber = (...keys) => {
|
||||||
|
for (const key of keys) {
|
||||||
|
const parsed = toProjetNumber(projetSource[key]);
|
||||||
|
if (parsed != null) return parsed;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setCheckboxState = (id, checked, dispatchClick) => {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (!element) return;
|
||||||
|
element.checked = Boolean(checked);
|
||||||
|
if (dispatchClick) {
|
||||||
|
element.dispatchEvent(new Event('click'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setFirstValue = (elements, value) => {
|
||||||
|
if (value == null) return;
|
||||||
|
for (const element of elements) {
|
||||||
|
if (element) {
|
||||||
|
element.value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeCotisation = projetSource.typeCot || projetSource.typeCotisation;
|
||||||
|
if (typeCotisation) {
|
||||||
|
const radio = document.getElementById(typeCotisation) || document.querySelector(`input[name="cotisation"][value="${typeCotisation}"]`);
|
||||||
|
if (radio) {
|
||||||
|
radio.checked = true;
|
||||||
|
radio.dispatchEvent(new Event('change'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasOwn('ca')) {
|
||||||
|
const caField = getElementByIdFlexible('CA') || getElementByIdFlexible('chiffreAffaire');
|
||||||
|
if (caField) {
|
||||||
|
const rawCA = String(projetSource.ca || '').trim();
|
||||||
|
caField.value = (!rawCA || rawCA.toLowerCase() === 'nous consulter') ? '' : rawCA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nbVehiculeField = getElementByIdFlexible('nbVehicules') || getElementByIdFlexible('nbrVehicule');
|
||||||
|
const nbVehFromProjet = toProjetNumber(projetSource.nombreVehicules ?? projetSource.nbVehicules);
|
||||||
|
const nbVehFromTable = Array.isArray(projetSource.designationVehicule) ? projetSource.designationVehicule.length : null;
|
||||||
|
if (nbVehiculeField) {
|
||||||
|
if (nbVehFromProjet != null) {
|
||||||
|
nbVehiculeField.value = Math.max(0, Math.round(nbVehFromProjet));
|
||||||
|
} else if (nbVehFromTable != null && nbVehFromTable > 0) {
|
||||||
|
nbVehiculeField.value = nbVehFromTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const activityMappings = [
|
||||||
|
{
|
||||||
|
keys: ['actVoiturier', 'actLoueur'],
|
||||||
|
checkboxId: 'checkVoiturier',
|
||||||
|
capitalKeys: ['valueActVoiturier', 'valueActLoueur'],
|
||||||
|
capitalFields: [
|
||||||
|
getElementByIdFlexible('capitalVoiturier'),
|
||||||
|
document.querySelector('input[name="selectActVoiturier/Loueur"]')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: ['actMultimodal'],
|
||||||
|
checkboxId: 'checkCommissionnaire',
|
||||||
|
capitalKeys: ['valueActMultimodal'],
|
||||||
|
capitalFields: [
|
||||||
|
getElementByIdFlexible('capitalCommissionnaire'),
|
||||||
|
document.querySelector('input[name="selectActCommissionnaire de Transport"]'),
|
||||||
|
document.querySelector('input[name="selectActCommissionnaireDeTransport"]')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: ['actDemEntr', 'actDemInterne', 'actDemPar', 'actDemParDom', 'actDemParAdv', 'actGardeMeuble'],
|
||||||
|
checkboxId: 'checkDemenageur',
|
||||||
|
capitalKeys: ['valueActDemEntr', 'valueActDemInterne', 'valueActDemPar', 'valueActDemParDom', 'valueActDemParAdv'],
|
||||||
|
capitalFields: [
|
||||||
|
getElementByIdFlexible('capitalDemenageur'),
|
||||||
|
document.querySelector('input[name="selectActDéménageur"]'),
|
||||||
|
document.querySelector('input[name="selectActDemenageur"]')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: ['actPrestaLog', 'actEntDep'],
|
||||||
|
checkboxId: 'checkLogistique',
|
||||||
|
capitalKeys: ['valueActPrestaLog', 'valueActEntDep'],
|
||||||
|
capitalFields: [
|
||||||
|
getElementByIdFlexible('capitalLogistique'),
|
||||||
|
document.querySelector('input[name="selectActLogistique"]')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: ['actAutocariste'],
|
||||||
|
checkboxId: 'checkAutocariste',
|
||||||
|
capitalKeys: ['valueActAutocariste'],
|
||||||
|
capitalFields: [
|
||||||
|
getElementByIdFlexible('capitalAutocariste'),
|
||||||
|
document.querySelector('input[name="selectActAutocariste"]')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: ['actAutres'],
|
||||||
|
checkboxId: 'checkAutres',
|
||||||
|
capitalKeys: ['valueActAutres'],
|
||||||
|
capitalFields: [
|
||||||
|
getElementByIdFlexible('capitalAutres'),
|
||||||
|
document.querySelector('input[name="selectActAutres activites"]'),
|
||||||
|
document.querySelector('input[name="selectActAutresActivites"]')
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
activityMappings.forEach((mapping) => {
|
||||||
|
if (!hasAny(mapping.keys)) return;
|
||||||
|
const selected = mapping.keys.some((key) => Boolean(projetSource[key]));
|
||||||
|
setCheckboxState(mapping.checkboxId, selected, true);
|
||||||
|
if (selected) {
|
||||||
|
const capitalValue = pickNumber(...mapping.capitalKeys);
|
||||||
|
setFirstValue(mapping.capitalFields, capitalValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasAny(['zone1', 'zone2', 'zone3', 'zone4', 'zone5', 'zone6'])) {
|
||||||
|
const zone1 = Boolean(projetSource.zone1);
|
||||||
|
const zone2 = Boolean(projetSource.zone2);
|
||||||
|
const zone3 = Boolean(projetSource.zone3);
|
||||||
|
const zone4 = Boolean(projetSource.zone4);
|
||||||
|
const zone5 = Boolean(projetSource.zone5);
|
||||||
|
const zone6 = Boolean(projetSource.zone6);
|
||||||
|
|
||||||
|
const zone1El = document.getElementById('zone1');
|
||||||
|
const zone2El = document.getElementById('zone2');
|
||||||
|
const zone3El = document.getElementById('zone3');
|
||||||
|
const zone4El = document.getElementById('zone4');
|
||||||
|
const zone5El = document.getElementById('zone5');
|
||||||
|
const zone6El = document.getElementById('zone6');
|
||||||
|
|
||||||
|
if (zone1El) {
|
||||||
|
zone1El.checked = zone1 || zone2 || zone3;
|
||||||
|
zone1El.disabled = zone2 || zone3;
|
||||||
|
}
|
||||||
|
if (zone2El) {
|
||||||
|
zone2El.checked = zone2 || zone3;
|
||||||
|
zone2El.disabled = zone3;
|
||||||
|
}
|
||||||
|
if (zone3El) zone3El.checked = zone3;
|
||||||
|
if (zone4El) zone4El.checked = zone4;
|
||||||
|
if (zone5El) zone5El.checked = zone5;
|
||||||
|
if (zone6El) zone6El.checked = zone6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasOwn('autresRC')) {
|
||||||
|
setCheckboxState('checkRCE', Boolean(projetSource.autresRC), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasOwn('pj')) {
|
||||||
|
setCheckboxState('checkPJ', Boolean(projetSource.pj), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const activitesComplementairesMap = [
|
||||||
|
{ field: 'activitesVoiturier', container: 'actComplVoiturier/Loueur' },
|
||||||
|
{ field: 'activitesCommissionnaire', container: 'actComplCommissionnaire de Transport' },
|
||||||
|
{ field: 'activitesDemenageur', container: 'actComplDéménageur' },
|
||||||
|
{ field: 'activitesLogistique', container: 'actComplLogistique' }
|
||||||
|
];
|
||||||
|
|
||||||
|
activitesComplementairesMap.forEach(({ field, container }) => {
|
||||||
|
if (!hasOwn(field)) return;
|
||||||
|
const wanted = parsePrefillArray(projetSource[field]);
|
||||||
|
const wantedSet = new Set(wanted.map((item) => String(item).trim()));
|
||||||
|
const checkboxes = document.querySelectorAll(`[name="${container}"] input[type="checkbox"]`);
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
const label = checkbox.nextElementSibling ? checkbox.nextElementSibling.textContent.trim() : checkbox.value;
|
||||||
|
checkbox.checked = wantedSet.has(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const marchandiseKeys = [
|
||||||
|
'marOrdinaire',
|
||||||
|
'marRoulant',
|
||||||
|
'marEngins',
|
||||||
|
'marRoulantDem',
|
||||||
|
'marMobilerUsag',
|
||||||
|
'marPerissable',
|
||||||
|
'marAnimaux',
|
||||||
|
'marCiterne',
|
||||||
|
'marBeton',
|
||||||
|
'marExceptionnels',
|
||||||
|
'marVrac'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (hasAny(marchandiseKeys)) {
|
||||||
|
const flags = {
|
||||||
|
marOrdinaire: Boolean(projetSource.marOrdinaire),
|
||||||
|
marRoulant: Boolean(projetSource.marRoulant),
|
||||||
|
marEngins: Boolean(projetSource.marEngins),
|
||||||
|
marRoulantDem: Boolean(projetSource.marRoulantDem),
|
||||||
|
marMobilerUsag: Boolean(projetSource.marMobilerUsag),
|
||||||
|
marPerissable: Boolean(projetSource.marPerissable),
|
||||||
|
marAnimaux: Boolean(projetSource.marAnimaux),
|
||||||
|
marCiterne: Boolean(projetSource.marCiterne),
|
||||||
|
marBeton: Boolean(projetSource.marBeton),
|
||||||
|
marExceptionnels: Boolean(projetSource.marExceptionnels),
|
||||||
|
marVrac: Boolean(projetSource.marVrac)
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldSelectMarchandise = (label) => {
|
||||||
|
const text = normalize(label);
|
||||||
|
if (!text) return false;
|
||||||
|
if (flags.marRoulantDem && text.includes('vehicules roulants') && text.includes('demenagement')) return true;
|
||||||
|
if (flags.marRoulant && text.includes('vehicules roulants') && !text.includes('demenagement')) return true;
|
||||||
|
if (flags.marOrdinaire && text.includes('ordinaires')) return true;
|
||||||
|
if (flags.marEngins && text.includes('engins de chantier')) return true;
|
||||||
|
if (flags.marMobilerUsag && text.includes('mobiliers')) return true;
|
||||||
|
if (flags.marPerissable && text.includes('perissables')) return true;
|
||||||
|
if (flags.marAnimaux && text.includes('animaux vivants')) return true;
|
||||||
|
if (flags.marCiterne && text.includes('citerne')) return true;
|
||||||
|
if (flags.marBeton && text.includes('beton')) return true;
|
||||||
|
if (flags.marExceptionnels && text.includes('exceptionnels')) return true;
|
||||||
|
if (flags.marVrac && (text.includes('benne') || text.includes('vrac'))) return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
'marVoiturier/Loueur',
|
||||||
|
'marCommissionnaire de Transport',
|
||||||
|
'marDéménageur',
|
||||||
|
'marLogistique',
|
||||||
|
'marAutocariste',
|
||||||
|
'marAutres activites'
|
||||||
|
].forEach((container) => {
|
||||||
|
const checkboxes = document.querySelectorAll(`[name="${container}"] input[type="checkbox"]`);
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
const label = checkbox.nextElementSibling ? checkbox.nextElementSibling.textContent : checkbox.value;
|
||||||
|
checkbox.checked = shouldSelectMarchandise(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Peupler le formulaire avec les données
|
// Peupler le formulaire avec les données
|
||||||
function populateFormData() {
|
function populateFormData() {
|
||||||
//Poupulate select historique
|
//Poupulate select historique
|
||||||
|
|
@ -984,7 +1305,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔄 Pré-remplissage du formulaire tarif avec les données RC:', rc);
|
console.log('Pre-remplissage du formulaire tarif avec les donnees RC:', rc);
|
||||||
|
|
||||||
// Type de cotisation
|
// Type de cotisation
|
||||||
if (rc.typeCotisation) {
|
if (rc.typeCotisation) {
|
||||||
|
|
@ -1095,7 +1416,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
{ field: 'actComplLogistique', name: 'actComplLogistique' }
|
{ field: 'actComplLogistique', name: 'actComplLogistique' }
|
||||||
];
|
];
|
||||||
|
|
||||||
console.log('🔄 Pré-remplissage des activités complémentaires...');
|
console.log('Pre-remplissage des activites complementaires...');
|
||||||
activitiesTypes.forEach(({ field, name }) => {
|
activitiesTypes.forEach(({ field, name }) => {
|
||||||
// D'abord DÉCOCHER toutes les checkboxes de cette activité
|
// D'abord DÉCOCHER toutes les checkboxes de cette activité
|
||||||
const allCheckboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]`);
|
const allCheckboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]`);
|
||||||
|
|
@ -1105,18 +1426,18 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
try {
|
try {
|
||||||
// PocketBase parse automatiquement les champs JSON, donc rc[field] est déjà un array
|
// 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]);
|
const activites = Array.isArray(rc[field]) ? rc[field] : JSON.parse(rc[field]);
|
||||||
console.log(` ✓ ${field}:`, activites);
|
console.log(` ${field}:`, activites);
|
||||||
activites.forEach(actText => {
|
activites.forEach(actText => {
|
||||||
// Chercher la checkbox dont le span adjacent contient ce texte
|
// Chercher la checkbox dont le span adjacent contient ce texte
|
||||||
allCheckboxes.forEach(cb => {
|
allCheckboxes.forEach(cb => {
|
||||||
const label = cb.nextElementSibling?.textContent.trim();
|
const label = cb.nextElementSibling?.textContent.trim();
|
||||||
if (label === actText) {
|
if (label === actText) {
|
||||||
cb.checked = true;
|
cb.checked = true;
|
||||||
console.log(` ✓ Coché: ${actText}`);
|
console.log(` Coche: ${actText}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (e) { console.error(`❌ Erreur parsing ${field}:`, e); }
|
} catch (e) { console.error(`Erreur parsing ${field}:`, e); }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1130,7 +1451,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
{ field: 'marchandisesAutres', name: 'marAutres activites' }
|
{ field: 'marchandisesAutres', name: 'marAutres activites' }
|
||||||
];
|
];
|
||||||
|
|
||||||
console.log('🔄 Pré-remplissage des marchandises...');
|
console.log('Pre-remplissage des marchandises...');
|
||||||
marchandisesTypes.forEach(({ field, name }) => {
|
marchandisesTypes.forEach(({ field, name }) => {
|
||||||
// D'abord DÉCOCHER toutes les checkboxes de cette marchandise
|
// D'abord DÉCOCHER toutes les checkboxes de cette marchandise
|
||||||
const allCheckboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]`);
|
const allCheckboxes = document.querySelectorAll(`[name="${name}"] input[type="checkbox"]`);
|
||||||
|
|
@ -1140,18 +1461,18 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
try {
|
try {
|
||||||
// PocketBase parse automatiquement les champs JSON, donc rc[field] est déjà un array
|
// 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]);
|
const marchandises = Array.isArray(rc[field]) ? rc[field] : JSON.parse(rc[field]);
|
||||||
console.log(` ✓ ${field}:`, marchandises);
|
console.log(` ${field}:`, marchandises);
|
||||||
marchandises.forEach(marText => {
|
marchandises.forEach(marText => {
|
||||||
// Chercher la checkbox dont le span adjacent contient ce texte
|
// Chercher la checkbox dont le span adjacent contient ce texte
|
||||||
allCheckboxes.forEach(cb => {
|
allCheckboxes.forEach(cb => {
|
||||||
const label = cb.nextElementSibling?.textContent.trim();
|
const label = cb.nextElementSibling?.textContent.trim();
|
||||||
if (label === marText) {
|
if (label === marText) {
|
||||||
cb.checked = true;
|
cb.checked = true;
|
||||||
console.log(` ✓ Coché: ${marText}`);
|
console.log(` Coche: ${marText}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (e) { console.error(`❌ Erreur parsing ${field}:`, e); }
|
} catch (e) { console.error(`Erreur parsing ${field}:`, e); }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1160,8 +1481,8 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
ensureDefaultMarchandisesVoiturier();
|
ensureDefaultMarchandisesVoiturier();
|
||||||
|
|
||||||
// Pré-remplir les pourcentages (depuis tarifRC)
|
// Pré-remplir les pourcentages (depuis tarifRC)
|
||||||
// Préférer l'objet tarif si présent, sinon retomber sur l'expansion RC
|
// Priorité au tarif persistant; ne pas retomber sur rc pour ces champs.
|
||||||
const tarifSource = tarif || rc?.["@expand"]?.tarifRC || rc?.tarifRC || rc || null;
|
const tarifSource = tarif || rc?.["@expand"]?.tarifRC || rc?.tarifRC || null;
|
||||||
// Fallback ultime : données de session (hook RC orchestrator) si tout est vide
|
// Fallback ultime : données de session (hook RC orchestrator) si tout est vide
|
||||||
let sessionTarifData = null;
|
let sessionTarifData = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -1268,7 +1589,33 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Formulaire tarif pré-rempli avec succès');
|
// Pré-remplissage Projet -> Tarif
|
||||||
|
// - si snapshot session: appliquer seulement les champs modifies sur Projet
|
||||||
|
// - sinon: utiliser Projet uniquement si on n'a pas de tarif persistant
|
||||||
|
let sessionProjetData = null;
|
||||||
|
try {
|
||||||
|
const storedProjetData = sessionStorage.getItem('rc_projet_data');
|
||||||
|
sessionProjetData = storedProjetData ? JSON.parse(storedProjetData) : null;
|
||||||
|
} catch (error) {
|
||||||
|
sessionProjetData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let projetPrefillSource = null;
|
||||||
|
if (sessionProjetData) {
|
||||||
|
projetPrefillSource = buildProjetPrefillDelta(sessionProjetData, projet);
|
||||||
|
} else if (!tarifSource && !sessionTarifData && projet) {
|
||||||
|
projetPrefillSource = projet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projetPrefillSource) {
|
||||||
|
applyProjetDataToTarif(projetPrefillSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionProjetData) {
|
||||||
|
sessionStorage.removeItem('rc_projet_data');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Formulaire tarif pre-rempli avec succes');
|
||||||
|
|
||||||
// Recalculer après pré-remplissage
|
// Recalculer après pré-remplissage
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -2967,8 +3314,8 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== LOGS DE DÉBOGAGE =====
|
// ===== LOGS DE DÉBOGAGE =====
|
||||||
console.log('📊 === DÉBUT SAUVEGARDE TARIF RC ===');
|
console.log('=== DEBUT SAUVEGARDE TARIF RC ===');
|
||||||
console.log('🔍 rcMainData:', rcMainData);
|
console.log('rcMainData:', rcMainData);
|
||||||
|
|
||||||
// ===== ÉTAPE 2: Collecter les résultats de calculs pour tarifRC =====
|
// ===== ÉTAPE 2: Collecter les résultats de calculs pour tarifRC =====
|
||||||
const tarifRCData = {
|
const tarifRCData = {
|
||||||
|
|
@ -3068,7 +3415,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
// ===== ÉTAPE 3: Sauvegarder/Mettre à jour tarifRC =====
|
// ===== ÉTAPE 3: Sauvegarder/Mettre à jour tarifRC =====
|
||||||
if (tarif && tarif.id) {
|
if (tarif && tarif.id) {
|
||||||
// Mettre à jour un enregistrement tarifRC existant
|
// Mettre à jour un enregistrement tarifRC existant
|
||||||
console.log(`📝 Mise à jour tarifRC existant (ID: ${tarif.id})`);
|
console.log(`Mise a jour tarifRC existant (ID: ${tarif.id})`);
|
||||||
const response = await fetch(`/rc/tarif/update/${tarif.id}`, {
|
const response = await fetch(`/rc/tarif/update/${tarif.id}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(tarifRCData),
|
body: JSON.stringify(tarifRCData),
|
||||||
|
|
@ -3077,16 +3424,16 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log('📥 Réponse serveur tarifRC update:', data);
|
console.log('Reponse serveur tarifRC update:', data);
|
||||||
if (data.valid) {
|
if (data.valid) {
|
||||||
idTarifRC = data.tarifRc.id;
|
idTarifRC = data.tarifRc.id;
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Échec de la mise à jour de tarifRC:', data.message);
|
console.error('Echec de la mise a jour de tarifRC:', data.message);
|
||||||
return { valid: false, message: data.message };
|
return { valid: false, message: data.message };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Créer un nouvel enregistrement tarifRC
|
// Créer un nouvel enregistrement tarifRC
|
||||||
console.log('📝 Création nouveau tarifRC');
|
console.log('Creation nouveau tarifRC');
|
||||||
const response = await fetch(`/rc/tarif/create`, {
|
const response = await fetch(`/rc/tarif/create`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(tarifRCData),
|
body: JSON.stringify(tarifRCData),
|
||||||
|
|
@ -3095,11 +3442,11 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log('📥 Réponse serveur tarifRC create:', data);
|
console.log('Reponse serveur tarifRC create:', data);
|
||||||
if (data.valid) {
|
if (data.valid) {
|
||||||
idTarifRC = data.tarifRc.id;
|
idTarifRC = data.tarifRc.id;
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Échec de la création de tarifRC:', data.message);
|
console.error('Echec de la creation de tarifRC:', data.message);
|
||||||
return { valid: false, message: data.message };
|
return { valid: false, message: data.message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3107,8 +3454,8 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
// ===== ÉTAPE 4: Mettre à jour RC principal avec les données communes ET la référence tarifRC =====
|
// ===== É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
|
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(`Mise a jour RC principal (ID: ${rcId}) avec reference tarifRC: ${idTarifRC}`);
|
||||||
console.log('🔍 Données envoyées pour RC:', rcMainData);
|
console.log('Donnees envoyees pour RC:', rcMainData);
|
||||||
|
|
||||||
const updateRCResponse = await fetch(`/rc/update/${rcId}`, {
|
const updateRCResponse = await fetch(`/rc/update/${rcId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
@ -3118,15 +3465,15 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const updateRCData = await updateRCResponse.json();
|
const updateRCData = await updateRCResponse.json();
|
||||||
console.log('📥 Réponse serveur RC update:', updateRCData);
|
console.log('Reponse serveur RC update:', updateRCData);
|
||||||
|
|
||||||
if (!updateRCData.valid) {
|
if (!updateRCData.valid) {
|
||||||
console.error('❌ Échec de la mise à jour de RC principal:', updateRCData.message);
|
console.error('Echec de la mise a jour de RC principal:', updateRCData.message);
|
||||||
return { valid: false, message: 'Échec mise à jour RC principal' };
|
return { valid: false, message: 'Échec mise à jour RC principal' };
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ === TARIF RC SAUVEGARDÉ AVEC SUCCÈS ===');
|
console.log('=== TARIF RC SAUVEGARDE AVEC SUCCES ===');
|
||||||
console.log('✅ RC ID:', rcId, '| TarifRC ID:', idTarifRC);
|
console.log('RC ID:', rcId, '| TarifRC ID:', idTarifRC);
|
||||||
return { valid: true, idTarifRC, idRC: rcId };
|
return { valid: true, idTarifRC, idRC: rcId };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la sauvegarde de tarifRC:', error);
|
console.error('Erreur lors de la sauvegarde de tarifRC:', error);
|
||||||
|
|
@ -3374,7 +3721,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
window.modalTarifCom.close();
|
window.modalTarifCom.close();
|
||||||
|
|
||||||
// Afficher un loader
|
// Afficher un loader
|
||||||
M.toast({html: '⏳ Sauvegarde en cours...', classes: 'blue'});
|
M.toast({html: 'Sauvegarde en cours...', classes: 'blue'});
|
||||||
|
|
||||||
// Sauvegarder le tarif
|
// Sauvegarder le tarif
|
||||||
const saveResult = await saveTarifRC();
|
const saveResult = await saveTarifRC();
|
||||||
|
|
@ -3384,7 +3731,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
|
|
||||||
// Rediriger vers la page projet après un court délai
|
// Rediriger vers la page projet après un court délai
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log('🚀 Redirection vers projet...');
|
console.log('Redirection vers projet...');
|
||||||
// Construire l'URL de redirection vers projet
|
// Construire l'URL de redirection vers projet
|
||||||
const numParcours = parcours?.numParcours;
|
const numParcours = parcours?.numParcours;
|
||||||
if (numParcours) {
|
if (numParcours) {
|
||||||
|
|
@ -3394,7 +3741,7 @@ window.initSubmenuForm = initSubmenuForm;// Module IIFE pour éviter la pollutio
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
M.toast({html: '❌ Erreur lors de la sauvegarde du tarif', classes: 'red'});
|
M.toast({html: 'Erreur lors de la sauvegarde du tarif', classes: 'red'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue