mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
- Add ShippingLineBookingsPage for listing and managing shipping line bookings. - Create ShippingLineDocumentsModal for document uploads related to bookings. - Introduce ShippingLineInitiateModal for initiating new shipping line bookings. - Implement booking document state management with booking-doc-state utility. - Add shipping line bookings service for API interactions. - Update index to export new components and services. - Enhance types for freight to include shipping line credits.
111 lines
3.9 KiB
TypeScript
111 lines
3.9 KiB
TypeScript
import { BaseEntity } from "@edr/api-common";
|
|
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
|
|
|
import { Booking } from "../../bookings/entities/booking.entity";
|
|
import { Invoice } from "../../billing/entities/invoice.entity";
|
|
import { ShippingLineCompany } from "./shipping-line-company.entity";
|
|
|
|
/** Where a credit sits between "service used" and "money received". */
|
|
export enum ShippingLineCreditStatus {
|
|
/** Service used, priced, not yet on any invoice. Counts as debt. */
|
|
Unbilled = "UNBILLED",
|
|
/** Finance put it on an invoice; awaiting payment. Still counts as debt. */
|
|
Billed = "BILLED",
|
|
/** The invoice settled. Terminal — no longer debt, and never re-billed. */
|
|
Paid = "PAID",
|
|
/** Written off / booking voided. Terminal, excluded from every total. */
|
|
Cancelled = "CANCELLED",
|
|
}
|
|
|
|
/** Statuses a shipping line still owes money for. */
|
|
export const OUTSTANDING_CREDIT_STATUSES = [
|
|
ShippingLineCreditStatus.Unbilled,
|
|
ShippingLineCreditStatus.Billed,
|
|
] as const;
|
|
|
|
/**
|
|
* What a shipping line owes for one booking.
|
|
*
|
|
* Shipping lines get the service first and pay later, so a booking of theirs
|
|
* raises no invoice and passes no payment gate — it raises one of these. The
|
|
* amount is frozen when the booking is priced and is never recalculated, so a
|
|
* later rate change cannot silently alter a debt already incurred.
|
|
*
|
|
* Finance batches unbilled credits into one invoice (see
|
|
* `ShippingLineCreditsService.generateInvoice`); the line pays that invoice
|
|
* through the ordinary CBE flow; settlement flips the batch to PAID and the
|
|
* debt disappears. The outstanding figure is always derived by summing
|
|
* {@link OUTSTANDING_CREDIT_STATUSES} rows — there is no balance column,
|
|
* because a stored balance is one missed UPDATE away from being a lie.
|
|
*/
|
|
@Entity({ schema: "freight", name: "shipping_line_credits" })
|
|
@Index(["shippingLineCompanyId", "status"])
|
|
@Index(["invoiceId"])
|
|
export class ShippingLineCredit extends BaseEntity {
|
|
/** The line that owes this. */
|
|
@Column({ name: "shipping_line_company_id", type: "uuid" })
|
|
shippingLineCompanyId!: string;
|
|
|
|
@ManyToOne(() => ShippingLineCompany)
|
|
@JoinColumn({ name: "shipping_line_company_id" })
|
|
shippingLineCompany?: ShippingLineCompany;
|
|
|
|
/**
|
|
* The booking that incurred the charge. Unique among live rows (partial
|
|
* index excludes soft-deleted and CANCELLED), so one booking can never be
|
|
* billed twice.
|
|
*/
|
|
@Column({ name: "booking_id", type: "uuid" })
|
|
bookingId!: string;
|
|
|
|
@ManyToOne(() => Booking)
|
|
@JoinColumn({ name: "booking_id" })
|
|
booking?: Booking;
|
|
|
|
/** Frozen at pricing time. Never recalculated. */
|
|
@Column({ name: "amount", type: "numeric", precision: 14, scale: 2 })
|
|
amount!: number;
|
|
|
|
@Column({ name: "currency", type: "varchar", length: 8, default: "ETB" })
|
|
currency!: string;
|
|
|
|
@Column({
|
|
name: "status",
|
|
type: "enum",
|
|
enum: ShippingLineCreditStatus,
|
|
default: ShippingLineCreditStatus.Unbilled,
|
|
})
|
|
status!: ShippingLineCreditStatus;
|
|
|
|
/** What the charge is for; becomes the invoice line description. */
|
|
@Column({ name: "description", type: "varchar", length: 255, nullable: true })
|
|
description?: string | null;
|
|
|
|
/** The invoice this credit was billed on; null while UNBILLED. */
|
|
@Column({ name: "invoice_id", type: "uuid", nullable: true })
|
|
invoiceId?: string | null;
|
|
|
|
@ManyToOne(() => Invoice)
|
|
@JoinColumn({ name: "invoice_id" })
|
|
invoice?: Invoice;
|
|
|
|
/** When finance put it on an invoice. */
|
|
@Column({ name: "billed_at", type: "timestamptz", nullable: true })
|
|
billedAt?: Date | null;
|
|
|
|
/** When that invoice settled. */
|
|
@Column({ name: "paid_at", type: "timestamptz", nullable: true })
|
|
paidAt?: Date | null;
|
|
|
|
@Column({ name: "cancelled_at", type: "timestamptz", nullable: true })
|
|
cancelledAt?: Date | null;
|
|
|
|
@Column({
|
|
name: "cancellation_reason",
|
|
type: "varchar",
|
|
length: 255,
|
|
nullable: true,
|
|
})
|
|
cancellationReason?: string | null;
|
|
}
|