feat: empty container Import

This commit is contained in:
hager
2026-09-04 22:43:20 +00:00
parent 2b6c78cf71
commit 3fb5cdf29f
36 changed files with 968 additions and 49 deletions

View File

@@ -430,6 +430,8 @@ export class ContractTransitionService {
(contract.cargoScope ?? []).find((c) => c.cargoTypeId)?.cargoTypeId,
// Ethiopian-customs-only service types resolve to the Ethiopian variant.
contract.serviceType?.includesEthiopianCustomsOnly,
// An empty-equipment contract resolves to the carriage-only paper.
contract.cargoCondition,
);
if (!active) return null;
return {

View File

@@ -433,6 +433,7 @@ export class ContractsService {
renewalOfId: dto.renewalOfId ?? null,
tradeDirection: dto.tradeDirection,
freightType: dto.freightType,
cargoCondition: dto.cargoCondition === 'EMPTY' ? 'EMPTY' : 'LADEN',
serviceTypeId: dto.serviceTypeId,
// A contract is always QUOTED in USD — the billing currency is chosen per
// booking (or on the shipment request when GL books for the customer), so

View File

@@ -23,6 +23,7 @@ import { CONTRACT_KINDS } from '../entities/contract.entity';
const TRADE_DIRECTIONS = ['IMPORT', 'EXPORT', 'DOMESTIC'] as const;
const FREIGHT_TYPES = ['CONTAINER', 'BULK'] as const;
const CARGO_CONDITIONS = ['LADEN', 'EMPTY'] as const;
const PAYMENT_CURRENCIES = ['ETB', 'USD'] as const;
// Canonical UPPERCASE — everything downstream (booking gating, pricing
// surcharge, GL/portal booking forms) compares contract.equipmentReturn
@@ -154,6 +155,15 @@ export class CreateContractDto {
@IsIn([...FREIGHT_TYPES])
freightType!: string;
/**
* LADEN (default) or EMPTY. EMPTY commits to moving bare equipment and is
* container freight only.
*/
@ApiPropertyOptional({ enum: CARGO_CONDITIONS, default: 'LADEN' })
@IsOptional()
@IsIn([...CARGO_CONDITIONS])
cargoCondition?: string;
@ApiProperty({ format: 'uuid', description: 'FK to service_types.id' })
@IsUUID()
serviceTypeId!: string;

View File

@@ -150,6 +150,14 @@ export class Contract extends BaseEntity {
@Column({ name: 'freight_type', type: 'varchar', length: 20 })
freightType!: string;
/**
* LADEN (the default, and every pre-existing row) or EMPTY. An EMPTY contract
* commits to moving bare equipment and resolves the IMPORT_EMPTY_CONTAINER
* template — a straight carriage agreement with no cargo or customs articles.
*/
@Column({ name: 'cargo_condition', type: 'varchar', length: 10, default: 'LADEN' })
cargoCondition!: string;
@Column({ name: 'service_type_id', type: 'uuid' })
serviceTypeId!: string;