feat: ajouter region_csc à toutes les références marchés

Implémente buildRef(r) dans calc.js :
  ref = id_marche + ' - ' + region_csc  (ex: AO 58/2024 : Lot01 - ULS Gabes)

Propagé dans :
- services/calc.js       → champ ref de normalizeMarche()
- services/export-xlsx.js → toutes les cellules référence
- routes/export.js        → PPTX + DOCX (3 occurrences)
- index.html              → normalizeMarche() champ id_marche

export-pdf.js déjà couvert via r.ref (utilise normalizeMarche)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nabil Derouiche 2026-04-19 10:40:07 +01:00
parent 2074893978
commit 7ca0eccb96
4 changed files with 26 additions and 12 deletions

View File

@ -741,10 +741,16 @@ function buildRegionOptions(selectId, includeAll = true) {
}
/* ── NORMALIZE API FIELDS ── */
function buildRef(r) {
const base = r.id_marche || r.reference || '';
const reg = r.region_csc || r.region || '';
return reg ? `${base} - ${reg}` : base;
}
function normalizeMarche(r) {
return {
...r,
id_marche: r.id_marche || r.reference || '',
id_marche: buildRef(r),
region: r.region || r.region_csc || '',
taux_phy: parseNum(r.taux_phy ?? r.avt_phy ?? 0),
tot_marche: parseNum(r.tot_marche ?? r.m_max ?? r.totmarche ?? 0),

View File

@ -13,6 +13,7 @@ const {
isCloture, normalizeMarche, parseNum, formatMontant, selectVal,
getDelaiRestant, niveauAlerte, niveauAvancement, niveauRisque,
DELAI_CRITIQUE, DELAI_ATTENTION, SEUIL_STANDARD, SEUIL_CRITIQUE_PCT,
buildRef,
} = require('../services/calc');
const pdfGen = require('../services/export-pdf');
@ -50,7 +51,7 @@ async function buildViewData(view, req) {
const alertes = actifs
.map(r=>({...r,_d:getDelaiRestant(r)}))
.filter(r=>r._d!==null&&r._d<=DELAI_ATTENTION)
.map(r=>({ref:r.id_marche||r.reference||'',projet:r.projet||'',region:r.region||'',entrepreneur:r.entrepreneur||'',delai_restant:r._d,niveau:niveauAlerte(r._d)}))
.map(r=>({ref:buildRef(r),projet:r.projet||'',region:r.region||'',entrepreneur:r.entrepreneur||'',delai_restant:r._d,niveau:niveauAlerte(r._d)}))
.sort((a,b)=>a.delai_restant-b.delai_restant);
return {
total: rows.length, actifs: actifs.length, clotures: clotures.length,
@ -315,7 +316,7 @@ router.get('/pptx', async (req, res) => {
const alertRows = alerteItems.slice(0, 18).map(r => {
const alColor = r._d <= DELAI_CRITIQUE ? 'EF4444' : 'EA580C';
return [
{ text: r.id_marche||r.reference||'', options: { fontSize: 8, color: 'CBD5E1' } },
{ text: buildRef(r), options: { fontSize: 8, color: 'CBD5E1' } },
{ text: r.projet||'', options: { fontSize: 8, color: 'CBD5E1' } },
{ text: r.region||'', options: { fontSize: 8, color: 'CBD5E1' } },
{ text: r.entrepreneur||'', options: { fontSize: 8, color: 'CBD5E1' } },
@ -355,7 +356,7 @@ router.get('/pptx', async (req, res) => {
const t = parseN(r.taux_phy||r.avt_phy);
const res = classify(r);
return [
{ text: r.id_marche||r.reference||'', options: { fontSize: 8, color: 'CBD5E1' } },
{ text: buildRef(r), options: { fontSize: 8, color: 'CBD5E1' } },
{ text: r.projet||'', options: { fontSize: 8, color: 'CBD5E1' } },
{ text: r.region||'', options: { fontSize: 8, color: 'CBD5E1' } },
{ text: r.entrepreneur||'', options: { fontSize: 8, color: 'CBD5E1' } },
@ -564,7 +565,7 @@ router.get('/docx', async (req, res) => {
rows: [
tr([['Référence',2500,navyFill],['Projet',3000,navyFill],['Région',1200,navyFill],['Délai (j)',1200,navyFill]], true),
...alerteItems.slice(0,20).map((r, i) => tr([
[r.id_marche||r.reference||'', 2500, i%2===1?altFill:undefined],
[buildRef(r), 2500, i%2===1?altFill:undefined],
[r.projet||'', 3000, i%2===1?altFill:undefined],
[r.region||'', 1200, i%2===1?altFill:undefined],
[String(r._d||'—'), 1200, i%2===1?altFill:undefined],
@ -594,7 +595,7 @@ router.get('/docx', async (req, res) => {
...regActifs.map((r, i) => {
const phy = parseN(r.taux_phy||r.avt_phy);
return tr([
[r.id_marche||r.reference||'', 2500, i%2===1?altFill:undefined],
[buildRef(r), 2500, i%2===1?altFill:undefined],
[r.projet||'', 2800, i%2===1?altFill:undefined],
[r.entrepreneur||'', 2000, i%2===1?altFill:undefined],
[fmtPct(phy), 700, i%2===1?altFill:undefined],
@ -620,7 +621,7 @@ router.get('/docx', async (req, res) => {
rows: [
tr([['Référence',2200,navyFill],['Projet',2500,navyFill],['Région',1000,navyFill],['Entrepreneur',1800,navyFill],['Phy %',700,navyFill],['Résultat',1300,navyFill]], true),
...pilotItems.map(({ r, res, phy }, i) => tr([
[r.id_marche||r.reference||'', 2200, i%2===1?altFill:undefined],
[buildRef(r), 2200, i%2===1?altFill:undefined],
[r.projet||'', 2500, i%2===1?altFill:undefined],
[r.region||'', 1000, i%2===1?altFill:undefined],
[r.entrepreneur||'', 1800, i%2===1?altFill:undefined],

View File

@ -139,6 +139,12 @@ function niveauRisque(r) {
// ─── Normalisation d'un marché ───────────────────────────────────────────────
function buildRef(r) {
const base = r.id_marche || r.reference || String(r.id || '');
const reg = r.region_csc || r.region || '';
return reg ? `${base} - ${reg}` : base;
}
function normalizeMarche(r) {
const obsValue = selectVal(r.observation);
const natureValue = selectVal(r.nature);
@ -152,7 +158,7 @@ function normalizeMarche(r) {
return {
id: r.id,
ref: r.id_marche || r.reference || String(r.id || ''),
ref: buildRef(r),
projet: r.projet || '',
region: r.region || r.region_csc || '',
region_csc: r.region_csc || r.region || '',
@ -197,5 +203,5 @@ module.exports = {
formatMontant, formatDateFR, formatPct,
isCloture, getDelaiRestant, niveauAlerte,
niveauAvancement, resultatFinancier, resultatPhysique, niveauRisque,
normalizeMarche,
normalizeMarche, buildRef,
};

View File

@ -3,6 +3,7 @@
* Génération XLSX comprehensive Situation des Marchés RLA Zone Sud
*/
const ExcelJS = require('exceljs');
const { buildRef } = require('./calc');
const C = {
NAVY: 'FF002D62',
@ -244,7 +245,7 @@ async function buildSheet1(wb, actifs) {
subtotalFin += finDT;
const rd = ws.addRow([
r.id_marche || r.reference || '',
buildRef(r),
r.projet || '',
r.entrepreneur || '',
nat,
@ -422,7 +423,7 @@ async function buildSheet2(wb, actifs) {
const result = classify(r);
const rd = ws.addRow([
r.id_marche || r.reference || '',
buildRef(r),
r.projet || '',
r.entrepreneur || '',
r.region || '',