Spaces:
Running
-- ============================================================================ -- Database Schema for Sales, Returns & Credit Notes -- PostgreSQL 14+ -- ============================================================================
-- Enable UUID extension CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE SCHEMA IF NOT EXISTS trans;
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 );
-- ========================================================================= -- SALES ORDERS MODULE -- ============================================================================
-- Sales Orders Table CREATE TABLE 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 Information
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),
-- Financial Summary
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 Information
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 Information
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 Information
invoice_id VARCHAR(26),
invoice_number VARCHAR(50),
invoice_date TIMESTAMP WITH TIME ZONE,
invoice_pdf_url TEXT,
-- Additional Information
notes TEXT,
internal_notes TEXT,
-- Audit Fields
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,
-- Metadata
source VARCHAR(20) DEFAULT 'web',
channel VARCHAR(50),
tags TEXT[],
version INTEGER NOT NULL DEFAULT 1,
-- Foreign Keys
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)
);
-- Sales Order Items Table CREATE TABLE trans.sales_order_items ( id VARCHAR(26) PRIMARY KEY, sales_order_id VARCHAR(26) NOT NULL,
-- Product Information
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 and Pricing
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,
-- Tax Information
hsn_code VARCHAR(10),
uom VARCHAR(20) NOT NULL,
-- Traceability
batch_no VARCHAR(50),
serials TEXT[],
-- Service Specific
staff_id VARCHAR(26),
staff_name VARCHAR(255),
-- Additional
remarks TEXT,
-- Audit
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- Foreign Keys
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)
);
-- Sales Order Addresses Table CREATE TABLE 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
);
-- Sales Order Shipments Table CREATE TABLE 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
);
-- Sales Order Documents Table CREATE TABLE 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
);