-- ============================================================
-- 润滑油行业 B2B ERP/CRM 综合系统 - PostgreSQL 数据库建模
-- 技术栈: Python (FastAPI) + PostgreSQL
-- 生成时间: 2026-02-27
-- ============================================================

-- 启用 uuid-ossp 扩展（用于 UUID 主键生成）
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- ============================================================
-- 通用函数：自动更新 updated_at 触发器
-- ============================================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;


-- ************************************************************
-- 1. RBAC 权限域
-- ************************************************************

-- ============================================================
-- 1.1 部门树表 sys_departments
-- ============================================================
CREATE TABLE sys_departments (
    id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    parent_id   UUID            REFERENCES sys_departments(id),
    name        VARCHAR(100)    NOT NULL,
    sort_order  INT             DEFAULT 0,
    status      SMALLINT        DEFAULT 1,       -- 1:启用 0:停用
    created_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted  BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  sys_departments                IS '部门树表';
COMMENT ON COLUMN sys_departments.id             IS '部门主键 UUID';
COMMENT ON COLUMN sys_departments.parent_id      IS '父级部门ID，NULL表示顶级';
COMMENT ON COLUMN sys_departments.name           IS '部门名称';
COMMENT ON COLUMN sys_departments.sort_order     IS '排序序号';
COMMENT ON COLUMN sys_departments.status         IS '状态 1:启用 0:停用';

CREATE INDEX idx_dept_parent ON sys_departments(parent_id) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_dept_updated
    BEFORE UPDATE ON sys_departments
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 1.2 角色表 sys_roles
-- ============================================================
CREATE TABLE sys_roles (
    id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    role_name   VARCHAR(50)     NOT NULL UNIQUE,
    data_scope  VARCHAR(20)     NOT NULL DEFAULT 'self',  -- all / dept_and_sub / self
    menu_keys   JSONB           DEFAULT '[]'::JSONB,      -- 菜单与按钮权限键集合
    description VARCHAR(255),
    status      SMALLINT        DEFAULT 1,
    created_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted  BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  sys_roles                IS '角色表';
COMMENT ON COLUMN sys_roles.id             IS '角色主键 UUID';
COMMENT ON COLUMN sys_roles.role_name      IS '角色名称';
COMMENT ON COLUMN sys_roles.data_scope     IS '数据权限范围: all=全部 / dept_and_sub=本部门及下属 / self=仅本人';
COMMENT ON COLUMN sys_roles.menu_keys      IS '拥有的菜单/按钮权限键列表 (JSONB数组)';

CREATE TRIGGER trg_role_updated
    BEFORE UPDATE ON sys_roles
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 1.3 员工/账号表 sys_users
-- ============================================================
CREATE TABLE sys_users (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    dept_id         UUID            REFERENCES sys_departments(id),
    role_id         UUID            REFERENCES sys_roles(id),
    username        VARCHAR(50)     NOT NULL UNIQUE,
    password_hash   VARCHAR(255)    NOT NULL,
    real_name       VARCHAR(50),
    phone           VARCHAR(20),
    email           VARCHAR(100),
    avatar_url      VARCHAR(500),
    status          SMALLINT        DEFAULT 1,       -- 1:在职 0:离职
    last_login_at   TIMESTAMP,
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  sys_users                    IS '员工/账号表';
COMMENT ON COLUMN sys_users.id                 IS '用户主键 UUID';
COMMENT ON COLUMN sys_users.dept_id            IS '所属部门ID';
COMMENT ON COLUMN sys_users.role_id            IS '所属角色ID';
COMMENT ON COLUMN sys_users.username           IS '登录账号';
COMMENT ON COLUMN sys_users.password_hash      IS '密码哈希值';
COMMENT ON COLUMN sys_users.real_name          IS '真实姓名';
COMMENT ON COLUMN sys_users.status             IS '状态 1:在职 0:离职';

CREATE INDEX idx_user_dept ON sys_users(dept_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_user_role ON sys_users(role_id) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_user_updated
    BEFORE UPDATE ON sys_users
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ************************************************************
-- 2. CRM 客户域
-- ************************************************************

-- ============================================================
-- 2.1 客户主表 crm_customers
-- ============================================================
CREATE TABLE crm_customers (
    id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name        VARCHAR(200)    NOT NULL,
    level       CHAR(1)         DEFAULT 'C',       -- A / B / C 三级
    industry    VARCHAR(100),
    contact     VARCHAR(50),                        -- 联系人姓名
    phone       VARCHAR(30),
    email       VARCHAR(100),
    address     TEXT,
    ai_score    NUMERIC(5,2)    DEFAULT 0,          -- AI 客情健康度评分 0~100
    owner_id    UUID            REFERENCES sys_users(id),  -- 负责销售
    status      SMALLINT        DEFAULT 1,          -- 1:活跃 0:冻结
    created_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted  BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  crm_customers                IS '客户主表';
COMMENT ON COLUMN crm_customers.id             IS '客户主键 UUID';
COMMENT ON COLUMN crm_customers.name           IS '客户/公司名称';
COMMENT ON COLUMN crm_customers.level          IS '客户等级 A/B/C';
COMMENT ON COLUMN crm_customers.ai_score       IS 'AI客情健康度评分 0~100';
COMMENT ON COLUMN crm_customers.owner_id       IS '负责销售ID';

CREATE INDEX idx_cust_level   ON crm_customers(level)    WHERE is_deleted = FALSE;
CREATE INDEX idx_cust_owner   ON crm_customers(owner_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_cust_name    ON crm_customers(name)     WHERE is_deleted = FALSE;

CREATE TRIGGER trg_cust_updated
    BEFORE UPDATE ON crm_customers
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 2.2 客户跟进日志表 crm_follow_up_logs
-- ============================================================
CREATE TABLE crm_follow_up_logs (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    customer_id     UUID            NOT NULL REFERENCES crm_customers(id),
    salesperson_id  UUID            NOT NULL REFERENCES sys_users(id),
    content         TEXT            NOT NULL,
    emotion_type    VARCHAR(20),                    -- positive / neutral / negative
    next_visit_time TIMESTAMP,
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  crm_follow_up_logs                     IS '客户跟进日志表（AI简报数据源）';
COMMENT ON COLUMN crm_follow_up_logs.customer_id         IS '关联客户ID';
COMMENT ON COLUMN crm_follow_up_logs.salesperson_id      IS '操作销售人员ID';
COMMENT ON COLUMN crm_follow_up_logs.content             IS '跟进内容';
COMMENT ON COLUMN crm_follow_up_logs.emotion_type        IS '情感标记: positive/neutral/negative';
COMMENT ON COLUMN crm_follow_up_logs.next_visit_time     IS '计划下次拜访时间';

CREATE INDEX idx_follow_cust  ON crm_follow_up_logs(customer_id)    WHERE is_deleted = FALSE;
CREATE INDEX idx_follow_sales ON crm_follow_up_logs(salesperson_id) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_follow_updated
    BEFORE UPDATE ON crm_follow_up_logs
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ************************************************************
-- 3. ERP 供应链域
-- ************************************************************

-- ============================================================
-- 3.1 产品分类树 erp_product_categories
-- ============================================================
CREATE TABLE erp_product_categories (
    id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    parent_id   UUID            REFERENCES erp_product_categories(id),
    name        VARCHAR(100)    NOT NULL,
    sort_order  INT             DEFAULT 0,
    created_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted  BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_product_categories           IS '产品分类树表（左树结构支撑）';
COMMENT ON COLUMN erp_product_categories.parent_id IS '父级分类ID，NULL为顶级分类';

CREATE INDEX idx_pcat_parent ON erp_product_categories(parent_id) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_pcat_updated
    BEFORE UPDATE ON erp_product_categories
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 3.2 产品 SKU 表 erp_product_skus
-- ============================================================
CREATE TABLE erp_product_skus (
    id                UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    category_id       UUID            REFERENCES erp_product_categories(id),
    sku_code          VARCHAR(50)     NOT NULL UNIQUE,
    name              VARCHAR(200)    NOT NULL,
    spec              VARCHAR(100),                  -- 规格，如 200L/桶
    standard_price    NUMERIC(12,2)   NOT NULL DEFAULT 0,
    stock_qty         NUMERIC(12,2)   NOT NULL DEFAULT 0,
    warning_threshold NUMERIC(12,2)   DEFAULT 0,     -- 库存预警阈值
    unit              VARCHAR(20)     DEFAULT '桶',
    status            SMALLINT        DEFAULT 1,     -- 1:在售 0:停售
    created_at        TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at        TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted        BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_product_skus                      IS '产品SKU主档表';
COMMENT ON COLUMN erp_product_skus.sku_code             IS 'SKU编号，全局唯一';
COMMENT ON COLUMN erp_product_skus.spec                 IS '包装规格，如 200L/桶、18L/桶';
COMMENT ON COLUMN erp_product_skus.standard_price       IS '标准售价';
COMMENT ON COLUMN erp_product_skus.stock_qty            IS '当前库存数量';
COMMENT ON COLUMN erp_product_skus.warning_threshold    IS '库存预警阈值，低于此值触发预警';

CREATE INDEX idx_sku_category ON erp_product_skus(category_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_sku_code     ON erp_product_skus(sku_code)    WHERE is_deleted = FALSE;

CREATE TRIGGER trg_sku_updated
    BEFORE UPDATE ON erp_product_skus
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 3.3 出入库流水表 erp_inventory_flows
-- ============================================================
CREATE TABLE erp_inventory_flows (
    id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    sku_id      UUID            NOT NULL REFERENCES erp_product_skus(id),
    change_qty  NUMERIC(12,2)   NOT NULL,            -- 正数=入库，负数=出库
    reason      VARCHAR(50)     NOT NULL,             -- purchase/shipment/loss/adjust
    remark      TEXT,
    operator_id UUID            REFERENCES sys_users(id),
    created_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted  BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_inventory_flows                IS '出入库流水账表';
COMMENT ON COLUMN erp_inventory_flows.sku_id         IS '关联SKU ID';
COMMENT ON COLUMN erp_inventory_flows.change_qty     IS '变动数量：正=入库 负=出库';
COMMENT ON COLUMN erp_inventory_flows.reason         IS '变动原因: purchase/shipment/loss/adjust';
COMMENT ON COLUMN erp_inventory_flows.operator_id    IS '操作人ID';

CREATE INDEX idx_invflow_sku      ON erp_inventory_flows(sku_id)      WHERE is_deleted = FALSE;
CREATE INDEX idx_invflow_operator ON erp_inventory_flows(operator_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_invflow_time     ON erp_inventory_flows(created_at)  WHERE is_deleted = FALSE;

CREATE TRIGGER trg_invflow_updated
    BEFORE UPDATE ON erp_inventory_flows
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ************************************************************
-- 4. ERP 交易域
-- ************************************************************

-- ============================================================
-- 4.1 订单主表 erp_orders
-- ============================================================
CREATE TABLE erp_orders (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    order_no        VARCHAR(30)     NOT NULL UNIQUE,     -- 业务单号，如 ORD-20260227-001
    customer_id     UUID            NOT NULL REFERENCES crm_customers(id),
    salesperson_id  UUID            REFERENCES sys_users(id),
    total_amount    NUMERIC(14,2)   NOT NULL DEFAULT 0,
    shipping_state  VARCHAR(20)     NOT NULL DEFAULT 'pending',   -- pending / partial / shipped
    payment_state   VARCHAR(20)     NOT NULL DEFAULT 'unpaid',    -- unpaid / partial / cleared
    paid_amount     NUMERIC(14,2)   DEFAULT 0,
    remark          TEXT,
    order_date      DATE            DEFAULT CURRENT_DATE,
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_orders                     IS '订单主表';
COMMENT ON COLUMN erp_orders.order_no            IS '业务订单号';
COMMENT ON COLUMN erp_orders.customer_id         IS '下单客户ID';
COMMENT ON COLUMN erp_orders.salesperson_id      IS '负责销售ID';
COMMENT ON COLUMN erp_orders.total_amount        IS '订单总金额';
COMMENT ON COLUMN erp_orders.shipping_state      IS '发货状态: pending/partial/shipped';
COMMENT ON COLUMN erp_orders.payment_state       IS '付款状态: unpaid/partial/cleared';
COMMENT ON COLUMN erp_orders.paid_amount         IS '已付金额';

CREATE INDEX idx_order_no       ON erp_orders(order_no)       WHERE is_deleted = FALSE;
CREATE INDEX idx_order_cust     ON erp_orders(customer_id)    WHERE is_deleted = FALSE;
CREATE INDEX idx_order_sales    ON erp_orders(salesperson_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_order_date     ON erp_orders(order_date)     WHERE is_deleted = FALSE;

CREATE TRIGGER trg_order_updated
    BEFORE UPDATE ON erp_orders
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 4.2 订单明细表 erp_order_items
-- ============================================================
CREATE TABLE erp_order_items (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    order_id        UUID            NOT NULL REFERENCES erp_orders(id),
    sku_id          UUID            NOT NULL REFERENCES erp_product_skus(id),
    qty             NUMERIC(12,2)   NOT NULL,
    unit_price      NUMERIC(12,2)   NOT NULL,            -- 本次成交单价（可能是专属价）
    sub_total       NUMERIC(14,2)   NOT NULL,
    shipped_qty     NUMERIC(12,2)   DEFAULT 0,           -- 已发货累计量（用于分批发货扣减）
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_order_items                    IS '订单明细行表';
COMMENT ON COLUMN erp_order_items.order_id           IS '归属订单ID';
COMMENT ON COLUMN erp_order_items.sku_id             IS '关联SKU ID';
COMMENT ON COLUMN erp_order_items.qty                IS '下单数量';
COMMENT ON COLUMN erp_order_items.unit_price         IS '成交单价（可能为客户专属价）';
COMMENT ON COLUMN erp_order_items.sub_total          IS '小计金额 = qty * unit_price';
COMMENT ON COLUMN erp_order_items.shipped_qty        IS '已发货累计数量，用于分批发货进度追踪';

CREATE INDEX idx_oitem_order ON erp_order_items(order_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_oitem_sku   ON erp_order_items(sku_id)   WHERE is_deleted = FALSE;

CREATE TRIGGER trg_oitem_updated
    BEFORE UPDATE ON erp_order_items
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ************************************************************
-- 5. ERP 物流域
-- ************************************************************

-- ============================================================
-- 5.1 发货主单表 erp_shipping_records
-- ============================================================
CREATE TABLE erp_shipping_records (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    shipping_no     VARCHAR(30)     NOT NULL UNIQUE,       -- 发货单号 SHP-xxx
    order_id        UUID            NOT NULL REFERENCES erp_orders(id),
    carrier         VARCHAR(100),                          -- 承运方，如德邦
    tracking_no     VARCHAR(100),                          -- 物流追踪号
    status          VARCHAR(20)     NOT NULL DEFAULT 'transit',   -- transit / delivered
    ship_date       DATE            DEFAULT CURRENT_DATE,
    remark          TEXT,
    operator_id     UUID            REFERENCES sys_users(id),
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_shipping_records                   IS '发货主单表';
COMMENT ON COLUMN erp_shipping_records.shipping_no       IS '发货单号';
COMMENT ON COLUMN erp_shipping_records.order_id          IS '关联订单ID';
COMMENT ON COLUMN erp_shipping_records.carrier           IS '承运方';
COMMENT ON COLUMN erp_shipping_records.tracking_no       IS '物流追踪号';
COMMENT ON COLUMN erp_shipping_records.status            IS '物流状态: transit=运输中 / delivered=已签收';

CREATE INDEX idx_ship_order ON erp_shipping_records(order_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_ship_no    ON erp_shipping_records(shipping_no) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_ship_updated
    BEFORE UPDATE ON erp_shipping_records
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 5.2 发货明细表 erp_shipping_items
-- ============================================================
CREATE TABLE erp_shipping_items (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    shipping_id     UUID            NOT NULL REFERENCES erp_shipping_records(id),
    order_item_id   UUID            NOT NULL REFERENCES erp_order_items(id),
    sku_id          UUID            NOT NULL REFERENCES erp_product_skus(id),
    shipped_qty     NUMERIC(12,2)   NOT NULL,              -- 本次发货数量
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  erp_shipping_items                     IS '发货明细行表（承接分批发货扣减）';
COMMENT ON COLUMN erp_shipping_items.shipping_id         IS '归属发货单ID';
COMMENT ON COLUMN erp_shipping_items.order_item_id       IS '关联订单明细行ID（用于回写已发货量）';
COMMENT ON COLUMN erp_shipping_items.sku_id              IS '关联SKU ID';
COMMENT ON COLUMN erp_shipping_items.shipped_qty         IS '本次实际发货数量';

CREATE INDEX idx_sitem_shipping ON erp_shipping_items(shipping_id)   WHERE is_deleted = FALSE;
CREATE INDEX idx_sitem_oitem    ON erp_shipping_items(order_item_id) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_sitem_updated
    BEFORE UPDATE ON erp_shipping_items
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ************************************************************
-- 6. 财务票据域
-- ************************************************************

-- ============================================================
-- 6.1 统一发票池表 fin_invoice_pool
-- ============================================================
CREATE TABLE fin_invoice_pool (
    id                  UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    uploader_id         UUID            REFERENCES sys_users(id),
    file_url            VARCHAR(500),
    merchant_name       VARCHAR(200),
    amount              NUMERIC(14,2)   NOT NULL DEFAULT 0,
    invoice_date        DATE,
    type                VARCHAR(30)     NOT NULL DEFAULT 'expense',  -- customer=客户发票 / expense=报销发票
    ai_extracted_data   JSONB           DEFAULT '{}'::JSONB,         -- OCR + AI 解析的原始结构化数据
    is_used             BOOLEAN         DEFAULT FALSE,               -- 是否已被报销单引用
    created_at          TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at          TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted          BOOLEAN         DEFAULT FALSE                -- 软删除=作废
);

COMMENT ON TABLE  fin_invoice_pool                       IS '统一发票池表（上传即OCR提取）';
COMMENT ON COLUMN fin_invoice_pool.uploader_id           IS '上传人ID';
COMMENT ON COLUMN fin_invoice_pool.file_url              IS '原始票据文件URL';
COMMENT ON COLUMN fin_invoice_pool.merchant_name         IS '商户/开票方名称';
COMMENT ON COLUMN fin_invoice_pool.amount                IS '票面金额';
COMMENT ON COLUMN fin_invoice_pool.type                  IS '票据类型: customer=客户发票 / expense=报销发票';
COMMENT ON COLUMN fin_invoice_pool.ai_extracted_data     IS 'AI/OCR提取的结构化数据 (JSONB)';
COMMENT ON COLUMN fin_invoice_pool.is_used               IS '是否已被报销单引用';
COMMENT ON COLUMN fin_invoice_pool.is_deleted            IS '软删除标识（作废，防物理篡改）';

CREATE INDEX idx_inv_uploader ON fin_invoice_pool(uploader_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_inv_type     ON fin_invoice_pool(type)        WHERE is_deleted = FALSE;
CREATE INDEX idx_inv_date     ON fin_invoice_pool(invoice_date) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_inv_updated
    BEFORE UPDATE ON fin_invoice_pool
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 6.2 报销单主表 fin_expense_records
-- ============================================================
CREATE TABLE fin_expense_records (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    system_no       VARCHAR(30)     NOT NULL UNIQUE,         -- 系统单号 EXP-xxx
    applicant_id    UUID            NOT NULL REFERENCES sys_users(id),
    total_amount    NUMERIC(14,2)   NOT NULL DEFAULT 0,
    status          VARCHAR(20)     NOT NULL DEFAULT 'draft', -- draft/pending/approved/rejected
    remark          TEXT,
    approved_by     UUID            REFERENCES sys_users(id),
    approved_at     TIMESTAMP,
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  fin_expense_records                    IS '报销单主表';
COMMENT ON COLUMN fin_expense_records.system_no          IS '系统报销单号';
COMMENT ON COLUMN fin_expense_records.applicant_id       IS '申请人ID';
COMMENT ON COLUMN fin_expense_records.total_amount       IS '报销总金额';
COMMENT ON COLUMN fin_expense_records.status             IS '报销状态: draft/pending/approved/rejected';
COMMENT ON COLUMN fin_expense_records.approved_by        IS '审批人ID';

CREATE INDEX idx_exp_applicant ON fin_expense_records(applicant_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_exp_status    ON fin_expense_records(status)       WHERE is_deleted = FALSE;
CREATE INDEX idx_exp_no        ON fin_expense_records(system_no)    WHERE is_deleted = FALSE;

CREATE TRIGGER trg_exp_updated
    BEFORE UPDATE ON fin_expense_records
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 6.3 报销明细行表 fin_expense_details
-- ============================================================
CREATE TABLE fin_expense_details (
    id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    expense_id      UUID            NOT NULL REFERENCES fin_expense_records(id),
    invoice_id      UUID            REFERENCES fin_invoice_pool(id),
    expense_desc    VARCHAR(500),                            -- 费用说明
    original_type   VARCHAR(50),                             -- 原始费用类型: fuel/entertainment/travel/office
    offset_type     VARCHAR(50),                             -- 冲顶类型（二级类型转换后）
    amount          NUMERIC(14,2)   NOT NULL DEFAULT 0,
    created_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
    is_deleted      BOOLEAN         DEFAULT FALSE
);

COMMENT ON TABLE  fin_expense_details                    IS '报销明细行表';
COMMENT ON COLUMN fin_expense_details.expense_id         IS '归属报销单ID';
COMMENT ON COLUMN fin_expense_details.invoice_id         IS '关联发票ID';
COMMENT ON COLUMN fin_expense_details.expense_desc       IS '费用说明描述';
COMMENT ON COLUMN fin_expense_details.original_type      IS '原始费用类型: fuel/entertainment/travel/office';
COMMENT ON COLUMN fin_expense_details.offset_type        IS '冲顶类型（二级票据类型转换后的类型）';
COMMENT ON COLUMN fin_expense_details.amount             IS '本行金额';

CREATE INDEX idx_expd_expense ON fin_expense_details(expense_id) WHERE is_deleted = FALSE;
CREATE INDEX idx_expd_invoice ON fin_expense_details(invoice_id) WHERE is_deleted = FALSE;

CREATE TRIGGER trg_expd_updated
    BEFORE UPDATE ON fin_expense_details
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();


-- ============================================================
-- 完成：输出建表结果摘要
-- ============================================================
-- 共创建 13 张业务表：
--   RBAC 权限域:  sys_departments, sys_roles, sys_users
--   CRM 客户域:   crm_customers, crm_follow_up_logs
--   ERP 供应链域: erp_product_categories, erp_product_skus, erp_inventory_flows
--   ERP 交易域:   erp_orders, erp_order_items
--   ERP 物流域:   erp_shipping_records, erp_shipping_items
--   财务票据域:   fin_invoice_pool, fin_expense_records, fin_expense_details
--
-- 全局规范落地：
--   ✓ 主键统一 UUID (uuid_generate_v4)
--   ✓ 每表必带 created_at / updated_at / is_deleted 审计三件套
--   ✓ updated_at 自动触发器 (update_updated_at_column)
--   ✓ 灵活字段采用 JSONB (menu_keys, ai_extracted_data)
--   ✓ 外键关联完整，部分索引 (WHERE is_deleted=FALSE) 优化查询
