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

@@ -41,10 +41,15 @@ export const BOOKING_STATUSES = [
'CANCELLED',
'PENDING_CONSOLIDATION',
'CONSOLIDATED',
'CONTRACT_ACTIVE',
'CONTRACT_CLOSED',
] as const;
export type BookingStatus = (typeof BOOKING_STATUSES)[number];
export const BOOKING_TYPES = ['ONE_TIME', 'GENERAL_CONTRACT'] as const;
export type BookingTypeValue = (typeof BOOKING_TYPES)[number];
export const PAYMENT_STATUSES = [
'PENDING',
'PNR_GENERATED',
@@ -125,8 +130,28 @@ export class Booking extends BaseEntity {
@Column({ name: 'status', type: 'varchar', length: 40, default: 'DRAFT' })
status!: string;
@Column({ name: 'scheduled_date', type: 'timestamptz' })
scheduledDate!: Date;
/**
* ONE_TIME for a normal single-shipment booking; GENERAL_CONTRACT for an
* umbrella contract that is signed/paid once and then drawn down by many
* orders (each order spawns its own ONE_TIME child booking).
*/
@Column({ name: 'booking_type', type: 'varchar', length: 20, default: 'ONE_TIME' })
bookingType!: string;
/**
* Nullable: general contracts have no shipment date at creation — the date is
* chosen per drawdown order. One-time bookings always set this (the pool day key).
*/
@Column({ name: 'scheduled_date', type: 'timestamptz', nullable: true })
scheduledDate?: Date | null;
/**
* General contracts only: when the ordering window closes, computed from the
* global CONTRACT_PERIOD_MONTHS setting at activation. Null for one-time
* bookings and for contracts that are not yet active.
*/
@Column({ name: 'expires_at', type: 'timestamptz', nullable: true })
expiresAt?: Date | null;
@Column({ name: 'total_amount', type: 'numeric', precision: 14, scale: 2, default: 0 })
totalAmount!: number;