Files
edr-platform/apps/edr-freight-api/src/modules/contracts/contract-booking.initiate-gate.spec.ts
Marshal 40904049cf feat: implement consolidation approval process for shared-wagon bookings
- Add migration for consolidation approvals table and status enum
- Create ConsolidationApprovalService to handle approval logic
- Implement repository for managing consolidation approvals
- Add entity for consolidation approval with necessary fields
- Develop frontend components for displaying and managing consolidation approvals
- Create tests for consolidation approval service to ensure correct behavior
2026-08-18 13:17:55 +00:00

76 lines
2.5 KiB
TypeScript

import { ForbiddenException } from '@nestjs/common';
import { ContractBookingService } from './contract-booking.service';
import { Contract } from './entities/contract.entity';
/**
* Who may open a shipment instance on a customs (Path B) contract. The customer
* initiates his own ONE_TIME customs booking and uploads the GL-input documents
* on it; GL still clears it and completes it with cargo and price. GENERAL
* customs instances come from a shipment request, and completing/creating a
* customs booking outright stays GL-only.
*/
describe('ContractBookingService — customs booking gate', () => {
function makeService() {
return new ContractBookingService(
{} as never, // contractsRepository
{} as never, // bookingsRepository
{} as never, // bookingPricingService
{} as never, // consolidationService
{} as never, // containerTypesService
{} as never, // ruleEngineService
{} as never, // milestoneService
{} as never, // invoiceService
{} as never, // bookingNotifier
{} as never, // dataSource
{} as never, // trainSchedulingService
{} as never, // bookingBatchService
{} as never, // bookingTransitionService
{} as never, // consolidationApprovalService
);
}
type WithPrivate = {
assertGate: (
c: Contract,
isGlActor: boolean,
isInitiate?: boolean,
) => Promise<string>;
};
const customsContract = (contractKind: 'ONE_TIME' | 'GENERAL'): Contract =>
({
id: 'c-1',
contractKind,
status: 'FULLY_EXECUTED',
customsClearingEnabled: true,
}) as Contract;
const gate = (c: Contract, isGl: boolean, isInitiate?: boolean) =>
(makeService() as never as WithPrivate).assertGate(c, isGl, isInitiate);
it('lets the customer initiate a ONE_TIME customs shipment', async () => {
await expect(gate(customsContract('ONE_TIME'), false, true)).resolves.toBe(
'CUSTOMER',
);
});
it('still lets GL initiate on the customer behalf', async () => {
await expect(gate(customsContract('ONE_TIME'), true, true)).resolves.toBe(
'GL_ET',
);
});
it('rejects a customer creating a customs booking outright (cargo + day)', async () => {
await expect(gate(customsContract('ONE_TIME'), false)).rejects.toBeInstanceOf(
ForbiddenException,
);
});
it('rejects a customer initiating a GENERAL customs shipment (request only)', async () => {
await expect(
gate(customsContract('GENERAL'), false, true),
).rejects.toBeInstanceOf(ForbiddenException);
});
});