Spaces:
Running
Running
| -- ============================================================================ | |
| -- Database Schema for SCM Microservice | |
| -- Includes: Trans Schema, SCM Tables, and Sales Order Tables | |
| -- ============================================================================ | |
| -- Enable UUID extension | |
| CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; | |
| -- Create Role if not exists | |
| DO $$ | |
| BEGIN | |
| IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'trans_owner') THEN | |
| CREATE ROLE trans_owner WITH LOGIN PASSWORD 'trans_password'; -- Set a default password or leave it nologin | |
| END IF; | |
| END | |
| $$; | |
| -- Create Schema | |
| CREATE SCHEMA IF NOT EXISTS trans; | |
| ALTER SCHEMA trans OWNER TO trans_owner; | |
| -- ============================================================================ | |
| -- Core Reference Tables | |
| -- ============================================================================ | |
| -- Catalogue Reference | |
| CREATE TABLE IF NOT EXISTS trans.catalogue_ref ( | |
| catalogue_id TEXT PRIMARY KEY, | |
| catalogue_code TEXT, | |
| catalogue_type TEXT NOT NULL, | |
| catalogue_name TEXT NOT NULL, | |
| sku TEXT, | |
| barcode_number TEXT, | |
| hsn_code TEXT, | |
| gst_rate NUMERIC(5,2), | |
| mrp NUMERIC(12,2), | |
| base_price NUMERIC(12,2), | |
| track_inventory BOOLEAN DEFAULT FALSE, | |
| batch_managed BOOLEAN DEFAULT FALSE, | |
| status TEXT NOT NULL, | |
| created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| merchant_id TEXT[], | |
| pricing_levels JSON | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_catalogue_ref_catalogue_code ON trans.catalogue_ref (catalogue_code); | |
| CREATE INDEX IF NOT EXISTS idx_catalogue_ref_catalogue_type ON trans.catalogue_ref (catalogue_type); | |
| CREATE INDEX IF NOT EXISTS idx_catalogue_ref_sku ON trans.catalogue_ref (sku); | |
| CREATE INDEX IF NOT EXISTS idx_catalogue_ref_status ON trans.catalogue_ref (status); | |
| CREATE INDEX IF NOT EXISTS idx_catalogue_ref_pricing_levels_currency ON trans.catalogue_ref USING GIN ((pricing_levels->>'currency')); | |
| -- UOM Groups | |
| CREATE TABLE IF NOT EXISTS trans.scm_uom_group_ref ( | |
| uom_group_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| uom_group_code VARCHAR(50) UNIQUE, | |
| name VARCHAR(100) NOT NULL, | |
| base_unit VARCHAR(50) NOT NULL, | |
| status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive')), | |
| units JSON NOT NULL DEFAULT '[]', | |
| created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_uom_group_code ON trans.scm_uom_group_ref (uom_group_code); | |
| CREATE INDEX IF NOT EXISTS idx_uom_group_name ON trans.scm_uom_group_ref (name); | |
| -- Stored Objects (Documents) | |
| CREATE TABLE IF NOT EXISTS trans.stored_objects ( | |
| id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| tenant_id TEXT NOT NULL, | |
| domain TEXT NOT NULL, | |
| entity_id TEXT NOT NULL, | |
| bucket_name TEXT NOT NULL, | |
| object_key TEXT NOT NULL, | |
| category TEXT NOT NULL, | |
| file_name TEXT NOT NULL, | |
| mime_type TEXT NOT NULL, | |
| file_size BIGINT, | |
| checksum_sha256 TEXT, | |
| visibility VARCHAR(16) NOT NULL DEFAULT 'private', | |
| created_by TEXT NOT NULL, | |
| created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| deleted_at TIMESTAMP, | |
| legal_hold BOOLEAN NOT NULL DEFAULT FALSE, | |
| CONSTRAINT uq_stored_object_active_key UNIQUE (tenant_id, domain, entity_id, object_key, deleted_at) | |
| ); | |
| CREATE INDEX IF NOT EXISTS ix_stored_objects_active ON trans.stored_objects (tenant_id, domain, entity_id) WHERE deleted_at IS NULL; | |
| CREATE INDEX IF NOT EXISTS ix_stored_objects_checksum ON trans.stored_objects (tenant_id, checksum_sha256) WHERE deleted_at IS NULL; | |
| -- ============================================================================ | |
| -- SCM Purchase Orders | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_po ( | |
| po_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| po_no VARCHAR(50) UNIQUE NOT NULL, | |
| buyer_id UUID NOT NULL, | |
| buyer_type VARCHAR(20) NOT NULL, | |
| supplier_id UUID NOT NULL, | |
| supplier_type VARCHAR(20) NOT NULL, | |
| po_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| exp_delivery_dt DATE, | |
| currency VARCHAR(3) NOT NULL DEFAULT 'INR', | |
| total_amt NUMERIC(14, 2) NOT NULL, | |
| tax_amt NUMERIC(14, 2) DEFAULT 0, | |
| net_amt NUMERIC(14, 2) NOT NULL, | |
| status VARCHAR(20) NOT NULL, | |
| remarks TEXT, | |
| created_by VARCHAR(64) NOT NULL, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_po_item ( | |
| po_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| po_id UUID NOT NULL REFERENCES trans.scm_po(po_id) ON DELETE CASCADE, | |
| catalogue_id UUID NOT NULL, | |
| sku VARCHAR(64) NOT NULL, | |
| batch_managed BOOLEAN, | |
| ord_qty NUMERIC(12, 3) NOT NULL, | |
| ord_uom_qty NUMERIC(12, 3) NOT NULL, | |
| rcvd_qty NUMERIC(12, 3) DEFAULT 0, | |
| invoiced_qty NUMERIC(12, 3) DEFAULT 0, | |
| returned_qty NUMERIC(12, 3) DEFAULT 0, | |
| dispatched_qty NUMERIC(12, 3) DEFAULT 0, | |
| rejected_qty NUMERIC(12, 3) DEFAULT 0, | |
| uom VARCHAR(10) NOT NULL, | |
| ord_uom VARCHAR(10) NOT NULL, | |
| unit_price NUMERIC(12, 2) NOT NULL, | |
| line_amt NUMERIC(14, 2) NOT NULL, | |
| tax_rate NUMERIC(5, 2) DEFAULT 0, | |
| tax_amt NUMERIC(12, 2) DEFAULT 0, | |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_po_status_log ( | |
| log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| po_id UUID NOT NULL REFERENCES trans.scm_po(po_id), | |
| status VARCHAR(20) NOT NULL, | |
| changed_by VARCHAR(64), | |
| changed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, | |
| remarks TEXT | |
| ); | |
| -- ============================================================================ | |
| -- SCM PO Returns | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_po_return ( | |
| po_return_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| po_return_no VARCHAR(40) UNIQUE NOT NULL, | |
| po_id UUID NOT NULL, | |
| supplier_id VARCHAR(64) NOT NULL, | |
| client_id VARCHAR(64) NOT NULL, | |
| warehouse_id VARCHAR(64), | |
| return_date TIMESTAMP NOT NULL, | |
| status VARCHAR(20) NOT NULL, | |
| reason_code VARCHAR(50), | |
| remarks TEXT, | |
| created_by VARCHAR(64), | |
| created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_po_return_po_id ON trans.scm_po_return(po_id); | |
| CREATE INDEX IF NOT EXISTS idx_po_return_supplier_id ON trans.scm_po_return(supplier_id); | |
| CREATE INDEX IF NOT EXISTS idx_po_return_client_id ON trans.scm_po_return(client_id); | |
| CREATE TABLE IF NOT EXISTS trans.scm_po_return_item ( | |
| po_return_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| po_return_id UUID NOT NULL REFERENCES trans.scm_po_return(po_return_id) ON DELETE CASCADE, | |
| po_item_id UUID NOT NULL, | |
| catalogue_id UUID NOT NULL, | |
| batch_no VARCHAR(50) NOT NULL, | |
| expiry_date TIMESTAMP, | |
| return_qty NUMERIC(12, 3) NOT NULL, | |
| uom VARCHAR(20) NOT NULL DEFAULT 'PCS', | |
| cost_price NUMERIC(12, 2) NOT NULL, | |
| return_value NUMERIC(14, 2) GENERATED ALWAYS AS (return_qty * cost_price) STORED, | |
| created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_po_return_item_po_item_id ON trans.scm_po_return_item(po_item_id); | |
| -- ============================================================================ | |
| -- SCM Goods Receipt Notes (GRN) | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_grn ( | |
| grn_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| grn_no VARCHAR(50) UNIQUE NOT NULL, | |
| po_id UUID REFERENCES trans.scm_po(po_id), | |
| shipment_id UUID, | |
| receiver_id VARCHAR(64), | |
| supplier_id UUID NOT NULL, | |
| received_by VARCHAR(64), | |
| transporter VARCHAR(64), | |
| recv_dt TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| wh_location VARCHAR(64), | |
| status VARCHAR(20) NOT NULL, | |
| total_qty NUMERIC(14, 3), | |
| remarks TEXT, | |
| created_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_grn_item ( | |
| grn_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| grn_id UUID NOT NULL REFERENCES trans.scm_grn(grn_id) ON DELETE CASCADE, | |
| po_item_id UUID REFERENCES trans.scm_po_item(po_item_id), | |
| catalogue_id UUID, | |
| sku VARCHAR(64) NOT NULL, | |
| recv_qty NUMERIC(12, 3) NOT NULL, | |
| acc_qty NUMERIC(12, 3) NOT NULL, | |
| rej_qty NUMERIC(12, 3) DEFAULT 0, | |
| uom VARCHAR(10) NOT NULL, | |
| batch_no VARCHAR(50), | |
| mfg_dt DATE, | |
| exp_dt DATE, | |
| qc_status VARCHAR(20) DEFAULT 'accepted', | |
| remarks TEXT, | |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_grn_issue ( | |
| issue_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| grn_item_id UUID NOT NULL REFERENCES trans.scm_grn_item(grn_item_id), | |
| issue_type VARCHAR(50) NOT NULL, | |
| description TEXT, | |
| status VARCHAR(20) NOT NULL, | |
| created_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| -- ============================================================================ | |
| -- SCM Inventory / Stock | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock_ledger ( | |
| ledger_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| merchant_id VARCHAR(64) NOT NULL, | |
| warehouse_id VARCHAR(64) NOT NULL, | |
| catalogue_id VARCHAR(64), | |
| sku VARCHAR(64) NOT NULL, | |
| batch_no VARCHAR(50), | |
| txn_type VARCHAR(20) NOT NULL, | |
| qty NUMERIC(12, 3) NOT NULL, | |
| uom VARCHAR(20), | |
| ref_type VARCHAR(20) NOT NULL, | |
| ref_id UUID NOT NULL, | |
| ref_no VARCHAR(50), | |
| remarks TEXT, | |
| created_by VARCHAR(64) NOT NULL, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock ( | |
| stock_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| merchant_id VARCHAR(64) NOT NULL, | |
| warehouse_id VARCHAR(64) NOT NULL, | |
| sku VARCHAR(64) NOT NULL, | |
| batch_no VARCHAR(50), | |
| catalogue_id VARCHAR(64), | |
| uom VARCHAR(20) DEFAULT 'PCS', | |
| qty_on_hand NUMERIC(12, 3) DEFAULT 0 CHECK (qty_on_hand >= 0), | |
| qty_reserved NUMERIC(12, 3) DEFAULT 0 CHECK (qty_reserved >= 0), | |
| qty_available NUMERIC(12, 3) DEFAULT 0 CHECK (qty_available >= 0), | |
| cost_price NUMERIC(12, 2), | |
| expiry_date DATE, | |
| ledger_id UUID, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| CONSTRAINT uq_scm_stock_sku_batch UNIQUE (merchant_id, warehouse_id, catalogue_id, batch_no) | |
| ); | |
| -- Stock Adjustment (Master/Detail) | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock_adjustment_master ( | |
| adjustment_master_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| adjustment_number VARCHAR(50) NOT NULL, | |
| merchant_id VARCHAR(64) NOT NULL, | |
| warehouse_id VARCHAR(64) NOT NULL, | |
| adjustment_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| description TEXT, | |
| additional_notes TEXT, | |
| status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'pending', 'approved', 'rejected', 'applied', 'cancelled')), | |
| total_items INTEGER DEFAULT 0, | |
| total_adjustment_value NUMERIC(15, 2) DEFAULT 0, | |
| requires_approval BOOLEAN DEFAULT TRUE, | |
| approval_threshold NUMERIC(15, 2), | |
| created_by VARCHAR(64) NOT NULL, | |
| approved_by VARCHAR(64), | |
| rejected_by VARCHAR(64), | |
| applied_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| approved_at TIMESTAMP WITH TIME ZONE, | |
| rejected_at TIMESTAMP WITH TIME ZONE, | |
| applied_at TIMESTAMP WITH TIME ZONE, | |
| rejection_reason TEXT | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock_adjustment_details ( | |
| adjustment_detail_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| adjustment_master_id UUID NOT NULL REFERENCES trans.scm_stock_adjustment_master(adjustment_master_id), | |
| sku VARCHAR(64) NOT NULL, | |
| batch_no VARCHAR(50), | |
| adj_type VARCHAR(20) NOT NULL CHECK (adj_type IN ('damage', 'expired', 'shrinkage', 'cycle_count')), | |
| qty NUMERIC(12, 3) NOT NULL CHECK (qty > 0), | |
| system_qty NUMERIC(12, 3) NOT NULL DEFAULT 0 CHECK (system_qty >= 0), | |
| direction VARCHAR(10) NOT NULL DEFAULT 'OUT' CHECK (direction IN ('IN', 'OUT')), | |
| reason TEXT NOT NULL, | |
| unit_cost NUMERIC(12, 4), | |
| adjustment_value NUMERIC(15, 2), | |
| line_status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (line_status IN ('pending', 'approved', 'rejected', 'applied')), | |
| ledger_id UUID, | |
| remarks TEXT, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| -- Stock Take (Master/Detail) | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock_take_master ( | |
| stock_take_master_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| stock_take_number VARCHAR(50) NOT NULL, | |
| merchant_id VARCHAR(64) NOT NULL, | |
| warehouse_id VARCHAR(64) NOT NULL, | |
| stock_take_date TIMESTAMP WITH TIME ZONE NOT NULL, | |
| description TEXT, | |
| additional_notes TEXT, | |
| status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'in_progress', 'completed', 'submitted', 'approved', 'rejected', 'cancelled')), | |
| total_items INTEGER DEFAULT 0, | |
| total_variance_value NUMERIC(15, 2) DEFAULT 0, | |
| created_by VARCHAR(64) NOT NULL, | |
| approved_by VARCHAR(64), | |
| rejected_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| approved_at TIMESTAMP WITH TIME ZONE, | |
| rejected_at TIMESTAMP WITH TIME ZONE, | |
| rejection_reason TEXT | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock_take_details ( | |
| stock_take_detail_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| stock_take_master_id UUID NOT NULL REFERENCES trans.scm_stock_take_master(stock_take_master_id), | |
| sku VARCHAR(64) NOT NULL, | |
| batch_no VARCHAR(50), | |
| system_qty NUMERIC(12, 3) NOT NULL CHECK (system_qty >= 0), | |
| physical_qty NUMERIC(12, 3) NOT NULL CHECK (physical_qty >= 0), | |
| variance_qty NUMERIC(12, 3) NOT NULL, | |
| unit_cost NUMERIC(12, 4), | |
| variance_value NUMERIC(15, 2), | |
| line_status VARCHAR(20) NOT NULL DEFAULT 'counted' CHECK (line_status IN ('counted', 'verified', 'adjusted')), | |
| adjustment_id UUID, | |
| remarks TEXT, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.scm_stock_take_status_log ( | |
| log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| stock_take_master_id UUID NOT NULL REFERENCES trans.scm_stock_take_master(stock_take_master_id) ON DELETE CASCADE, | |
| status VARCHAR(50) NOT NULL, | |
| changed_by VARCHAR(255), | |
| changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| remarks TEXT | |
| ); | |
| -- ============================================================================ | |
| -- Trade Relationships | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_trade_relationship ( | |
| relationship_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| from_merchant_id UUID NOT NULL, | |
| to_merchant_id UUID NOT NULL, | |
| relationship_type VARCHAR(30) NOT NULL DEFAULT 'procurement', | |
| status VARCHAR(20) NOT NULL DEFAULT 'draft', | |
| valid_from DATE NOT NULL DEFAULT CURRENT_DATE, | |
| valid_to DATE, | |
| credit_allowed BOOLEAN DEFAULT FALSE, | |
| credit_limit NUMERIC(14, 2), | |
| payment_terms VARCHAR(50), | |
| price_list_id VARCHAR(50), | |
| allowed_regions TEXT[], | |
| allowed_categories TEXT[], | |
| created_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, | |
| CONSTRAINT chk_different_merchants CHECK (from_merchant_id != to_merchant_id), | |
| CONSTRAINT chk_validity_range CHECK (valid_to IS NULL OR valid_to >= valid_from), | |
| CONSTRAINT chk_credit_configuration CHECK (credit_allowed = false OR (credit_allowed = true AND credit_limit IS NOT NULL AND credit_limit > 0)) | |
| ); | |
| CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_relationship ON trans.scm_trade_relationship (from_merchant_id, to_merchant_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_from_merchant ON trans.scm_trade_relationship (from_merchant_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_to_merchant ON trans.scm_trade_relationship (to_merchant_id); | |
| -- ============================================================================ | |
| -- Trade Schemes | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.trade_schemes ( | |
| scheme_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| scheme_code VARCHAR(50) UNIQUE NOT NULL, | |
| scheme_name VARCHAR(200) NOT NULL, | |
| description TEXT, | |
| scheme_type VARCHAR(20) NOT NULL, | |
| status VARCHAR(20) NOT NULL DEFAULT 'DRAFT', | |
| applicable_level VARCHAR(20) NOT NULL, | |
| merchant_id UUID, | |
| valid_from DATE NOT NULL, | |
| valid_to DATE NOT NULL, | |
| settlement_type VARCHAR(20) NOT NULL, | |
| settlement_frequency VARCHAR(20) NOT NULL, | |
| inherit_to_children BOOLEAN DEFAULT TRUE, | |
| allow_child_override BOOLEAN DEFAULT TRUE, | |
| allow_better_only BOOLEAN DEFAULT TRUE, | |
| currency VARCHAR(3) DEFAULT 'INR', | |
| created_by VARCHAR(100), | |
| approved_by VARCHAR(100), | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| approved_at TIMESTAMP, | |
| version INTEGER DEFAULT 1 | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_trade_schemes_type_status ON trans.trade_schemes (scheme_type, status); | |
| CREATE INDEX IF NOT EXISTS idx_trade_schemes_validity ON trans.trade_schemes (valid_from, valid_to); | |
| CREATE TABLE IF NOT EXISTS trans.trade_scheme_conditions ( | |
| condition_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id), | |
| min_quantity NUMERIC(15, 3), | |
| max_quantity NUMERIC(15, 3), | |
| qualifying_sku VARCHAR(50), | |
| min_order_value NUMERIC(15, 2), | |
| max_order_value NUMERIC(15, 2), | |
| sku_list JSON, | |
| category_list JSON, | |
| brand_list JSON, | |
| excluded_skus JSON, | |
| excluded_categories JSON, | |
| channel VARCHAR(20), | |
| aggregate_basis VARCHAR(20), | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.trade_scheme_benefits ( | |
| benefit_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id), | |
| discount_type VARCHAR(20), | |
| discount_percentage NUMERIC(5, 2), | |
| discount_amount NUMERIC(15, 2), | |
| free_sku VARCHAR(50), | |
| free_quantity NUMERIC(15, 3), | |
| rebate_type VARCHAR(20), | |
| rebate_percentage NUMERIC(5, 2), | |
| rebate_amount NUMERIC(15, 2), | |
| apply_on VARCHAR(20) DEFAULT 'TOTAL', | |
| max_benefit_amount NUMERIC(15, 2), | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.trade_scheme_accruals ( | |
| accrual_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id), | |
| merchant_id UUID NOT NULL, | |
| invoice_id VARCHAR(50), | |
| invoice_date DATE, | |
| accrual_amount NUMERIC(15, 2) NOT NULL, | |
| currency VARCHAR(3) DEFAULT 'INR', | |
| settlement_period VARCHAR(20), | |
| status VARCHAR(20) DEFAULT 'PENDING', | |
| credit_note_id VARCHAR(50), | |
| settled_at TIMESTAMP, | |
| settled_amount NUMERIC(15, 2), | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_accruals_scheme_merchant ON trans.trade_scheme_accruals (scheme_id, merchant_id); | |
| CREATE TABLE IF NOT EXISTS trans.trade_scheme_applications ( | |
| application_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id), | |
| merchant_id UUID NOT NULL, | |
| invoice_id UUID NOT NULL, | |
| applied_amount NUMERIC(15, 2) NOT NULL, | |
| benefit_type VARCHAR(20), | |
| status VARCHAR(20) DEFAULT 'APPLIED', | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_applications_invoice ON trans.trade_scheme_applications (invoice_id); | |
| -- ============================================================================ | |
| -- Trade Shipment (Sales) | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_trade_shipment ( | |
| shipment_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| shipment_no VARCHAR(40) UNIQUE NOT NULL, | |
| order_id UUID NOT NULL REFERENCES trans.scm_po(po_id), | |
| supplier_id UUID NOT NULL, | |
| client_id UUID NOT NULL, | |
| warehouse_id UUID NOT NULL, | |
| status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'shipped', 'closed')), | |
| shipment_date DATE NOT NULL, | |
| transporter VARCHAR(100), | |
| lr_no VARCHAR(50), | |
| vehicle_no VARCHAR(20), | |
| created_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), | |
| total_amt NUMERIC(14, 2) NOT NULL DEFAULT 0.00, | |
| tax_amt NUMERIC(14, 2) NOT NULL DEFAULT 0.00, | |
| net_amt NUMERIC(14, 2) NOT NULL DEFAULT 0.00 | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_order_id ON trans.scm_trade_shipment(order_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_supplier_id ON trans.scm_trade_shipment(supplier_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_client_id ON trans.scm_trade_shipment(client_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_date ON trans.scm_trade_shipment(shipment_date); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_status ON trans.scm_trade_shipment(status); | |
| CREATE TABLE IF NOT EXISTS trans.scm_trade_shipment_item ( | |
| item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| shipment_id UUID NOT NULL REFERENCES trans.scm_trade_shipment(shipment_id) ON DELETE CASCADE, | |
| po_item_id UUID NOT NULL REFERENCES trans.scm_po_item(po_item_id), | |
| sku VARCHAR(64) NOT NULL, | |
| batch_no VARCHAR(50), | |
| ordered_qty NUMERIC(12,3) NOT NULL, | |
| shipped_qty NUMERIC(12,3) NOT NULL, | |
| balance_qty NUMERIC(12,3) NOT NULL, | |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), | |
| catalogue_id UUID, | |
| exp_dt DATE, | |
| unit_price NUMERIC(14, 2) NOT NULL, | |
| line_amt NUMERIC(14, 2) NOT NULL, | |
| tax_amt NUMERIC(14, 2), | |
| tax_rate NUMERIC(5, 2), | |
| CONSTRAINT chk_trade_shipment_item_qty CHECK ( | |
| shipped_qty >= 0 AND | |
| ordered_qty >= 0 AND | |
| balance_qty >= 0 AND | |
| shipped_qty <= ordered_qty | |
| ) | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_item_shipment_id ON trans.scm_trade_shipment_item(shipment_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_item_po_item_id ON trans.scm_trade_shipment_item(po_item_id); | |
| CREATE INDEX IF NOT EXISTS idx_trade_shipment_item_sku ON trans.scm_trade_shipment_item(sku); | |
| -- ============================================================================ | |
| -- Trade Invoices | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_invoice ( | |
| invoice_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| invoice_no VARCHAR(50) UNIQUE NOT NULL, | |
| po_id UUID NOT NULL, | |
| supplier_id UUID NOT NULL, | |
| buyer_id UUID NOT NULL, | |
| invoice_date DATE NOT NULL, | |
| payment_terms VARCHAR(30), | |
| due_date DATE, | |
| currency VARCHAR(3) NOT NULL DEFAULT 'INR', | |
| subtotal_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| discount_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| taxable_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| cgst_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| sgst_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| igst_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| total_tax_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| grand_total_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| status VARCHAR(30) NOT NULL DEFAULT 'draft', | |
| reverse_charge BOOLEAN NOT NULL DEFAULT FALSE, | |
| remarks TEXT, | |
| freight_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| packing_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| other_charges_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| round_off_amt NUMERIC(14, 2) NOT NULL DEFAULT 0, | |
| created_by VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_supplier_id ON trans.scm_invoice(supplier_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_buyer_id ON trans.scm_invoice(buyer_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_po_id ON trans.scm_invoice(po_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_status ON trans.scm_invoice(status); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_date ON trans.scm_invoice(invoice_date); | |
| CREATE TABLE IF NOT EXISTS trans.scm_invoice_item ( | |
| invoice_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| invoice_id UUID NOT NULL REFERENCES trans.scm_invoice(invoice_id) ON DELETE CASCADE, | |
| po_item_id UUID NOT NULL, | |
| catalogue_id UUID NOT NULL, | |
| sku VARCHAR(64) NOT NULL, | |
| hsn_code VARCHAR(10), | |
| invoice_qty NUMERIC(12, 3) NOT NULL, | |
| unit_price NUMERIC(12, 2) NOT NULL, | |
| discount_pct NUMERIC(5, 2), | |
| discount_amt NUMERIC(12, 2), | |
| tax_rate NUMERIC(5, 2), | |
| tax_amt NUMERIC(12, 2), | |
| line_total NUMERIC(14, 2) NOT NULL | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_item_invoice_id ON trans.scm_invoice_item(invoice_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_invoice_item_po_item_id ON trans.scm_invoice_item(po_item_id); | |
| CREATE TABLE IF NOT EXISTS trans.scm_invoice_status_log ( | |
| log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| invoice_id UUID NOT NULL REFERENCES trans.scm_invoice(invoice_id) ON DELETE CASCADE, | |
| action VARCHAR(20), | |
| from_status VARCHAR(20), | |
| to_status VARCHAR(20), | |
| remarks TEXT, | |
| performed_by VARCHAR(64), | |
| performed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| -- ============================================================================ | |
| -- Credit/Debit Notes (Invoice Adjustments) | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_invoice_adjustment_note ( | |
| note_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| note_no VARCHAR(50) UNIQUE NOT NULL, | |
| invoice_id UUID NOT NULL, | |
| supplier_id UUID NOT NULL, | |
| buyer_id UUID NOT NULL, | |
| category_code VARCHAR(30) NOT NULL, | |
| reason_code VARCHAR(50) NOT NULL, | |
| note_type VARCHAR(10) NOT NULL, | |
| note_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| original_amount NUMERIC(14, 2), | |
| revised_amount NUMERIC(14, 2), | |
| adjustment_amount NUMERIC(14, 2), | |
| taxable_amount NUMERIC(14, 2), | |
| original_tax_rate NUMERIC(5, 2), | |
| correct_tax_rate NUMERIC(5, 2), | |
| tax_adjustment_amt NUMERIC(14, 2), | |
| description TEXT NOT NULL, | |
| remarks TEXT, | |
| status VARCHAR(20) NOT NULL DEFAULT 'draft', | |
| created_by VARCHAR(64), | |
| created_by_username VARCHAR(64), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_by VARCHAR(64), | |
| updated_by_username VARCHAR(64), | |
| submitted_by VARCHAR(64), | |
| submitted_at TIMESTAMP WITH TIME ZONE, | |
| approved_by VARCHAR(64), | |
| approved_at TIMESTAMP WITH TIME ZONE, | |
| rejected_by VARCHAR(64), | |
| rejected_at TIMESTAMP WITH TIME ZONE, | |
| applied_by VARCHAR(64), | |
| applied_at TIMESTAMP WITH TIME ZONE | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_invoice_id ON trans.scm_invoice_adjustment_note(invoice_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_supplier_id ON trans.scm_invoice_adjustment_note(supplier_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_buyer_id ON trans.scm_invoice_adjustment_note(buyer_id); | |
| CREATE TABLE IF NOT EXISTS trans.scm_invoice_adjustment_status_log ( | |
| log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| note_id UUID NOT NULL REFERENCES trans.scm_invoice_adjustment_note(note_id) ON DELETE CASCADE, | |
| action VARCHAR(20), | |
| from_status VARCHAR(20), | |
| to_status VARCHAR(20), | |
| remarks TEXT, | |
| performed_by VARCHAR(64), | |
| performed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| -- ============================================================================ | |
| -- Spa Partner Orders | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.spa_partner_orders ( | |
| order_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| order_number VARCHAR(50) UNIQUE NOT NULL, | |
| partner_id VARCHAR(50) NOT NULL, | |
| merchant_id VARCHAR(50) NOT NULL, | |
| order_status VARCHAR(30) NOT NULL, | |
| total_amount NUMERIC(12, 2) NOT NULL, | |
| tax_amount NUMERIC(12, 2), | |
| discount_amount NUMERIC(12, 2), | |
| net_amount NUMERIC(12, 2), | |
| payment_status VARCHAR(30), | |
| payment_mode VARCHAR(30), | |
| delivery_address TEXT, | |
| city VARCHAR(100), | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.spa_partner_order_items ( | |
| id SERIAL PRIMARY KEY, | |
| order_id UUID NOT NULL REFERENCES trans.spa_partner_orders(order_id), | |
| product_id VARCHAR(50) NOT NULL, | |
| product_name VARCHAR(200), | |
| quantity INTEGER NOT NULL, | |
| unit_price NUMERIC(10, 2) NOT NULL, | |
| tax_percent NUMERIC(5, 2), | |
| total_price NUMERIC(12, 2) | |
| ); | |
| -- ============================================================================ | |
| -- Trade Returns | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.scm_return ( | |
| return_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| return_no VARCHAR(50) UNIQUE NOT NULL, | |
| return_type VARCHAR(20) NOT NULL CHECK (return_type IN ('PURCHASE', 'SALES')), | |
| status VARCHAR(20) NOT NULL DEFAULT 'DRAFT' CHECK (status IN ('DRAFT', 'SUBMITTED', 'APPROVED', 'COMPLETED', 'REJECTED')), | |
| invoice_id UUID NOT NULL, | |
| invoice_no VARCHAR(50) NOT NULL, | |
| buyer_id VARCHAR(64) NOT NULL, | |
| buyer_name VARCHAR(200) NOT NULL, | |
| supplier_id VARCHAR(64) NOT NULL, | |
| supplier_name VARCHAR(200) NOT NULL, | |
| reason_code VARCHAR(50) NOT NULL CHECK (reason_code IN ('DAMAGED_GOODS', 'EXPIRED_STOCK', 'QUALITY_ISSUE', 'WRONG_ITEM', 'EXCESS_STOCK', 'DEFECTIVE', 'RECALL', 'OTHER')), | |
| remarks TEXT, | |
| dispatch_date TIMESTAMP WITH TIME ZONE, | |
| dispatch_reference VARCHAR(100), | |
| received_date TIMESTAMP WITH TIME ZONE, | |
| received_by VARCHAR(100), | |
| qc_completed_date TIMESTAMP WITH TIME ZONE, | |
| qc_performed_by VARCHAR(100), | |
| created_by VARCHAR(64) NOT NULL, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_by VARCHAR(64), | |
| updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_invoice_id ON trans.scm_return(invoice_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_buyer_id ON trans.scm_return(buyer_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_supplier_id ON trans.scm_return(supplier_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_status ON trans.scm_return(status); | |
| CREATE TABLE IF NOT EXISTS trans.scm_return_item ( | |
| return_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| return_id UUID NOT NULL REFERENCES trans.scm_return(return_id) ON DELETE CASCADE, | |
| invoice_item_id UUID NOT NULL, | |
| catalogue_id UUID NOT NULL, | |
| sku VARCHAR(64) NOT NULL, | |
| description VARCHAR(500) NOT NULL, | |
| batch_no VARCHAR(50) NOT NULL, | |
| expiry_date TIMESTAMP WITH TIME ZONE, | |
| return_qty NUMERIC(12, 3) NOT NULL, | |
| qc_status VARCHAR(20) NOT NULL DEFAULT 'PENDING' CHECK (qc_status IN ('PENDING', 'ACCEPTED', 'REJECTED')), | |
| qc_qty NUMERIC(12, 3), | |
| qc_rejected_qty NUMERIC(12, 3), | |
| qc_remarks TEXT, | |
| qc_performed_by VARCHAR(100), | |
| qc_performed_at TIMESTAMP WITH TIME ZONE, | |
| unit_price NUMERIC(10, 2), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_item_return_id ON trans.scm_return_item(return_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_item_invoice_item_id ON trans.scm_return_item(invoice_item_id); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_item_sku ON trans.scm_return_item(sku); | |
| CREATE TABLE IF NOT EXISTS trans.scm_return_status_log ( | |
| log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), | |
| return_id UUID NOT NULL REFERENCES trans.scm_return(return_id) ON DELETE CASCADE, | |
| action VARCHAR(20) NOT NULL, | |
| from_status VARCHAR(20), | |
| to_status VARCHAR(20) NOT NULL, | |
| performed_by VARCHAR(64) NOT NULL, | |
| performed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| remarks TEXT, | |
| reference_no VARCHAR(100) | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_scm_return_status_log_return_id ON trans.scm_return_status_log(return_id); | |
| -- ============================================================================ | |
| -- Legacy Sales Orders (B2C) | |
| -- ============================================================================ | |
| CREATE TABLE IF NOT EXISTS trans.branches ( | |
| branch_id VARCHAR(26) PRIMARY KEY | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.merchants ( | |
| merchant_id VARCHAR(26) PRIMARY KEY | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.customers ( | |
| customer_id VARCHAR(26) PRIMARY KEY | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.users ( | |
| user_id VARCHAR(26) PRIMARY KEY | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.catalogues ( | |
| catalogue_id VARCHAR(26) PRIMARY KEY | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.sales_orders ( | |
| sales_order_id VARCHAR(26) PRIMARY KEY, | |
| order_number VARCHAR(50) UNIQUE NOT NULL, | |
| branch_id VARCHAR(26) NOT NULL, | |
| merchant_id VARCHAR(26) NOT NULL, | |
| order_date TIMESTAMP WITH TIME ZONE NOT NULL, | |
| status VARCHAR(20) NOT NULL CHECK (status IN ('draft', 'confirmed', 'processing', 'fulfilled', 'partially_fulfilled', 'cancelled', 'on_hold')), | |
| customer_id VARCHAR(26) NOT NULL, | |
| customer_name VARCHAR(255) NOT NULL, | |
| customer_type VARCHAR(10) NOT NULL CHECK (customer_type IN ('b2b', 'b2c')), | |
| customer_phone VARCHAR(20), | |
| customer_email VARCHAR(255), | |
| customer_gstin VARCHAR(15), | |
| subtotal DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| total_discount DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| total_tax DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| shipping_charges DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| grand_total DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| cgst DECIMAL(12,2) DEFAULT 0, | |
| sgst DECIMAL(12,2) DEFAULT 0, | |
| igst DECIMAL(12,2) DEFAULT 0, | |
| payment_type VARCHAR(20) NOT NULL CHECK (payment_type IN ('prepaid', 'cod', 'credit', 'partial')), | |
| payment_status VARCHAR(20) NOT NULL CHECK (payment_status IN ('unpaid', 'partial', 'paid', 'refunded', 'overdue')), | |
| payment_method VARCHAR(50), | |
| payment_date TIMESTAMP WITH TIME ZONE, | |
| payment_reference VARCHAR(100), | |
| amount_paid DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| amount_due DECIMAL(12,2) NOT NULL DEFAULT 0, | |
| credit_terms VARCHAR(50), | |
| credit_limit DECIMAL(12,2), | |
| fulfillment_status VARCHAR(20) NOT NULL CHECK (fulfillment_status IN ('pending', 'allocated', 'picked', 'packed', 'shipped', 'delivered')), | |
| expected_delivery_date DATE, | |
| actual_delivery_date DATE, | |
| invoice_id VARCHAR(26), | |
| invoice_number VARCHAR(50), | |
| invoice_date TIMESTAMP WITH TIME ZONE, | |
| invoice_pdf_url TEXT, | |
| notes TEXT, | |
| internal_notes TEXT, | |
| created_by VARCHAR(26) NOT NULL, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| approved_by VARCHAR(26), | |
| approved_at TIMESTAMP WITH TIME ZONE, | |
| source VARCHAR(20) DEFAULT 'web', | |
| channel VARCHAR(50), | |
| tags TEXT[], | |
| version INTEGER NOT NULL DEFAULT 1, | |
| CONSTRAINT fk_sales_order_branch FOREIGN KEY (branch_id) REFERENCES trans.branches(branch_id), | |
| CONSTRAINT fk_sales_order_merchant FOREIGN KEY (merchant_id) REFERENCES trans.merchants(merchant_id), | |
| CONSTRAINT fk_sales_order_customer FOREIGN KEY (customer_id) REFERENCES trans.customers(customer_id), | |
| CONSTRAINT fk_sales_order_created_by FOREIGN KEY (created_by) REFERENCES trans.users(user_id) | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.sales_order_items ( | |
| id VARCHAR(26) PRIMARY KEY, | |
| sales_order_id VARCHAR(26) NOT NULL, | |
| sku VARCHAR(50) NOT NULL, | |
| product_id VARCHAR(26) NOT NULL, | |
| product_name VARCHAR(255) NOT NULL, | |
| item_type VARCHAR(20) NOT NULL CHECK (item_type IN ('product', 'service')), | |
| quantity INTEGER NOT NULL CHECK (quantity > 0), | |
| unit_price DECIMAL(10,2) NOT NULL, | |
| tax_percent DECIMAL(5,2) NOT NULL DEFAULT 0, | |
| discount_percent DECIMAL(5,2) NOT NULL DEFAULT 0, | |
| line_total DECIMAL(12,2) NOT NULL, | |
| hsn_code VARCHAR(10), | |
| uom VARCHAR(20) NOT NULL, | |
| batch_no VARCHAR(50), | |
| serials TEXT[], | |
| staff_id VARCHAR(26), | |
| staff_name VARCHAR(255), | |
| remarks TEXT, | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| CONSTRAINT fk_sales_order_item_order FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE, | |
| CONSTRAINT fk_sales_order_item_product FOREIGN KEY (product_id) REFERENCES trans.catalogues(catalogue_id) | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.sales_order_addresses ( | |
| id VARCHAR(26) PRIMARY KEY, | |
| sales_order_id VARCHAR(26) NOT NULL, | |
| address_type VARCHAR(20) NOT NULL CHECK (address_type IN ('billing', 'shipping')), | |
| line1 VARCHAR(255) NOT NULL, | |
| line2 VARCHAR(255), | |
| city VARCHAR(100) NOT NULL, | |
| state VARCHAR(100) NOT NULL, | |
| postal_code VARCHAR(20) NOT NULL, | |
| country VARCHAR(100) NOT NULL DEFAULT 'India', | |
| landmark VARCHAR(255), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| CONSTRAINT fk_sales_order_address FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.sales_order_shipments ( | |
| shipment_id VARCHAR(26) PRIMARY KEY, | |
| sales_order_id VARCHAR(26) NOT NULL, | |
| carrier VARCHAR(100), | |
| tracking_number VARCHAR(100), | |
| awb_number VARCHAR(100), | |
| shipping_method VARCHAR(50), | |
| dispatch_date TIMESTAMP WITH TIME ZONE, | |
| expected_delivery_date DATE, | |
| actual_delivery_date DATE, | |
| status VARCHAR(20) CHECK (status IN ('pending', 'picked', 'in_transit', 'out_for_delivery', 'delivered', 'failed')), | |
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| CONSTRAINT fk_sales_order_shipment FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE | |
| ); | |
| CREATE TABLE IF NOT EXISTS trans.sales_order_documents ( | |
| id VARCHAR(26) PRIMARY KEY, | |
| sales_order_id VARCHAR(26) NOT NULL, | |
| filename VARCHAR(255) NOT NULL, | |
| file_url TEXT NOT NULL, | |
| document_type VARCHAR(50) NOT NULL, | |
| file_size INTEGER, | |
| mime_type VARCHAR(100), | |
| uploaded_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| uploaded_by VARCHAR(26), | |
| CONSTRAINT fk_sales_order_document FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE | |
| ); | |
| -- ============================================================================ | |
| -- Additional Indexes for Performance Optimization | |
| -- ============================================================================ | |
| -- Invoice Adjustment Note Indexes | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_status ON trans.scm_invoice_adjustment_note(status); | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_type ON trans.scm_invoice_adjustment_note(note_type); | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_category ON trans.scm_invoice_adjustment_note(category_code); | |
| CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_date ON trans.scm_invoice_adjustment_note(note_date); | |
| -- Trade Return Composite Indexes | |
| CREATE INDEX IF NOT EXISTS idx_returns_type_status ON trans.scm_return (return_type, status); | |
| CREATE INDEX IF NOT EXISTS idx_returns_buyer_status ON trans.scm_return (buyer_id, status); | |
| CREATE INDEX IF NOT EXISTS idx_returns_supplier_status ON trans.scm_return (supplier_id, status); | |
| CREATE INDEX IF NOT EXISTS idx_returns_invoice_type ON trans.scm_return (invoice_id, return_type); | |
| CREATE INDEX IF NOT EXISTS idx_returns_created_status ON trans.scm_return (created_at, status); | |
| -- Trade Return Item Indexes | |
| CREATE INDEX IF NOT EXISTS idx_return_items_sku_batch ON trans.scm_return_item (sku, batch_no); | |
| CREATE INDEX IF NOT EXISTS idx_return_items_qc_status ON trans.scm_return_item (qc_status); | |
| CREATE INDEX IF NOT EXISTS idx_return_items_catalogue_batch ON trans.scm_return_item (catalogue_id, batch_no); | |
| -- Trade Return Log Indexes | |
| CREATE INDEX IF NOT EXISTS idx_return_logs_action_date ON trans.scm_return_status_log (action, performed_at); | |
| CREATE INDEX IF NOT EXISTS idx_return_logs_status_date ON trans.scm_return_status_log (to_status, performed_at); | |