Skip to content

feat(15-12a): clôture des exercices dans l'ordre, garde de création, 409 EARLIER_FISCAL_YEAR_OPEN (refs #543) - #573

Merged
guycorbaz merged 13 commits into
mainfrom
story/15-12a-cloture-dans-l-ordre
Oct 9, 2026
Merged

guycorbaz merged 13 commits into
mainfrom
story/15-12a-cloture-dans-l-ordre

Conversation

@guycorbaz

@guycorbaz guycorbaz commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

refs #543. C'est la 15-12b qui fermera l'issue.

Ce qui change

Clôture dans l'ordre. Les exercices se clôturent du plus ancien vers le plus récent. close procède ainsi :

  1. il lit sans verrou la liste des exercices antérieurs ;
  2. il les verrouille un par un, dans l'ordre de leur date de début ;
  3. il verrouille l'exercice à clôturer ;
  4. il relit les antérieurs sous verrou.

Tant qu'un exercice antérieur est ouvert, il refuse avec 409 EARLIER_FISCAL_YEAR_OPEN. L'ordre des verrous est fixé par le code et ne dépend pas du plan d'exécution.

Création gardée. Créer un exercice antérieur à un exercice déjà clos est refusé (400 LATER_FISCAL_YEAR_CLOSED), avec un message propre à ce cas.

Message borné. Le message de LATER_FISCAL_YEAR_CLOSED ne dit plus que ce que le code refuse réellement : la modification et la suppression, pas la saisie.

Rejeu. La clôture et la création sont rejouées en cas d'interblocage.

Écran des exercices. Les boutons « Clôturer » et « Réouvrir » sont désactivés, avec une infobulle, quand l'ordre l'interdit.

Documentation à jour : manuels (texte et PDF), api-external.md, patrons de verrous et CHANGELOG.

Gate

Exécuté localement, sur l'état rebasé sur 39b52628 :

  • Backend (scripts/test-fast.sh) : 2951 tests sur 2951, 4 ignorés.
  • Frontend : check, lint-i18n-ownership, test:unit (1095 tests) et build verts.
  • E2E complet : 245 passés et 9 échecs, tous attendus : sept de la KF-029, deux de l'issue [KF-051] invoices.spec.ts:405 et :429 échouent le MATIN et passent l'après-midi — sentAt codé à T12:00:00 comparé à Utc::now() #421 (avant midi UTC).
  • Mesures de départ : les deux requêtes de recherche passent par l'index uq_fiscal_years_company_start_date, sans filesort. Les interblocages prévus se produisent bien, et leur rejeu est testé.
  • Mutations : sept tuées (dont la (xi), « garde de création non verrouillante », par le test 13 b3). Une huitième a été observée.

Revues

Revue Passe Résultat
Validation de la spec P1 à P4 (15-12 puis 15-12a) 0 au-dessus de LOW à la P4
Revue de code P1, Sonnet ×3 2 MEDIUM, remédiés
Revue de code P2 ciblée (Haiku) 0

Les deux MEDIUM de la revue de code :

  • le message du refus affirmait à tort que rien ne pouvait être « enregistré » ;
  • aucun test ne prouvait le verrou de la garde de création. C'est désormais le rôle du test 13 b3.

À la passe ciblée, l'orchestrateur a vérifié lui-même le test 13 b3 : il appelle bien la vraie garde, et l'attente de la clôture est observée, pas supposée.

🤖 Generated with Claude Code

guycorbaz and others added 13 commits October 9, 2026 04:48
…main (fiches, prompts, registre par union)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…isés sur 5e4bec5, mesures des verrous, entrées 15-12 au registre de sprint (refs #543)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s de concurrence (refs #543)

- DbError::EarlierFiscalYearOpen ; close en étapes (a)-(e) : antérieurs listés
  sans verrou puis verrouillés un par un par clé primaire, l'exercice, relecture
  verrouillante du plus ancien antérieur ouvert (C119).
- create refuse un exercice antérieur à un exercice clos (LaterFiscalYearClosed).
- LOCK_IN_COMPANY_SQL partagé par close, reopen et update_name.
- Tests : refus, précédence, autre société, ids inversés, exercice disparu ;
  13 a, 13 b1, 13 b2, 13 c, 13 d à entrelacement forcé ; mutations (i), (ii),
  (iv) tuées, (iii) observée.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ISCAL_YEAR_CLOSED, clôture et création rejouées (refs #543)

- Mapping 409 EARLIER_FISCAL_YEAR_OPEN ; clé neuve error-later-fiscal-year-closed ;
  message propre à la création (AppError::FiscalYearBeforeClosedYear, C-15-12a-1) ;
  ancienne clé alignée (quatre locales, repli frontend).
- create_fiscal_year et close_fiscal_year dans retry_on_deadlock ; tests HTTP de
  rejeu 9 et 10 (mutations (ix) et (x) tuées) ; tests HTTP 409 / 400 /
  chevauchement ; doc-comment du registre (points (ii), (iii bis), (iv), (vi)).
- Doc-comment de reverse_in_tx_inner : cycles avec la clôture et la création.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…térieur ouvert, refus 409 traité avant « déjà clôturé » (refs #543)

Vitest : bouton désactivé nommant le plus ancien antérieur ouvert, antérieur clos
non bloquant, branche EARLIER_FISCAL_YEAR_OPEN (mutation (viii) tuée). Borne
sitesTotal de i18n-keys.test.ts recomptée aux deux bornes (1915 → 1916).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…15-8a/15-8b (refs #543)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…api-external, patrons de verrous, CHANGELOG — PDF régénérés (refs #543)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…543)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… mutation xi), message neutre borné à la modification et à la suppression, infobulle des boutons désactivés, #569 cité (refs #543)

- A1 = B-2 = E1 (MEDIUM) : test 13 b3, la garde de `create` tient Y ; mutation
  « garde non verrouillante » jouée, seul le 13 b3 rougit. Doc-comments et fiche
  disent ce que prouve chaque test.
- B-1 = E4 (MEDIUM) : `error-later-fiscal-year-closed` (4 locales + repli) ne
  promet plus que ce que le code garde.
- LOW : isolation entre sociétés et frontière de la garde, refus par clé
  read-write, affichage du refus de création (Vitest), enveloppe d'infobulle,
  références orphelines, #569 aux replis, api-external, doc de module.

Gates : backend 2901/2901, Vitest 1095/1095, E2E 245 / 9 attendus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… complets sur l'état rebasé, statut done (refs #543)

Boucle de revue de code close : P1 Sonnet ×3 (2 MEDIUM d'origine) → P2 ciblée
Haiku 0, sans remédiation. Gates sur l'état rebasé : backend 2934/2934,
Vitest 1095/1095, E2E 244 / 9 attendus (7 KF-029, 2 KF-045) + 1 échec de
montage (KESH_TEST_MODE côté runner) rejoué vert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…complets sur l'état rebasé (refs #543)

Conflit de code dans rejeu_interblocage_e2e.rs : les tests de la 15-6a et
de la 15-12a gardés. Gates : backend 2951/2951, Vitest 1095/1095, E2E 245 /
9 attendus (7 KF-029, 2 KF-045).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@guycorbaz
guycorbaz force-pushed the story/15-12a-cloture-dans-l-ordre branch from ec26c8d to 582495f Compare October 9, 2026 03:08
@guycorbaz
guycorbaz merged commit 012fc43 into main Oct 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant