82 lines
3.4 KiB
SQL
82 lines
3.4 KiB
SQL
-- AvtoAmbor schema. Money is stored as INTEGER dirams (1 TJS = 100 dirams).
|
|
-- Translated fields use _en / _tg suffixes.
|
|
|
|
CREATE TABLE IF NOT EXISTS categories (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name_en TEXT NOT NULL,
|
|
name_tg TEXT NOT NULL,
|
|
sort_order INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS suppliers (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
phone TEXT,
|
|
address TEXT,
|
|
notes TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS parts (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
sku TEXT NOT NULL UNIQUE,
|
|
name_en TEXT NOT NULL,
|
|
name_tg TEXT NOT NULL,
|
|
description_en TEXT,
|
|
description_tg TEXT,
|
|
category_id INTEGER REFERENCES categories(id) ON DELETE SET NULL,
|
|
unit TEXT NOT NULL DEFAULT 'pcs',
|
|
cost_price INTEGER NOT NULL DEFAULT 0, -- dirams
|
|
sale_price INTEGER NOT NULL DEFAULT 0, -- dirams
|
|
quantity_on_hand INTEGER NOT NULL DEFAULT 0,
|
|
reorder_level INTEGER NOT NULL DEFAULT 0,
|
|
location TEXT,
|
|
barcode TEXT,
|
|
active INTEGER NOT NULL DEFAULT 1,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS stock_movements (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
part_id INTEGER NOT NULL REFERENCES parts(id) ON DELETE CASCADE,
|
|
movement_type TEXT NOT NULL CHECK(movement_type IN ('in','out','adjust')),
|
|
quantity INTEGER NOT NULL, -- positive for in/adjust-up, negative for out/adjust-down
|
|
unit_price INTEGER, -- dirams; nullable for adjustments
|
|
supplier_id INTEGER REFERENCES suppliers(id) ON DELETE SET NULL,
|
|
reference TEXT,
|
|
notes TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_parts_sku ON parts(sku);
|
|
CREATE INDEX IF NOT EXISTS idx_parts_barcode ON parts(barcode);
|
|
CREATE INDEX IF NOT EXISTS idx_parts_category ON parts(category_id);
|
|
CREATE INDEX IF NOT EXISTS idx_movements_part ON stock_movements(part_id);
|
|
CREATE INDEX IF NOT EXISTS idx_movements_created ON stock_movements(created_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS invoices (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
status TEXT NOT NULL CHECK(status IN ('pending','saved')) DEFAULT 'pending',
|
|
total_dirams INTEGER NOT NULL DEFAULT 0,
|
|
notes TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
saved_at TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS invoice_lines (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
|
|
part_id INTEGER REFERENCES parts(id) ON DELETE SET NULL,
|
|
label TEXT,
|
|
quantity INTEGER NOT NULL CHECK(quantity > 0),
|
|
unit_price_dirams INTEGER NOT NULL DEFAULT 0,
|
|
affects_inventory INTEGER NOT NULL DEFAULT 1,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_invoice_lines_invoice ON invoice_lines(invoice_id);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_invoices_one_pending
|
|
ON invoices(status) WHERE status = 'pending';
|