mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 22:18:12 +00:00
130 lines
4.2 KiB
TypeScript
130 lines
4.2 KiB
TypeScript
import { BookingPricingService } from './booking-pricing.service';
|
||
import type { Booking } from './entities/booking.entity';
|
||
import type { Rate } from '../rule-engine/entities/rate.entity';
|
||
|
||
const MOCK_CBE_RATE = 130;
|
||
|
||
describe('BookingPricingService — domestic corridor', () => {
|
||
const intercityBulkUsd: Rate = {
|
||
id: 'rate-intercity-bulk-usd',
|
||
rateType: 'INTERCITY_BULK',
|
||
currency: 'USD',
|
||
rateValue: 35,
|
||
rateUnit: 'PER_TON',
|
||
status: 'LIVE',
|
||
containerTypeId: null,
|
||
} as Rate;
|
||
|
||
const intercityContainerUsd: Rate = {
|
||
id: 'rate-intercity-container-usd',
|
||
rateType: 'INTERCITY_CONTAINER',
|
||
currency: 'USD',
|
||
rateValue: 400,
|
||
rateUnit: 'PER_CONTAINER',
|
||
status: 'LIVE',
|
||
containerTypeId: null,
|
||
} as Rate;
|
||
|
||
let service: BookingPricingService;
|
||
let bookingsRepository: { calculateWagonCount: jest.Mock };
|
||
let ratesService: { findLiveRates: jest.Mock };
|
||
let exchangeService: { getRate: jest.Mock };
|
||
|
||
beforeEach(() => {
|
||
bookingsRepository = { calculateWagonCount: jest.fn().mockResolvedValue(2) };
|
||
ratesService = {
|
||
findLiveRates: jest.fn().mockResolvedValue([intercityBulkUsd, intercityContainerUsd]),
|
||
};
|
||
exchangeService = {
|
||
getRate: jest.fn().mockResolvedValue(MOCK_CBE_RATE),
|
||
};
|
||
|
||
service = new BookingPricingService(
|
||
bookingsRepository as never,
|
||
{} as never,
|
||
{} as never,
|
||
ratesService as never,
|
||
{} as never,
|
||
exchangeService as never,
|
||
);
|
||
});
|
||
|
||
it('prices domestic bulk in ETB using INTERCITY_BULK USD rate × CBE exchange rate', async () => {
|
||
const booking = {
|
||
id: 'b-1',
|
||
freightType: 'BULK',
|
||
tradeDirection: 'DOMESTIC',
|
||
paymentCurrency: 'ETB',
|
||
cargoTotalWeightVgm: 120,
|
||
bookingContainers: [],
|
||
} as unknown as Booking;
|
||
|
||
const result = await (
|
||
service as unknown as {
|
||
computeBaseRailLinesWithRates: (
|
||
b: Booking,
|
||
input: { containers: [] },
|
||
) => Promise<{ lineItems: Array<{ amount: number; code: string; currency: string }> }>;
|
||
}
|
||
).computeBaseRailLinesWithRates(booking, { containers: [] });
|
||
|
||
expect(result.lineItems).toHaveLength(1);
|
||
expect(result.lineItems[0].code).toBe('INTERCITY_BULK');
|
||
expect(result.lineItems[0].currency).toBe('ETB');
|
||
expect(result.lineItems[0].amount).toBe(Math.round(35 * 120 * MOCK_CBE_RATE));
|
||
});
|
||
|
||
it('prices domestic bulk in USD using INTERCITY_BULK USD rate directly', async () => {
|
||
const booking = {
|
||
id: 'b-1-usd',
|
||
freightType: 'BULK',
|
||
tradeDirection: 'DOMESTIC',
|
||
paymentCurrency: 'USD',
|
||
cargoTotalWeightVgm: 120,
|
||
bookingContainers: [],
|
||
} as unknown as Booking;
|
||
|
||
const result = await (
|
||
service as unknown as {
|
||
computeBaseRailLinesWithRates: (
|
||
b: Booking,
|
||
input: { containers: [] },
|
||
) => Promise<{ lineItems: Array<{ amount: number; code: string; currency: string }> }>;
|
||
}
|
||
).computeBaseRailLinesWithRates(booking, { containers: [] });
|
||
|
||
expect(result.lineItems).toHaveLength(1);
|
||
expect(result.lineItems[0].code).toBe('INTERCITY_BULK');
|
||
expect(result.lineItems[0].currency).toBe('USD');
|
||
expect(result.lineItems[0].amount).toBe(35 * 120);
|
||
});
|
||
|
||
it('prices domestic container in ETB using INTERCITY_CONTAINER USD fallback × CBE rate', async () => {
|
||
const booking = {
|
||
id: 'b-2',
|
||
freightType: 'CONTAINER',
|
||
tradeDirection: 'DOMESTIC',
|
||
paymentCurrency: 'ETB',
|
||
cargoTotalWeightVgm: 50,
|
||
bookingContainers: [],
|
||
} as unknown as Booking;
|
||
|
||
const result = await (
|
||
service as unknown as {
|
||
computeBaseRailLinesWithRates: (
|
||
b: Booking,
|
||
input: {
|
||
containers: Array<{ containerTypeId: string; quantity: number }>;
|
||
},
|
||
) => Promise<{ lineItems: Array<{ amount: number; code: string; currency: string }> }>;
|
||
}
|
||
).computeBaseRailLinesWithRates(booking, {
|
||
containers: [{ containerTypeId: 'ct-20', quantity: 3 }],
|
||
});
|
||
|
||
expect(result.lineItems.some((l) => l.code === 'INTERCITY_CONTAINER')).toBe(true);
|
||
const line = result.lineItems.find((l) => l.code === 'INTERCITY_CONTAINER')!;
|
||
expect(line.currency).toBe('ETB');
|
||
});
|
||
});
|