mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 14:08:11 +00:00
split export
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { ContractRateScheduleBuilder } from './contract-rate-schedule.builder';
|
||||
import { Rate } from '../modules/rule-engine/entities/rate.entity';
|
||||
|
||||
/** Minimal Rate factory for the builder unit tests. */
|
||||
function rate(partial: Partial<Rate>): Rate {
|
||||
return {
|
||||
trigger: 'ALWAYS',
|
||||
appliesTo: 'CONTAINER',
|
||||
tradeDirection: 'IMPORT',
|
||||
rateType: 'CONTAINER_IMPORT',
|
||||
currency: 'USD',
|
||||
rateValue: 200,
|
||||
rateUnit: 'PER_CONTAINER',
|
||||
...partial,
|
||||
} as Rate;
|
||||
}
|
||||
|
||||
describe('ContractRateScheduleBuilder', () => {
|
||||
const LIVE: Rate[] = [
|
||||
rate({
|
||||
appliesTo: 'CONTAINER',
|
||||
tradeDirection: 'IMPORT',
|
||||
rateType: 'CONTAINER_IMPORT',
|
||||
rateValue: 200,
|
||||
rateUnit: 'PER_CONTAINER',
|
||||
originYard: { label: 'Negad' } as never,
|
||||
destinationYard: { label: 'Mojo Dry Port' } as never,
|
||||
containerType: { label: '40ft GP' } as never,
|
||||
}),
|
||||
rate({
|
||||
appliesTo: 'CONTAINER',
|
||||
tradeDirection: 'EXPORT', // wrong direction — must be filtered out for import
|
||||
rateType: 'CONTAINER_EXPORT',
|
||||
rateValue: 819,
|
||||
originYard: { label: 'GMP' } as never,
|
||||
destinationYard: { label: 'SGTD' } as never,
|
||||
}),
|
||||
rate({
|
||||
appliesTo: 'BULK', // wrong freight — filtered out for a container contract
|
||||
tradeDirection: 'IMPORT',
|
||||
rateType: 'BULK_IMPORT',
|
||||
rateUnit: 'PER_WAGON',
|
||||
rateValue: 100,
|
||||
}),
|
||||
rate({
|
||||
appliesTo: 'FIRST_MILE',
|
||||
trigger: 'ALWAYS',
|
||||
tradeDirection: null,
|
||||
rateUnit: 'PER_CONTAINER',
|
||||
rateValue: 50,
|
||||
}),
|
||||
rate({
|
||||
appliesTo: 'OTHER',
|
||||
trigger: 'CUSTOMS_CLEARANCE',
|
||||
tradeDirection: null,
|
||||
rateType: 'CUSTOMS_CLEARANCE',
|
||||
rateUnit: 'FLAT',
|
||||
rateValue: 120,
|
||||
}),
|
||||
];
|
||||
|
||||
const build = (dir: 'IMP' | 'EXP' | 'DOM', freight: 'CON' | 'BULK') => {
|
||||
const service = { findLiveRatesDetailed: jest.fn().mockResolvedValue(LIVE) };
|
||||
return new ContractRateScheduleBuilder(service as never).build(dir, freight);
|
||||
};
|
||||
|
||||
it('shows only import container lanes for an import container contract', async () => {
|
||||
const s = await build('IMP', 'CON');
|
||||
expect(s.freightLanes).toHaveLength(1);
|
||||
expect(s.freightLanes[0]).toMatchObject({
|
||||
route: 'Negad → Mojo Dry Port',
|
||||
cargo: '40ft GP',
|
||||
currency: 'USD',
|
||||
amount: '200',
|
||||
unit: 'per container',
|
||||
});
|
||||
});
|
||||
|
||||
it('always lists route-agnostic services and surcharges', async () => {
|
||||
const s = await build('IMP', 'CON');
|
||||
expect(s.additionalServices).toHaveLength(1);
|
||||
expect(s.additionalServices[0].route).toBe('First-mile pickup by truck');
|
||||
expect(s.surcharges).toHaveLength(1);
|
||||
expect(s.surcharges[0].route).toBe('Customs clearance service');
|
||||
});
|
||||
|
||||
it('excludes container lanes from a bulk contract', async () => {
|
||||
const s = await build('IMP', 'BULK');
|
||||
expect(s.freightLanes).toHaveLength(1);
|
||||
expect(s.freightLanes[0]).toMatchObject({ amount: '100', unit: 'per wagon' });
|
||||
});
|
||||
|
||||
it('flags an empty schedule when nothing priced matches', async () => {
|
||||
const service = { findLiveRatesDetailed: jest.fn().mockResolvedValue([]) };
|
||||
const s = await new ContractRateScheduleBuilder(service as never).build('DOM', 'CON');
|
||||
expect(s.isEmpty).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user