Chaque transaction du relevé devient une ligne « à trier » : type autre,
répartition vide (liseré rouge existant via field_ecart), tag field_flag
« IMP AAMMJJ » (liseré ambre + filtre existants), client rapproché par
mots (ClientMatcher : séquence contiguë, sinon mot significatif unique --
jamais en sous-chaîne, jamais auto-créé).
- src/Import/ : CsvReleveParser (ISO-8859-1 confirmé, en-tête strict,
fgetcsv avec escape '' explicite -- dépréciation PHP 8.4, rejets
propres avec n° de ligne), ReleveImportBatch (Batch API par lots de
25, dédoublonnage COMPTÉ par empreinte field_import_fitid -- max(0,
k−m) importe les vrais doublons légitimes et dédoublonne à travers
des fichiers qui se chevauchent --, totaux de contrôle au centime
sur la page de résultat, résumé en tempstore privé).
- ReleveUploadForm : upload private://releves (fichier conservé +
usage, hors de portée du cron), parse en validateForm(), batch,
redirection vers la page de résultat.
- field_montant_releve : référence bancaire immuable, écrite une fois
à l'import et jamais par presave ; affichée en TEXTE sous Montant
TTC (widget remplacé par un #type item -- un item ne soumet rien et
extractFormValues() saute le champ sans valeur soumise, la valeur
survit donc à chaque save) ; masquée sur les lignes sans montant.
- SkipValidationContext : contournement du contrôle de répartition
requête-scopé (ferme le trou de concurrence de l'ancien state
global, AUDIT-2026-09-09 §2.2) -- presave honore le service (state
gardé pour compat), updateType/updateField basculent dessus.
- Permissions (AUDIT §2.2 priorité 1) : access figli ledger sur toutes
les routes du module + autocomplete (RouteSubscriber), import
réservé Éditeur/Admin, access content retiré du rôle Authenticated
(config/sync re-exportée pour les 4 rôles).
- Gin : hook_gin_ignore_sticky_form_actions() -- sans ça, le bouton
Importer partait dans la barre sticky du chrome masqué.
- install : 8011 champs, 8012 index sur les empreintes, 8013/8014
montant_releve sur le formulaire sous le TTC (poids renumérotés).
- /lignes : boutons + Ajouter / Importer / Historique dans le footer
sticky (compacts), footer colspan dès la première colonne, badges de
signalement qui reviennent à la ligne au lieu de déborder.
Every save now forces a new revision, unconditionally:
- Form: hide the "Create new revision" checkbox and the log message
field (#access = FALSE, not just a default) so submitted values for
either can't override them -- Form API discards user input for
#access-denied elements and falls back to #default_value.
- hook_node_presave(): the same thing enforced for any save that
doesn't go through the form (drush scripts, etc.), plus explicitly
setting the revision author (current user) and revision timestamp.
setNewRevision(TRUE) alone does NOT refresh revision_timestamp -- it
carries over the previous revision's value, which would silently
mislabel every edit with its predecessor's save time. Verified via a
drush test save before/after.
- Applies regardless of figli_compta_ledger.skip_validation: that flag
is about the répartition-sum check on historical imports, a
different concern -- revision history is never exempted.
New /lignes/historique page (HistoryController): a single reverse-
chronological feed across every ligne_comptable's revisions, gated by
the 'view ligne_comptable revisions' permission (granted to all three
associate roles). Conceptually a revision of one ligne is a revision
of the grand livre as a whole, so this aggregates across nodes rather
than reusing Drupal's per-node revision history page. Each row links
to that specific revision via core's existing revision-view route.
Linked from the /lignes toolbar, shown only when the current user has
the permission.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
root (renamed from the default admin/admin account) keeps full,
unrestricted access outside any role system. These three cover the
actual associates:
- user: read-only, 'access content' only -- can browse /lignes and
/dashboard, nothing else.
- editeur: 'access content' + create/edit any/delete any
ligne_comptable content -- can enter and correct accounting lines,
no site configuration.
- admin: identical permission set to editeur for now (per instruction,
actual config permissions to be scoped later).
Left the pre-existing "administrator" (is_admin bypass -- too broad)
and "content_editor" (generic Standard-recipe scaffolding, permissions
unrelated to ligne_comptable) roles untouched but unused; worth
pruning later if nothing ends up using them.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>