/** * Mirrors the backend contract: the `dto.py` and `schemas.py` of each module * under `cbh/api`. * * Every enum there is an `IntEnum`, so pydantic serialises it as a number and * these numeric enums are the same values, not a parallel vocabulary. */ export enum TradeDirection { IMPORT = 1, EXPORT = 2, BOTH = 3, WAREHOUSE = 4, } /** The customs procedure the declaration is filed under. */ export enum CustomsProcedure { RELEASE_FOR_FREE_CIRCULATION = 1, EXTERNAL_TRANSIT_T1 = 2, INTERNAL_TRANSIT_T2 = 3, CUSTOMS_WAREHOUSE = 4, } export enum LineStatus { OK = 1, AMBIGUOUS = 2, INVALID = 3, EXPIRING = 4, } export enum ResolutionMethod { EXACT_10 = 1, /** The single declarable code is a real subdivision the tool picked. */ EXPANDED_FROM_PREFIX = 2, NOT_RESOLVED = 3, /** Only zeros were added: `6203 42 31` → `6203 42 31 00`. Normalisation. */ PADDED = 4, } /** How the code going out relates to the code that came in. */ export enum CodeChange { UNCHANGED = 1, /** Only zeros added to reach ten digits — shown plainly, never struck through. */ PADDED = 2, /** Different digits: a subdivision, a replacement, a pin or a correction. */ CHANGED = 3, } export enum WarningSeverity { INFO = 1, WARNING = 2, BLOCKING = 3, } export enum WarningType { ANTIDUMPING = 1, COUNTERVAILING = 2, SAFEGUARD = 3, PHYTOSANITARY = 4, VETERINARY_CHED = 5, CITES = 6, DUAL_USE_OUT_OF_SCOPE = 7, CODE_EXPIRING_SOON = 8, CODE_NOT_VALID_AT_DATE = 9, CODE_REPLACED = 10, CODE_AMBIGUOUS = 11, CODE_UNKNOWN = 12, CODE_NOT_DECLARABLE = 13, PROHIBITION = 14, RESTRICTION = 15, QUOTA = 16, SURVEILLANCE = 17, EXCISE = 18, NO_MEASURES_FOUND = 19, REFERENCE_DATA_MISSING = 20, COUNTRY_UNKNOWN = 21, CHAPTER_OUT_OF_SCOPE = 22, ADDITIONAL_CODE_REQUIRED = 23, NVWA_CHAPTER_EXCLUDED = 24, DESTINATION_UNKNOWN = 25, RULE_APPLIED = 26, TRANSIT_DUTY_SUSPENDED = 27, NATIONAL_MEASURE = 28, CBAM = 29, /** On an ambiguous line: a measure that binds only some of the candidates. */ CANDIDATE_MEASURE = 30, } export enum DocumentRequirementType { REQUIRED = 1, ALTERNATIVE = 2, EXEMPTION = 3, SUSPENDED = 4, /** Only claims a benefit — a preference, a suspension. Never needed to pass. */ OPTIONAL = 5, /** Owed only for some consignments of the code, e.g. low-value parcels. */ CONDITIONAL = 6, } /** What one condition group of a measure asks of the declaration. */ export enum ObligationKind { /** Without one of the documents the goods are stopped. */ MANDATORY = 1, /** Without them the goods still pass; they only claim a benefit. */ BENEFIT = 2, /** Depends on the consignment, not on the code. */ CONDITIONAL = 3, } export enum DocumentCodeType { CERTIFICATE = 1, NATIONAL = 2, EXEMPTION = 3, SPECIAL = 4, UNKNOWN = 99, } export enum ConfidenceLevel { RED = 1, AMBER = 2, GREEN = 3, } export enum ReferenceSource { TARIC = 1, CODEBOEK = 2, MANUAL = 3, NONE = 99, } export enum MeasureCategory { TARIFF_DUTY = 1, ANTIDUMPING = 2, COUNTERVAILING = 3, SAFEGUARD = 4, PROHIBITION = 5, RESTRICTION = 6, VETERINARY_CONTROL = 7, PHYTOSANITARY_CONTROL = 8, CITES = 9, DUAL_USE = 10, QUOTA = 11, SURVEILLANCE = 12, EXCISE = 13, VAT = 14, CBAM = 15, OTHER = 99, } export enum RuleAction { PIN_CODE = 1, ADD_DOCUMENTS = 2, REMOVE_DOCUMENTS = 3, NOTE = 4, } export interface LineCheckRequest { code: string; originCountry?: string | null; destinationCountry?: string | null; direction: TradeDirection; date?: string | null; additionalCodes?: string[]; description?: string | null; clientProfileId?: string | null; } export interface CodeCandidate { code: string; formattedCode: string; description?: string | null; descriptionEn?: string | null; /** Descriptions from just under the typed prefix down to this code. */ path?: string[]; pathNl?: string[]; /** `path` joined, ready for an option label. */ label?: string | null; validFrom?: string | null; validTo?: string | null; } export interface DocumentRequirement { code: string; documentType: DocumentCodeType; requirementType: DocumentRequirementType; description?: string | null; source: ReferenceSource; validFrom?: string | null; validTo?: string | null; measureSid?: string | null; measureTypeId?: string | null; measureTypeDescription?: string | null; conditionCode?: string | null; alternativeGroup?: string | null; /** Where the obligation comes from: the legal act and the publication. */ regulationId?: string | null; sourceFile?: string | null; sourcePublishedAt?: string | null; } export interface DocumentObligation { measureSid: string; measureTypeId: string; measureTypeDescription?: string | null; conditionCode: string; kind: ObligationKind; /** Documents that meet the obligation: a certificate, a licence. */ satisfiedBy: string[]; /** Codes stating the goods are not concerned. */ exemptedBy: string[]; note?: string | null; suspended: boolean; regulationId?: string | null; } export interface LineWarning { type: WarningType; severity: WarningSeverity; message: string; measureSid?: string | null; measureTypeId?: string | null; documentCode?: string | null; relatedCodes: string[]; } export interface AppliedRule { ruleId: string; name: string; action: RuleAction; conditions: Record; note?: string | null; } export interface AppliedMeasure { measureSid: string; goodsCode: string; measureTypeId: string; measureTypeDescription?: string | null; category: MeasureCategory; geoAreaCode: string; validFrom?: string | null; validTo?: string | null; national?: boolean; suspended?: boolean; dutyExpression?: string | null; quotaOrderNumber?: string | null; regulationId?: string | null; sourceFile?: string | null; sourcePublishedAt?: string | null; } /** * The tariff preference an import line can declare (D/E 4/17): 100 the * third-country duty, 300 a preference, 320 a preference within a quota. * The claim the measures allow — the proof of origin is what backs it. */ export interface LinePreference { preferenceCode: string; preferentialRate?: string | null; thirdCountryRate?: string | null; /** Only when the code draws on a quota. */ quotaOrderNumber?: string | null; agreementArea?: string | null; agreementDescription?: string | null; measureSid?: string | null; regulationId?: string | null; /** One of these is declared to claim the preference. */ originProofs: DocumentRequirement[]; /** TARIC when read from the measure, MANUAL when from the agreement. */ originProofSource: ReferenceSource; /** A quota open for the code that the proposed code does not draw on. */ availableQuotaOrderNumber?: string | null; availableQuotaRate?: string | null; note?: string | null; } export interface LineCheckResponse { inputCode: string; originCountry?: string | null; destinationCountry?: string | null; measureCountry?: string | null; direction: TradeDirection; checkedOn: string; resolvedCode?: string | null; formattedCode?: string | null; codeDescription?: string | null; resolutionMethod: ResolutionMethod; candidates: CodeCandidate[]; replacementCodes: string[]; codeChange?: CodeChange; documentsRequired: DocumentRequirement[]; documentsAlternatives: DocumentRequirement[][]; documentsExemption: DocumentRequirement[]; /** Owed, but deferred by the procedure to the office of destination. */ documentsSuspended: DocumentRequirement[]; documentsOptional: DocumentRequirement[]; documentsConditional: DocumentRequirement[]; obligations: DocumentObligation[]; noneRequired: boolean; warnings: LineWarning[]; status: LineStatus; expiringOn?: string | null; codeConfidence: ConfidenceLevel; codeConfidenceReason: string; documentConfidence: ConfidenceLevel; documentConfidenceReason: string; source: ReferenceSource; appliedMeasures: AppliedMeasure[]; appliedRules: AppliedRule[]; preference?: LinePreference | null; referenceAsOf?: string | null; } export interface ReferenceDataStatus { counts: Record; referenceAsOf?: string | null; } export interface GeoArea { code: string; name?: string | null; memberCodes: string[]; } export interface Paging { pageSize: number; pageIndex: number; totalCount: number; } export interface AllObjectsResponse { paging: Paging; data: T[]; } export interface ClientProfile { id: string; name: string; description?: string | null; /** Canonical field → the client's own column header. */ columnMapping: Record; /** Which sheet row holds the headers. A Softpak pack has metadata above it. */ headerRow: number; sheetName?: string | null; missingRequiredFields: string[]; } // --------------------------------------------------------------------------- // Shipments: upload, the review table, the export. // --------------------------------------------------------------------------- export enum BatchStatus { UPLOADED = 1, MAPPING_REQUIRED = 2, PROCESSING = 3, COMPLETED = 4, FAILED = 5, } export enum ReviewStage { NOT_STARTED = 1, IN_REVIEW = 2, REVIEWED = 3, } export enum BatchSource { UPLOAD = 1, MANUAL = 2, } export enum ExportFormat { REVIEW = 1, SOURCE = 2, SOFTPAK = 3, SCOPE = 4, FITON = 5, } export enum RowDecision { PENDING = 1, ACCEPTED = 2, CORRECTED = 3, } export enum RuleScope { CLIENT = 1, TENANT = 2, } export interface ClientProfileRef { id: string; name: string; } export interface BatchMetrics { totalLines: number; uniqueLookups: number; machineSeconds: number; reviewSeconds?: number | null; statusCounts: Record; extractionScore: number; documentScore: number; codeConfidenceCounts: Record; documentConfidenceCounts: Record; /** Null when the pack does not state the figure — not the same as zero. */ totalPackages: number | null; totalGrossWeight: number | null; totalNetWeight: number | null; totalValue: number | null; } export interface BatchResponse { id: string; name: string; clientProfile: ClientProfileRef; status: BatchStatus; source: BatchSource; sourceFileName?: string | null; resultFileName?: string | null; checkDate?: string | null; defaultDirection: TradeDirection; destinationCountry?: string | null; shipmentReference?: string | null; currency: string; metrics: BatchMetrics; errors: string[]; reviewStage: ReviewStage; reviewStartedAt?: string | null; reviewFinishedAt?: string | null; referenceAsOf?: string | null; datetimeInserted: string; } export interface ReviewDocuments { required: DocumentRequirement[]; alternatives: DocumentRequirement[][]; exemption: DocumentRequirement[]; suspended: DocumentRequirement[]; /** Owed only for some consignments of the code. */ conditional?: DocumentRequirement[]; /** Only claim a benefit; not needed for the goods to pass. */ optional?: DocumentRequirement[]; noneRequired: boolean; label: string; } export interface ReviewRow { rowIndex: number; description?: string | null; inputCode?: string | null; proposedCode?: string | null; formattedCode?: string | null; codeDescription?: string | null; candidates: string[]; /** The same candidates with their description path, for the picker. */ candidateOptions?: CodeCandidate[]; replacementCodes: string[]; /** Strike the input through only on CHANGED. */ codeChange?: CodeChange; originCountry?: string | null; destinationCountry?: string | null; measureCountry?: string | null; direction?: TradeDirection | null; procedure?: CustomsProcedure | null; codeConfidence: ConfidenceLevel; codeConfidenceReason: string; documentConfidence: ConfidenceLevel; documentConfidenceReason: string; source: ReferenceSource; documents: ReviewDocuments; /** Null on export lines and on rows checked before preferences were read. */ preference?: LinePreference | null; warnings: LineWarning[]; appliedRules: AppliedRule[]; packages?: number | null; grossWeight?: number | null; netWeight?: number | null; value?: number | null; decision: RowDecision; correctedCode?: string | null; cbamPermitNumber?: string | null; eudrReference?: string | null; licenceNumbers: string[]; reviewNote?: string | null; status: string; needsReview: boolean; } export interface ShipmentTotals { /** Null when the pack does not state the figure — not the same as zero. */ packages: number | null; grossWeight: number | null; netWeight: number | null; value: number | null; currency: string; } export interface ReviewHeader { batchId: string; shipmentReference?: string | null; name: string; clientProfile: ClientProfileRef; status: BatchStatus; source: BatchSource; direction: TradeDirection; procedure: CustomsProcedure; originCountries: string[]; destinationCountry?: string | null; checkDate?: string | null; referenceAsOf?: string | null; totals: ShipmentTotals; totalLines: number; extractionScore: number; documentScore: number; codeConfidenceCounts: Record; documentConfidenceCounts: Record; linesNeedingReview: number; } export interface ReviewTableResponse { header: ReviewHeader; paging: Paging; rows: ReviewRow[]; } export interface RowReviewRequest { correctedCode?: string | null; decision?: RowDecision | null; cbamPermitNumber?: string | null; eudrReference?: string | null; licenceNumbers?: string[] | null; reviewNote?: string | null; } export interface MakeRuleRequest { name: string; description?: string | null; scope: RuleScope; action: RuleAction; pinnedCode?: string | null; documentCodes: string[]; note?: string | null; useCodePrefix: boolean; codePrefixLength: number; useOriginCountry: boolean; useDestinationCountry: boolean; useDirection: boolean; descriptionContains?: string | null; createdBy?: string | null; } export interface RuleResponse { id: string; name: string; description?: string | null; action: RuleAction; conditions: Record; active: boolean; hitCount: number; } export interface ExportFormatResponse { format: ExportFormat; name: string; description: string; available: boolean; unavailableReason?: string | null; isProfileDefault: boolean; } export interface ColumnMappingSuggestion { headers: string[]; suggestedMapping: Record; unmappedHeaders: string[]; missingRequiredFields: string[]; } export interface UploadOptions { clientProfileId: string; file: File; name?: string; checkDate?: string; destinationCountry?: string; direction?: TradeDirection; shipmentReference?: string; } export interface ReviewQuery { needsReviewOnly?: boolean; confidence?: ConfidenceLevel; pageSize?: number; pageIndex?: number; }