Add field_numero_facture (N° Facture), a Facture column, and backfill existing content

New plain string field on ligne_comptable, positioned after Client in
both form and view displays. Added as a "Facture" column in both the
main table and the entrée/sortie drill-down modal, right after Type.

Backfilled via figli_compta_ledger_update_8002() by extracting an
invoice number from field_notes (or title, same fallback the front-end
libellé already uses) wherever the pattern is unambiguous: literal F,
optional _/-, 2-8 digits, optional "-digits" continuations for a
compound reference (e.g. "F2549-50-51"), optional 0-3 trailing
uppercase letters (e.g. "F250427A"), with a hard boundary right after --
not immediately followed by more letters/digits/underscore. That last
part is what skips "F58_260506_FIGLI" or "F_2601_FIGLI_EPAU": no way to
tell whether the trailing "_xxx" belongs to the reference or is an
unrelated client/description code glued on, so those are left blank
rather than guessed, per explicit instruction to skip when unsure.

Verified the pattern against every existing ligne_comptable's
notes/title before writing the migration: 319 confident matches with no
false positives found on manual review of the full list, 1236 left
blank. Applied via drush updb, config exported.
This commit is contained in:
2026-09-05 22:37:34 +02:00
parent 852eda2056
commit b6540e56c7
7 changed files with 151 additions and 13 deletions
@@ -102,6 +102,7 @@
<th>Date</th>
<th>Client</th>
<th>Type</th>
<th>Facture</th>
<th>Libellé / Détail</th>
<th class="amount">Montant HT</th>
<th class="amount">Montant TTC</th>
@@ -111,13 +112,13 @@
</thead>
<tbody>
<tr ref="topSentinel" class="figli-sentinel-row">
<td :colspan="6 + allComptes.length + 3">
<td :colspan="7 + allComptes.length + 3">
<span v-if="loadingOlder">Chargement des mois précédents…</span>
</td>
</tr>
<template v-for="item in groupedRows" :key="item.key">
<tr v-if="item.isGroup" class="figli-group-row" :data-year="item.year">
<td :colspan="6 + allComptes.length + 3">{{ item.label }} <span class="figli-note">({{ item.count }} lignes)</span></td>
<td :colspan="7 + allComptes.length + 3">{{ item.label }} <span class="figli-note">({{ item.count }} lignes)</span></td>
</tr>
<tr v-else :class="{'figli-error-row': item.hasError}" :data-year="item.date ? item.date.slice(0, 4) : null">
<td class="actions-col">
@@ -162,6 +163,7 @@
@click="startEditType(item)"
>{{ typeLabel(item.type) }}</span>
</td>
<td>{{ item.facture }}</td>
<td class="figli-libelle">
{{ item.libelle }}
<span
@@ -191,7 +193,7 @@
</tr>
</template>
<tr ref="bottomSentinel" class="figli-sentinel-row">
<td :colspan="6 + allComptes.length + 3">
<td :colspan="7 + allComptes.length + 3">
<span v-if="loadingNewer">Chargement des mois suivants…</span>
</td>
</tr>
@@ -200,7 +202,7 @@
<tr class="figli-totals-row">
<td class="actions-col"></td>
<td class="actions-col"></td>
<td colspan="4">
<td colspan="5">
Solde {{ currentYear || '…' }} (créditeur / débiteur)
<span v-if="currentYearLoading" class="figli-note">chargement…</span>
</td>
@@ -227,6 +229,7 @@
<th>Date</th>
<th>Client</th>
<th>Type</th>
<th>Facture</th>
<th>Libellé / Détail</th>
<th class="amount">Montant HT</th>
<th class="amount">Montant TTC</th>
@@ -246,6 +249,7 @@
<td>{{ formatDate(item.date) }}</td>
<td>{{ item.client || '—' }}</td>
<td><span class="figli-badge" :class="'type-' + item.type">{{ typeLabel(item.type) }}</span></td>
<td>{{ item.facture }}</td>
<td class="figli-libelle">
{{ item.libelle }}
<span
@@ -268,7 +272,7 @@
<tfoot>
<tr class="figli-totals-row">
<td class="actions-col"></td>
<td colspan="4">Solde entrées et sorties liées (créditeur / débiteur)</td>
<td colspan="5">Solde entrées et sorties liées (créditeur / débiteur)</td>
<td class="amount">{{ drilldownTotals ? formatEur(drilldownTotals.montant_ht) : '' }}</td>
<td class="amount">{{ drilldownTotals ? formatEur(drilldownTotals.montant_ttc) : '' }}</td>
<td v-for="c in modalComptes" :key="c" class="amount compte-col" :class="drilldownTotals ? soldeClass(drilldownTotals.par_compte[c]) : ''">{{ drilldownTotals && drilldownTotals.par_compte[c] !== undefined ? formatEur(drilldownTotals.par_compte[c]) : '' }}</td>