132 lines
4.3 KiB
TypeScript
132 lines
4.3 KiB
TypeScript
/**
|
|
* ════════════════════════════════════════════════════════════
|
|
* مُصادَق (Musadaq) — Invoice Entity
|
|
* ════════════════════════════════════════════════════════════
|
|
*/
|
|
|
|
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
CreateDateColumn,
|
|
UpdateDateColumn,
|
|
ManyToOne,
|
|
OneToMany,
|
|
JoinColumn,
|
|
Index,
|
|
} from 'typeorm';
|
|
import { Tenant } from '../../tenants/entities/tenant.entity';
|
|
import { Company } from '../../companies/entities/company.entity';
|
|
import { InvoiceLine } from './invoice-line.entity';
|
|
|
|
export enum InvoiceStatus {
|
|
UPLOADED = 'uploaded',
|
|
EXTRACTING = 'extracting',
|
|
EXTRACTED = 'extracted',
|
|
VALIDATED = 'validated',
|
|
VALIDATION_FAILED = 'validation_failed',
|
|
SUBMITTING = 'submitting',
|
|
APPROVED = 'approved',
|
|
REJECTED = 'rejected',
|
|
}
|
|
|
|
@Entity('invoices')
|
|
export class Invoice {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id!: string;
|
|
|
|
@Column({ name: 'tenant_id', type: 'uuid' })
|
|
tenant_id!: string;
|
|
|
|
@ManyToOne(() => Tenant, { onDelete: 'CASCADE' })
|
|
@JoinColumn({ name: 'tenant_id' })
|
|
tenant!: Tenant;
|
|
|
|
@Column({ name: 'company_id', type: 'uuid' })
|
|
company_id!: string;
|
|
|
|
@ManyToOne(() => Company, { onDelete: 'CASCADE' })
|
|
@JoinColumn({ name: 'company_id' })
|
|
company!: Company;
|
|
|
|
// ── Invoice Identity ─────────────────────────────────────
|
|
@Column({ type: 'varchar', length: 100, nullable: true })
|
|
invoice_number?: string;
|
|
|
|
@Column({ type: 'date', nullable: true })
|
|
invoice_date?: Date;
|
|
|
|
@Column({ type: 'enum', enum: ['cash', 'credit'], default: 'cash' })
|
|
invoice_type!: 'cash' | 'credit';
|
|
|
|
@Column({ type: 'varchar', length: 3, default: '388' }) // 388: Sales, 381: Credit Note
|
|
ubl_type_code!: string;
|
|
|
|
@Column({ type: 'varchar', length: 3, default: '013' }) // 013: Cash, 023: Credit
|
|
payment_method_code!: string;
|
|
|
|
// ── Parties ──────────────────────────────────────────────
|
|
@Column({ type: 'varchar', length: 20, nullable: true })
|
|
supplier_tin?: string;
|
|
|
|
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
supplier_name?: string;
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
supplier_address?: string;
|
|
|
|
@Column({ type: 'varchar', length: 20, nullable: true })
|
|
buyer_tin?: string;
|
|
|
|
@Column({ type: 'varchar', length: 20, nullable: true })
|
|
buyer_national_id?: string;
|
|
|
|
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
buyer_name?: string;
|
|
|
|
// ── Totals (decimal 15,3) ────────────────────────────────
|
|
@Column({ type: 'decimal', precision: 15, scale: 3, default: 0 })
|
|
subtotal!: number;
|
|
|
|
@Column({ type: 'decimal', precision: 15, scale: 3, default: 0 })
|
|
discount_total!: number;
|
|
|
|
@Column({ type: 'decimal', precision: 15, scale: 3, default: 0 })
|
|
tax_amount!: number;
|
|
|
|
@Column({ type: 'decimal', precision: 15, scale: 3, default: 0 })
|
|
grand_total!: number;
|
|
|
|
@Column({ type: 'char', length: 3, default: 'JOD' })
|
|
currency_code!: string;
|
|
|
|
// ── Processing Status ────────────────────────────────────
|
|
@Column({ type: 'enum', enum: InvoiceStatus, default: InvoiceStatus.UPLOADED })
|
|
status!: InvoiceStatus;
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
original_file_path?: string;
|
|
|
|
@Column({ type: 'varchar', length: 20, default: 'simplified' })
|
|
invoice_category!: string;
|
|
|
|
@Column({ type: 'jsonb', nullable: true })
|
|
validation_errors?: string[];
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
qr_code?: string;
|
|
|
|
@Column({ type: 'decimal', precision: 4, scale: 3, nullable: true })
|
|
ai_confidence_score?: number;
|
|
|
|
@CreateDateColumn({ type: 'timestamp' })
|
|
created_at!: Date;
|
|
|
|
@UpdateDateColumn({ type: 'timestamp' })
|
|
updated_at!: Date;
|
|
|
|
// ── One-to-Many Relationship ─────────────────────────────
|
|
@OneToMany(() => InvoiceLine, (line) => line.invoice, { cascade: true })
|
|
lines!: InvoiceLine[];
|
|
}
|