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.
Modules extend your site functionality beyond Drupal core. WHAT TO PLACE IN THIS DIRECTORY? -------------------------------- Placing downloaded and custom modules in this directory separates downloaded and custom modules from Drupal core's modules. This allows Drupal core to be updated without overwriting these files. DOWNLOAD ADDITIONAL MODULES --------------------------- Contributed modules from the Drupal community may be downloaded at https://www.drupal.org/project/project_module. ORGANIZING MODULES IN THIS DIRECTORY ------------------------------------ You may create subdirectories in this directory, to organize your added modules, without breaking the site. Some common subdirectories include "contrib" for contributed modules, and "custom" for custom modules. Note that if you move a module to a subdirectory after it has been enabled, you may need to clear the Drupal cache so it can be found. There are number of directories that are ignored when looking for modules. These are 'src', 'lib', 'vendor', 'assets', 'css', 'files', 'images', 'js', 'misc', 'templates', 'includes', 'fixtures' and 'Drupal'. MULTISITE CONFIGURATION ----------------------- In multisite configurations, modules found in this directory are available to all sites. You may also put modules in the sites/all/modules directory, and the versions in sites/all/modules will take precedence over versions of the same module that are here. Alternatively, the sites/your_site_name/modules directory pattern may be used to restrict modules to a specific site instance. MORE INFORMATION ---------------- Refer to the “Developing for Drupal” section of the README.md in the Drupal root directory for further information on extending Drupal with custom modules.