-- ==========================================================
-- DMS v0.5.0
-- Database v5.1 - Deploy Script Schema
-- Server: Container Station on QNAPQNAP TS-473A
-- Database service: MariaDB 10.11
-- database ui: phpmyadmin 5-apache
-- backend sevice: node.js
-- frontend sevice: next.js
-- reverse proxy: nginx 1.27-alpine
-- cron service: n8n
-- scripts: alpine:3.20
-- Notes:
-- ==========================================================

SET NAMES utf8mb4;
SET time_zone = '+07:00';
SET FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS audit_logs;
DROP TABLE IF EXISTS user_project_roles;
DROP TABLE IF EXISTS user_roles;
DROP TABLE IF EXISTS role_permissions;
DROP TABLE IF EXISTS permissions;
DROP TABLE IF EXISTS roles;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS projects;
DROP TABLE IF EXISTS organizations;
DROP TABLE IF EXISTS project_parties;
DROP TABLE IF EXISTS correspondence_references;
DROP TABLE IF EXISTS correspondence_cc_recipients;
DROP TABLE IF EXISTS correspondences;
DROP TABLE IF EXISTS email_details;
DROP TABLE IF EXISTS instruction_details;
DROP TABLE IF EXISTS letter_details;
DROP TABLE IF EXISTS memorandum_details;
DROP TABLE IF EXISTS minutes_of_meeting_details;
DROP TABLE IF EXISTS rfi_details;
DROP TABLE IF EXISTS rfa_items;
DROP TABLE IF EXISTS rfas;
DROP TABLE IF EXISTS technicaldocs;
DROP TABLE IF EXISTS approve_codes;
DROP TABLE IF EXISTS document_status_codes;
DROP TABLE IF EXISTS document_types;
DROP TABLE IF EXISTS contract_dwg;
DROP TABLE IF EXISTS contract_dwg_sub_cat;
DROP TABLE IF EXISTS contract_dwg_cat;
DROP TABLE IF EXISTS contract_dwg_subcat_cat_map;
DROP TABLE IF EXISTS contract_dwg_volume;
DROP TABLE IF EXISTS transmittal_items;
DROP TABLE IF EXISTS cir_users;
DROP TABLE IF EXISTS circulations;
DROP TABLE IF EXISTS cir_status_codes;
DROP TABLE IF EXISTS doc_no_sequences;
DROP TABLE IF EXISTS global_default_roles;

-- ----------------------------------------------------------
-- CREATE tables
-- ----------------------------------------------------------
-- 1.1 users
CREATE TABLE users (
  user_id         INT AUTO_INCREMENT PRIMARY KEY,
  username        VARCHAR(100) NOT NULL UNIQUE,
  first_name      VARCHAR(100) NULL DEFAULT NULL,
  last_name       VARCHAR(100) NULL DEFAULT NULL,
  email           VARCHAR(255) NULL UNIQUE,
  line_id         VARCHAR(255) NULL,  
  password_hash   VARCHAR(255) NOT NULL,
  org_id          INT NULL, -- link to organizations for ADMIN scope
  is_active       TINYINT(1) NOT NULL DEFAULT 1,
  failed_attempts INT NOT NULL DEFAULT 0,
  locked_until    DATETIME NULL,
  last_login_at   DATETIME NULL,
  created_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at      TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
  -- CONSTRAINT fk_users_org FOREIGN KEY (org_id) REFERENCES organizations(org_id) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  
-- 2.1 Organizations (with primary_role as source of truth)
CREATE TABLE organizations (
  org_id       INT AUTO_INCREMENT PRIMARY KEY,
  org_code     VARCHAR(50) NOT NULL,
  org_name     VARCHAR(255) NOT NULL,
  primary_role ENUM('OWNER','DESIGNER','CONSULTANT','CONTRACTOR','THIRD_PARTY') NULL,
  created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  created_by INT NULL,
  updated_by INT NULL,
  deleted_at DATETIME NULL,
  CONSTRAINT uq_org_code UNIQUE (org_code),
  CONSTRAINT fk_org_created_by FOREIGN KEY (created_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_org_updated_by FOREIGN KEY (updated_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE INDEX idx_org_primary_role ON organizations(primary_role);

ALTER TABLE users
ADD CONSTRAINT fk_users_org FOREIGN KEY (org_id) REFERENCES organizations(org_id) ON UPDATE CASCADE ON DELETE SET NULL;

-- 2.2 Projects (contractor optional, FK -> organizations with SET NULL)
CREATE TABLE projects (
  project_id         INT AUTO_INCREMENT PRIMARY KEY,
  project_code       VARCHAR(50)  NOT NULL UNIQUE,
  project_name       VARCHAR(255) NOT NULL,
  parent_project_id  INT NULL,
  contractor_org_id  INT NULL,
  is_active          TINYINT(1) NOT NULL DEFAULT 0,
  created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  created_by INT NULL,
  updated_by INT NULL,
  deleted_at DATETIME NULL,
  CONSTRAINT uq_pro_code UNIQUE (project_code),
  CONSTRAINT fk_pro_parent      FOREIGN KEY (parent_project_id) REFERENCES projects(project_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_proj_contractor  FOREIGN KEY (contractor_org_id) REFERENCES organizations(org_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_proj_created_by FOREIGN KEY (created_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_proj_updated_by FOREIGN KEY (updated_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE INDEX idx_pp_parent ON projects(parent_project_id);
CREATE INDEX idx_pp_contractor ON projects(contractor_org_id);

-- 1.2 roles
CREATE TABLE roles (
  role_id     INT AUTO_INCREMENT PRIMARY KEY,
  role_code   VARCHAR(50) NOT NULL UNIQUE, -- SUPER_ADMIN / ADMIN / EDITOR / VIEWER
  role_name   VARCHAR(100) NOT NULL,
  description VARCHAR(255) NULL,
  is_system   TINYINT(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 1.3 permissions
CREATE TABLE permissions (
  permission_id INT AUTO_INCREMENT PRIMARY KEY,
  perm_code     VARCHAR(100) NOT NULL UNIQUE,
  perm_name     VARCHAR(150) NOT NULL,
  description   VARCHAR(255) NULL,
  module        VARCHAR(50)  NULL,
  scope_level   ENUM('GLOBAL','ORG','PROJECT') DEFAULT 'GLOBAL',
  is_active     TINYINT(1) NOT NULL DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 1.4 role_permissions
CREATE TABLE role_permissions (
  role_id       INT NOT NULL,
  permission_id INT NOT NULL,
  PRIMARY KEY (role_id, permission_id),
  CONSTRAINT fk_rp_role FOREIGN KEY (role_id) REFERENCES roles(role_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_rp_perm FOREIGN KEY (permission_id) REFERENCES permissions(permission_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 1.5 user_roles
CREATE TABLE user_roles (
  user_id INT NOT NULL,
  role_id INT NOT NULL,
  PRIMARY KEY (user_id, role_id),
  CONSTRAINT fk_ur_user FOREIGN KEY (user_id) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_ur_role FOREIGN KEY (role_id) REFERENCES roles(role_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 1.6 user_project_roles (project-scoped roles)
CREATE TABLE user_project_roles (
  user_id    INT NOT NULL,
  project_id INT NOT NULL,
  role_id    INT NOT NULL,
  PRIMARY KEY (user_id, project_id, role_id),
  CONSTRAINT fk_upr_user    FOREIGN KEY (user_id)    REFERENCES users(user_id)      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_upr_project FOREIGN KEY (project_id) REFERENCES projects(project_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_upr_role    FOREIGN KEY (role_id)    REFERENCES roles(role_id)      ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 1.7 audit_logs (optional)
CREATE TABLE audit_logs (
  audit_id     BIGINT AUTO_INCREMENT PRIMARY KEY,
  user_id      INT NULL,
  action       VARCHAR(100) NOT NULL,   -- e.g., login.success, rfa.create
  entity_type  VARCHAR(50) NULL,        -- table/model name
  entity_id    VARCHAR(50) NULL,
  details_json JSON NULL,
  ip_address   VARCHAR(45) NULL,
  user_agent   VARCHAR(255) NULL,
  created_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT fk_audit_user FOREIGN KEY (user_id) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE INDEX idx_audit_created ON audit_logs(created_at);

-- 2.3 Project Parties (enforce <=1 contractor per project via generated column + unique index)
CREATE TABLE project_parties (
  project_id INT NOT NULL,
  org_id     INT NOT NULL,
  role       ENUM('OWNER','DESIGNER','CONSULTANT','CONTRACTOR','THIRD_PARTY') NOT NULL,
  contractor_flag TINYINT GENERATED ALWAYS AS (CASE WHEN role='CONTRACTOR' THEN 1 ELSE NULL END) STORED,
  created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  created_by INT NULL,
  updated_by INT NULL,
  deleted_at DATETIME NULL,
  PRIMARY KEY (project_id, org_id, role),
  CONSTRAINT uq_propar_one_contractor_per_project UNIQUE (project_id, contractor_flag),
  CONSTRAINT fk_propar_project FOREIGN KEY (project_id) REFERENCES projects(project_id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT fk_propar_org     FOREIGN KEY (org_id)     REFERENCES organizations(org_id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT fk_propar_created_by FOREIGN KEY (created_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_pp_updated_by FOREIGN KEY (updated_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE INDEX  idx_pp_org  ON project_parties(org_id);
CREATE INDEX  idx_pp_role ON project_parties(role);


-- ---------- CORRESPONDENCE MASTERS ----------
DROP TABLE IF EXISTS correspondence_types;
CREATE TABLE correspondence_types (
  type_id INT AUTO_INCREMENT PRIMARY KEY,
  type_code VARCHAR(50) UNIQUE,
  type_name VARCHAR(255) NOT NULL,
  sort_order INT DEFAULT 0,
  is_active TINYINT(1) DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

DROP TABLE IF EXISTS correspondence_status;
CREATE TABLE correspondence_status (
  status_id INT AUTO_INCREMENT PRIMARY KEY,
  status_code VARCHAR(50) UNIQUE,
  status_name VARCHAR(255) NOT NULL,
  sort_order INT DEFAULT 0,
  is_active TINYINT(1) DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- =========================================================
-- 3.x CORRESPONDENCES (fixed constraints & revision model)
-- =========================================================
CREATE TABLE correspondences (
  corr_id        INT AUTO_INCREMENT PRIMARY KEY,

  -- root of a document family (first revision)
  root_id        INT NULL,

  correspondence_number    VARCHAR(100) NOT NULL,
  correspondence_type_id   INT NOT NULL,
  correspondence_status_id INT NOT NULL,

  is_internal_communication TINYINT(1) NOT NULL DEFAULT 0,
  revision       VARCHAR(50) NULL,   -- e.g., A,B or 1,2; NULL for first issue if desired
  project_id     INT NOT NULL,
  originator_id  INT NULL,           -- organizations.org_id
  recipient_id   INT NULL,           -- organizations.org_id
  title          VARCHAR(255) NOT NULL,
  keywords       VARCHAR(255) NULL,
  created_at     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by     INT NULL,
  issued_date    DATETIME NULL,
  updated_by     INT NULL,
  deleted_at     DATETIME NULL,
  pdf_path       VARCHAR(500) NULL,

  CONSTRAINT chk_cor_internal CHECK (is_internal_communication IN (0,1)),

  -- doc number uniqueness per project
  CONSTRAINT uq_cor_no_per_project UNIQUE (project_id, correspondence_number),

  -- enforce unique revision per root per project
  CONSTRAINT uq_root_rev_per_project UNIQUE (root_id, revision, project_id),

  -- FKs
  CONSTRAINT fk_cor_project     FOREIGN KEY (project_id)     REFERENCES projects(project_id)      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_cor_originator  FOREIGN KEY (originator_id)  REFERENCES organizations(org_id)     ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_cor_recipient   FOREIGN KEY (recipient_id)   REFERENCES organizations(org_id)     ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_cor_created_by  FOREIGN KEY (created_by)     REFERENCES users(user_id)            ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_cor_updated_by  FOREIGN KEY (updated_by)     REFERENCES users(user_id)            ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_cor_type        FOREIGN KEY (correspondence_type_id)   REFERENCES correspondence_types(type_id)     ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT fk_cor_status      FOREIGN KEY (correspondence_status_id) REFERENCES correspondence_status(status_id)  ON UPDATE CASCADE ON DELETE RESTRICT,

  -- self reference; prevent deleting root accidentally
  CONSTRAINT fk_cor_root        FOREIGN KEY (root_id)        REFERENCES correspondences(corr_id)  ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE INDEX idx_cor_project     ON correspondences(project_id);
CREATE INDEX idx_cor_originator  ON correspondences(originator_id);
CREATE INDEX idx_cor_recipient   ON correspondences(recipient_id);
CREATE INDEX idx_cor_type        ON correspondences(correspondence_type_id);
CREATE INDEX idx_cor_status      ON correspondences(correspondence_status_id);
CREATE INDEX idx_cor_created_at  ON correspondences(created_at);

-- CC recipients (org-level)
CREATE TABLE correspondence_cc_recipients (
  corr_id INT NOT NULL,
  org_id  INT NOT NULL,
  PRIMARY KEY (corr_id, org_id),
  CONSTRAINT fk_cc_cor  FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_cc_org  FOREIGN KEY (org_id)  REFERENCES organizations(org_id)   ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- cross references between correspondences
CREATE TABLE correspondence_references (
  src_corr_id INT NOT NULL,
  tgt_corr_id INT NOT NULL,
  PRIMARY KEY (src_corr_id, tgt_corr_id),
  CONSTRAINT fk_ref_src FOREIGN KEY (src_corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_ref_tgt FOREIGN KEY (tgt_corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- =========================================
-- 3.x DETAILS per correspondence type
-- (fixed commas/syntax)
-- =========================================
CREATE TABLE email_details (
  corr_id      INT PRIMARY KEY,
  email_from   VARCHAR(255) NULL,
  email_to     TEXT NULL,
  email_cc     TEXT NULL,
  email_bcc    TEXT NULL,
  sent_at      DATETIME NULL,
  message_id   VARCHAR(255) NULL,
  headers_json LONGTEXT NULL,
  CONSTRAINT fk_emadet_corrid FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE instruction_details (
  corr_id        INT PRIMARY KEY,
  instruction_no VARCHAR(100) NULL,
  effective_date DATE NULL,
  due_date       DATE NULL,
  instruction_text LONGTEXT NULL,
  CONSTRAINT fk_insdet_corrid FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE letter_details (
  corr_id   INT PRIMARY KEY,
  salutation VARCHAR(200) NULL,
  recipient  VARCHAR(200) NULL,
  closing    VARCHAR(200) NULL,
  signed_by  VARCHAR(200) NULL,
  CONSTRAINT fk_letdet_corrid FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE memorandum_details (
  corr_id      INT PRIMARY KEY,
  memo_to      VARCHAR(200) NULL,
  memo_from    VARCHAR(200) NULL,
  cc           TEXT NULL,
  body_summary LONGTEXT NULL,
  CONSTRAINT fk_memdet_corrid FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE minutes_of_meeting_details (
  corr_id      INT PRIMARY KEY,
  meeting_date DATETIME NULL,
  location     VARCHAR(255) NULL,
  chairperson  VARCHAR(200) NULL,
  attendees    TEXT NULL,
  agenda       LONGTEXT NULL,
  actions      LONGTEXT NULL,
  next_meeting DATETIME NULL,
  CONSTRAINT fk_momdet_corrid FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE rfi_details (
  corr_id       INT PRIMARY KEY,
  rfi_no        VARCHAR(100) NULL,
  question_text LONGTEXT NULL,
  requested_by  VARCHAR(200) NULL,
  requested_date DATE NULL,
  due_date       DATE NULL,
  answered_by    VARCHAR(200) NULL,
  answered_date  DATE NULL,
  answer_text    LONGTEXT NULL,
  CONSTRAINT fk_rfidet_corrid FOREIGN KEY (corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- =========================================================
-- 3.3 TECHNICAL DOCS + RFA ITEMS (fixed)
-- =========================================================
CREATE TABLE document_types (
  document_types_id INT AUTO_INCREMENT PRIMARY KEY,
  code        VARCHAR(20)  NOT NULL UNIQUE,
  name        VARCHAR(100) NOT NULL,
  sort_order  INT DEFAULT 0,
  is_active   TINYINT(1) DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE document_status_codes (
  status_code_id INT AUTO_INCREMENT PRIMARY KEY,
  code        VARCHAR(20) NOT NULL UNIQUE,
  description VARCHAR(255) NULL,
  sort_order  INT DEFAULT 0,
  is_active   TINYINT(1) DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE approve_codes (
  approve_code_id INT AUTO_INCREMENT PRIMARY KEY,
  code        VARCHAR(20) NOT NULL UNIQUE,
  description VARCHAR(255) NULL,
  sort_order  INT DEFAULT 0,
  is_active   TINYINT(1) DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE technicaldocs (
  id               INT AUTO_INCREMENT PRIMARY KEY,
  document_type_id INT NOT NULL,
  original_id      INT NOT NULL,
  revision         VARCHAR(50) NOT NULL,
  title            VARCHAR(255) NOT NULL,
  project_id       INT NOT NULL,
  status_code_id   INT NOT NULL,
  approve_code_id  INT NULL,
  created_at       DATETIME DEFAULT CURRENT_TIMESTAMP,
  created_by       INT NULL,
  updated_by       INT NULL,
  deleted_at       DATETIME NULL,
  pdf_path         VARCHAR(500) NULL,
  CONSTRAINT fk_techdoc_created_by FOREIGN KEY (created_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_techdoc_updated_by FOREIGN KEY (updated_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_techdoc_status  FOREIGN KEY (status_code_id)  REFERENCES document_status_codes(status_code_id),
  CONSTRAINT fk_techdoc_approve FOREIGN KEY (approve_code_id)  REFERENCES approve_codes(approve_code_id)      ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_techdoc_type    FOREIGN KEY (document_type_id) REFERENCES document_types(document_types_id),
  CONSTRAINT fk_techdoc_project FOREIGN KEY (project_id)       REFERENCES projects(project_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE UNIQUE INDEX idx_unique_techdoc_revision ON technicaldocs (original_id, revision, project_id);

-- RFA ↔ TechnicalDocs (RFA เป็นชนิดหนึ่งของ correspondences)
CREATE TABLE rfa_items (
  rfa_corr_id      INT NOT NULL,  -- FK to correspondences.corr_id (type=RFA)
  technical_doc_id INT NOT NULL UNIQUE, -- one techdoc appears in at most one RFA
  PRIMARY KEY (rfa_corr_id, technical_doc_id),
  CONSTRAINT fk_rfa_corr  FOREIGN KEY (rfa_corr_id)      REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_rfa_tech  FOREIGN KEY (technical_doc_id) REFERENCES technicaldocs(id)        ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE INDEX idx_rfaitems_rfa     ON rfa_items(rfa_corr_id);
CREATE INDEX idx_rfaitems_techdoc ON rfa_items(technical_doc_id);

CREATE TABLE rfas (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  code VARCHAR(64) NULL,
  title VARCHAR(255) NOT NULL,
  discipline VARCHAR(64) NULL,
  due_date DATE NULL,
  description TEXT NULL,
  status VARCHAR(32) NOT NULL DEFAULT 'draft',
  owner_id INT UNSIGNED NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  KEY idx_rfas_code (code),
  KEY idx_rfas_status_updated (status, updated_at),
  KEY idx_rfas_due_date (due_date),
  KEY idx_rfas_updated_at (updated_at),
  CONSTRAINT fk_rfas_owner
    FOREIGN KEY (owner_id) REFERENCES users(id)
    ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- =========================================================
-- CONTRACT DRAWINGS (normalized cat 1:M subcat; dwg → sub_cat)
-- =========================================================

/* ===========================================================
   1) Category (ต่อโปรเจกต์)
   - unique: (project_id, cat_name)
   - เพิ่ม unique (project_id, cat_id) เพื่อรองรับ composite FK
   =========================================================== */
CREATE TABLE contract_dwg_cat (
  cat_id     INT AUTO_INCREMENT PRIMARY KEY,
  project_id INT NOT NULL,
  cat_code   VARCHAR(100) NULL,
  cat_name   VARCHAR(255) NOT NULL,

  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,

  UNIQUE KEY ux_cat_project_name   (project_id, cat_name),
  UNIQUE KEY ux_cat_project_catid  (project_id, cat_id),

  KEY idx_cat_project              (project_id),
  KEY idx_cat_project_code         (project_id, cat_code),

  CONSTRAINT fk_cat_project
    FOREIGN KEY (project_id) REFERENCES projects(project_id)
    ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

/* ===========================================================
   2) Sub-Category (ต่อโปรเจกต์)
   - unique: (project_id, sub_cat_name)
   - เพิ่ม unique (project_id, sub_cat_id) เพื่อรองรับ composite FK
   =========================================================== */
CREATE TABLE contract_dwg_sub_cat (
  sub_cat_id   INT AUTO_INCREMENT PRIMARY KEY,
  project_id   INT NOT NULL,
  sub_cat_code VARCHAR(100) NULL,
  sub_cat_name VARCHAR(255) NOT NULL,

  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,

  UNIQUE KEY ux_subcat_project_name    (project_id, sub_cat_name),
  UNIQUE KEY ux_subcat_project_subcatid(project_id, sub_cat_id),

  KEY idx_subcat_project               (project_id),
  KEY idx_subcat_project_code          (project_id, sub_cat_code),

  CONSTRAINT fk_subcat_project
    FOREIGN KEY (project_id) REFERENCES projects(project_id)
    ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

/* ===========================================================
   3) Mapping: Sub-Category ↔ Category (Many-to-Many ภายในโปรเจกต์)
   - บังคับให้อยู่ project เดียวกัน ผ่าน composite FK
   - unique: (project_id, sub_cat_id, cat_id)
   =========================================================== */
CREATE TABLE contract_dwg_subcat_cat_map (
  project_id INT NOT NULL,
  sub_cat_id INT NOT NULL,
  cat_id     INT NOT NULL,

  UNIQUE KEY ux_map_unique           (project_id, sub_cat_id, cat_id),

  KEY idx_map_project_subcat         (project_id, sub_cat_id),
  KEY idx_map_project_cat            (project_id, cat_id),

  CONSTRAINT fk_map_subcat
    FOREIGN KEY (project_id, sub_cat_id)
    REFERENCES contract_dwg_sub_cat (project_id, sub_cat_id)
    ON UPDATE CASCADE ON DELETE CASCADE,

  CONSTRAINT fk_map_cat
    FOREIGN KEY (project_id, cat_id)
    REFERENCES contract_dwg_cat (project_id, cat_id)
    ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

/* ===========================================================
   4) Volume (ต่อโปรเจกต์)
   - unique: (project_id, volume_code)
   - เพิ่ม unique (project_id, volume_id) เพื่อรองรับ composite FK
   =========================================================== */
CREATE TABLE contract_dwg_volume (
  volume_id    INT AUTO_INCREMENT PRIMARY KEY,
  project_id   INT NOT NULL,
  volume_code  VARCHAR(100) NOT NULL,      -- เช่น V1, VOL-01
  volume_name  VARCHAR(255) NULL,
  description  TEXT NULL,

  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,

  UNIQUE KEY ux_volume_project_code  (project_id, volume_code),
  UNIQUE KEY ux_volume_project_volid (project_id, volume_id),

  KEY idx_volume_project            (project_id),
  KEY idx_volume_project_code       (project_id, volume_code),

  CONSTRAINT fk_volume_project
    FOREIGN KEY (project_id) REFERENCES projects(project_id)
    ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

/* ===========================================================
   5) Drawings (ต่อโปรเจกต์)
   - 1 drawing ∈ 1 project
   - ชี้ 1 sub-category (ในโปรเจกต์เดียวกัน)
   - ชี้ 1 volume     (ในโปรเจกต์เดียวกัน)
   - unique: (project_id, condwg_no)
   =========================================================== */

CREATE TABLE contract_dwg (
  condwg_id   INT AUTO_INCREMENT PRIMARY KEY,
  project_id  INT NOT NULL,
  condwg_no   VARCHAR(255) NOT NULL,      -- รหัส/เลขดรอว์อิง
  title       VARCHAR(255) NULL,
  sub_cat_id  INT NOT NULL,               -- 1 drawing → 1 sub-category
  volume_id   INT NOT NULL,               -- 1 drawing → 1 volume
  sub_no      INT NULL,                   -- หมายเลขย่อย (ถ้ามี)
  remark      VARCHAR(500) NULL,

  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,

  UNIQUE KEY ux_condwg_no_project (project_id, condwg_no),

  KEY idx_condwg_project      (project_id),
  KEY idx_condwg_sub_cat      (project_id, sub_cat_id),
  KEY idx_condwg_volume       (project_id, volume_id),
  KEY idx_condwg_no           (condwg_no),

  CONSTRAINT fk_condwg_project
    FOREIGN KEY (project_id) REFERENCES projects(project_id)
    ON UPDATE CASCADE ON DELETE CASCADE,

  /* same-project guard ด้วย composite FK */
  CONSTRAINT fk_condwg_subcat_same_project
    FOREIGN KEY (project_id, sub_cat_id)
    REFERENCES contract_dwg_sub_cat (project_id, sub_cat_id)
    ON UPDATE CASCADE ON DELETE RESTRICT,

  CONSTRAINT fk_condwg_volume_same_project
    FOREIGN KEY (project_id, volume_id)
    REFERENCES contract_dwg_volume (project_id, volume_id)
    ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- =========================================================
-- TRANSMITTALS (as correspondence type)
-- =========================================================
CREATE TABLE transmittal_items (
  transmittal_corr_id INT NOT NULL,  -- correspondence of type TRANSMITTAL
  item_corr_id        INT NOT NULL,  -- correspondence attached in the transmittal
  PRIMARY KEY (transmittal_corr_id, item_corr_id),
  CONSTRAINT fk_tra_hdr  FOREIGN KEY (transmittal_corr_id) REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_tra_item FOREIGN KEY (item_corr_id)        REFERENCES correspondences(corr_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE INDEX idx_tra_hdr  ON transmittal_items(transmittal_corr_id);
CREATE INDEX idx_tra_item ON transmittal_items(item_corr_id);

-- =========================================================
-- CIRCULATIONS (fixed FKs)
-- =========================================================
CREATE TABLE cir_status_codes (
  cir_status_code_id INT AUTO_INCREMENT PRIMARY KEY,
  code        VARCHAR(20) NOT NULL UNIQUE,
  description VARCHAR(255) NULL,
  sort_order  INT DEFAULT 0,
  is_active   TINYINT(1) DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE circulations (
  cir_id    INT AUTO_INCREMENT PRIMARY KEY,
  corr_id   INT UNIQUE,        -- one circulation record per correspondence (optional)
  org_id    INT NOT NULL,      -- owning org
  cir_no    VARCHAR(100) NOT NULL,
  status_id INT NOT NULL DEFAULT 1,
  title     VARCHAR(255) NOT NULL,
  note      LONGTEXT NULL,
  submitted_date DATE NULL,
  response_date  DATE NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  created_by INT NULL,
  updated_by INT NULL,
  deleted_at DATETIME NULL,
  pdf_path  VARCHAR(500) NULL,
  CONSTRAINT uq_cir_org_no UNIQUE(org_id, cir_no),

  CONSTRAINT fk_cir_status    FOREIGN KEY (status_id) REFERENCES cir_status_codes(cir_status_code_id) ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT fk_cir_corr      FOREIGN KEY (corr_id)   REFERENCES correspondences(corr_id)             ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_cir_org       FOREIGN KEY (org_id)    REFERENCES organizations(org_id)                ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT fk_cir_created_by FOREIGN KEY (created_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
  CONSTRAINT fk_cir_updated_by FOREIGN KEY (updated_by) REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE INDEX idx_cir_org    ON circulations(org_id);
CREATE INDEX idx_cir_status ON circulations(status_id);
CREATE INDEX idx_cir_corr   ON circulations(corr_id);

CREATE TABLE cir_users (
  id       INT AUTO_INCREMENT PRIMARY KEY,
  cir_id   INT NOT NULL,
  user_id  INT NOT NULL,
  is_main  TINYINT(1) DEFAULT 0,
  is_action TINYINT(1) DEFAULT 0,
  CONSTRAINT uq_cir_user UNIQUE (cir_id, user_id),
  CONSTRAINT fk_cirusr_cir  FOREIGN KEY (cir_id)  REFERENCES circulations(cir_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT fk_cirusr_user FOREIGN KEY (user_id) REFERENCES users(user_id)      ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- ตารางเชื่อม (ใหม่): shopdoc_contract_dwg dwgdoc_contract_dwg
-- ลบก่อนเผื่อมีอยู่
DROP TABLE IF EXISTS dwgdoc_contract_dwg;
CREATE TABLE dwgdoc_contract_dwg (
  technical_doc_id INT NOT NULL,      -- FK -> technicaldocs.id (ต้องเป็น DWG)
  condwg_id        INT NOT NULL,      -- FK -> contract_dwg.condwg_id

  PRIMARY KEY (technical_doc_id, condwg_id),

  CONSTRAINT fk_scd_dwgdoc
    FOREIGN KEY (technical_doc_id) REFERENCES technicaldocs(id)
    ON UPDATE CASCADE ON DELETE CASCADE,

  CONSTRAINT fk_scd_condwg
    FOREIGN KEY (condwg_id) REFERENCES contract_dwg(condwg_id)
    ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- สำหรับ reverse lookup จาก contract_dwg ไปหา dwg docs
CREATE INDEX idx_scd_condwg ON dwgdoc_contract_dwg(condwg_id);

-- ---------------------------------------------------------------------
-- Add table from ChatGPT ปรับปรุง V5.1 -> V5.2
-- ---------------------------------------------------------------------
-- ทำ sp_next_doc_no ให้ใช้งานจริง (เลขเอกสารรายโปรเจกต์ + รายชนิด) เพิ่มตาราง sequence
-- NEW: table for running numbers per project+type

CREATE TABLE doc_no_sequences (
  project_id INT NOT NULL,
  type_code  VARCHAR(20) NOT NULL,
  last_no    INT NOT NULL DEFAULT 0,
  PRIMARY KEY (project_id, type_code),
  CONSTRAINT fk_seq_proj FOREIGN KEY (project_id) REFERENCES projects(project_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- Global default roles (template defaults)
CREATE TABLE global_default_roles (
  id        TINYINT NOT NULL DEFAULT 1,
  role      ENUM('OWNER','DESIGNER','CONSULTANT') NOT NULL,
  position  TINYINT NOT NULL,
  org_id    INT NOT NULL,
  PRIMARY KEY (id, role, position),
  UNIQUE KEY ux_gdr_unique_org_per_role (id, role, org_id),
  CONSTRAINT fk_gdr_org FOREIGN KEY (org_id) REFERENCES organizations(org_id) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


-- เพิ่ม “ตาราง/วิว Allowed Status Transition” เพื่อตรวจ business rule บน 
-- sp_correspondence_update_status (ยังทำแบบ soft rule ใน proc)
-- NEW: table of allowed transitions (per type)
DROP TABLE IF EXISTS correspondence_status_transitions;
CREATE TABLE correspondence_status_transitions(
  type_id INT NOT NULL,
  from_status_id INT NOT NULL,
  to_status_id   INT NOT NULL,
  PRIMARY KEY (type_id, from_status_id, to_status_id),
  CONSTRAINT fk_cst_type   FOREIGN KEY (type_id)        REFERENCES correspondence_types(type_id),
  CONSTRAINT fk_cst_from   FOREIGN KEY (from_status_id)  REFERENCES correspondence_status(status_id),
  CONSTRAINT fk_cst_to     FOREIGN KEY (to_status_id)    REFERENCES correspondence_status(status_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


SET FOREIGN_KEY_CHECKS=1;