Add FR CTC Flow 10 and Flow 6 addons#820
Conversation
Introduce two new French CTC addons — reporting (Flow 10, on bill.Invoice and bill.Payment) and lifecycle status (Flow 6, on bill.Status) — and reorganise Flow 2 under addons/fr/ctc/flow2/ so the three variants sit side by side. Flow 10 (e-reporting) covers B2B and B2C invoices plus B2B and B2C payments, gated by a b2c tag. Validates billing mode (G1.02), allowed UNTDID document types, final-after-advance invariant (G1.60), currency convertibility to EUR, address country, supplier/customer legal scheme (G2.19), VAT ID when scheme is SIREN/EU-VAT (G2.33), exempt categories, G1.24 rate whitelist on invoices and payments, B2C transaction category (G1.68), and payment receipt/lines/document refs. Normalizes SIREN and EU VAT identities from TaxID, defaults billing mode (M1/M2) and the B2C category (TNT1), and maps rate keys to UNTDID 5305 categories. Flow 6 (CDV lifecycle) is standalone — does not require Flow 2. Carries the authoritative tables gobl.cii reads for the CDAR round-trip: ProcessConditionCode 200–213 (extends bill.StatusEvents with 8 France-specific keys), 45 ReasonCodes with bucket + default-for-key flag, 7 RequestedActionCodes. Three extensions (fr-ctc-role, fr-ctc-reason-code) plus a Characteristic complement covering MDT-207 and the MEN for paid lines. Validations for the rules surfaced in BR-FR-CDV (supplier SIREN, doc code/issue-date, reason required on rejection-like statuses, TypeCode whitelist, characteristic ReasonCode link to sibling Reason); the Type-dependent role and recipient routing rules are intentionally left to PPF-side business logic. The Flow 2 move (addons/fr/ctc/ → addons/fr/ctc/flow2/) renames the package to flow2 and shortens Flow2Key/Flow2V1 to Key/V1. addons.go blank-imports all three flows. Tests are one _test.go per source file in each package (internal package so unexported helpers are reachable), with individual named tests wired to tiny per-axis helpers instead of table-driven loops. Coverage: flow2 93.0%, flow10 90.1%, flow6 96.4%. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #820 +/- ##
==========================================
+ Coverage 93.38% 93.54% +0.16%
==========================================
Files 369 377 +8
Lines 20048 20868 +820
==========================================
+ Hits 18721 19521 +800
- Misses 888 900 +12
- Partials 439 447 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Five GOBL example documents covering the new addons: - Flow 10 B2B invoice, B2C invoice, B2B payment - Flow 6 accepted status, paid status with MEN complement - Flow 6 now enforces exactly one StatusLine per bill.Status (CDAR carries a single status per CDV message) - Tighten Flow 2 description copy Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Each source file now matches a single domain: bill_invoice.go owns the invoice rules, normalizers, and shared VAT-key map; bill_payment.go owns the payment rules and helpers. The catch-all bill.go file is removed; tests follow the same split. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Merge bill.go (invoice helpers) and bill_invoices.go (invoice rules) into a single bill_invoice.go matching the flow10 layout. Tests follow the rename. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- Tighten descriptions on rules 03/04 (corrective preceding), 09 (factoring vs advance-payment doc type), 24/25 (consolidated credit note contracts) so each message says what it actually checks. - Default the flow2 billing mode the same way flow10 does — M2 if Totals.Paid(), M1 otherwise; user-supplied values are preserved. - Auto-fill the three BR-FR-05 regulatory mentions (PMT / PMD / AAB) with minimal, business-neutral text when missing. - Auto-fill the BR-FR-CO-14 TXD / MEMBRE_ASSUJETTI_UNIQUE note when the supplier carries an STC-scheme (0231) identity. - Regenerate data/ artefacts via go generate. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The flow2 test files were external (package flow2_test) so the defensive nil / wrong-type paths in unexported helpers were unreachable, dragging coverage below the rest of the suite. Switching to package flow2 lets the same one-test-per-source layout reach the helpers; adding a focused set of nil/wrong-type tests pushes coverage to 97.5%. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Lint flagged "TXD", "MEMBRE_ASSUJETTI_UNIQUE", and "peppol" as repeated literals. Lift the first two into noteSubjectTXD / stcMembreAssujettiUnique constants in flow2/bill_invoice.go, and switch all "peppol" references to the existing org.InboxKeyPeppol constant. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Pull "BAR" / "B2B" out of bill_invoice.go into noteSubjectBAR and barTreatmentB2B so the goconst lint stops complaining and the isB2BTransaction / notesValidBARText helpers read clearly. No behaviour change: the BAR note is intentionally not auto-defaulted — its value (B2B / B2BINT / B2C / OUTOFSCOPE / ARCHIVEONLY) is transaction-specific and must come from the caller. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Per BR-FR-22 ("règle à exécuter si la facture fait l'objet d'un
traitement B2B ou si elle contient une note (BG-1) avec un code sujet
(BT-21) = BAR et un contenu (BT-22) = B2B"), the B2B-specific rules
should fire whenever flow2 is in scope — flow2 *is* the B2B addon —
unless the caller explicitly opts the invoice out via a BAR note with
a non-B2B treatment (B2BINT / B2C / OUTOFSCOPE / ARCHIVEONLY).
Previously isB2BTransaction returned true only when an explicit BAR=B2B
note was present, which silently let invoices skip the customer-SIREN,
supplier-SIREN-inbox and self-billed-customer-inbox checks. Flip the
default so absence of a BAR note keeps the B2B path active.
The international b2bint example is updated to carry an explicit
BAR=B2BINT note to opt out, with no Key on the note so the en16931
normalizer doesn't rewrite the subject code based on note.Key.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR expands the France CTC support by introducing two new addons (Flow 10 e-reporting and Flow 6 lifecycle statuses), while reorganizing and tightening the existing Flow 2 addon implementation and updating rules, schemas, and examples accordingly.
Changes:
- Add
fr-ctc-flow10-v1(Flow 10) addon with scenarios/tags, validation + normalization for invoices and payments, and new examples. - Add
fr-ctc-flow6-v1(Flow 6) addon forbill.Statuslifecycle messages, including aCharacteristiccomplement schema, code tables, validation/normalization, and new examples. - Move/rename Flow 2 into
addons/fr/ctc/flow2(package rename + API rename), add normalization defaults (billing mode + required mentions), and refine rule descriptions.
Reviewed changes
Copilot reviewed 48 out of 54 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/ops/bulk_test.go | Updates schema list fixture to include the new Flow 6 characteristic schema. |
| examples_test.go | Skips an additional path during examples scanning. |
| examples/fr/status-fr-fr-ctc-flow6-paid.yaml | New Flow 6 “paid” status example (includes characteristic/MEN). |
| examples/fr/status-fr-fr-ctc-flow6-accepted.yaml | New Flow 6 “accepted” status example. |
| examples/fr/payment-fr-fr-ctc-flow10-b2b.yaml | New Flow 10 B2B payment receipt example. |
| examples/fr/out/status-fr-fr-ctc-flow6-paid.json | Generated output for the Flow 6 “paid” status example. |
| examples/fr/out/status-fr-fr-ctc-flow6-accepted.json | Generated output for the Flow 6 “accepted” status example. |
| examples/fr/out/payment-fr-fr-ctc-flow10-b2b.json | Generated output for the Flow 10 B2B payment example. |
| examples/fr/out/invoice-fr-fr-ctc-flow10-b2c.json | Generated output for the Flow 10 B2C invoice example. |
| examples/fr/out/invoice-fr-fr-ctc-flow10-b2b.json | Generated output for the Flow 10 B2B invoice example. |
| examples/fr/out/invoice-fr-de-ctc-b2bint.json | Updates generated output (adds BAR note + digest changes). |
| examples/fr/invoice-fr-fr-ctc-flow10-b2c.yaml | New Flow 10 B2C invoice input example. |
| examples/fr/invoice-fr-fr-ctc-flow10-b2b.yaml | New Flow 10 B2B invoice input example. |
| examples/fr/invoice-fr-de-ctc-b2bint.yaml | Updates input example to include BAR note. |
| data/schemas/tax/addon-list.json | Registers Flow 6 and Flow 10 addon keys in the addon list schema. |
| data/schemas/addons/fr/ctc/flow6/characteristic.json | New JSON Schema for the Flow 6 characteristic complement. |
| data/rules/fr-ctc-flow6.json | New rule definitions for Flow 6 validations. |
| data/rules/fr-ctc-flow2.json | Updates Flow 2 rule descriptions for clarity/accuracy. |
| data/rules/fr-ctc-flow10.json | New rule definitions for Flow 10 validations. |
| data/addons/fr-ctc-flow6-v1.json | New addon definition for Flow 6 (extensions + sources). |
| data/addons/fr-ctc-flow2-v1.json | Updates Flow 2 addon definition text (removes currency conversion note). |
| data/addons/fr-ctc-flow10-v1.json | New addon definition for Flow 10 (extensions, tags, scenarios). |
| addons/fr/ctc/item_test.go | Removes old CTC-level item meta validation tests (moved under Flow 2 tests). |
| addons/fr/ctc/flow6/org_party_test.go | Adds Flow 6 party extension/scheme validation tests. |
| addons/fr/ctc/flow6/org_party.go | Adds Flow 6 org.Party validation for role code + allowed identity schemes. |
| addons/fr/ctc/flow6/flow6.go | Registers Flow 6 addon, schema objects, rules, and normalizer. |
| addons/fr/ctc/flow6/extensions_test.go | Tests helper for unwrapping extensions passed by pointer/value. |
| addons/fr/ctc/flow6/extensions.go | Defines Flow 6 extensions + builds reason-code value list from table. |
| addons/fr/ctc/flow6/complements.go | Defines Flow 6 Characteristic type + MDT-207 type-code whitelist. |
| addons/fr/ctc/flow6/codes_test.go | Tests Process/Reason/Action code-table mappings and round-trips. |
| addons/fr/ctc/flow6/codes.go | Implements ProcessCondition/Reason/Action code tables and lookups. |
| addons/fr/ctc/flow6/bill_status_test.go | Adds Flow 6 status validation + normalization tests. |
| addons/fr/ctc/flow6/bill_status.go | Implements Flow 6 bill.Status/bill.Reason/bill.Action validation + normalization. |
| addons/fr/ctc/flow2/tags.go | Renames package from ctc to flow2. |
| addons/fr/ctc/flow2/org_test.go | Updates Flow 2 tests for package/API rename; adds/moves item meta tests here. |
| addons/fr/ctc/flow2/org_party.go | Renames package to flow2. |
| addons/fr/ctc/flow2/org.go | Renames package; switches inbox peppol key handling to constants. |
| addons/fr/ctc/flow2/flow2.go | Renames Flow 2 package and exports (Key/V1); updates registration/guard. |
| addons/fr/ctc/flow2/extensions.go | Renames package to flow2. |
| addons/fr/ctc/flow2/bill_invoice.go | Adds Flow 2 normalization defaults (billing mode + required mentions + TXD note) and BAR logic; updates rule descriptions. |
| addons/fr/ctc/flow10/tags.go | Adds Flow 10 B2C tag definition for invoices/payments. |
| addons/fr/ctc/flow10/scenarios.go | Adds Flow 10 scenarios mapping invoice types/tags → UNTDID document types. |
| addons/fr/ctc/flow10/party_test.go | Adds unit tests for Flow 10 party normalization/helpers. |
| addons/fr/ctc/flow10/party.go | Adds Flow 10 party normalization + legal scheme selection helpers. |
| addons/fr/ctc/flow10/flow10.go | Registers Flow 10 addon, rules, scenarios, tags, and normalizer. |
| addons/fr/ctc/flow10/extensions.go | Defines Flow 10 extensions and billing mode / B2C category values. |
| addons/fr/ctc/flow10/bill_payment_test.go | Adds Flow 10 payment validation tests. |
| addons/fr/ctc/flow10/bill_payment.go | Adds Flow 10 payment validation (receipt-only, value date, VAT whitelist, supplier SIREN, B2B doc refs). |
| addons/fr/ctc/flow10/bill_invoice_test.go | Adds Flow 10 invoice validation + normalization tests (B2B/B2C). |
| addons/fr/ctc/flow10/bill_invoice.go | Adds Flow 10 invoice validation + normalization (billing mode default, VAT whitelist, exempt rules, party scheme rules). |
| addons/fr/ctc/bill.go | Removes old shared CTC bill helpers (now Flow 2–scoped). |
| addons/addons.go | Registers new Flow 2/6/10 addon packages instead of the old monolithic CTC package. |
| CHANGELOG.md | Documents addition of Flow 6 and Flow 10 addons. |
Comments suppressed due to low confidence (1)
addons/fr/ctc/flow2/bill_invoice.go:838
- notesValidBARText currently allows a BAR note with an empty Text value to pass validation, but the corresponding rule message states the BAR text must be one of the allowed treatment values. If a BAR note is present, its Text should be non-empty and within allowedBARTreatments; otherwise return false so invalid/blank BAR notes don’t silently disable B2B processing.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The b2c distinction is naturally captured by Customer presence — a B2C sale is to an unidentified consumer, so the Customer slot is left unset. Drop the addon-specific TagB2C tag, the tags.go file, and the Tags wiring on the addon definition; flip invoiceIsB2C / paymentIsB2C to read Customer == nil. The b2c example loses its $tags and customer block accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The supplier-SIREN rule fires on both B2B and B2C, so the addon must also derive a SIREN-scheme identity from a French TaxID for B2C suppliers that ship without an Identities entry. Move normalizeParty calls before the B2C early return — Customer is nil for B2C so its call is a harmless no-op — and keep the B2C-specific bits (default TNT1 category) after. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The per-code Go comments said "Deposit of an already paid X invoice" (and similar) which contradicted the documented suffix semantics — the 2-suffix means "already paid", not "deposit". Rewrite each comment to state the actual meaning (B/S/M = goods / services / mixed; suffix = payment context), and add a header summarising the convention. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
fr-ctc-flow10-v1addon: French e-reporting for B2B/B2C invoices and payments (billing mode, document types, G1.24 rate whitelist, exempt-VAT rules, B2C transaction category, payment receipt validation)fr-ctc-flow6-v1addon: French CDV lifecycle statuses onbill.Statuswith CDAR code tables (ProcessConditionCode, ReasonCode, RequestedAction), role / reason-code extensions, and aCharacteristiccomplement carrying the MEN on paid lines; enforces exactly one status line per documentaddons/fr/ctc/flow2/; rename package toflow2and shortenFlow2Key/Flow2V1toKey/V1(breaking change for external consumers likegobl.ubl)_test.goper source file in internal package, individual named tests with helpers (no table-driven loops); regeneratedata/artefacts viago generatePre-Review Checklist
go generate .to ensure that the Schemas and Regime data are up to date.And if you are part of the org: