Volker's Lovable-generated spec, module, user manual and handover, read in full and measured. The architecture we designed absorbs it. The generated module does not get adopted; its good ideas do.
#1319 wants two §302 routes in Release 1: azh/Noventi (what #1197 already is) and direct GKV-DTA — EDIFACT ESOL/AUF files, per-payer encryption, DAVASO validation, Dakota transmission, KOTR payer files. The second route is a different order of magnitude. The generated module is a UI and data-model scaffold with every external touch stubbed, and it integrates with zero existing Maptara models. None of that changes the architecture. It changes the scope conversation.
lines · both routes · TA 21 + TA 22
15 models · 13 views · 3 security
measured by grep, not by reading the README
not claim.batch, not service.provider, not sale.order
| Claim in the handover | What the code does | Where |
|---|---|---|
| "Connection test" for billing providers | erfolg = bool(provider.api_url or provider.sftp_host) — passes if a string is non-empty. No socket is opened. | provider.py |
| "ESOL payload file — implemented (format profile)" | Four invented line types joined by \n. No UNA, no UNT, no SLGA, no ' terminators, none of the 14 SLLA body segments. 22 spec-mandated elements absent. The "format profile" that supposedly drives it is never read. | export.py:178-198 |
| "Encryption — interchangeable component, PKCS#7/CMS" | return b"-----MAPTARA-CMS-----\n" + inhalt. A 22-byte string prefix. So groesse_krypt == groesse_klar + 22, always, and verschluesselungsstatus = "verschluesselt" is set unconditionally. The non-mock branch calls self.env["maptara.302.krypto"] — a model that does not exist anywhere in the module. | export.py:196, 207-210 |
| "DAVASO check — REST/JSON adapter" | Empty endpoint → mock returns ok for everything. Endpoint set → the only code path is raise UserError. There is no branch that makes a request. Zero network imports in the slice. | davaso.py:80-82 |
| "Dakota handover — atomic write to protected directory" | Three field writes and an audit row. No file is written anywhere. | dakota.py:39-53 |
"duplikat_hash unique constraint prevents double status change" | A _sql_constraints tuple. Odoo 19 logs a warning and ignores that attribute. Same for KOTR unique(version) and Produktbereich unique(code) — all three uniqueness guarantees in the module are ghosts. | dakota.py:90 · kotr.py:44 · stammdaten.py:20 |
| "Immutability after finalisation" | Protects 5 fields. state, all six IKs, the case set and zahlungsstatus stay writable after finalisation. The exposed DAVASO button can re-state a finalised export. unlink() is two field writes away. | export.py:307, 316 |
| "Returns, clarification cases, return configuration" | ruecklauf.py has zero methods. Nothing imports, matches or parses a return. | ruecklauf.py |
| "Unique-or-lock parameter resolution" | Real. Both aufloesen() resolvers raise on no-hit and on ties. But "rank" is the integer prioritaet and nothing else — a global rule and an LE-specific rule with equal priority is a hard error, and version is never consulted. | parametersatz.py:112-119 · ik_umlenkung.py:49-53 |
| "IK redirection incl. uniqueness check" | No constraint of any kind, SQL or Python. Overlapping validity is not detected. | ik_umlenkung.py |
| "KOTR: check hash and signature" | if not (datei.hash_wert and datei.signatur) — a non-empty-string test. Nothing is hashed, nothing is verified. 3 of 8 lokaler_status values are never written by any code. | kotr.py:48 |
| "Every business action writes exactly one audit entry" | 12 models inherit the mixin; 24 explicit call sites; 3 inheriting models have zero calls (Bündelungsregel, IK-Umlenkung, Rücklauf). No create/write hook — editing a Parametersatz or an IK-Umlenkung writes nothing. Systemadmin has 1,1,1,1 on the "revisionssicher" audit table, including unlink. | audit.py · access.csv |
| "Record rules restrict all access to the tenant and the authorised service providers" | 4 rules, not 3. Only 3 restrict by company_id, covering 3 of 28 models. 0 restrict by service provider. | maptara_302_rules.xml |
| "Credentials displayed masked in the interface" | Neither masked nor shown: api_key/client_id/client_secret carry groups= and appear in no view at all. benutzername, api_url, sftp_host are readable by every group. | provider.py · provider_views.xml |
| Demo data | Demo IK 330100112 fails the IK check digit (computed 4, actual 2). The other two pass. | demo.xml |
| "Bundling and technical minimum separations" | maptara.302.sammelgruppe cannot be created: no code creates it, and the form cannot satisfy signatur (required, readonly, no default). pruefe_signatur has zero callers; the six seeded rules are never read. Whatever lands on one export goes into one flat ESOL — the TA21 separations are unenforced, silently. | lauf.py:221, 238 |
| "Post the individual invoices" | Flips a boolean. account.move is never created anywhere in the module, despite depends: account. | papier.py:98-114 · fall.py:57 |
| "Filter sets — saved filters, sorting, grouping" | Domains stored as text, never evaluated. Zero hits for safe_eval / literal_eval. | lauf.py |
"Long-running steps as ir.cron" | Zero cron records in the module. | data/ |
| Module installs on Odoo 19 | No. First data file, line 10: category_id on res.groups — removed in 19. create() raises. After that one fix: 0 dangling refs across 48 views, 23 actions, 25 menus, 113 ACL rows. | groups.xml:10 |
| Actions reachable from the UI | 8 of 23 action methods have no button — including Dakota handover and the provider connection test. | views/ |
Four parallel read-only analyses of the module, one per subsystem, each with file:line on every claim: A case → run → paper, B export → crypto → DAVASO → Dakota → returns, C rule engines, security, seed data, D docs-vs-code reconciliation and static installability. All four are in — 1 054 lines under evidence/ticket-1319/analysis/, synthesised in 08. Two of B's sharpest claims were re-verified against source before publishing.
The Lovable prompt, §20: "Die XML-Dateien müssen im MVP nicht produktiv erzeugt werden. Die spätere Adapterstruktur muss jedoch vorbereitet werden." It was commissioned as a clickable model of the workflow, and as that it is genuinely decent — the data model shows real thought. The problem is only that it will be read as "the module is 80% done", when the 20% it skipped is the entire technical risk.
maptara.302.fall re-models what maptara.claim.request (35 fields) and maptara.claim.batch (317 lines, state machine, 387 test lines) already are. maptara.302.provider re-models maptara.service.provider. The Leistungserbringer is a bare res.partner. Depends: base, mail, account, product — not one Maptara module.
Its own spec says otherwise — §4.2: "Bestehende Odoo-Module bleiben führend für Preis-, Vertrags-, Versorgungs- und Genehmigungsdaten" and §6.2 demands an "interne Abrechnungs-API oder Export-Snapshot aus den bestehenden Modulen". The module does not do what its spec requires. Installed as-is, a billing clerk would enter every case twice.
claim.request/claim.batch stay the source of truth. The snapshot the spec asks for is exactly maptara.claim.submission from the design, widened to hold the §302 fields (§04 below). No second case model.Spec §2.1: Release 1 = direct GKV-DTA and azh. The azh route is 34 fields into two XML files over SFTP — the design already covers it and it is in the October plan. The direct-DTA route is: EDIFACT per Technische Anlage 1/3 version 21 now and version 22 from 1 Feb 2027, both to be supported; per-payer certificate encryption with keys in secret management; DAVASO pre-validation with an endpoint nobody has; a Dakota file hub with a mailbox return channel; KOTR payer-file import with quarantine, signature check and versioned rollout; six distinct IK kinds; a versioned IK-redirection engine; a versioned bundling-rule engine with a signature; a versioned P302 parameter set with unique-or-lock resolution.
Nothing in the codebase does any of it — a repo-wide grep for ESOL, EDIFACT, Dakota, DAVASO, KOTR, SLGA, SLLA returns only substring noise. Greenfield, every line.
provider_dta, implementing submit_batch like the azh plugin does, plus one new driver class (a directory drop, §04). It fits without changing the contract. It does not fit in October, and the plan should say so rather than pretend.The most concrete business requirements are in ticket note #4 — 23 bullets in German covering IK-Umlenkung, bundling, saved filters, Pflegehilfsmittel separation, Stoma/Inko split, payment terms, per-Krankenkasse tax parameters, Belegnummer sort, ESOL with Kommissionierliste for Pierenkemper, positions view with manual adjustment, DAVASO-first-then-AUF, Heilung, ImageLink later, Dakota error log, KOTR batch import. Then a 2 635-line Lovable prompt. Then a 2 081-line generated spec with 34 fields marked "to be mapped" or "technically to be clarified" — including the physical sender IK and the entire AUF format.
None of it is a ticket with acceptance criteria. Two open items are already flagged inside the spec for a conversation "mit Michael": accelerated billing at Pierenkemper, and whether to implement §302 parameters at all or only net-price logic.
Volker's note #9: "see the attachments out of loveable, it includes the technical description, the user documentation and the modul". From the product side this reads as: spec done, manual done, module done — integrate it. From the code side: zero network, zero crypto, a toy ESOL, a fake connection test, zero integration, German identifiers throughout (lauf, fall, ruecklauf, uebergabe) against a repo convention of English identifiers with German domain terms glossed.
Measured in 08: it does not install on Odoo 19 (one four-line fix); after that the wiring is clean but no billing process runs — no bundling, no account.move, no file, no cron. 142 documented claims: 46 true, and the true ones are field names. The realistic reuse is the field list and the state names. Both are worth having. Neither is code.
| Concept in #1319 | Verdict | Where it lands in our model |
|---|---|---|
| Immutable snapshot at release — filter, parameters, routing, with hash | take | maptara.claim.submission. Already the design; #1319 confirms the shape and adds "hash it". |
| Six distinct IK kinds — Liefer, Abrechnungs, Zahlungs, Zertifikats, Kostenträger, DAS | take | Fields on the submission and on maptara.service.provider. Today we have le_ik and ekv_ik; the spec is right that conflating them breaks the moment a Betriebsstätte bills under a different IK than it delivers. |
| Separate status types — technical transmission, business acceptance, clarification, payment never merged | take | Four fields on the submission. This is the same lesson as Egeko's four status buckets, stated better. |
| Bundling signature — cases with different signatures never share a file | take | A computed key on the submission; the 3 000-split logic groups by it. Mandatory TA21 rules hardcoded, tenant rules in a table. |
| State written from the return file, never from the send | take | Already in the design (Fig 4). #1319's "Bereitstellung ist keine Versandbestätigung" is the same rule. |
| IK-Umlenkung — versioned, central, no per-case override | adapt | A small rule model, resolved at snapshot time. Needed for DTA; harmless for azh. Build with the DTA plugin, not before. |
| P302 parameter set — unique-or-lock resolution | adapt | Same pattern as the design's "never default an endpoint": no hit or ambiguous → refuse. Model comes with the DTA plugin. |
| KOTR payer-file rollout — quarantine, hash, versioned activation | adapt | DTA-only. Genuinely well specified in §20. Its own module when the time comes. |
| Audit mixin — one entry per business action | adapt | We have maptara.provider.activity and chatter. Extend, do not replace. |
| Paper process — order → reserve numbers → post → transfer to e-billing | adapt | Spec §22.2 makes it the leading process. It touches invoice numbering and account.move posting order — Sonia's domain more than ours. Flag, do not design here. |
maptara.302.fall as a new case model | no | Duplicates claim.request. Spec §4.2 forbids exactly this. |
maptara.302.provider as a new provider model | no | Duplicates maptara.service.provider. Its schnittstellenart Selection is our driver contract with the dispatch missing. |
Leistungserbringer as bare res.partner | no | We have a model for that with 22 modules depending on it. |
German identifiers — lauf, fall, ruecklauf, uebergabe | no | Repo convention: English identifiers, German domain terms kept only where untranslatable and glossed. Kostenträger stays; uebergabe is "handover". |
| The module itself | no | Reference material. Field list and state names get read; code does not get installed. |
The azh route is unchanged by #1319 — the spec's §9–10 describes exactly the azhDirekt 2.4 + azhIndex 1.0 interfaces the design already covers, and it confirms EPO/DIFF/AVO/IMG as the return types. Dev A's Egeko lane and Dev B's SFTP + azh lane stand as written.
Two additions, both cheap and both make the DTA route easier later: (1) put the six IK fields on maptara.claim.submission now rather than one — zero cost while the model is being created, a migration if added afterwards; (2) add route (azh | dta) and bundling_signature as fields, populated trivially for azh. The DTA plugin then finds the model already shaped for it.
Direct GKV-DTA. Spec §2.1 puts it in Release 1. It is a release on its own: EDIFACT generation validated against TA1 v21 and v22, certificate-based encryption with real key management, a DAVASO integration whose endpoint nobody has, a Dakota directory in a customer network, a mailbox parser, KOTR import, three rule engines. The generated module implements none of it and was not asked to.
If the product side believes both routes ship together, that belief needs correcting this week, not at the end of October. The honest framing: azh is Release 1. Direct DTA is Release 2, on the same contract, and the October work is shaped so Release 2 plugs in rather than starts over.
| # | Question | Why it matters |
|---|---|---|
| 1 | Is direct DTA required in the same release as azh, or is azh-first acceptable? | Decides whether October is a release or a fraction of one. Spec §2.1 says both; the generated module supports neither yet. |
| 2 | Which customer is the first DTA user, and via which Datenannahmestelle? Note #4 says "Kostenträger gruppierbar nach z.B. Davaso". | DTA cannot be built abstractly. TA1 test procedure, DAVASO access and a real DAS are prerequisites, and none are in hand. |
| 3 | Pierenkemper — note #4 twice: "Kommissionierliste zur Papierlogistik" and "beschleunigte Abrechnung". Is Pierenkemper a customer, a logistics partner, or both? | It is the only named party in the requirements and appears nowhere in the spec. |
| 4 | The "mit Michael" items — accelerated billing, and "§302 Parameter oder nur Nettopreislogik". | The second one decides whether the P302 parameter engine exists at all. |
| 5 | Confirm the integration principle: existing claim.request / claim.batch / service.provider remain the models; the §302 work extends them. The generated module is reference, not code. | Spec §4.2 and §6.2 already say this. It needs saying back so the generated module is not mistaken for the implementation. |
| 6 | Who owns the paper process (ordering, number reservation, posting sequence)? | Spec §22.2 makes it the leading process; it is an accounting workflow, not an interface one. |
Sources: .agent-work/ticket-1319/ — ticket export, 2054 spec (docx→txt, 2 081 lines), 2055 Lovable prompt (2 635 lines), Technical Handover EN (441), User Manual EN (340), module maptara_302 (37 files). Maturity measured by grep: mock 4, real network 0, cryptography 0, references to existing Maptara models 0. Overlap measured against maptara_san_claim/models/maptara_claim_request.py (35 fields) and maptara_claim_batch.py (317 lines).
Internal. Nothing here is implemented; the October plan is unchanged.