mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 14:08:11 +00:00
- Create migration for booking_requests table with necessary fields and indexes. - Implement BookingRequestRepository for database operations related to booking requests. - Develop BookingRequestService to handle business logic for submitting, accepting, rejecting, and canceling booking requests. - Create DTOs for creating booking requests and reviewing them. - Define BookingRequest entity to map to the booking_requests table. - Add UI components for managing shipment requests, including detail and list pages. - Implement OperationDatePicker component for selecting available shipment days.
81 lines
3.1 KiB
TypeScript
81 lines
3.1 KiB
TypeScript
import { BadRequestException } from '@nestjs/common';
|
|
import { BookingTransitionService } from './booking-transition.service';
|
|
|
|
/**
|
|
* Operation-request review for general-contract drawdown orders:
|
|
* - ACCEPT a train order → FULLY_EXECUTED and enqueued into the batch pool.
|
|
* - ACCEPT a road order → ROAD_DISPATCH_PENDING, NOT enqueued.
|
|
* - REQUEST_CHANGES requires a note → OPERATION_CHANGES_REQUESTED.
|
|
*/
|
|
describe('BookingTransitionService — operation review', () => {
|
|
function makeService(serviceTypeCode: string) {
|
|
const booking = {
|
|
id: 'b-1',
|
|
status: 'OPERATION_REQUEST_PENDING',
|
|
originYardId: 'o-1',
|
|
destinationYardId: 'd-1',
|
|
scheduledDate: new Date('2026-07-01T00:00:00.000Z'),
|
|
serviceType: { code: serviceTypeCode },
|
|
};
|
|
const bookingsRepository = {
|
|
update: jest.fn().mockResolvedValue({ id: 'b-1' }),
|
|
createReviewNote: jest.fn().mockResolvedValue(undefined),
|
|
};
|
|
const bookingsService = {
|
|
findById: jest.fn().mockResolvedValue(booking),
|
|
};
|
|
const bookingBatchService = {
|
|
enqueueRouteDayProcessing: jest.fn(),
|
|
};
|
|
|
|
const service = new BookingTransitionService(
|
|
bookingsRepository as never,
|
|
{} as never, // ruleEngineService
|
|
{} as never, // pricingService
|
|
{} as never, // contractService
|
|
{} as never, // filesService
|
|
{} as never, // fileUploadSettingsService
|
|
bookingBatchService as never,
|
|
bookingsService as never,
|
|
);
|
|
return { service, bookingsRepository, bookingBatchService };
|
|
}
|
|
|
|
it('ACCEPT of a train order → FULLY_EXECUTED and enqueues the batch pool', async () => {
|
|
const { service, bookingsRepository, bookingBatchService } =
|
|
makeService('RAIL_CONTAINER');
|
|
await service.reviewOperationRequest('b-1', 'ACCEPT', 'staff-1');
|
|
expect(bookingsRepository.update).toHaveBeenCalledWith(
|
|
'b-1',
|
|
expect.objectContaining({ status: 'FULLY_EXECUTED' }),
|
|
);
|
|
expect(bookingBatchService.enqueueRouteDayProcessing).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('ACCEPT of a road order → ROAD_DISPATCH_PENDING and does NOT enqueue', async () => {
|
|
const { service, bookingsRepository, bookingBatchService } =
|
|
makeService('ROAD_CONTAINER');
|
|
await service.reviewOperationRequest('b-1', 'ACCEPT', 'staff-1');
|
|
expect(bookingsRepository.update).toHaveBeenCalledWith(
|
|
'b-1',
|
|
expect.objectContaining({ status: 'ROAD_DISPATCH_PENDING' }),
|
|
);
|
|
expect(bookingBatchService.enqueueRouteDayProcessing).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('REQUEST_CHANGES requires a note → OPERATION_CHANGES_REQUESTED', async () => {
|
|
const { service, bookingsRepository } = makeService('RAIL_CONTAINER');
|
|
await expect(
|
|
service.reviewOperationRequest('b-1', 'REQUEST_CHANGES', 'staff-1', {}),
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
await service.reviewOperationRequest('b-1', 'REQUEST_CHANGES', 'staff-1', {
|
|
note: 'Fix the schedule',
|
|
});
|
|
expect(bookingsRepository.update).toHaveBeenCalledWith(
|
|
'b-1',
|
|
expect.objectContaining({ status: 'OPERATION_CHANGES_REQUESTED' }),
|
|
);
|
|
});
|
|
});
|