load() unconditionally set loading = true, which unmounts the whole
v-else table (the "Chargement…" paragraph takes its place) every time
-- including the background refresh after saving a line, which is
exactly the scroll-resetting, full-table-disappears flicker Vue's
keyed diffing is supposed to prevent. The post-edit refresh
(dialog:afterclose) now calls load(false): rows get reassigned in
place, and Vue patches only what changed.
Verified with a real click (not synthetic JS events, which don't
reliably trigger Drupal's mousedown-bound AJAX submit in headless
testing): same .figli-table-wrap DOM node before/after, "Chargement…"
never appeared.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Single anchor per row -- Montant TTC and the 8 compte columns stay
neutral, so the table doesn't turn into a red/green garland. No 0.5€
threshold like soldeClass (used for aggregate totals): individual
lines are often small (a -1.07€ OVH renewal shouldn't read as
"neutral"), any nonzero sign gets colored.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Link and edit icons get one dedicated column each instead of sharing
one text-align: center cell -- with a shared cell, a row with only the
edit icon (non-linkable types) centered differently than a row with
both icons, so pencils never lined up vertically across rows.
Separate columns line up by construction. Verified: identical left
offset (141px) for the edit icon across 15 consecutive rows.
Also: tighter cell padding (was using the table's default 0.6rem
horizontal padding, way more than an icon needs) and no column-hover
crosshair on these technical columns -- nothing meaningful to compare
across rows there.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dates render as jj/mm/aa instead of the API's ISO yyyy-mm-dd -- saves
width in a table already packed with 8 compte columns. Actions column
(edit pencil, link icon) moves from the right end to the first
column. Column-hover crosshair logic is unaffected: it walks colSpan
positions dynamically rather than assuming a fixed index.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New field_entree_liee (entity reference, node -> node) on
ligne_comptable, restricted to entrée-type nodes via a custom
EntreeClientSelection plugin -- narrows further to the same client as
the sortie being linked when one is already known, using the
referencing-entity context Drupal's selection handler API passes
through (getSelectionHandler($field, $entity)).
Quick-link UI (per the associates' explicit ask: no need to open the
full ligne_comptable form just for this):
- A chain-link icon next to the edit pencil on versement/achat/
hébergement rows (the only types that pay out against a client
invoice) opens LinkEntreeForm, a one-field AJAX modal, reusing the
same modal/close-on-save plumbing as the edit form. Filled/colored
when already linked, with the linked entrée's label on hover.
Also present (states-hidden unless one of those three types is
selected) on the full node form for whoever's already there anyway.
- Entrée rows get a reconciliation badge once at least one sortie
links back to them, clickable to drill the table down to just that
entrée and its linked sorties.
Conformity check assumes multi-compte répartition on both sides (an
entrée's répartition and each linked sortie's répartition can each
split across several comptes -- confirmed this is the real shape of
"hébergement" sorties, e.g. OVH/HETZNER renewals split across all 8
comptes, even though versement/achat lines happen to always be
single-compte in the current data). Per compte, compares the entrée's
répartition share (positive, owed) against the summed répartition of
every linked sortie (negative, paid) -- a residual near zero means
settled, positive means still owed ("reste à verser"), negative means
overpaid ("sur-versé", flagged for a closer look).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Pencil icon opens the existing node edit form in the same AJAX modal
as "+ Ajouter une ligne" -- no new form logic, reuses the form_alter
validation/close-on-save already in place for the add form.
Column highlight pairs with the existing row hover (from Gin's global
table CSS) to form a crosshair. Column position is computed logically
(accounting for colspan) rather than via DOM cellIndex, since the
totals row's label cell spans 4 columns and would otherwise misalign
every column after it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
27 lines (18 previously "charge", 9 "versement") that touch the EXT.WEB
compte in their répartition are now typed "hebergement" instead -- makes
Bachir's separate hosting activity filterable/visible as its own category
rather than blended into general charges/versements. Amounts/répartition
untouched, only the classification changed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- tfoot row: sum per compte (créditeur/débiteur colored) for the
currently filtered rows, plus HT/TTC/écart totals
- Fixed a real bug: fetchAllLignes() paginated without a unique sort key
(field_date_ligne alone, many ties), which let Drupal's JSON:API return
the same row on two pages -- silently inflating totals (Bachir showed
-3115,38€ instead of -3013,56€). Now sorts by
field_date_ligne,drupal_internal__nid (home) / drupal_internal__nid
(dashboard), plus a defensive client-side de-dup by node id either way.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Not used going forward. Deleted the term + its 2 répartition paragraphs
(the standalone opening line was removed entirely since it had nothing
left; the EPAU F_2617 line now shows a real 5214,01€ écart instead of
silently absorbing that amount under a compte nobody uses).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- New /lignes route (set as site front page): full line-by-line table of
every ligne comptable, Vue app with filters (compte/client/type/année)
and month/year grouping, columns matching the original spreadsheet
(one per compte). Rows with répartition ≠ montant HT are visibly
flagged (red row + écart column), not hidden or auto-corrected.
- /dashboard now only holds the aggregate solde-par-compte/par-client view
- Migrated all 199 real 2026 transaction lines + 9 opening balances (from
REPORT CLOTURE 2025) via a drush import script, preserving raw source
data (known répartition mismatches included) -- validated with a new
state-flag bypass of the presave check, used only for historical import
- Added "Autre" as an allowed field_type_ligne value for edge-case rows
- Client taxonomy grew from 15 seeded terms to the full unified list
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>