fix(entities): Sync SalesOrder, Product, Partner entities with DDL
GAP-ENT-001: SalesOrder - aligned with sales.sales_orders DDL - Renamed name -> orderNumber - Changed currencyId (UUID) -> currency (string) - Changed paymentTermId -> paymentTermDays (int) - Added: partnerName, partnerEmail, billingAddress, shippingAddress - Added: requestedDate, promisedDate, shippedDate, deliveredDate - Added: warehouseId, discountAmount, shippingAmount - Added: shippingMethod, trackingNumber, carrier, internalNotes - Removed Odoo-style fields not in DDL GAP-ENT-002: Product - aligned with products.products DDL - Renamed salePrice -> price, costPrice -> cost - Renamed satProductCode -> taxCode, conversionFactor -> uomConversion - Added: shortDescription, volume, leadTimeDays, attributes (JSONB) - Removed: inventoryProductId, shortName, satUnitCode, tags, notes - Removed tracking fields (trackLots, trackSerials, trackExpiry) GAP-ENT-003: Partner - aligned with partners.partners DDL - Added: name (separate from displayName) - Added: taxIdType, verifiedAt, settings (JSONB) - Removed fields that belong in partner_tax_info: taxRegime, cfdiUse - Removed: currentBalance, priceListId, discountPercent, salesRepId Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
390bdd3923
commit
0f7feff3f8
@ -6,11 +6,17 @@ import {
|
||||
UpdateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Index,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
/**
|
||||
* Partner Entity
|
||||
*
|
||||
* Synchronized with DDL: database/ddl/16-partners.sql
|
||||
* Table: partners.partners
|
||||
*
|
||||
* Represents customers, suppliers, and other business partners.
|
||||
* Extended fiscal information is stored in partners.partner_tax_info (separate entity).
|
||||
*/
|
||||
@Entity({ name: 'partners', schema: 'partners' })
|
||||
export class Partner {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
@ -20,34 +26,34 @@ export class Partner {
|
||||
@Column({ name: 'tenant_id', type: 'uuid' })
|
||||
tenantId: string;
|
||||
|
||||
// Identificacion
|
||||
// Identification
|
||||
@Index()
|
||||
@Column({ type: 'varchar', length: 20, unique: true })
|
||||
@Column({ type: 'varchar', length: 30 })
|
||||
code: string;
|
||||
|
||||
@Column({ name: 'display_name', type: 'varchar', length: 200 })
|
||||
@Column({ type: 'varchar', length: 200 })
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'display_name', type: 'varchar', length: 200, nullable: true })
|
||||
displayName: string;
|
||||
|
||||
// Partner type
|
||||
@Index()
|
||||
@Column({ name: 'partner_type', type: 'varchar', length: 20, default: 'customer' })
|
||||
partnerType: 'customer' | 'supplier' | 'both' | 'contact';
|
||||
|
||||
// Fiscal data
|
||||
@Index()
|
||||
@Column({ name: 'tax_id', type: 'varchar', length: 50, nullable: true })
|
||||
taxId: string;
|
||||
|
||||
@Column({ name: 'tax_id_type', type: 'varchar', length: 20, nullable: true })
|
||||
taxIdType: string;
|
||||
|
||||
@Column({ name: 'legal_name', type: 'varchar', length: 200, nullable: true })
|
||||
legalName: string;
|
||||
|
||||
// Tipo de partner
|
||||
@Index()
|
||||
@Column({ name: 'partner_type', type: 'varchar', length: 20, default: 'customer' })
|
||||
partnerType: 'customer' | 'supplier' | 'both';
|
||||
|
||||
// Fiscal
|
||||
@Index()
|
||||
@Column({ name: 'tax_id', type: 'varchar', length: 20, nullable: true })
|
||||
taxId: string;
|
||||
|
||||
@Column({ name: 'tax_regime', type: 'varchar', length: 100, nullable: true })
|
||||
taxRegime: string;
|
||||
|
||||
@Column({ name: 'cfdi_use', type: 'varchar', length: 10, nullable: true })
|
||||
cfdiUse: string;
|
||||
|
||||
// Contacto principal
|
||||
// Primary contact
|
||||
@Column({ type: 'varchar', length: 255, nullable: true })
|
||||
email: string;
|
||||
|
||||
@ -57,48 +63,43 @@ export class Partner {
|
||||
@Column({ type: 'varchar', length: 30, nullable: true })
|
||||
mobile: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 500, nullable: true })
|
||||
@Column({ type: 'varchar', length: 255, nullable: true })
|
||||
website: string;
|
||||
|
||||
// Terminos de pago
|
||||
@Column({ name: 'payment_term_days', type: 'int', default: 0 })
|
||||
paymentTermDays: number;
|
||||
|
||||
// Credit and payments
|
||||
@Column({ name: 'credit_limit', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
creditLimit: number;
|
||||
|
||||
@Column({ name: 'current_balance', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
currentBalance: number;
|
||||
@Column({ name: 'payment_term_days', type: 'int', default: 0 })
|
||||
paymentTermDays: number;
|
||||
|
||||
// Lista de precios
|
||||
@Column({ name: 'price_list_id', type: 'uuid', nullable: true })
|
||||
priceListId: string;
|
||||
@Column({ name: 'payment_method', type: 'varchar', length: 50, nullable: true })
|
||||
paymentMethod: string;
|
||||
|
||||
// Descuentos
|
||||
@Column({ name: 'discount_percent', type: 'decimal', precision: 5, scale: 2, default: 0 })
|
||||
discountPercent: number;
|
||||
|
||||
// Categoria
|
||||
// Classification
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
category: string;
|
||||
|
||||
@Column({ type: 'text', array: true, default: '{}' })
|
||||
tags: string[];
|
||||
|
||||
// Notas
|
||||
@Column({ type: 'text', nullable: true })
|
||||
notes: string;
|
||||
|
||||
// Estado
|
||||
// Status
|
||||
@Column({ name: 'is_active', type: 'boolean', default: true })
|
||||
isActive: boolean;
|
||||
|
||||
@Column({ name: 'is_verified', type: 'boolean', default: false })
|
||||
isVerified: boolean;
|
||||
|
||||
// Vendedor asignado
|
||||
@Column({ name: 'sales_rep_id', type: 'uuid', nullable: true })
|
||||
salesRepId: string;
|
||||
@Column({ name: 'verified_at', type: 'timestamptz', nullable: true })
|
||||
verifiedAt: Date | null;
|
||||
|
||||
// Settings (flexible JSONB)
|
||||
@Column({ type: 'jsonb', default: '{}' })
|
||||
settings: Record<string, unknown>;
|
||||
|
||||
// Notes
|
||||
@Column({ type: 'text', nullable: true })
|
||||
notes: string;
|
||||
|
||||
// Metadata
|
||||
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
||||
|
||||
@ -12,22 +12,21 @@ import {
|
||||
import { ProductCategory } from './product-category.entity';
|
||||
|
||||
/**
|
||||
* Commerce Product Entity (schema: products.products)
|
||||
* Commerce Product Entity
|
||||
*
|
||||
* Synchronized with DDL: database/ddl/17-products.sql
|
||||
* Table: products.products
|
||||
*
|
||||
* NOTE: This is NOT a duplicate of inventory/entities/product.entity.ts
|
||||
*
|
||||
* Key differences:
|
||||
* - This entity: products.products - Commerce/retail focused
|
||||
* - Has: SAT codes, tax rates, detailed dimensions, min/max stock, reorder points
|
||||
* - Has: SAT codes, tax rates, pricing, attributes
|
||||
* - Used by: Sales, purchases, invoicing, POS
|
||||
*
|
||||
* - Inventory Product: inventory.products - Warehouse/stock management focused (Odoo-style)
|
||||
* - Has: valuationMethod, tracking (lot/serial), isStorable, StockQuant/Lot relations
|
||||
* - Used by: Inventory module for stock tracking, valuation, picking operations
|
||||
*
|
||||
* These are intentionally separate by domain. This commerce product entity handles
|
||||
* pricing, tax compliance (SAT/CFDI), and business rules. For physical stock tracking,
|
||||
* use the inventory module's product entity.
|
||||
*/
|
||||
@Entity({ name: 'products', schema: 'products' })
|
||||
export class Product {
|
||||
@ -46,19 +45,7 @@ export class Product {
|
||||
@JoinColumn({ name: 'category_id' })
|
||||
category: ProductCategory;
|
||||
|
||||
/**
|
||||
* Optional link to inventory.products for unified stock management.
|
||||
* This allows the commerce product to be linked to its inventory counterpart
|
||||
* for stock tracking, valuation (FIFO/AVERAGE), and warehouse operations.
|
||||
*
|
||||
* The inventory product handles: stock levels, lot/serial tracking, valuation layers
|
||||
* This commerce product handles: pricing, taxes, SAT compliance, commercial data
|
||||
*/
|
||||
@Index()
|
||||
@Column({ name: 'inventory_product_id', type: 'uuid', nullable: true })
|
||||
inventoryProductId: string | null;
|
||||
|
||||
// Identificacion
|
||||
// Identification
|
||||
@Index()
|
||||
@Column({ type: 'varchar', length: 50 })
|
||||
sku: string;
|
||||
@ -70,55 +57,48 @@ export class Product {
|
||||
@Column({ type: 'varchar', length: 200 })
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'short_name', type: 'varchar', length: 50, nullable: true })
|
||||
shortName: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
description: string;
|
||||
|
||||
// Tipo
|
||||
@Column({ name: 'short_description', type: 'varchar', length: 500, nullable: true })
|
||||
shortDescription: string;
|
||||
|
||||
// Type
|
||||
@Index()
|
||||
@Column({ name: 'product_type', type: 'varchar', length: 20, default: 'product' })
|
||||
productType: 'product' | 'service' | 'consumable' | 'kit';
|
||||
|
||||
// Precios
|
||||
@Column({ name: 'sale_price', type: 'decimal', precision: 15, scale: 4, default: 0 })
|
||||
salePrice: number;
|
||||
// Pricing
|
||||
@Column({ type: 'decimal', precision: 15, scale: 4, default: 0 })
|
||||
price: number;
|
||||
|
||||
@Column({ name: 'cost_price', type: 'decimal', precision: 15, scale: 4, default: 0 })
|
||||
costPrice: number;
|
||||
|
||||
@Column({ name: 'min_sale_price', type: 'decimal', precision: 15, scale: 4, nullable: true })
|
||||
minSalePrice: number;
|
||||
@Column({ type: 'decimal', precision: 15, scale: 4, default: 0 })
|
||||
cost: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 3, default: 'MXN' })
|
||||
currency: string;
|
||||
|
||||
// Impuestos
|
||||
@Column({ name: 'tax_included', type: 'boolean', default: true })
|
||||
taxIncluded: boolean;
|
||||
|
||||
// Taxes
|
||||
@Column({ name: 'tax_rate', type: 'decimal', precision: 5, scale: 2, default: 16 })
|
||||
taxRate: number;
|
||||
|
||||
@Column({ name: 'tax_included', type: 'boolean', default: false })
|
||||
taxIncluded: boolean;
|
||||
@Column({ name: 'tax_code', type: 'varchar', length: 20, nullable: true })
|
||||
taxCode: string;
|
||||
|
||||
// SAT (Mexico)
|
||||
@Column({ name: 'sat_product_code', type: 'varchar', length: 20, nullable: true })
|
||||
satProductCode: string;
|
||||
|
||||
@Column({ name: 'sat_unit_code', type: 'varchar', length: 10, nullable: true })
|
||||
satUnitCode: string;
|
||||
|
||||
// Unidad de medida
|
||||
// Unit of measure
|
||||
@Column({ type: 'varchar', length: 20, default: 'PZA' })
|
||||
uom: string;
|
||||
|
||||
@Column({ name: 'uom_purchase', type: 'varchar', length: 20, nullable: true })
|
||||
uomPurchase: string;
|
||||
|
||||
@Column({ name: 'conversion_factor', type: 'decimal', precision: 10, scale: 4, default: 1 })
|
||||
conversionFactor: number;
|
||||
@Column({ name: 'uom_conversion', type: 'decimal', precision: 10, scale: 4, default: 1 })
|
||||
uomConversion: number;
|
||||
|
||||
// Inventario
|
||||
// Inventory
|
||||
@Column({ name: 'track_inventory', type: 'boolean', default: true })
|
||||
trackInventory: boolean;
|
||||
|
||||
@ -131,26 +111,13 @@ export class Product {
|
||||
@Column({ name: 'reorder_point', type: 'decimal', precision: 15, scale: 4, nullable: true })
|
||||
reorderPoint: number;
|
||||
|
||||
@Column({ name: 'reorder_quantity', type: 'decimal', precision: 15, scale: 4, nullable: true })
|
||||
reorderQuantity: number;
|
||||
@Column({ name: 'lead_time_days', type: 'int', default: 0 })
|
||||
leadTimeDays: number;
|
||||
|
||||
// Lotes y series
|
||||
@Column({ name: 'track_lots', type: 'boolean', default: false })
|
||||
trackLots: boolean;
|
||||
|
||||
@Column({ name: 'track_serials', type: 'boolean', default: false })
|
||||
trackSerials: boolean;
|
||||
|
||||
@Column({ name: 'track_expiry', type: 'boolean', default: false })
|
||||
trackExpiry: boolean;
|
||||
|
||||
// Dimensiones
|
||||
// Physical characteristics
|
||||
@Column({ type: 'decimal', precision: 10, scale: 4, nullable: true })
|
||||
weight: number;
|
||||
|
||||
@Column({ name: 'weight_unit', type: 'varchar', length: 10, default: 'kg' })
|
||||
weightUnit: string;
|
||||
|
||||
@Column({ type: 'decimal', precision: 10, scale: 4, nullable: true })
|
||||
length: number;
|
||||
|
||||
@ -160,25 +127,21 @@ export class Product {
|
||||
@Column({ type: 'decimal', precision: 10, scale: 4, nullable: true })
|
||||
height: number;
|
||||
|
||||
@Column({ name: 'dimension_unit', type: 'varchar', length: 10, default: 'cm' })
|
||||
dimensionUnit: string;
|
||||
@Column({ type: 'decimal', precision: 10, scale: 4, nullable: true })
|
||||
volume: number;
|
||||
|
||||
// Imagenes
|
||||
// Images
|
||||
@Column({ name: 'image_url', type: 'varchar', length: 500, nullable: true })
|
||||
imageUrl: string;
|
||||
|
||||
@Column({ type: 'text', array: true, default: '{}' })
|
||||
@Column({ type: 'jsonb', default: '[]' })
|
||||
images: string[];
|
||||
|
||||
// Tags
|
||||
@Column({ type: 'text', array: true, default: '{}' })
|
||||
tags: string[];
|
||||
// Attributes (flexible JSONB for custom attributes like color, size, material)
|
||||
@Column({ type: 'jsonb', default: '{}' })
|
||||
attributes: Record<string, unknown>;
|
||||
|
||||
// Notas
|
||||
@Column({ type: 'text', nullable: true })
|
||||
notes: string;
|
||||
|
||||
// Estado
|
||||
// Status
|
||||
@Column({ name: 'is_active', type: 'boolean', default: true })
|
||||
isActive: boolean;
|
||||
|
||||
|
||||
@ -1,15 +1,22 @@
|
||||
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, Index, ManyToOne, JoinColumn } from 'typeorm';
|
||||
import { PaymentTerm } from '../../core/entities/payment-term.entity.js';
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Index,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
/**
|
||||
* Sales Order Entity
|
||||
*
|
||||
* Aligned with SQL schema used by orders.service.ts
|
||||
* Supports full Order-to-Cash flow with:
|
||||
* - PaymentTerms integration
|
||||
* - Automatic picking creation
|
||||
* - Stock reservation
|
||||
* - Invoice and delivery status tracking
|
||||
* Synchronized with DDL: database/ddl/22-sales.sql
|
||||
* Table: sales.sales_orders
|
||||
*
|
||||
* Represents confirmed sales orders with full order-to-delivery tracking.
|
||||
*/
|
||||
@Entity({ name: 'sales_orders', schema: 'sales' })
|
||||
export class SalesOrder {
|
||||
@ -20,110 +27,104 @@ export class SalesOrder {
|
||||
@Column({ name: 'tenant_id', type: 'uuid' })
|
||||
tenantId: string;
|
||||
|
||||
@Index()
|
||||
@Column({ name: 'company_id', type: 'uuid' })
|
||||
companyId: string;
|
||||
|
||||
// Order identification
|
||||
@Index()
|
||||
@Column({ type: 'varchar', length: 30 })
|
||||
name: string; // Order number (e.g., SO-000001)
|
||||
|
||||
@Column({ name: 'client_order_ref', type: 'varchar', length: 100, nullable: true })
|
||||
clientOrderRef: string | null; // Customer's reference number
|
||||
@Column({ name: 'order_number', type: 'varchar', length: 30 })
|
||||
orderNumber: string;
|
||||
|
||||
// Origin (from quotation)
|
||||
@Column({ name: 'quotation_id', type: 'uuid', nullable: true })
|
||||
quotationId: string | null;
|
||||
|
||||
// Partner/Customer
|
||||
// Customer
|
||||
@Index()
|
||||
@Column({ name: 'partner_id', type: 'uuid' })
|
||||
partnerId: string;
|
||||
|
||||
@Column({ name: 'partner_name', type: 'varchar', length: 200, nullable: true })
|
||||
partnerName: string | null;
|
||||
|
||||
@Column({ name: 'partner_email', type: 'varchar', length: 255, nullable: true })
|
||||
partnerEmail: string | null;
|
||||
|
||||
// Addresses (JSONB)
|
||||
@Column({ name: 'billing_address', type: 'jsonb', nullable: true })
|
||||
billingAddress: Record<string, unknown> | null;
|
||||
|
||||
@Column({ name: 'shipping_address', type: 'jsonb', nullable: true })
|
||||
shippingAddress: Record<string, unknown> | null;
|
||||
|
||||
// Dates
|
||||
@Column({ name: 'order_date', type: 'date', default: () => 'CURRENT_DATE' })
|
||||
orderDate: Date;
|
||||
|
||||
@Column({ name: 'validity_date', type: 'date', nullable: true })
|
||||
validityDate: Date | null;
|
||||
@Column({ name: 'requested_date', type: 'date', nullable: true })
|
||||
requestedDate: Date | null;
|
||||
|
||||
@Column({ name: 'commitment_date', type: 'date', nullable: true })
|
||||
commitmentDate: Date | null; // Promised delivery date
|
||||
@Column({ name: 'promised_date', type: 'date', nullable: true })
|
||||
promisedDate: Date | null;
|
||||
|
||||
// Currency and pricing
|
||||
@Index()
|
||||
@Column({ name: 'currency_id', type: 'uuid' })
|
||||
currencyId: string;
|
||||
@Column({ name: 'shipped_date', type: 'date', nullable: true })
|
||||
shippedDate: Date | null;
|
||||
|
||||
@Column({ name: 'pricelist_id', type: 'uuid', nullable: true })
|
||||
pricelistId: string | null;
|
||||
@Column({ name: 'delivered_date', type: 'date', nullable: true })
|
||||
deliveredDate: Date | null;
|
||||
|
||||
// Payment terms integration (TASK-003-01)
|
||||
@Index()
|
||||
@Column({ name: 'payment_term_id', type: 'uuid', nullable: true })
|
||||
paymentTermId: string | null;
|
||||
// Sales rep
|
||||
@Column({ name: 'sales_rep_id', type: 'uuid', nullable: true })
|
||||
salesRepId: string | null;
|
||||
|
||||
@ManyToOne(() => PaymentTerm)
|
||||
@JoinColumn({ name: 'payment_term_id' })
|
||||
paymentTerm: PaymentTerm;
|
||||
// Warehouse
|
||||
@Column({ name: 'warehouse_id', type: 'uuid', nullable: true })
|
||||
warehouseId: string | null;
|
||||
|
||||
// Sales team
|
||||
@Column({ name: 'user_id', type: 'uuid', nullable: true })
|
||||
userId: string | null; // Sales representative
|
||||
// Totals
|
||||
@Column({ type: 'varchar', length: 3, default: 'MXN' })
|
||||
currency: string;
|
||||
|
||||
@Column({ name: 'sales_team_id', type: 'uuid', nullable: true })
|
||||
salesTeamId: string | null;
|
||||
@Column({ type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
subtotal: number;
|
||||
|
||||
// Amounts
|
||||
@Column({ name: 'amount_untaxed', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
amountUntaxed: number;
|
||||
@Column({ name: 'tax_amount', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
taxAmount: number;
|
||||
|
||||
@Column({ name: 'amount_tax', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
amountTax: number;
|
||||
@Column({ name: 'discount_amount', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
discountAmount: number;
|
||||
|
||||
@Column({ name: 'amount_total', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
amountTotal: number;
|
||||
@Column({ name: 'shipping_amount', type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
shippingAmount: number;
|
||||
|
||||
// Status fields (Order-to-Cash tracking)
|
||||
@Column({ type: 'decimal', precision: 15, scale: 2, default: 0 })
|
||||
total: number;
|
||||
|
||||
// Payment terms
|
||||
@Column({ name: 'payment_term_days', type: 'int', default: 0 })
|
||||
paymentTermDays: number;
|
||||
|
||||
@Column({ name: 'payment_method', type: 'varchar', length: 50, nullable: true })
|
||||
paymentMethod: string | null;
|
||||
|
||||
// Status
|
||||
@Index()
|
||||
@Column({ type: 'varchar', length: 20, default: 'draft' })
|
||||
status: 'draft' | 'sent' | 'sale' | 'done' | 'cancelled';
|
||||
status: 'draft' | 'confirmed' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
|
||||
|
||||
@Index()
|
||||
@Column({ name: 'invoice_status', type: 'varchar', length: 20, default: 'pending' })
|
||||
invoiceStatus: 'pending' | 'partial' | 'invoiced';
|
||||
// Shipping
|
||||
@Column({ name: 'shipping_method', type: 'varchar', length: 50, nullable: true })
|
||||
shippingMethod: string | null;
|
||||
|
||||
@Index()
|
||||
@Column({ name: 'delivery_status', type: 'varchar', length: 20, default: 'pending' })
|
||||
deliveryStatus: 'pending' | 'partial' | 'delivered';
|
||||
@Column({ name: 'tracking_number', type: 'varchar', length: 100, nullable: true })
|
||||
trackingNumber: string | null;
|
||||
|
||||
@Column({ name: 'invoice_policy', type: 'varchar', length: 20, default: 'order' })
|
||||
invoicePolicy: 'order' | 'delivery';
|
||||
|
||||
// Delivery/Picking integration (TASK-003-03)
|
||||
@Column({ name: 'picking_id', type: 'uuid', nullable: true })
|
||||
pickingId: string | null;
|
||||
@Column({ type: 'varchar', length: 100, nullable: true })
|
||||
carrier: string | null;
|
||||
|
||||
// Notes
|
||||
@Column({ type: 'text', nullable: true })
|
||||
notes: string | null;
|
||||
|
||||
@Column({ name: 'terms_conditions', type: 'text', nullable: true })
|
||||
termsConditions: string | null;
|
||||
|
||||
// Confirmation tracking
|
||||
@Column({ name: 'confirmed_at', type: 'timestamptz', nullable: true })
|
||||
confirmedAt: Date | null;
|
||||
|
||||
@Column({ name: 'confirmed_by', type: 'uuid', nullable: true })
|
||||
confirmedBy: string | null;
|
||||
|
||||
// Cancellation tracking
|
||||
@Column({ name: 'cancelled_at', type: 'timestamptz', nullable: true })
|
||||
cancelledAt: Date | null;
|
||||
|
||||
@Column({ name: 'cancelled_by', type: 'uuid', nullable: true })
|
||||
cancelledBy: string | null;
|
||||
@Column({ name: 'internal_notes', type: 'text', nullable: true })
|
||||
internalNotes: string | null;
|
||||
|
||||
// Audit fields
|
||||
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
||||
|
||||
Loading…
Reference in New Issue
Block a user