-- 한약 재고관리 시스템 데이터베이스 스키마
-- SQLite 기준

-- 1) 도매상/공급업체
CREATE TABLE IF NOT EXISTS suppliers (
    supplier_id       INTEGER PRIMARY KEY AUTOINCREMENT,
    name              TEXT NOT NULL UNIQUE,
    business_no       TEXT,
    contact_person    TEXT,
    phone             TEXT,
    address           TEXT,
    is_active         INTEGER DEFAULT 1,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 2) 약재 마스터 (보험코드 9자리 기준)
CREATE TABLE IF NOT EXISTS herb_items (
    herb_item_id      INTEGER PRIMARY KEY AUTOINCREMENT,
    insurance_code    TEXT UNIQUE,           -- 보험코드 (9자리)
    herb_name         TEXT NOT NULL,         -- 약재명
    specification     TEXT,                  -- 규격/품질
    default_unit      TEXT DEFAULT 'g',      -- 기본 단위
    is_active         INTEGER DEFAULT 1,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 3) 환자 정보
CREATE TABLE IF NOT EXISTS patients (
    patient_id        INTEGER PRIMARY KEY AUTOINCREMENT,
    name              TEXT NOT NULL,
    phone             TEXT NOT NULL,
    jumin_no          TEXT,                  -- 주민번호 (암호화 필요)
    gender            TEXT CHECK(gender IN ('M', 'F')),
    birth_date        DATE,
    address           TEXT,
    notes             TEXT,
    is_active         INTEGER DEFAULT 1,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(phone, name)
);

-- 4) 입고장 헤더
CREATE TABLE IF NOT EXISTS purchase_receipts (
    receipt_id        INTEGER PRIMARY KEY AUTOINCREMENT,
    supplier_id       INTEGER NOT NULL,
    receipt_date      DATE NOT NULL,
    receipt_no        TEXT,                  -- 입고 번호/전표번호
    vat_included      INTEGER DEFAULT 1,     -- 부가세 포함 여부
    vat_rate          REAL DEFAULT 0.10,     -- 부가세율
    total_amount      REAL,                  -- 총 입고액
    source_file       TEXT,                  -- Excel 파일명
    notes             TEXT,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id)
);

-- 5) 입고장 상세 라인
CREATE TABLE IF NOT EXISTS purchase_receipt_lines (
    line_id           INTEGER PRIMARY KEY AUTOINCREMENT,
    receipt_id        INTEGER NOT NULL,
    herb_item_id      INTEGER NOT NULL,
    origin_country    TEXT,                  -- 원산지
    quantity_g        REAL NOT NULL,         -- 구입량(g)
    unit_price_per_g  REAL NOT NULL,         -- g당 단가 (VAT 포함)
    line_total        REAL,                  -- 라인 총액
    expiry_date       DATE,                  -- 유효기간
    lot_number        TEXT,                  -- 로트번호
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (receipt_id) REFERENCES purchase_receipts(receipt_id),
    FOREIGN KEY (herb_item_id) REFERENCES herb_items(herb_item_id)
);

-- 6) 재고 로트 (입고 라인별 재고 관리)
CREATE TABLE IF NOT EXISTS inventory_lots (
    lot_id            INTEGER PRIMARY KEY AUTOINCREMENT,
    herb_item_id      INTEGER NOT NULL,
    supplier_id       INTEGER NOT NULL,
    receipt_line_id   INTEGER NOT NULL,
    received_date     DATE NOT NULL,
    origin_country    TEXT,
    unit_price_per_g  REAL NOT NULL,
    quantity_received REAL NOT NULL,         -- 입고 수량
    quantity_onhand   REAL NOT NULL,         -- 현재 재고
    expiry_date       DATE,
    lot_number        TEXT,
    is_depleted       INTEGER DEFAULT 0,     -- 소진 여부
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (herb_item_id) REFERENCES herb_items(herb_item_id),
    FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id),
    FOREIGN KEY (receipt_line_id) REFERENCES purchase_receipt_lines(line_id)
);

-- 7) 재고 원장 (모든 재고 변동 기록)
CREATE TABLE IF NOT EXISTS stock_ledger (
    ledger_id         INTEGER PRIMARY KEY AUTOINCREMENT,
    event_time        DATETIME DEFAULT CURRENT_TIMESTAMP,
    event_type        TEXT NOT NULL CHECK(event_type IN ('RECEIPT', 'CONSUME', 'ADJUST', 'DISCARD', 'RETURN')),
    herb_item_id      INTEGER NOT NULL,
    lot_id            INTEGER,
    quantity_delta    REAL NOT NULL,         -- 증감량 (+입고, -사용)
    unit_cost_per_g   REAL,
    reference_table   TEXT,                  -- 참조 테이블 (compounds, adjustments 등)
    reference_id      INTEGER,               -- 참조 ID
    notes             TEXT,
    created_by        TEXT,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (herb_item_id) REFERENCES herb_items(herb_item_id),
    FOREIGN KEY (lot_id) REFERENCES inventory_lots(lot_id)
);

-- 8) 처방 마스터 (약속 처방)
CREATE TABLE IF NOT EXISTS formulas (
    formula_id        INTEGER PRIMARY KEY AUTOINCREMENT,
    formula_code      TEXT UNIQUE,           -- 처방 코드
    formula_name      TEXT NOT NULL,         -- 처방명 (예: 쌍화탕)
    formula_type      TEXT DEFAULT 'CUSTOM', -- INSURANCE(보험), CUSTOM(약속처방)
    base_cheop        INTEGER DEFAULT 20,    -- 기본 첩수 (1제 기준)
    base_pouches      INTEGER DEFAULT 30,    -- 기본 파우치수 (1제 기준)
    description       TEXT,
    is_active         INTEGER DEFAULT 1,
    created_by        TEXT,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 9) 처방 구성 약재
CREATE TABLE IF NOT EXISTS formula_ingredients (
    ingredient_id     INTEGER PRIMARY KEY AUTOINCREMENT,
    formula_id        INTEGER NOT NULL,
    herb_item_id      INTEGER NOT NULL,
    grams_per_cheop   REAL NOT NULL,         -- 1첩당 그램수
    notes             TEXT,
    sort_order        INTEGER DEFAULT 0,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (formula_id) REFERENCES formulas(formula_id),
    FOREIGN KEY (herb_item_id) REFERENCES herb_items(herb_item_id),
    UNIQUE (formula_id, herb_item_id)
);

-- 10) 조제 작업 (처방 실행)
CREATE TABLE IF NOT EXISTS compounds (
    compound_id       INTEGER PRIMARY KEY AUTOINCREMENT,
    patient_id        INTEGER,
    formula_id        INTEGER,
    compound_date     DATE NOT NULL,
    je_count          REAL NOT NULL,          -- 제수 (1제, 0.5제 등)
    cheop_total       REAL NOT NULL,          -- 총 첩수
    pouch_total       REAL NOT NULL,          -- 총 파우치수
    cost_total        REAL,                   -- 원가 총액
    sell_price_total  REAL,                   -- 판매 총액
    prescription_no   TEXT,                   -- 처방전 번호
    status            TEXT DEFAULT 'PREPARED', -- PREPARED, DISPENSED, CANCELLED
    notes             TEXT,
    created_by        TEXT,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (patient_id) REFERENCES patients(patient_id),
    FOREIGN KEY (formula_id) REFERENCES formulas(formula_id)
);

-- 11) 조제 약재 구성 (실제 조제시 사용된 약재 - 가감 포함)
CREATE TABLE IF NOT EXISTS compound_ingredients (
    compound_ingredient_id INTEGER PRIMARY KEY AUTOINCREMENT,
    compound_id       INTEGER NOT NULL,
    herb_item_id      INTEGER NOT NULL,
    grams_per_cheop   REAL NOT NULL,          -- 1첩당 그램수 (가감 반영)
    total_grams       REAL NOT NULL,          -- 총 사용량
    notes             TEXT,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (compound_id) REFERENCES compounds(compound_id),
    FOREIGN KEY (herb_item_id) REFERENCES herb_items(herb_item_id)
);

-- 12) 조제 소비 내역 (로트별 차감)
CREATE TABLE IF NOT EXISTS compound_consumptions (
    consumption_id    INTEGER PRIMARY KEY AUTOINCREMENT,
    compound_id       INTEGER NOT NULL,
    herb_item_id      INTEGER NOT NULL,
    lot_id            INTEGER NOT NULL,
    quantity_used     REAL NOT NULL,          -- 사용량(g)
    unit_cost_per_g   REAL NOT NULL,          -- 단가
    cost_amount       REAL,                   -- 원가액
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (compound_id) REFERENCES compounds(compound_id),
    FOREIGN KEY (herb_item_id) REFERENCES herb_items(herb_item_id),
    FOREIGN KEY (lot_id) REFERENCES inventory_lots(lot_id)
);

-- 인덱스 생성
CREATE INDEX IF NOT EXISTS idx_herb_items_name ON herb_items(herb_name);
CREATE INDEX IF NOT EXISTS idx_herb_items_code ON herb_items(insurance_code);
CREATE INDEX IF NOT EXISTS idx_inventory_lots_herb ON inventory_lots(herb_item_id, is_depleted);
CREATE INDEX IF NOT EXISTS idx_stock_ledger_herb ON stock_ledger(herb_item_id, event_time);
CREATE INDEX IF NOT EXISTS idx_compounds_patient ON compounds(patient_id);
CREATE INDEX IF NOT EXISTS idx_compounds_date ON compounds(compound_date);
CREATE INDEX IF NOT EXISTS idx_patients_phone ON patients(phone);

-- 뷰 생성 (자주 사용되는 조회)
-- 현재 재고 현황
CREATE VIEW IF NOT EXISTS v_current_stock AS
SELECT
    h.herb_item_id,
    h.insurance_code,
    h.herb_name,
    SUM(il.quantity_onhand) as total_quantity,
    COUNT(DISTINCT il.lot_id) as lot_count,
    AVG(il.unit_price_per_g) as avg_unit_price
FROM herb_items h
LEFT JOIN inventory_lots il ON h.herb_item_id = il.herb_item_id AND il.is_depleted = 0
GROUP BY h.herb_item_id, h.insurance_code, h.herb_name;

-- 처방별 구성 약재 뷰
CREATE VIEW IF NOT EXISTS v_formula_details AS
SELECT
    f.formula_id,
    f.formula_name,
    f.formula_code,
    h.herb_name,
    fi.grams_per_cheop,
    h.insurance_code
FROM formulas f
JOIN formula_ingredients fi ON f.formula_id = fi.formula_id
JOIN herb_items h ON fi.herb_item_id = h.herb_item_id
WHERE f.is_active = 1
ORDER BY f.formula_id, fi.sort_order;