168 lines
5.1 KiB
TypeScript
168 lines
5.1 KiB
TypeScript
import { pool } from './pool';
|
|
|
|
async function initDB() {
|
|
const client = await pool.connect();
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
console.log('Creating tables...');
|
|
|
|
// 1. Catalogue Module
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS drugs (
|
|
id VARCHAR(50) PRIMARY KEY,
|
|
generic_name VARCHAR(255) NOT NULL,
|
|
atc_code VARCHAR(50),
|
|
schedule VARCHAR(20),
|
|
is_nti BOOLEAN DEFAULT false,
|
|
pregnancy_category VARCHAR(10)
|
|
);
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS products (
|
|
id VARCHAR(50) PRIMARY KEY,
|
|
drug_id VARCHAR(50) REFERENCES drugs(id),
|
|
brand_name VARCHAR(255) NOT NULL,
|
|
manufacturer VARCHAR(255),
|
|
strength VARCHAR(50),
|
|
form VARCHAR(50),
|
|
mrp DECIMAL(10, 2),
|
|
dpco_ceiling DECIMAL(10, 2)
|
|
);
|
|
`);
|
|
|
|
// 2. Inventory Module
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS batches (
|
|
batch_no VARCHAR(100) PRIMARY KEY,
|
|
product_id VARCHAR(50) REFERENCES products(id),
|
|
expiry DATE NOT NULL,
|
|
qty_on_hand INTEGER NOT NULL CHECK (qty_on_hand >= 0),
|
|
purchase_price DECIMAL(10, 2),
|
|
status VARCHAR(50) DEFAULT 'available'
|
|
);
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS stock_movements (
|
|
id SERIAL PRIMARY KEY,
|
|
batch_no VARCHAR(100) REFERENCES batches(batch_no),
|
|
movement_type VARCHAR(50) NOT NULL, -- 'receipt', 'dispense', 'adjustment'
|
|
qty_delta INTEGER NOT NULL,
|
|
reference_id VARCHAR(100),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
// 3. Dispensing & Audit
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS dispensing_records (
|
|
id VARCHAR(50) PRIMARY KEY,
|
|
subject_ref VARCHAR(100) NOT NULL,
|
|
tenant_id VARCHAR(50) NOT NULL,
|
|
dispensed_by VARCHAR(100) NOT NULL,
|
|
prescription_id VARCHAR(50),
|
|
total_amount DECIMAL(10, 2) DEFAULT 0,
|
|
payment_method VARCHAR(50) DEFAULT 'cash',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS overrides_log (
|
|
id SERIAL PRIMARY KEY,
|
|
dispensing_id VARCHAR(50) REFERENCES dispensing_records(id),
|
|
code VARCHAR(50) NOT NULL,
|
|
reason TEXT NOT NULL,
|
|
actor_user_id VARCHAR(100) NOT NULL,
|
|
occurred_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS h1_registers (
|
|
id VARCHAR(50) PRIMARY KEY,
|
|
dispensing_id VARCHAR(50) REFERENCES dispensing_records(id),
|
|
patient_name VARCHAR(255) NOT NULL,
|
|
prescriber_name VARCHAR(255),
|
|
drug_name VARCHAR(255) NOT NULL,
|
|
batch_no VARCHAR(100),
|
|
qty INTEGER NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS order_drafts (
|
|
id VARCHAR(50) PRIMARY KEY,
|
|
subject_ref VARCHAR(100),
|
|
prescription_ref VARCHAR(50),
|
|
items JSONB,
|
|
status VARCHAR(20) DEFAULT 'draft',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS audit_logs (
|
|
id SERIAL PRIMARY KEY,
|
|
call_id VARCHAR(100),
|
|
actor_user_id VARCHAR(100),
|
|
task_type VARCHAR(50),
|
|
details JSONB,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
// 4. Phase 2: Prescriptions
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS prescriptions (
|
|
id VARCHAR(50) PRIMARY KEY,
|
|
image_path TEXT NOT NULL,
|
|
image_hash VARCHAR(64) NOT NULL,
|
|
status VARCHAR(20) DEFAULT 'processing',
|
|
extracted_data JSONB,
|
|
confirmed_data JSONB,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
console.log('Seeding initial data...');
|
|
// Seed Dummy Data for UI
|
|
await client.query(`
|
|
INSERT INTO drugs (id, generic_name, schedule) VALUES
|
|
('drg_001', 'Losartan Potassium', 'H'),
|
|
('drg_002', 'Sertraline', 'H')
|
|
ON CONFLICT (id) DO NOTHING;
|
|
`);
|
|
|
|
await client.query(`
|
|
INSERT INTO products (id, drug_id, brand_name, form, mrp) VALUES
|
|
('prd_4410', 'drg_001', 'Losar 50', 'tablet', 78.50),
|
|
('prd_5510', 'drg_002', 'Sertra 50', 'tablet', 110.00)
|
|
ON CONFLICT (id) DO NOTHING;
|
|
`);
|
|
|
|
// Add batches. Let's add a near-expiry batch so the UI alert triggers
|
|
await client.query(`
|
|
INSERT INTO batches (batch_no, product_id, expiry, qty_on_hand, purchase_price) VALUES
|
|
('B4421', 'prd_4410', CURRENT_DATE + INTERVAL '15 days', 240, 50.00),
|
|
('B4630', 'prd_5510', CURRENT_DATE + INTERVAL '200 days', 500, 80.00)
|
|
ON CONFLICT (batch_no) DO NOTHING;
|
|
`);
|
|
|
|
await client.query('COMMIT');
|
|
console.log('Database initialization and seeding completed successfully!');
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
console.error('Error initializing database:', error);
|
|
} finally {
|
|
client.release();
|
|
pool.end();
|
|
}
|
|
}
|
|
|
|
initDB();
|