feat: setup invoice entityt

This commit is contained in:
Nathnael
2026-06-26 13:38:48 +00:00
parent f86bdb1c36
commit aa59e30ea7
3 changed files with 108 additions and 13 deletions

View File

@@ -0,0 +1,43 @@
import { BaseEntity } from "@edr/api-common";
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
import { Invoice } from "./invoice.entity";
@Entity({ schema: "freight", name: "invoice_lines" })
export class InvoiceLine extends BaseEntity {
@Column({ name: "invoice_id", type: "uuid", nullable: false })
invoiceId!: string;
@ManyToOne(() => Invoice, { onDelete: "CASCADE" })
@JoinColumn({ name: "invoice_id" })
invoice!: Invoice;
@Column({ name: "charge_type", type: "varchar", nullable: false })
chargeType!: string;
@Column({ name: "description", type: "varchar", length: 255, nullable: true })
description?: string;
/** Units this line bills for (e.g. container count, wagon count, tons). */
@Column({ name: "quantity", type: "numeric", precision: 12, scale: 2, default: 1 })
quantity!: number;
/** Price per unit; `amount` is normally `quantity * unitRate`. */
@Column({ name: "unit_rate", type: "numeric", precision: 14, scale: 2, default: 0 })
unitRate!: number;
@Column({
name: "amount",
type: "numeric",
precision: 14,
scale: 2,
nullable: false,
})
amount!: number;
@Column({ name: "currency", type: "varchar", length: 8, default: "ETB" })
currency!: string;
@Column({ name: "metadata", type: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null;
}

View File

@@ -1,17 +1,35 @@
import { BaseEntity } from "@edr/api-common";
import { Freight } from "@edr/types";
import { Column, Entity } from "typeorm";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
import { PaymentEntity } from "../../payment/entities/payment.entity";
import { Company } from "../../companies/entities/company.entity";
import { CompanyProfile } from "../../companies/entities/company-profile.entity";
@Entity({schema:"freight", name: "invoices" })
@Entity({ schema: "freight", name: "invoices" })
@Index(["companyId"])
@Index(["companyProfileId"])
export class Invoice extends BaseEntity {
@Column({ name: "booking_id", type: "uuid" })
bookingId!: string;
@Column({ name: "invoice_number", type: "varchar", length: 64, unique: true })
invoiceNumber!: string;
@Column({ name: "amount", type: "numeric", precision: 14, scale: 2 })
amount!: number;
/** The customer (company) this invoice is billed to. */
@Column({ name: "company_id", type: "uuid" })
companyId!: string;
@ManyToOne(() => Company)
@JoinColumn({ name: "company_id" })
company?: Company;
/** The specific company profile (importer/exporter/forwarder/...) billed. */
@Column({ name: "company_profile_id", type: "uuid" })
companyProfileId!: string;
@ManyToOne(() => CompanyProfile)
@JoinColumn({ name: "company_profile_id" })
companyProfile?: CompanyProfile;
@Column({ name: "total_amount", type: "numeric", precision: 14, scale: 2 })
totalAmount!: number;
@Column({ name: "currency", type: "varchar", length: 8, default: "ETB" })
currency!: string;
@@ -19,13 +37,38 @@ export class Invoice extends BaseEntity {
@Column({
name: "status",
type: "enum",
enum: Freight.PaymentStatus,
default: Freight.PaymentStatus.Pending,
enum: Freight.InvoiceStatus,
default: Freight.InvoiceStatus.Draft,
})
status!: Freight.PaymentStatus;
status!: Freight.InvoiceStatus;
@Column({ name: "issued_at", type: "timestamptz" })
issuedAt!: Date;
/** The source of the payment (e.g. booking, customer, etc.). */
@Column({ name: "source", type: "varchar", length: 255, nullable: false })
source!: string;
/** The ID of the source (e.g. booking ID, customer ID, etc.). */
@Column({ name: "source_id", type: "varchar", length: 255, nullable: false })
sourceId!: string;
/** The type of Invoice (e.g. prepaid, credit, etc.). it suppose to answer the question "what is the invoice for?" */
@Column({
type: "varchar",
length: 255,
nullable: false,
})
type!: string;
/** Set when the invoice is actually issued (DRAFT invoices leave this null). */
@Column({ name: "issued_at", type: "timestamptz", nullable: true })
issuedAt?: Date | null;
/** The ID of the payment that generated this invoice. */
@Column({ name: "payment_id", type: "uuid", nullable: true })
paymentId?: string | null;
@ManyToOne(() => PaymentEntity)
@JoinColumn({ name: "payment_id" })
payment?: PaymentEntity;
@Column({ name: "due_at", type: "timestamptz" })
dueAt!: Date;

View File

@@ -23,7 +23,7 @@ export const GOVERNMENT_PRIORITY_BONUS = 50_000;
export interface GovernmentBookingFields {
isGovernment: boolean;
governmentInstitution?: string | null;
governmentInstitution?: string | null;
}
export enum ExceededAction {
@@ -128,6 +128,15 @@ export enum PaymentStatus {
Refunded = "REFUNDED",
}
export enum InvoiceStatus {
Draft = "DRAFT",
Pending = "PENDING",
Paid = "PAID",
Overdue = "OVERDUE",
Cancelled = "CANCELLED",
Refunded = "REFUNDED",
}
export enum SchedulingStatus {
NotScheduled = "NOT_SCHEDULED",
Holding = "HOLDING",