refactor(bookings): replace RFQ/quotation flow with submit, staff review, approval routing, and payment stubs

This commit is contained in:
marshal
2026-06-03 15:45:38 +03:00
parent f93a502247
commit 4ed0e22f55
16 changed files with 1448 additions and 367 deletions

View File

@@ -0,0 +1,26 @@
import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
import { Booking } from './booking.entity';
export const REVIEW_NOTE_TYPES = ['CHANGES_REQUESTED', 'REJECTION'] as const;
export type ReviewNoteType = (typeof REVIEW_NOTE_TYPES)[number];
@Entity({ schema: 'freight', name: 'booking_review_note' })
@Index(['bookingId'])
export class BookingReviewNote extends BaseEntity {
@Column({ name: 'booking_id', type: 'uuid' })
bookingId!: string;
@ManyToOne(() => Booking, (b) => b.reviewNotes, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'booking_id' })
booking?: Booking;
@Column({ name: 'author_id', type: 'uuid', nullable: true })
authorId?: string | null;
@Column({ name: 'note', type: 'text' })
note!: string;
@Column({ name: 'type', type: 'varchar', length: 30 })
type!: ReviewNoteType;
}

View File

@@ -11,25 +11,47 @@ import { BookingApprovalStep } from './booking-approval-step.entity';
import { BookingCargoModifier } from './booking-cargo-modifier.entity';
import { BookingContainer } from './booking-container.entity';
import { BookingRateSnapshot } from './booking-rate-snapshot.entity';
import { BookingReviewNote } from './booking-review-note.entity';
export const BOOKING_STATUSES = [
'DRAFT',
'RFQ_SUBMITTED',
'QUOTATION_SENT',
'QUOTATION_APPROVED',
'QUOTATION_REJECTED',
'SUBMITTED',
'CHANGES_REQUESTED',
'PENDING_APPROVAL',
'APPROVED_PENDING_SIGNATURE',
'APPROVED',
'CONTRACT_READY',
'SIGNED_CUSTOMER',
'FULLY_EXECUTED',
'PNR_GENERATED',
'PAYMENT_VERIFICATION_IN_PROGRESS',
'PAID',
'IN_TRANSIT',
'COMPLETED',
'REJECTED',
'CANCELLED',
'PENDING_CONSOLIDATION',
'CONSOLIDATED',
] as const;
export type BookingStatus = (typeof BOOKING_STATUSES)[number];
export const PAYMENT_STATUSES = [
'PENDING',
'PNR_GENERATED',
'VERIFICATION_IN_PROGRESS',
'PAID',
'FAILED',
] as const;
export type PaymentStatus = (typeof PAYMENT_STATUSES)[number];
/** Statuses where the customer may edit booking fields. */
export const CUSTOMER_EDITABLE_STATUSES: BookingStatus[] = [
'DRAFT',
'CHANGES_REQUESTED',
];
@Entity({ schema: 'freight', name: 'bookings' })
export class Booking extends BaseEntity {
@Column({ name: 'reference', type: 'varchar', length: 64, unique: true })
@@ -169,6 +191,18 @@ export class Booking extends BaseEntity {
@Column({ name: 'fully_executed_at', type: 'timestamptz', nullable: true })
fullyExecutedAt?: Date | null;
@Column({ name: 'marketing_approved_by_id', type: 'uuid', nullable: true })
marketingApprovedById?: string | null;
@Column({ name: 'marketing_approved_at', type: 'timestamptz', nullable: true })
marketingApprovedAt?: Date | null;
@Column({ name: 'contract_summary', type: 'text', nullable: true })
contractSummary?: string | null;
@Column({ name: 'locked_at', type: 'timestamptz', nullable: true })
lockedAt?: Date | null;
@Column({ name: 'priority_score', type: 'int', default: 0 })
priorityScore!: number;
@@ -194,6 +228,9 @@ export class Booking extends BaseEntity {
@OneToMany(() => BookingRateSnapshot, (s) => s.booking)
rateSnapshots?: BookingRateSnapshot[];
@OneToMany(() => BookingReviewNote, (n) => n.booking)
reviewNotes?: BookingReviewNote[];
@OneToMany(() => FileRecord, (file) => file.resourceId, {
createForeignKeyConstraints: false,
})