feat: Implement general contract booking orders functionality

- Add DTOs for creating booking orders and viewing contract quantities.
- Create entities for booking orders and booking order lines.
- Implement service for managing general contract operations, including activation after payment and retrieving quantity lines.
- Develop UI components for contract detail and list pages, including order placement dialog.
- Integrate API service for booking orders, enabling listing and creating orders against contracts.
- Enhance contract status display and quantity pool visualization in the UI.
This commit is contained in:
Marshal
2026-06-20 19:31:51 +00:00
parent cc62482d4e
commit b6d5047d27
43 changed files with 2256 additions and 37 deletions

View File

@@ -1,4 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { CargoUnitOfMeasure } from '@edr/types';
export class BookingReferenceYardDto {
@ApiProperty({ format: 'uuid' })
@@ -73,6 +74,9 @@ export class BookingReferenceCargoTypeChildDto {
@ApiProperty()
show_free_text_box!: boolean;
@ApiProperty({ enum: CargoUnitOfMeasure, nullable: true, required: false })
unit_of_measure?: CargoUnitOfMeasure | null;
}
export class BookingReferenceCargoTypeGroupDto {

View File

@@ -17,7 +17,7 @@ import {
ValidateIf,
ValidateNested,
} from 'class-validator';
import { BOOKING_STATUSES, FREIGHT_TYPES } from '../entities/booking.entity';
import { BOOKING_STATUSES, BOOKING_TYPES, FREIGHT_TYPES } from '../entities/booking.entity';
import { BookingFreightShapeConstraint } from './validators/booking-freight.validator';
const CONTRACT_TYPES = ['NEW', 'RENEWAL'] as const;
@@ -27,6 +27,7 @@ const PAYMENT_CURRENCIES = ['ETB', 'USD'] as const;
export {
BOOKING_STATUSES,
BOOKING_TYPES,
CONTRACT_TYPES,
EQUIPMENT_RETURNS,
FREIGHT_TYPES,
@@ -105,10 +106,24 @@ export class CreateBookingDto {
@IsUUID()
trainScheduleId?: string;
/** The day the customer wants to ship (the pool day key). */
@ApiProperty({ example: '2026-06-15T00:00:00.000Z' })
@ApiPropertyOptional({
enum: BOOKING_TYPES,
default: 'ONE_TIME',
description:
'ONE_TIME (default) for a normal booking; GENERAL_CONTRACT for an umbrella contract drawn down by orders.',
})
@IsOptional()
@IsIn([...BOOKING_TYPES])
bookingType?: string;
/**
* The day the customer wants to ship (the pool day key). Required for one-time
* bookings; omitted for general contracts, which pick the date per order.
*/
@ApiPropertyOptional({ example: '2026-06-15T00:00:00.000Z' })
@ValidateIf((o) => o.bookingType !== 'GENERAL_CONTRACT')
@IsDateString()
scheduledDate!: string;
scheduledDate?: string;
@ApiProperty({ enum: CONTRACT_TYPES })
@IsIn([...CONTRACT_TYPES])

View File

@@ -3,6 +3,7 @@ import { Transform } from 'class-transformer';
import { IsIn, IsOptional, IsUUID } from 'class-validator';
import {
BOOKING_STATUSES,
BOOKING_TYPES,
FREIGHT_TYPES,
PAYMENT_CURRENCIES,
TRADE_DIRECTIONS,
@@ -56,6 +57,11 @@ export class FilterBookingDto {
@IsIn([...FREIGHT_TYPES])
freightType?: string;
@ApiPropertyOptional({ enum: BOOKING_TYPES, description: 'ONE_TIME or GENERAL_CONTRACT' })
@IsOptional()
@IsIn([...BOOKING_TYPES])
bookingType?: string;
@ApiPropertyOptional({ enum: TRADE_DIRECTIONS })
@IsOptional()
@IsIn([...TRADE_DIRECTIONS])