From f93f6d14ff2063e22d7f2928fe944896b23e58ee Mon Sep 17 00:00:00 2001 From: stephan Date: Thu, 23 Jul 2026 12:50:47 -0400 Subject: [PATCH] =?UTF-8?q?MSIN-4469=20=E2=80=94=20Refactor=20fxBibProduct?= =?UTF-8?q?ionBuildOrderXml=20function=20to=20improve=20handling=20of=20Ex?= =?UTF-8?q?cel=20row=20counts=20and=20remove=20unnecessary=20empty=20rows.?= =?UTF-8?q?=20Update=20logic=20for=20shifting=20rows=20and=20add=20validat?= =?UTF-8?q?ion=20for=20printer=20lines=20in=20the=20output.=20Increment=20?= =?UTF-8?q?version=20code.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- php/inc_fx_bib_production.php | 118 ++++++++++++++++--------- php/inc_fx_promoteur.php | 1 + sql/MSIN-4469-col-lignes-imprimeur.sql | 46 ++++++++++ 3 files changed, 122 insertions(+), 43 deletions(-) create mode 100644 sql/MSIN-4469-col-lignes-imprimeur.sql diff --git a/php/inc_fx_bib_production.php b/php/inc_fx_bib_production.php index 75f7de1..539c0a8 100644 --- a/php/inc_fx_bib_production.php +++ b/php/inc_fx_bib_production.php @@ -467,17 +467,37 @@ function fxBibProductionBuildOrderXml($strXml, array $tabSnapshot, array $tabLab } } - $intSlotCount = max(9, count($tabOrderRows)); - $intExtraRows = ($intSlotCount - 9) * 3; - $intTotalRow = 31 + $intExtraRows; + // MSIN-4469 — Le gabarit a 9 emplacements ; on n'en garde que le nombre + // réel de séquences (sinon lignes jaunes vides avant le TOTAL). + $intTemplateSlots = 9; + $intSlotCount = count($tabOrderRows); + $intRowDelta = ($intSlotCount - $intTemplateSlots) * 3; + $intTotalRow = 31 + $intRowDelta; + $tabRemove = []; foreach ($objXpath->query('//m:sheetData/m:row') as $objRow) { if (!($objRow instanceof DOMElement)) { continue; } $intCurrentRow = (int)$objRow->getAttribute('r'); - if ($intCurrentRow >= 31 && $intExtraRows > 0) { - $intShiftedRow = $intCurrentRow + $intExtraRows; + if ($intCurrentRow >= 4 && $intCurrentRow <= 30) { + $tabRemove[] = $objRow; + } + } + foreach ($tabRemove as $objRow) { + $objSheetData->removeChild($objRow); + } + + if ($intRowDelta !== 0) { + foreach ($objXpath->query('//m:sheetData/m:row') as $objRow) { + if (!($objRow instanceof DOMElement)) { + continue; + } + $intCurrentRow = (int)$objRow->getAttribute('r'); + if ($intCurrentRow < 31) { + continue; + } + $intShiftedRow = $intCurrentRow + $intRowDelta; $objRow->setAttribute('r', (string)$intShiftedRow); foreach ($objRow->childNodes as $objCell) { if ($objCell instanceof DOMElement && $objCell->localName === 'c') { @@ -486,34 +506,17 @@ function fxBibProductionBuildOrderXml($strXml, array $tabSnapshot, array $tabLab } } } - } - - if ($intExtraRows > 0) { foreach ($objXpath->query('//m:mergeCell') as $objMerge) { if (!($objMerge instanceof DOMElement)) { continue; } $objMerge->setAttribute( 'ref', - fxBibProductionXmlShiftReference($objMerge->getAttribute('ref'), 31, $intExtraRows) + fxBibProductionXmlShiftReference($objMerge->getAttribute('ref'), 31, $intRowDelta) ); } } - $tabRemove = []; - foreach ($objXpath->query('//m:sheetData/m:row') as $objRow) { - if (!($objRow instanceof DOMElement)) { - continue; - } - $intCurrentRow = (int)$objRow->getAttribute('r'); - if ($intCurrentRow >= 4 && $intCurrentRow < $intTotalRow) { - $tabRemove[] = $objRow; - } - } - foreach ($tabRemove as $objRow) { - $objSheetData->removeChild($objRow); - } - $objTotal = fxBibProductionXmlFindRow($objXpath, $intTotalRow); if (!$objTotal) { throw new Exception('MSIN-4469 total row missing'); @@ -525,21 +528,23 @@ function fxBibProductionBuildOrderXml($strXml, array $tabSnapshot, array $tabLab $objSecondRow = fxBibProductionXmlCloneRow($objBaseSecond, $intRow + 1); $objBlankRow = fxBibProductionXmlCloneRow($objBaseBlank, $intRow + 2); - if (isset($tabOrderRows[$intSlot])) { - $tabRow = $tabOrderRows[$intSlot]; - fxBibProductionXmlSetInlineString($objDom, $objEventRow, 'A', $intRow, $tabRow['label']); - fxBibProductionXmlSetNumber($objDom, $objEventRow, 'F', $intRow, $tabRow['quantity']); - fxBibProductionXmlSetNumber($objDom, $objEventRow, 'G', $intRow, $tabRow['start']); - fxBibProductionXmlSetNumber($objDom, $objEventRow, 'H', $intRow, $tabRow['finish']); - fxBibProductionXmlSetFormula($objDom, $objEventRow, 'I', $intRow, 'H' . $intRow . '-G' . $intRow . '+1'); - fxBibProductionXmlSetFormula($objDom, $objEventRow, 'J', $intRow, 'I' . $intRow . '=F' . $intRow); - // MSIN-4469 — V1 : une puce par dossard, avec le même numéro. - fxBibProductionXmlSetNumber($objDom, $objEventRow, 'L', $intRow, $tabRow['quantity']); - fxBibProductionXmlSetNumber($objDom, $objEventRow, 'M', $intRow, $tabRow['start']); - fxBibProductionXmlSetNumber($objDom, $objEventRow, 'N', $intRow, $tabRow['finish']); - fxBibProductionXmlSetFormula($objDom, $objEventRow, 'O', $intRow, 'G' . $intRow . '=M' . $intRow); - fxBibProductionXmlSetFormula($objDom, $objEventRow, 'P', $intRow, 'H' . $intRow . '=N' . $intRow); - } + $tabRow = $tabOrderRows[$intSlot]; + $objCellF = fxBibProductionXmlFindCell($objEventRow, 'F'); + $strStyleK = $objCellF ? (string)$objCellF->getAttribute('s') : ''; + fxBibProductionXmlSetInlineString($objDom, $objEventRow, 'A', $intRow, $tabRow['label']); + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'F', $intRow, $tabRow['quantity']); + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'G', $intRow, $tabRow['start']); + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'H', $intRow, $tabRow['finish']); + fxBibProductionXmlSetFormula($objDom, $objEventRow, 'I', $intRow, 'H' . $intRow . '-G' . $intRow . '+1'); + fxBibProductionXmlSetFormula($objDom, $objEventRow, 'J', $intRow, 'I' . $intRow . '=F' . $intRow); + // MSIN-4469 — À côté de la quantité : lignes Imprimeur pour cette séquence. + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'K', $intRow, $tabRow['quantity'], $strStyleK); + // MSIN-4469 — V1 : une puce par dossard, avec le même numéro. + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'L', $intRow, $tabRow['quantity']); + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'M', $intRow, $tabRow['start']); + fxBibProductionXmlSetNumber($objDom, $objEventRow, 'N', $intRow, $tabRow['finish']); + fxBibProductionXmlSetFormula($objDom, $objEventRow, 'O', $intRow, 'G' . $intRow . '=M' . $intRow); + fxBibProductionXmlSetFormula($objDom, $objEventRow, 'P', $intRow, 'H' . $intRow . '=N' . $intRow); $objSheetData->insertBefore($objEventRow, $objTotal); $objSheetData->insertBefore($objSecondRow, $objTotal); @@ -557,14 +562,40 @@ function fxBibProductionBuildOrderXml($strXml, array $tabSnapshot, array $tabLab ); } + // MSIN-4469 — Colonne K : validation quantité vs lignes onglet Imprimeur (hors vides). + $objHeaderRow = fxBibProductionXmlFindRow($objXpath, 3); + if ($objHeaderRow) { + $objHeaderCellF = fxBibProductionXmlFindCell($objHeaderRow, 'F'); + $strHeaderStyleK = $objHeaderCellF + ? (string)$objHeaderCellF->getAttribute('s') + : ''; + fxBibProductionXmlSetInlineString( + $objDom, + $objHeaderRow, + 'K', + 3, + $tabLabels['printer_lines'], + $strHeaderStyleK + ); + } + fxBibProductionXmlSetInlineString($objDom, $objTotal, 'A', $intTotalRow, $tabLabels['total']); fxBibProductionXmlSetFormula($objDom, $objTotal, 'F', $intTotalRow, 'SUM(F4:F' . ($intTotalRow - 1) . ')'); fxBibProductionXmlSetFormula($objDom, $objTotal, 'I', $intTotalRow, 'SUM(I4:I' . ($intTotalRow - 1) . ')'); fxBibProductionXmlSetFormula($objDom, $objTotal, 'L', $intTotalRow, 'SUM(L4:L' . ($intTotalRow - 1) . ')'); + // COUNT ne compte que les numéros (ignore en-tête texte et lignes blanches entre épreuves). + fxBibProductionXmlSetFormula($objDom, $objTotal, 'K', $intTotalRow, 'COUNT(Imprimeur!A:A)'); + fxBibProductionXmlSetFormula( + $objDom, + $objTotal, + 'J', + $intTotalRow, + 'F' . $intTotalRow . '=K' . $intTotalRow + ); $objDimension = $objXpath->query('//m:dimension')->item(0); if ($objDimension instanceof DOMElement) { - $objDimension->setAttribute('ref', 'A1:Q' . (48 + $intExtraRows)); + $objDimension->setAttribute('ref', 'A1:Q' . (48 + $intRowDelta)); } return $objDom->saveXML(); } @@ -764,10 +795,11 @@ function fxBibProductionCreateOfficialOrder($intEveId, $strLangue = 'fr') { $tabSnapshot, $strAbsoluteFile, [ - 'bib' => fxBibTexte('bib_v5_production_col_bib', 0), - 'race' => fxBibTexte('bib_v5_production_col_race', 0), - 'total' => fxBibTexte('bib_v5_production_total', 0), - 'title' => fxBibTexte('bib_v5_production_excel_title', 0), + 'bib' => fxBibTexte('bib_v5_production_col_bib', 0), + 'race' => fxBibTexte('bib_v5_production_col_race', 0), + 'total' => fxBibTexte('bib_v5_production_total', 0), + 'title' => fxBibTexte('bib_v5_production_excel_title', 0), + 'printer_lines' => fxBibTexte('bib_v5_production_col_printer_lines', 0), ] ); diff --git a/php/inc_fx_promoteur.php b/php/inc_fx_promoteur.php index 4720943..f72066b 100644 --- a/php/inc_fx_promoteur.php +++ b/php/inc_fx_promoteur.php @@ -3671,6 +3671,7 @@ function fxBibStaticFallback($clef) { 'bib_v5_production_file_missing' => ['fr' => 'Le fichier Excel enregistré est introuvable.', 'en' => 'The saved Excel file could not be found.'], 'bib_v5_production_col_bib' => ['fr' => 'Numéro de dossard', 'en' => 'Bib number'], 'bib_v5_production_col_race' => ['fr' => 'Épreuve', 'en' => 'Race'], + 'bib_v5_production_col_printer_lines' => ['fr' => 'Lignes Imprimeur', 'en' => 'Printer lines'], 'bib_v5_production_total' => ['fr' => 'TOTAL', 'en' => 'TOTAL'], 'bib_v5_production_locked_error' => ['fr' => 'Les séquences sont verrouillées parce que le fichier est en impression.', 'en' => 'The ranges are locked because the file is in print.'], 'bib_v5_production_print_lock_col' => ['fr' => 'Impression', 'en' => 'Printing'], diff --git a/sql/MSIN-4469-col-lignes-imprimeur.sql b/sql/MSIN-4469-col-lignes-imprimeur.sql new file mode 100644 index 0000000..42b71d7 --- /dev/null +++ b/sql/MSIN-4469-col-lignes-imprimeur.sql @@ -0,0 +1,46 @@ +-- MSIN-4469 — Colonne validation « Lignes Imprimeur » (Commande MS1) +-- Prérequis : MSIN-4469-production-excel-dossards.sql +-- Notes : exécution UNIQUEMENT sur dev préprod ; autres env = Navicat structure + sync_static_db + +INSERT INTO info ( + info_clef, + info_langue, + info_texte, + info_aide, + info_prg, + info_description, + info_trie, + info_actif, + info_option1, + info_option2, + info_option3, + info_creation +) +SELECT + src.info_clef, + src.info_langue, + src.info_texte, + src.info_aide, + 'compte.php', + 'MSIN-4469', + 0, + 1, + '', + '', + '', + NOW() +FROM ( + SELECT 'bib_v5_production_col_printer_lines' info_clef, 'fr' info_langue, + 'Lignes Imprimeur' info_texte, + 'Nombre de lignes de l’onglet Imprimeur (hors lignes vides). Doit égaler la quantité de dossards.' info_aide + UNION ALL SELECT 'bib_v5_production_col_printer_lines', 'en', + 'Printer lines', + 'Number of rows on the Printer sheet (excluding blank rows). Must match the bib quantity.' +) src +WHERE NOT EXISTS ( + SELECT 1 + FROM info current_info + WHERE current_info.info_clef = src.info_clef + AND current_info.info_langue = src.info_langue + AND current_info.info_prg = 'compte.php' +);