Customs declarations
Regimes
Dossier.Regime |
System | Message | XML envelope |
|---|---|---|---|
IM — Import |
IDMS | IE415 | IE415B / IIE415B |
EX — Export |
AES | CC515 | TBD |
T1 / T2 — Transit |
NCTS | CC015C | CC015C |
The regime is set at upload time and determines the entire downstream processing: AI extraction prompt, transport cost calculation target value, XML generator used, and declaration type options on the Declare page.
Declaration types
IM — Import
| Field | Options |
|---|---|
DeclarationType |
IM |
AdditionalDeclarationType |
A — Standard, D — Simplified, E — Simplified (warehouse), X — Pre-arrival |
UseH2B = false (H1B) |
Standard import, procedure 40 |
UseH2B = true (H2B) |
Customs warehouse entry, procedure 71 — adds Warehouse element to XML |
EX — Export
| Field | Options |
|---|---|
DeclarationType |
EX |
AdditionalDeclarationType |
A — Standard, C — Simplified (authorised location), D — Simplified (standard), F — Pre-lodged |
| Procedure codes | 10 — Standard export, 21 — Re-export from warehouse, 23 — Temporary admission re-export |
Dossier workflow
flowchart TD
UP(["Upload + select regime"])
UP -->|PDF — IM / EX| B["ProcessingWorker"]
UP -->|PDF — T1 / T2| BT["ProcessingWorker"]
UP -->|XLSX| XP["XlsxProcessor\ndirect parse"]
subgraph imex["IM / EX extraction"]
B --> ADI["Azure Document Intelligence\nOCR / layout"]
ADI -->|OCR text| CL["Azure OpenAI\nclassify_document"]
CL -->|invoice / packing_list| EX["Azure OpenAI\nextract_invoice / extract_packing_list"]
end
subgraph transit["Transit extraction"]
BT --> TADI["Azure Document Intelligence\nOCR / layout"]
TADI -->|OCR text| TEX["Azure OpenAI\nextract_transit"]
end
EX -->|status=Review| C["Review page\ncorrect extracted data"]
TEX -->|status=Review| C
XP -->|status=Review| C
EX -->|status=Failed| F
TEX -->|status=Failed| F
C --> D["TransportCosts page\nadd freight / insurance"]
D --> E["Declare page\nreferences & contacts"]
E -->|IM| G1["IE415BXmlGenerator\nIE415"]
E -->|T1/T2| G3["CC015CXmlGenerator\nCC015C"]
E -->|EX| NX["Export XML generation\nnot yet implemented"]
G1 & G3 --> H(["Download / submit\nto customs"])
F(["Failed\nsee LastErrorMessage"]) -->|Retry| B
F -->|Retry| BT
Dossier statuses
stateDiagram-v2
[*] --> Draft : upload
Draft --> Processing : queued for extraction
Processing --> Review : AI extraction OK
Processing --> Failed : AI / endpoint error
Failed --> Draft : Retry
Review --> Approved : Review saved
Approved --> Submitted : XML generated
Submitted --> [*]
| Status | Enum value | Meaning |
|---|---|---|
Draft |
0 | Just uploaded; not yet queued or processing |
Queued |
6 | Waiting in the processing channel queue |
Processing |
1 | AI extraction in progress |
Review |
2 | Extraction complete; awaiting user review |
Approved |
3 | Reviewed and approved; ready to declare |
Submitted |
4 | XML generated and submitted to customs |
Failed |
5 | AI extraction or endpoint error — see LastErrorMessage; use Retry button |
Transport cost division
Applies to both IM and EX. Handled on the /Dossiers/{id}/TransportCosts page.
| Regime | Target value | What to enter |
|---|---|---|
| IM | CIF — cost + insurance + freight to EU border | International freight (from origin to BE) |
| EX | FOB — free on board at EU exit point | Internal transport cost to EU border |
Distribution is proportional by line value across all goods items. The incoterm group (E/F, C, DAP) determines whether costs are added or deducted and which formula applies:
- E & F terms (EXW, FOB, FCA…): add AK (sender → EU border), add CA (EU border → destination), subtract FA (declaration cost)
- C terms (CIF, CFR, CPT…): no AK, add CA, subtract FA
- DAP / DDP / DPU: deduct BA (inside-EU portion), add CA, subtract FA
XML generation (IM / CC415)
Implementation note: in code this message is generated through the IE415B flow for IDMS import declarations.
Two message sub-types driven by CustomsDeclaration.UseH2B:
| CC415_H1B | CC415_H2B | |
|---|---|---|
| Procedure | 40 | 71 |
| Trader | Exporter |
Seller |
| Warehouse element | — | ✅ |
| SupportingDocument 4006 | — | ✅ (AGP licence) |
HS code format
| Regime | Digits | Split for XML |
|---|---|---|
| IM / EX | 10 digits (no dots) | 1–6 → harmonizedSystemSubheadingCode7–8 → combinedNomenclatureCode9–10 → taricCode |
| T1 / T2 | 8 digits (no dots) | 1–6 → harmonizedSystemSubheadingCode7–8 → combinedNomenclatureCode |
Transit does not use taricCode.
Country resolution
Country names from AI extractions are resolved to ISO2 via the Tarbel GeographicalArea table. Unknown names (e.g. TURKIYE, USA) are resolved via the CountryAliases section in appsettings.json — see configuration.md.
XML generation (EX / CC515)
Not yet implemented. A separate CC515XmlGenerator service is planned — do not extend IE415BXmlGenerator.
Key differences from CC415:
- Root element and envelope differ
- ExportOperation instead of ImportOperation
- Exporter is mandatory with full address
- CountryOfDestination + CountryOfExport instead of CountryOfDispatch + Destination
- No Warehouse element
SMF schema validation
When Descartes wrapper validation is enabled (Descartes:Smf:ValidateXsd=true), generated SMF XML is validated against SMF.xsd before returning/submitting.
Required settings:
- Descartes:Smf:ValidateXsd
- Descartes:Smf:XsdFolder
In Docker images built from this repo, XSD files are bundled under /app/schemas/smf, and Docker defaults set:
- Descartes__Smf__ValidateXsd=true
- Descartes__Smf__XsdFolder=/app/schemas/smf