251213:1509 Docunment Number Businee Rule not correct
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
# LCBP3-DMS - Project Overview
|
||||
|
||||
**Project Name:** Laem Chabang Port Phase 3 - Document Management System (LCBP3-DMS)
|
||||
**Version:** 1.5.1
|
||||
**Status:** Active Development (~80% Complete)
|
||||
**Last Updated:** 2025-12-09
|
||||
**Version:** 1.6.0
|
||||
**Status:** Active Development (~95% Complete)
|
||||
**Last Updated:** 2025-12-13
|
||||
|
||||
---
|
||||
|
||||
@@ -188,7 +188,7 @@ lcbp3/
|
||||
│ ├── 04-operations/ # Deployment & operations
|
||||
│ ├── 05-decisions/ # Architecture Decision Records (17 ADRs)
|
||||
│ ├── 06-tasks/ # Development tasks & progress
|
||||
│ ├── 07-database/ # Database schema v1.5.1 & seed data
|
||||
│ ├── 07-database/ # Database schema v1.6.0 & seed data
|
||||
│ └── 09-history/ # Archived implementations
|
||||
│
|
||||
├── docker-compose.yml # Docker services configuration
|
||||
@@ -384,9 +384,9 @@ lcbp3/
|
||||
|
||||
## 📝 Document Control
|
||||
|
||||
- **Version:** 1.5.1
|
||||
- **Version:** 1.6.0
|
||||
- **Status:** Active Development
|
||||
- **Last Updated:** 2025-12-09
|
||||
- **Last Updated:** 2025-12-13
|
||||
- **Next Review:** 2026-01-01
|
||||
- **Owner:** System Architect
|
||||
- **Classification:** Internal Use Only
|
||||
@@ -397,6 +397,7 @@ lcbp3/
|
||||
|
||||
| Version | Date | Description |
|
||||
| ------- | ---------- | ------------------------------------------ |
|
||||
| 1.6.0 | 2025-12-13 | Schema refactoring, documentation updated |
|
||||
| 1.5.1 | 2025-12-09 | TASK-FE-011/012 completed, docs updated |
|
||||
| 1.5.1 | 2025-12-02 | Reorganized documentation structure |
|
||||
| 1.5.0 | 2025-12-01 | Complete specification with ADRs and tasks |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Glossary - คำศัพท์และคำย่อทางเทคนิค
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -471,26 +471,26 @@ Logging library สำหรับ Node.js
|
||||
|
||||
## 📚 Acronyms Reference (อ้างอิงตัวย่อ)
|
||||
|
||||
| Acronym | Full Form | Thai |
|
||||
| ------- | --------------------------------- | ------------------------------- |
|
||||
| Acronym | Full Form | Thai |
|
||||
| ------- | --------------------------------- | -------------------------- |
|
||||
| ADR | Architecture Decision Record | บันทึกการตัดสินใจทางสถาปัตยกรรม |
|
||||
| API | Application Programming Interface | ส่วนต่อประสานโปรแกรม |
|
||||
| CRUD | Create, Read, Update, Delete | สร้าง อ่าน แก้ไข ลบ |
|
||||
| DMS | Document Management System | ระบบจัดการเอกสาร |
|
||||
| API | Application Programming Interface | ส่วนต่อประสานโปรแกรม |
|
||||
| CRUD | Create, Read, Update, Delete | สร้าง อ่าน แก้ไข ลบ |
|
||||
| DMS | Document Management System | ระบบจัดการเอกสาร |
|
||||
| DTO | Data Transfer Object | วัตถุถ่ายโอนข้อมูล |
|
||||
| JWT | JSON Web Token | โทเคนเว็บ JSON |
|
||||
| JWT | JSON Web Token | โทเคนเว็บ JSON |
|
||||
| LCBP3 | Laem Chabang Port Phase 3 | ท่าเรือแหลมฉบังระยะที่ 3 |
|
||||
| MVP | Minimum Viable Product | ผลิตภัณฑ์ขั้นต่ำที่ใช้งานได้ |
|
||||
| MVP | Minimum Viable Product | ผลิตภัณฑ์ขั้นต่ำที่ใช้งานได้ |
|
||||
| ORM | Object-Relational Mapping | การแมปวัตถุกับฐานข้อมูล |
|
||||
| RBAC | Role-Based Access Control | การควบคุมการเข้าถึงตามบทบาท |
|
||||
| REST | Representational State Transfer | การถ่ายโอนสถานะแบบนำเสนอ |
|
||||
| RFA | Request for Approval | เอกสารขออนุมัติ |
|
||||
| RTO | Recovery Time Objective | เวลาเป้าหมายในการกู้คืน |
|
||||
| RBAC | Role-Based Access Control | การควบคุมการเข้าถึงตามบทบาท |
|
||||
| REST | Representational State Transfer | การถ่ายโอนสถานะแบบนำเสนอ |
|
||||
| RFA | Request for Approval | เอกสารขออนุมัติ |
|
||||
| RTO | Recovery Time Objective | เวลาเป้าหมายในการกู้คืน |
|
||||
| RPO | Recovery Point Objective | จุดเป้าหมายในการกู้คืน |
|
||||
| UAT | User Acceptance Testing | การทดสอบการยอมรับของผู้ใช้ |
|
||||
| UAT | User Acceptance Testing | การทดสอบการยอมรับของผู้ใช้ |
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Quick Start Guide
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -579,5 +579,5 @@ git push origin feature/my-feature
|
||||
|
||||
**Welcome aboard! 🎉**
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
---
|
||||
title: 'Functional Requirements: Document Numbering Management'
|
||||
version: 1.5.1
|
||||
version: 1.6.0
|
||||
status: draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-12-02
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 📋 Requirements Specification
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Status:** Active
|
||||
**Last Updated:** 2025-12-02
|
||||
**Last Updated:** 2025-12-13
|
||||
|
||||
---
|
||||
|
||||
@@ -66,6 +66,12 @@ This directory contains the functional and non-functional requirements for the L
|
||||
|
||||
## 🔄 Recent Changes
|
||||
|
||||
### v1.6.0 (2025-12-13)
|
||||
|
||||
- ✅ **Schema Refactoring** - Major restructuring of correspondence and RFA tables
|
||||
- ✅ Updated data dictionary for schema v1.6.0
|
||||
- ✅ Breaking changes documented in CHANGELOG.md
|
||||
|
||||
### v1.5.1 (2025-12-02)
|
||||
|
||||
- ✅ **Reorganized Document Numbering documentation**
|
||||
@@ -172,8 +178,8 @@ All requirements documents must meet these criteria:
|
||||
|
||||
## 📝 Document Control
|
||||
|
||||
- **Version:** 1.5.1
|
||||
- **Version:** 1.6.0
|
||||
- **Owner:** System Architect (Nattanin Peancharoen)
|
||||
- **Last Review:** 2025-12-10
|
||||
- **Last Review:** 2025-12-13
|
||||
- **Next Review:** 2026-01-01
|
||||
- **Classification:** Internal Use Only
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
| Attribute | Value |
|
||||
| ------------------ | -------------------------------- |
|
||||
| **Version** | 1.5.1 |
|
||||
| **Version** | 1.6.0 |
|
||||
| **Status** | Active |
|
||||
| **Last Updated** | 2025-12-02 |
|
||||
| **Last Updated** | 2025-12-13 |
|
||||
| **Owner** | Nattanin Peancharoen |
|
||||
| **Classification** | Internal Technical Documentation |
|
||||
|
||||
@@ -463,6 +463,7 @@ sequenceDiagram
|
||||
|
||||
| Version | Date | Author | Changes |
|
||||
| ------- | ---------- | ----------- | ---------------------------------- |
|
||||
| 1.6.0 | 2025-12-13 | Nattanin P. | Schema refactoring v1.6.0 |
|
||||
| 1.5.0 | 2025-11-30 | Nattanin P. | Initial architecture specification |
|
||||
| 1.4.5 | 2025-11-29 | - | Added security requirements |
|
||||
| 1.4.4 | 2025-11-28 | - | Enhanced resilience patterns |
|
||||
@@ -489,7 +490,7 @@ sequenceDiagram
|
||||
|
||||
<div align="center">
|
||||
|
||||
**LCBP3-DMS Architecture Specification v1.5.0**
|
||||
**LCBP3-DMS Architecture Specification v1.6.0**
|
||||
|
||||
[System Architecture](./system-architecture.md) • [API Design](./api-design.md) • [Data Model](./data-model.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
---
|
||||
|
||||
**title:** 'API Design'
|
||||
**version:** 1.5.1
|
||||
**version:** 1.6.0
|
||||
**status:** active
|
||||
**owner:** Nattanin Peancharoen
|
||||
**last_updated:** 2025-12-02
|
||||
@@ -546,7 +546,7 @@ X-API-Deprecation-Info: https://docs.np-dms.work/migration/v2
|
||||
|
||||
**Document Control:**
|
||||
|
||||
- **Version:** 1.5.1
|
||||
- **Version:** 1.6.0
|
||||
- **Status:** Active
|
||||
- **Last Updated:** 2025-12-02
|
||||
- **Last Updated:** 2025-12-13
|
||||
- **Owner:** Nattanin Peancharoen
|
||||
|
||||
@@ -943,9 +943,9 @@ graph LR
|
||||
|
||||
**Document Control:**
|
||||
|
||||
- **Version:** 1.5.1
|
||||
- **Version:** 1.6.0
|
||||
- **Status:** Active
|
||||
- **Last Updated:** 2025-12-02
|
||||
- **Last Updated:** 2025-12-13
|
||||
- **Owner:** Nattanin Peancharoen
|
||||
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Operations Documentation
|
||||
|
||||
**Project:** LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System)
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -185,6 +185,6 @@ graph TB
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Status:** Active
|
||||
**Classification:** Internal Use Only
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Backup & Recovery Procedures
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -369,6 +369,6 @@ WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 YEAR);
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-01
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
---
|
||||
|
||||
**Project:** LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System)
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
**Owner:** Operations Team
|
||||
**Status:** Active
|
||||
@@ -932,6 +932,6 @@ docker exec lcbp3-mariadb mysql -u root -p -e "
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
**Next Review:** 2026-06-01
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
---
|
||||
title: 'Operations Guide: Document Numbering System'
|
||||
version: 1.5.1
|
||||
version: 1.6.0
|
||||
status: draft
|
||||
owner: Operations Team
|
||||
last_updated: 2025-12-02
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Environment Setup & Configuration
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -458,6 +458,6 @@ docker exec lcbp3-backend env | grep NODE_ENV
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-01
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Incident Response Procedures
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -478,6 +478,6 @@ Database connection pool was exhausted due to slow queries not releasing connect
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-01
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintenance Procedures
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -496,6 +496,6 @@ echo "Security maintenance completed: $(date)"
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-01
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Monitoring & Alerting
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -438,6 +438,6 @@ ab -n 1000 -c 10 \
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-01
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Security Operations
|
||||
|
||||
**Project:** LCBP3-DMS
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
|
||||
---
|
||||
@@ -439,6 +439,6 @@ echo "Account compromise response completed for User ID: $USER_ID"
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-01
|
||||
**Next Review:** 2026-03-01
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Architecture Decision Records (ADRs)
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Updated:** 2025-12-02
|
||||
**Project:** LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System)
|
||||
|
||||
@@ -28,45 +28,45 @@ Architecture Decision Records (ADRs) เป็นเอกสารที่บ
|
||||
|
||||
### Core Architecture Decisions
|
||||
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ------------------------------- | ----------- | ---------- | ---------------------------------------------------------------------------- |
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ------------------------------- | ---------- | ---------- | ------------------------------------------------------------------------- |
|
||||
| [ADR-001](./ADR-001-unified-workflow-engine.md) | Unified Workflow Engine | ✅ Accepted | 2025-11-30 | ใช้ DSL-based Workflow Engine สำหรับ Correspondences, RFAs, และ Circulations |
|
||||
| [ADR-002](./ADR-002-document-numbering-strategy.md) | Document Numbering Strategy | ✅ Accepted | 2025-11-30 | Double-lock mechanism (Redis + DB Optimistic Lock) สำหรับเลขที่เอกสาร |
|
||||
| [ADR-003](./ADR-003-file-storage-approach.md) | Two-Phase File Storage Approach | ✅ Accepted | 2025-11-30 | Upload → Temp → Commit to Permanent เพื่อป้องกัน Orphan Files |
|
||||
| [ADR-002](./ADR-002-document-numbering-strategy.md) | Document Numbering Strategy | ✅ Accepted | 2025-11-30 | Double-lock mechanism (Redis + DB Optimistic Lock) สำหรับเลขที่เอกสาร |
|
||||
| [ADR-003](./ADR-003-file-storage-approach.md) | Two-Phase File Storage Approach | ✅ Accepted | 2025-11-30 | Upload → Temp → Commit to Permanent เพื่อป้องกัน Orphan Files |
|
||||
|
||||
### Security & Access Control
|
||||
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| ------------------------------------------- | ----------------------------- | ----------- | ---------- | ------------------------------------------------------------- |
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| ------------------------------------------- | ----------------------------- | ---------- | ---------- | ------------------------------------------------------------- |
|
||||
| [ADR-004](./ADR-004-rbac-implementation.md) | RBAC Implementation (4-Level) | ✅ Accepted | 2025-11-30 | Hierarchical RBAC: Global → Organization → Project → Contract |
|
||||
|
||||
### Technology & Infrastructure
|
||||
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ------------------------------------ | ----------- | ---------- | -------------------------------------------------------------- |
|
||||
| [ADR-005](./ADR-005-technology-stack.md) | Technology Stack Selection | ✅ Accepted | 2025-11-30 | Full Stack TypeScript: NestJS + Next.js + MariaDB + Redis |
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ------------------------------------ | ---------- | ---------- | ------------------------------------------------------------ |
|
||||
| [ADR-005](./ADR-005-technology-stack.md) | Technology Stack Selection | ✅ Accepted | 2025-11-30 | Full Stack TypeScript: NestJS + Next.js + MariaDB + Redis |
|
||||
| [ADR-006](./ADR-006-redis-caching-strategy.md) | Redis Usage & Caching Strategy | ✅ Accepted | 2025-11-30 | Redis สำหรับ Distributed Lock, Cache, Queue, และ Rate Limiting |
|
||||
| [ADR-009](./ADR-009-database-migration-strategy.md) | Database Migration & Deployment | ✅ Accepted | 2025-12-01 | TypeORM Migrations พร้อม Blue-Green Deployment |
|
||||
| [ADR-015](./ADR-015-deployment-infrastructure.md) | Deployment & Infrastructure Strategy | ✅ Accepted | 2025-12-01 | Docker Compose with Blue-Green Deployment on QNAP |
|
||||
| [ADR-016](./ADR-016-security-authentication.md) | Security & Authentication Strategy | ✅ Accepted | 2025-12-01 | JWT + bcrypt + OWASP Security Best Practices |
|
||||
| [ADR-009](./ADR-009-database-migration-strategy.md) | Database Migration & Deployment | ✅ Accepted | 2025-12-01 | TypeORM Migrations พร้อม Blue-Green Deployment |
|
||||
| [ADR-015](./ADR-015-deployment-infrastructure.md) | Deployment & Infrastructure Strategy | ✅ Accepted | 2025-12-01 | Docker Compose with Blue-Green Deployment on QNAP |
|
||||
| [ADR-016](./ADR-016-security-authentication.md) | Security & Authentication Strategy | ✅ Accepted | 2025-12-01 | JWT + bcrypt + OWASP Security Best Practices |
|
||||
|
||||
### API & Integration
|
||||
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ----------------------------- | ----------- | ---------- | ----------------------------------------------------------------------------- |
|
||||
| [ADR-007](./ADR-007-api-design-error-handling.md) | API Design & Error Handling | ✅ Accepted | 2025-12-01 | Standard REST API with Custom Error Format + NestJS Exception Filters |
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ----------------------------- | ---------- | ---------- | --------------------------------------------------------------------------- |
|
||||
| [ADR-007](./ADR-007-api-design-error-handling.md) | API Design & Error Handling | ✅ Accepted | 2025-12-01 | Standard REST API with Custom Error Format + NestJS Exception Filters |
|
||||
| [ADR-008](./ADR-008-email-notification-strategy.md) | Email & Notification Strategy | ✅ Accepted | 2025-12-01 | BullMQ + Redis Queue สำหรับ Multi-channel Notifications (Email, LINE, In-app) |
|
||||
|
||||
### Observability
|
||||
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ----------------------------- | ----------- | ---------- | ------------------------------------------------------------- |
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| --------------------------------------------------- | ----------------------------- | ---------- | ---------- | ------------------------------------------------------------ |
|
||||
| [ADR-010](./ADR-010-logging-monitoring-strategy.md) | Logging & Monitoring Strategy | ✅ Accepted | 2025-12-01 | Winston Structured Logging พร้อม Future ELK Stack Integration |
|
||||
|
||||
### Frontend Architecture
|
||||
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| ------------------------------------------------ | -------------------------------- | ----------- | ---------- | ----------------------------------------------------- |
|
||||
| ADR | Title | Status | Date | Summary |
|
||||
| ------------------------------------------------ | -------------------------------- | ---------- | ---------- | ----------------------------------------------------- |
|
||||
| [ADR-011](./ADR-011-nextjs-app-router.md) | Next.js App Router & Routing | ✅ Accepted | 2025-12-01 | App Router with Server Components and Nested Layouts |
|
||||
| [ADR-012](./ADR-012-ui-component-library.md) | UI Component Library (Shadcn/UI) | ✅ Accepted | 2025-12-01 | Shadcn/UI + Tailwind CSS for Full Component Ownership |
|
||||
| [ADR-013](./ADR-013-form-handling-validation.md) | Form Handling & Validation | ✅ Accepted | 2025-12-01 | React Hook Form + Zod for Type-Safe Forms |
|
||||
@@ -356,5 +356,5 @@ graph TB
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.5.1
|
||||
**Version:** 1.6.0
|
||||
**Last Review:** 2025-12-02
|
||||
|
||||
251
specs/06-tasks/TASK-BE-015-schema-v160-migration.md
Normal file
251
specs/06-tasks/TASK-BE-015-schema-v160-migration.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# Task: Backend Schema v1.6.0 Migration
|
||||
|
||||
**Status:** ✅ Completed
|
||||
**Priority:** P1 (High - Breaking Changes)
|
||||
**Estimated Effort:** 3-5 days
|
||||
**Dependencies:** Schema v1.6.0 already created
|
||||
**Owner:** Backend Team
|
||||
|
||||
---
|
||||
|
||||
## 📋 Overview
|
||||
|
||||
อัพเดท Backend Entities และ DTOs ให้ตรงกับ Schema v1.6.0 ที่มีการ Refactor โครงสร้างตาราง
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Objectives
|
||||
|
||||
- [x] Update Correspondence Entities
|
||||
- [x] Update RFA Entities (Shared PK Pattern)
|
||||
- [x] Update DTOs for new field names
|
||||
- [x] Update Services for new relationships
|
||||
- [x] Add/Update Unit Tests
|
||||
|
||||
---
|
||||
|
||||
## 📝 Schema Changes Summary
|
||||
|
||||
### Breaking Changes ⚠️
|
||||
|
||||
| Table | Change | Impact |
|
||||
| --------------------------- | ---------------------------------------------- | --------------- |
|
||||
| `correspondence_recipients` | FK → `correspondences(id)` | Update relation |
|
||||
| `rfa_items` | `rfarev_correspondence_id` → `rfa_revision_id` | Rename column |
|
||||
|
||||
### Column Changes
|
||||
|
||||
| Table | Old | New | Notes |
|
||||
| -------------------------- | ------------------- | ----------------------------- | ----------- |
|
||||
| `correspondence_revisions` | `title` | `subject` | Rename |
|
||||
| `correspondence_revisions` | - | `body`, `remarks` | Add columns |
|
||||
| `rfa_revisions` | `title` | `subject` | Rename |
|
||||
| `rfa_revisions` | `correspondence_id` | - | Remove |
|
||||
| `rfa_revisions` | - | `body`, `remarks`, `due_date` | Add columns |
|
||||
|
||||
### Architecture Changes
|
||||
|
||||
| Table | Change |
|
||||
| ------ | ---------------------------------------------------- |
|
||||
| `rfas` | Shared PK with `correspondences` (no AUTO_INCREMENT) |
|
||||
| `rfas` | `id` references `correspondences(id)` |
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Implementation Steps
|
||||
|
||||
### 1. Update CorrespondenceRevision Entity
|
||||
|
||||
```typescript
|
||||
// File: backend/src/modules/correspondence/entities/correspondence-revision.entity.ts
|
||||
|
||||
// BEFORE
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
// AFTER
|
||||
@Column()
|
||||
subject: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
body: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
remarks: string;
|
||||
|
||||
@Column({ name: 'schema_version', default: 1 })
|
||||
schemaVersion: number;
|
||||
```
|
||||
|
||||
### 2. Update CorrespondenceRecipient Entity
|
||||
|
||||
```typescript
|
||||
// File: backend/src/modules/correspondence/entities/correspondence-recipient.entity.ts
|
||||
|
||||
// BEFORE
|
||||
@ManyToOne(() => CorrespondenceRevision, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'correspondence_id', referencedColumnName: 'correspondenceId' })
|
||||
revision: CorrespondenceRevision;
|
||||
|
||||
// AFTER
|
||||
@ManyToOne(() => Correspondence, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'correspondence_id' })
|
||||
correspondence: Correspondence;
|
||||
```
|
||||
|
||||
### 3. Update RFA Entity (Shared PK Pattern)
|
||||
|
||||
```typescript
|
||||
// File: backend/src/modules/rfa/entities/rfa.entity.ts
|
||||
|
||||
// BEFORE
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
// AFTER
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@OneToOne(() => Correspondence, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'id' })
|
||||
correspondence: Correspondence;
|
||||
```
|
||||
|
||||
### 4. Update RfaRevision Entity
|
||||
|
||||
```typescript
|
||||
// File: backend/src/modules/rfa/entities/rfa-revision.entity.ts
|
||||
|
||||
// REMOVE
|
||||
@Column({ name: 'correspondence_id' })
|
||||
correspondenceId: number;
|
||||
|
||||
// RENAME
|
||||
@Column()
|
||||
subject: string; // was: title
|
||||
|
||||
// ADD
|
||||
@Column({ type: 'text', nullable: true })
|
||||
body: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
remarks: string;
|
||||
|
||||
@Column({ name: 'due_date', type: 'datetime', nullable: true })
|
||||
dueDate: Date;
|
||||
```
|
||||
|
||||
### 5. Update RfaItem Entity
|
||||
|
||||
```typescript
|
||||
// File: backend/src/modules/rfa/entities/rfa-item.entity.ts
|
||||
|
||||
// BEFORE
|
||||
@Column({ name: 'rfarev_correspondence_id' })
|
||||
rfaRevCorrespondenceId: number;
|
||||
|
||||
// AFTER
|
||||
@Column({ name: 'rfa_revision_id' })
|
||||
rfaRevisionId: number;
|
||||
|
||||
@ManyToOne(() => RfaRevision, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'rfa_revision_id' })
|
||||
rfaRevision: RfaRevision;
|
||||
```
|
||||
|
||||
### 6. Update DTOs
|
||||
|
||||
```typescript
|
||||
// correspondence/dto/create-correspondence-revision.dto.ts
|
||||
export class CreateCorrespondenceRevisionDto {
|
||||
subject: string; // was: title
|
||||
body?: string;
|
||||
remarks?: string;
|
||||
}
|
||||
|
||||
// rfa/dto/create-rfa-revision.dto.ts
|
||||
export class CreateRfaRevisionDto {
|
||||
subject: string; // was: title
|
||||
body?: string;
|
||||
remarks?: string;
|
||||
dueDate?: Date;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Files to Modify
|
||||
|
||||
### Entities
|
||||
|
||||
| File | Status | Changes |
|
||||
| ------------------------------------ | ------ | ----------------------------------------- |
|
||||
| `correspondence.entity.ts` | ✅ | Minor: add recipients relation |
|
||||
| `correspondence-revision.entity.ts` | ✅ | Rename title→subject, add body/remarks |
|
||||
| `correspondence-recipient.entity.ts` | ✅ | FK change to correspondence |
|
||||
| `rfa.entity.ts` | ✅ | Shared PK pattern |
|
||||
| `rfa-revision.entity.ts` | ✅ | Remove correspondenceId, add body/remarks |
|
||||
| `rfa-item.entity.ts` | ✅ | Rename column |
|
||||
|
||||
### DTOs
|
||||
|
||||
| File | Status | Changes |
|
||||
| --------------------------------------- | ------ | ------------------------------- |
|
||||
| `create-correspondence-revision.dto.ts` | ✅ | title→subject, add body/remarks |
|
||||
| `update-correspondence-revision.dto.ts` | ✅ | Same |
|
||||
| `create-rfa-revision.dto.ts` | ✅ | title→subject, add fields |
|
||||
| `update-rfa-revision.dto.ts` | ✅ | Same |
|
||||
| `create-rfa-item.dto.ts` | ✅ | Column rename |
|
||||
|
||||
### Services
|
||||
|
||||
| File | Status | Changes |
|
||||
| --------------------------- | ------ | -------------------------------- |
|
||||
| `correspondence.service.ts` | ✅ | Update queries for new relations |
|
||||
| `rfa.service.ts` | ✅ | Handle Shared PK creation |
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```bash
|
||||
# Run existing tests to verify compatibility
|
||||
pnpm test:watch correspondence
|
||||
pnpm test:watch rfa
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
1. Create new Correspondence → verify subject field saved
|
||||
2. Create new RFA → verify Shared PK pattern works
|
||||
3. Verify recipients linked to correspondence (not revision)
|
||||
4. Verify RFA items linked via rfa_revision_id
|
||||
|
||||
---
|
||||
|
||||
## 📚 Related Documents
|
||||
|
||||
- [Schema v1.6.0](../07-database/lcbp3-v1.6.0-schema.sql)
|
||||
- [Data Dictionary v1.6.0](../07-database/data-dictionary-v1.6.0.md)
|
||||
- [CHANGELOG v1.6.0](../../CHANGELOG.md)
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Risks & Mitigation
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
| ----------------- | ------ | ------------------------------------ |
|
||||
| Breaking frontend | High | Update frontend types simultaneously |
|
||||
| Data migration | Medium | Schema already handles FK changes |
|
||||
| Test failures | Low | Update tests with new field names |
|
||||
|
||||
---
|
||||
|
||||
## 📌 Notes
|
||||
|
||||
- Schema v1.6.0 SQL files already exist in `specs/07-database/`
|
||||
- This task focuses on **backend code changes only**
|
||||
- Frontend will need separate task for DTO/type updates
|
||||
- Consider feature flag for gradual rollout
|
||||
263
specs/06-tasks/TASK-FE-016-schema-v160-adaptation.md
Normal file
263
specs/06-tasks/TASK-FE-016-schema-v160-adaptation.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# Task: Frontend Schema v1.6.0 Adaptation
|
||||
|
||||
**Status:** ✅ Completed
|
||||
**Priority:** P1 (High - Breaking Changes)
|
||||
**Estimated Effort:** 2-3 days
|
||||
**Dependencies:** TASK-BE-015 (Backend Migration)
|
||||
**Owner:** Frontend Team
|
||||
|
||||
---
|
||||
|
||||
## 📋 Overview
|
||||
|
||||
อัพเดท Frontend Types, Services และ Forms ให้รองรับ Schema v1.6.0
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Objectives
|
||||
|
||||
- [x] Update TypeScript Interfaces/Types
|
||||
- [x] Update Form Components (field names)
|
||||
- [x] Update API Service Calls
|
||||
- [x] Update List/Table Columns
|
||||
- [x] Verify E2E functionality
|
||||
|
||||
---
|
||||
|
||||
## 📊 Business Rule Changes Analysis
|
||||
|
||||
### 1. Correspondence Revisions ⚠️ UI IMPACT
|
||||
|
||||
| Change | Old Field | New Field | Business Rule |
|
||||
| ---------- | --------- | --------- | --------------------------------------- |
|
||||
| **Rename** | `title` | `subject` | Form label เปลี่ยนจาก "หัวเรื่อง" เป็น "เรื่อง" |
|
||||
| **Add** | - | `body` | เพิ่ม Rich Text Editor สำหรับเนื้อความ |
|
||||
| **Add** | - | `remarks` | เพิ่ม Textarea สำหรับหมายเหตุ |
|
||||
| **Add** | - | `dueDate` | เพิ่ม Date Picker สำหรับกำหนดส่ง |
|
||||
|
||||
**UI Impact:**
|
||||
- Correspondence Form: เพิ่ม 3 fields ใหม่
|
||||
- Correspondence List: เปลี่ยน column header
|
||||
- Correspondence Detail: แสดง body และ remarks
|
||||
|
||||
### 2. Correspondence Recipients ⚠️ RELATION CHANGE
|
||||
|
||||
| Before | After | Business Rule |
|
||||
| ------------------------ | ---------------------- | -------------------------- |
|
||||
| Recipients ผูกกับ Revision | Recipients ผูกกับ Master | ผู้รับคงที่ตลอด Revisions ทั้งหมด |
|
||||
|
||||
**UI Impact:**
|
||||
- ย้าย Recipients Selection ออกจาก Revision Form
|
||||
- ไปอยู่ใน Master Correspondence Form แทน
|
||||
- Recipients จะไม่เปลี่ยนเมื่อสร้าง New Revision
|
||||
|
||||
### 3. RFA System 🔄 ARCHITECTURE CHANGE
|
||||
|
||||
| Change | Description | Business Rule |
|
||||
| ---------------- | -------------------------- | -------------------------------------------- |
|
||||
| **Shared ID** | RFA.id = Correspondence.id | สร้าง Correspondence ก่อน แล้ว RFA ใช้ ID เดียวกัน |
|
||||
| **Subject** | `title` → `subject` | เหมือนกับ Correspondence |
|
||||
| **Body/Remarks** | เพิ่ม fields ใหม่ | เหมือนกับ Correspondence |
|
||||
| **Due Date** | เพิ่ม field | กำหนดวันที่ต้องตอบกลับ |
|
||||
|
||||
**UI Impact:**
|
||||
- RFA Form: เพิ่ม body, remarks, dueDate
|
||||
- RFA Creation Flow: อาจต้อง adjust การ submit
|
||||
|
||||
### 4. RFA Items ⚠️ API CHANGE
|
||||
|
||||
| Before | After | Impact |
|
||||
| ------------------------ | --------------- | ------------------------------------------- |
|
||||
| `rfaRevCorrespondenceId` | `rfaRevisionId` | เปลี่ยน property name ใน API request/response |
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Implementation Steps
|
||||
|
||||
### 1. Update TypeScript Types
|
||||
|
||||
```typescript
|
||||
// lib/types/correspondence.ts
|
||||
|
||||
// BEFORE
|
||||
interface CorrespondenceRevision {
|
||||
title: string;
|
||||
// ...
|
||||
}
|
||||
|
||||
// AFTER
|
||||
interface CorrespondenceRevision {
|
||||
subject: string; // renamed from title
|
||||
body?: string; // NEW
|
||||
remarks?: string; // NEW
|
||||
dueDate?: string; // NEW
|
||||
schemaVersion?: number; // NEW
|
||||
// ...
|
||||
}
|
||||
|
||||
// Move recipients to master level
|
||||
interface Correspondence {
|
||||
// ...existing fields
|
||||
recipients: CorrespondenceRecipient[]; // MOVED from revision
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// lib/types/rfa.ts
|
||||
|
||||
// BEFORE
|
||||
interface RfaRevision {
|
||||
correspondenceId: number;
|
||||
title: string;
|
||||
// ...
|
||||
}
|
||||
|
||||
// AFTER
|
||||
interface RfaRevision {
|
||||
// correspondenceId: REMOVED
|
||||
subject: string; // renamed from title
|
||||
body?: string; // NEW
|
||||
remarks?: string; // NEW
|
||||
dueDate?: string; // NEW
|
||||
// ...
|
||||
}
|
||||
|
||||
// BEFORE
|
||||
interface RfaItem {
|
||||
rfaRevCorrespondenceId: number;
|
||||
// ...
|
||||
}
|
||||
|
||||
// AFTER
|
||||
interface RfaItem {
|
||||
rfaRevisionId: number; // renamed
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Update Form Components
|
||||
|
||||
```typescript
|
||||
// app/(dashboard)/correspondences/new/page.tsx
|
||||
// app/(dashboard)/correspondences/[id]/edit/page.tsx
|
||||
|
||||
// CHANGES:
|
||||
// 1. Rename form field: title → subject
|
||||
// 2. Add new fields: body, remarks, dueDate
|
||||
// 3. Move recipients to master section (not revision)
|
||||
|
||||
<FormField name="subject" label="เรื่อง" required /> {/* was: title */}
|
||||
<FormField name="body" label="เนื้อความ" type="richtext" /> {/* NEW */}
|
||||
<FormField name="remarks" label="หมายเหตุ" type="textarea" /> {/* NEW */}
|
||||
<FormField name="dueDate" label="กำหนดส่ง" type="date" /> {/* NEW */}
|
||||
```
|
||||
|
||||
### 3. Update List Columns
|
||||
|
||||
```typescript
|
||||
// components/correspondence/correspondence-list.tsx
|
||||
|
||||
const columns = [
|
||||
// BEFORE: { header: 'หัวเรื่อง', accessorKey: 'title' }
|
||||
// AFTER:
|
||||
{ header: 'เรื่อง', accessorKey: 'subject' },
|
||||
{ header: 'กำหนดส่ง', accessorKey: 'dueDate' }, // NEW column
|
||||
];
|
||||
```
|
||||
|
||||
### 4. Update API Services
|
||||
|
||||
```typescript
|
||||
// lib/services/correspondence.service.ts
|
||||
// lib/services/rfa.service.ts
|
||||
|
||||
// Update DTO property names in API calls
|
||||
// Ensure field mapping matches backend changes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Files to Modify
|
||||
|
||||
### Types
|
||||
|
||||
| File | Status | Changes |
|
||||
| ----------------------------- | ------ | --------------------------------------- |
|
||||
| `lib/types/correspondence.ts` | ✅ | title→subject, add body/remarks/dueDate |
|
||||
| `lib/types/rfa.ts` | ✅ | Same + remove correspondenceId |
|
||||
|
||||
### Forms
|
||||
|
||||
| File | Status | Changes |
|
||||
| ---------------------------------------------------- | ------ | ---------------------- |
|
||||
| `app/(dashboard)/correspondences/new/page.tsx` | ✅ | Add new fields, rename |
|
||||
| `app/(dashboard)/correspondences/[id]/edit/page.tsx` | ✅ | Same |
|
||||
| `app/(dashboard)/rfas/new/page.tsx` | ✅ | Add new fields, rename |
|
||||
| `app/(dashboard)/rfas/[id]/edit/page.tsx` | ✅ | Same |
|
||||
|
||||
### Lists/Tables
|
||||
|
||||
| File | Status | Changes |
|
||||
| --------------------------------------------------- | ------ | ------------- |
|
||||
| `components/correspondence/correspondence-list.tsx` | ✅ | Column rename |
|
||||
| `components/rfa/rfa-list.tsx` | ✅ | Column rename |
|
||||
|
||||
### Services
|
||||
|
||||
| File | Status | Changes |
|
||||
| ---------------------------------------- | ------ | ----------- |
|
||||
| `lib/services/correspondence.service.ts` | ✅ | DTO mapping |
|
||||
| `lib/services/rfa.service.ts` | ✅ | DTO mapping |
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification
|
||||
|
||||
### Manual Testing
|
||||
|
||||
1. **Correspondence Flow:**
|
||||
- [ ] Create new correspondence → verify subject, body, remarks saved
|
||||
- [ ] Edit existing → verify field display correctly
|
||||
- [ ] List view shows "เรื่อง" column
|
||||
|
||||
2. **RFA Flow:**
|
||||
- [ ] Create new RFA → verify new fields
|
||||
- [ ] Add RFA Items → verify API works with new field names
|
||||
- [ ] Due date displays and functions correctly
|
||||
|
||||
3. **Recipients:**
|
||||
- [ ] Recipients assigned at master level
|
||||
- [ ] Creating new revision doesn't reset recipients
|
||||
|
||||
### E2E Tests
|
||||
|
||||
```bash
|
||||
pnpm test:e2e -- --grep "correspondence"
|
||||
pnpm test:e2e -- --grep "rfa"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Related Documents
|
||||
|
||||
- [TASK-BE-015](./TASK-BE-015-schema-v160-migration.md) - Backend Migration
|
||||
- [Schema v1.6.0](../07-database/lcbp3-v1.6.0-schema.sql)
|
||||
- [CHANGELOG v1.6.0](../../CHANGELOG.md)
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Risks & Mitigation
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
| ---------------------- | ------ | ---------------------------- |
|
||||
| Field name mismatch | High | Coordinate with backend team |
|
||||
| Form validation errors | Medium | Test all forms thoroughly |
|
||||
| List display issues | Low | Update column configs |
|
||||
|
||||
---
|
||||
|
||||
## 📌 Notes
|
||||
|
||||
- ต้องรอ Backend deploy ก่อน จึงจะ test ได้
|
||||
- Recipients logic change อาจส่งผลต่อ business flow
|
||||
- Consider feature flag for gradual rollout
|
||||
@@ -20,6 +20,7 @@
|
||||
| **TASK-BE-011** | Notification & Audit | ✅ **Done** | 100% | Global Audit Interceptor & Notification Module active. |
|
||||
| **TASK-BE-012** | Master Data Management | ✅ **Done** | 100% | Disciplines, SubTypes, Tags, Config APIs complete. |
|
||||
| **TASK-BE-013** | User Management | ✅ **Done** | 100% | CRUD, Assignments, Preferences, Soft Delete complete. |
|
||||
| **TASK-BE-015** | Schema v1.6.0 Migration | ✅ **Done** | 100% | Correspondence/RFA Shared PK, New Fields (2025-12-13). |
|
||||
|
||||
## 🛠 Detailed Findings by Component
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
| **TASK-FE-013** | Circulation & Transmittal | ✅ **Done** | 100% | Circulation and Transmittal modules implemented with DataTable. |
|
||||
| **TASK-FE-014** | Reference Data UI | ✅ **Done** | 100% | Generic CRUD Table refactored (Skeleton/Dialogs). All pages linked. |
|
||||
| **TASK-FE-015** | Security Admin UI | ✅ **Done** | 100% | RBAC Matrix, Roles, Active Sessions, System Logs implemented. |
|
||||
| **TASK-FE-016** | Schema v1.6.0 Adaptation | ✅ **Done** | 100% | Update Forms/Types/Lists for v1.6.0 changes (2025-12-13). |
|
||||
|
||||
## 🛠 Detailed Status by Component
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# **ตารางฐานข้อมูล (Data Dictionary) - LCBP3-DMS (V1.5.1)**
|
||||
# **ตารางฐานข้อมูล (Data Dictionary) - LCBP3-DMS (V1.6.0)**
|
||||
|
||||
เอกสารนี้สรุปโครงสร้างตาราง,
|
||||
FOREIGN KEYS (FK),
|
||||
และ Constraints ที่สำคัญทั้งหมดในฐานข้อมูล LCBP3 - DMS (v1.5.1) เพื่อใช้เป็นเอกสารอ้างอิงสำหรับทีมพัฒนา Backend (NestJS) และ Frontend (Next.js) โดยอิงจาก Requirements และ SQL Script ล่าสุด ** สถานะ: ** FINAL GUIDELINE ** วันที่: ** 2025 -12 -04 ** อ้างอิง: ** Requirements v1.5.1 & FullStackJS Guidelines v1.5.1 ** Classification: ** Internal Technical Documentation ## 📝 สรุปรายการปรับปรุง (Summary of Changes in v1.5.1)
|
||||
1.** Enhanced Document Numbering **: ปรับปรุงตาราง `document_number_counters` ให้รองรับ 8 - COLUMN Composite PK และเพิ่มตาราง `document_number_audit`,
|
||||
`document_number_errors` 2.** Unified Workflow ENGINE **: เพิ่มตาราง `workflow_definitions`,
|
||||
`workflow_instances`,
|
||||
`workflow_histories` เพื่อรองรับ Workflow แบบ DYNAMIC 3.** New MASTER TABLES **: เพิ่มตาราง `disciplines` และ `correspondence_sub_types` ตาม Req 6B 4.** System Enhancements **: เพิ่มตาราง `json_schemas` และ `user_preferences` 5.** Schema Updates **: เพิ่ม `discipline_id` ในตาราง `correspondences` และ `rfas` ---
|
||||
และ Constraints ที่สำคัญทั้งหมดในฐานข้อมูล LCBP3 - DMS (v1.6.0) เพื่อใช้เป็นเอกสารอ้างอิงสำหรับทีมพัฒนา Backend (NestJS) และ Frontend (Next.js) โดยอิงจาก Requirements และ SQL Script ล่าสุด ** สถานะ: ** FINAL GUIDELINE ** วันที่: ** 2025 -12 -13 ** อ้างอิง: ** Requirements v1.6.0 & FullStackJS Guidelines v1.6.0 ** Classification: ** Internal Technical Documentation ## 📝 สรุปรายการปรับปรุง (Summary of Changes in v1.6.0)
|
||||
1.** Schema Refactoring **: ปรับโครงสร้างตาราง `correspondences`, `correspondence_revisions`, `rfas`, `rfa_revisions` ให้เป็นมาตรฐานเดียวกัน
|
||||
2.** Shared PK Pattern **: ตาราง `rfas` ใช้ ID ร่วมกับ `correspondences` (FK Reference แทน AUTO_INCREMENT)
|
||||
3.** Column Rename **: เปลี่ยน `title` เป็น `subject` ในตาราง revision และเพิ่ม `body`, `remarks`
|
||||
4.** Virtual Columns **: เพิ่ม Virtual Columns สำหรับ Index ข้อมูลจาก JSON details
|
||||
5.** FK Updates **: `correspondence_recipients` FK ชี้ไป `correspondences(id)` แทน `correspondence_revisions` ---
|
||||
|
||||
## **1. 🏢 Core & Master Data Tables (องค์กร, โครงการ, สัญญา)**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.5.1 Document Management System Database
|
||||
-- DMS v1.6.0 Document Management System Database
|
||||
-- Deploy Script Schema
|
||||
-- Server: Container Station on QNAP TS-473A
|
||||
-- Database service: MariaDB 11.8
|
||||
@@ -10,14 +10,11 @@
|
||||
-- reverse proxy: jc21/nginx-proxy-manager:latest
|
||||
-- cron service: n8n
|
||||
-- ==========================================================
|
||||
-- [v1.5.1 UPDATE] Enhanced Document Numbering System
|
||||
-- Update: Upgraded from v1.4.5
|
||||
-- Last Updated: 2025-12-02
|
||||
-- [v1.6.0 UPDATE] Refactor Schema
|
||||
-- Update: Upgraded from v1.5.1
|
||||
-- Last Updated: 2025-12-13
|
||||
-- Major Changes:
|
||||
-- 1. Document Numbering: 8-column composite PK (was 5 columns)
|
||||
-- 2. New Tables: document_number_audit, document_number_errors
|
||||
-- 3. Enhanced indexes and constraints for document_number_counters
|
||||
-- 4. Based on specs v1.5.1 (refs: 03.11-document-numbering.md)
|
||||
-- 1. ปรับปรุง: corespondences, correspondence_revisions, correspondence_recipients, rfas, rfa_revisions
|
||||
-- ==========================================================
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
@@ -397,6 +394,20 @@ CREATE TABLE contract_organizations (
|
||||
-- =====================================================
|
||||
-- 3. ✉️ Correspondences (เอกสารหลัก, Revisions)
|
||||
-- =====================================================
|
||||
-- ตารางเก็บข้อมูลสาขางาน (Disciplines) แยกตามสัญญา
|
||||
CREATE TABLE disciplines (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
contract_id INT NOT NULL COMMENT 'ผูกกับสัญญา',
|
||||
discipline_code VARCHAR(10) NOT NULL COMMENT 'รหัสสาขา (เช่น GEN, STR)',
|
||||
code_name_th VARCHAR(255) COMMENT 'ชื่อไทย',
|
||||
code_name_en VARCHAR(255) COMMENT 'ชื่ออังกฤษ',
|
||||
is_active TINYINT(1) DEFAULT 1 COMMENT 'สถานะการใช้งาน',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
|
||||
UNIQUE KEY uk_discipline_contract (contract_id, discipline_code)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเก็บข้อมูลสาขางาน (Disciplines) ตาม Req 6B';
|
||||
|
||||
-- ตาราง Master เก็บประเภทเอกสารโต้ตอบ
|
||||
CREATE TABLE correspondence_types (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
@@ -409,6 +420,19 @@ CREATE TABLE correspondence_types (
|
||||
deleted_at DATETIME NULL COMMENT 'วันที่ลบ (Soft Delete)'
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง Master เก็บประเภทเอกสารโต้ตอบ';
|
||||
|
||||
-- ตารางเก็บประเภทหนังสือย่อย (Sub Types) สำหรับ Mapping เลขรหัส
|
||||
CREATE TABLE correspondence_sub_types (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
contract_id INT NOT NULL COMMENT 'ผูกกับสัญญา',
|
||||
correspondence_type_id INT NOT NULL COMMENT 'ผูกกับประเภทเอกสารหลัก (เช่น RFA)',
|
||||
sub_type_code VARCHAR(20) NOT NULL COMMENT 'รหัสย่อย (เช่น MAT, SHP)',
|
||||
sub_type_name VARCHAR(255) COMMENT 'ชื่อประเภทหนังสือย่อย',
|
||||
sub_type_number VARCHAR(10) COMMENT 'เลขรหัสสำหรับ Running Number (เช่น 11, 22)',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types (id) ON DELETE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเก็บประเภทหนังสือย่อย (Sub Types) ตาม Req 6B';
|
||||
|
||||
-- ตาราง Master เก็บสถานะของเอกสาร
|
||||
CREATE TABLE correspondence_status (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
@@ -421,8 +445,9 @@ CREATE TABLE correspondence_status (
|
||||
-- ตาราง "แม่" ของเอกสารโต้ตอบ เก็บข้อมูลที่ไม่เปลี่ยนตาม Revision
|
||||
CREATE TABLE correspondences (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง (นี่คือ "Master ID" ที่ใช้เชื่อมโยง)',
|
||||
correspondence_type_id INT NOT NULL COMMENT 'ประเภทเอกสาร ใช้แบ่งแยกว่าเป็น RFA หรือ อื่นๆ',
|
||||
correspondence_number VARCHAR(100) NOT NULL COMMENT 'เลขที่เอกสาร (สร้างจาก DocumentNumberingModule)',
|
||||
correspondence_type_id INT NOT NULL COMMENT 'ประเภทเอกสาร',
|
||||
discipline_id INT NULL COMMENT 'สาขางาน (ถ้ามี)',
|
||||
is_internal_communication TINYINT(1) DEFAULT 0 COMMENT '(1 = ภายใน, 0 = ภายนอก)',
|
||||
project_id INT NOT NULL COMMENT 'อยู่ในโครงการ',
|
||||
originator_id INT COMMENT 'องค์กรผู้ส่ง',
|
||||
@@ -431,47 +456,13 @@ CREATE TABLE correspondences (
|
||||
deleted_at DATETIME NULL COMMENT 'สำหรับ Soft Delete',
|
||||
FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types (id) ON DELETE RESTRICT,
|
||||
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (originator_id) REFERENCES organizations (id) ON DELETE
|
||||
SET NULL,
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL,
|
||||
UNIQUE KEY uq_corr_no_per_project (
|
||||
project_id,
|
||||
correspondence_number
|
||||
)
|
||||
FOREIGN KEY (originator_id) REFERENCES organizations (id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE SET NULL,
|
||||
-- Foreign Key ที่รวมเข้ามาจาก ALTER (ระบุชื่อ Constraint ตามที่ต้องการ)
|
||||
CONSTRAINT fk_corr_discipline FOREIGN KEY (discipline_id) REFERENCES disciplines (id) ON DELETE SET NULL,
|
||||
UNIQUE KEY uq_corr_no_per_project (project_id, correspondence_number)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "แม่" ของเอกสารโต้ตอบ เก็บข้อมูลที่ไม่เปลี่ยนตาม Revision';
|
||||
|
||||
-- ตาราง "ลูก" เก็บประวัติการแก้ไข (Revisions) ของ correspondences (1:N)
|
||||
CREATE TABLE correspondence_revisions (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของ Revision',
|
||||
correspondence_id INT NOT NULL COMMENT 'Master ID',
|
||||
revision_number INT NOT NULL COMMENT 'หมายเลข Revision (0, 1, 2...)',
|
||||
revision_label VARCHAR(10) COMMENT 'Revision ที่แสดง (เช่น A, B, 1.1)',
|
||||
is_current BOOLEAN DEFAULT FALSE COMMENT '(1 = Revision ปัจจุบัน)',
|
||||
correspondence_status_id INT NOT NULL COMMENT 'สถานะของ Revision นี้',
|
||||
title VARCHAR(255) NOT NULL COMMENT 'เรื่อง',
|
||||
document_date DATE COMMENT 'วันที่ในเอกสาร',
|
||||
issued_date DATETIME COMMENT 'วันที่ออกเอกสาร',
|
||||
received_date DATETIME COMMENT 'วันที่ลงรับเอกสาร',
|
||||
due_date DATETIME COMMENT 'วันที่ครบกำหนด',
|
||||
description TEXT COMMENT 'คำอธิบายการแก้ไขใน Revision นี้',
|
||||
details JSON COMMENT 'ข้อมูลเฉพาะ (เช่น RFI details)',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้างเอกสาร',
|
||||
created_by INT COMMENT 'ผู้สร้าง',
|
||||
updated_by INT COMMENT 'ผู้แก้ไขล่าสุด',
|
||||
FOREIGN KEY (correspondence_id) REFERENCES correspondences (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (correspondence_status_id) REFERENCES correspondence_status (id) ON DELETE RESTRICT,
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL,
|
||||
FOREIGN KEY (updated_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL,
|
||||
UNIQUE KEY uq_master_revision_number (
|
||||
correspondence_id,
|
||||
revision_number
|
||||
),
|
||||
UNIQUE KEY uq_master_current (correspondence_id, is_current)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "ลูก" เก็บประวัติการแก้ไข (Revisions) ของ correspondences (1 :N)';
|
||||
|
||||
-- ตารางเชื่อมผู้รับ (TO/CC) สำหรับเอกสารแต่ละฉบับ (M:N)
|
||||
CREATE TABLE correspondence_recipients (
|
||||
correspondence_id INT COMMENT 'ID ของเอกสาร',
|
||||
@@ -482,10 +473,60 @@ CREATE TABLE correspondence_recipients (
|
||||
recipient_organization_id,
|
||||
recipient_type
|
||||
),
|
||||
FOREIGN KEY (correspondence_id) REFERENCES correspondence_revisions (correspondence_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (correspondence_id) REFERENCES correspondences (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (recipient_organization_id) REFERENCES organizations (id) ON DELETE RESTRICT
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเชื่อมผู้รับ (TO / CC) สำหรับเอกสารแต่ละฉบับ (M :N)';
|
||||
|
||||
-- ตาราง "ลูก" เก็บประวัติการแก้ไข (Revisions) ของ correspondences (1:N)
|
||||
CREATE TABLE correspondence_revisions (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของ Revision',
|
||||
|
||||
correspondence_id INT NOT NULL COMMENT 'Master ID',
|
||||
revision_number INT NOT NULL COMMENT 'หมายเลข Revision (0, 1, 2...)',
|
||||
revision_label VARCHAR(10) COMMENT 'Revision ที่แสดง (เช่น A, B, 1.1)',
|
||||
is_current BOOLEAN DEFAULT FALSE COMMENT '(1 = Revision ปัจจุบัน)',
|
||||
|
||||
-- ข้อมูลเนื้อหาที่เปลี่ยนได้
|
||||
correspondence_status_id INT NOT NULL COMMENT 'สถานะของ Revision นี้',
|
||||
|
||||
subject VARCHAR(500) NOT NULL COMMENT 'หัวข้อเรื่อง',
|
||||
description TEXT COMMENT 'คำอธิบายการแก้ไขใน Revision นี้',
|
||||
body TEXT NULL COMMENT 'เนื้อความ (ถ้ามี)',
|
||||
remarks TEXT COMMENT 'หมายเหตุ',
|
||||
|
||||
document_date DATE COMMENT 'วันที่ในเอกสาร',
|
||||
issued_date DATETIME COMMENT 'วันที่ออกเอกสาร',
|
||||
received_date DATETIME COMMENT 'วันที่ลงรับเอกสาร',
|
||||
due_date DATETIME COMMENT 'วันที่ครบกำหนด',
|
||||
|
||||
-- Standard Meta Columns
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้างเอกสาร',
|
||||
created_by INT COMMENT 'ผู้สร้าง',
|
||||
updated_by INT COMMENT 'ผู้แก้ไขล่าสุด',
|
||||
|
||||
-- ส่วนของ JSON และ Schema Version
|
||||
details JSON COMMENT 'ข้อมูลเฉพาะ (เช่น LETTET details)',
|
||||
schema_version INT DEFAULT 1 COMMENT 'เวอร์ชันของ Schema ที่ใช้กับ details',
|
||||
|
||||
-- Generated Virtual Columns (ดึงค่าจาก JSON โดยอัตโนมัติ)
|
||||
v_ref_project_id INT GENERATED ALWAYS AS (
|
||||
CAST(JSON_UNQUOTE(JSON_EXTRACT(details, '$.projectId')) AS UNSIGNED)
|
||||
) VIRTUAL COMMENT 'Virtual Column: Project ID จาก JSON',
|
||||
|
||||
v_doc_subtype VARCHAR(50) GENERATED ALWAYS AS (
|
||||
JSON_UNQUOTE(JSON_EXTRACT(details, '$.subType'))
|
||||
) VIRTUAL COMMENT 'Virtual Column: Document Subtype จาก JSON',
|
||||
|
||||
FOREIGN KEY (correspondence_id) REFERENCES correspondences (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (correspondence_status_id) REFERENCES correspondence_status (id) ON DELETE RESTRICT,
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (updated_by) REFERENCES users (user_id) ON DELETE SET NULL,
|
||||
UNIQUE KEY uq_master_revision_number (correspondence_id, revision_number ),
|
||||
UNIQUE KEY uq_master_current (correspondence_id, is_current),
|
||||
INDEX idx_corr_rev_v_project (v_ref_project_id),
|
||||
INDEX idx_corr_rev_v_subtype (v_doc_subtype)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "ลูก" เก็บประวัติการแก้ไข (Revisions) ของ correspondences (1 :N)';
|
||||
|
||||
-- ตาราง Master เก็บ Tags ทั้งหมดที่ใช้ในระบบ
|
||||
CREATE TABLE tags (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
@@ -533,42 +574,6 @@ CREATE TABLE rfa_types (
|
||||
FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง Master สำหรับประเภท RFA';
|
||||
|
||||
-- [NEW 6B] ตารางเก็บข้อมูลสาขางาน (Disciplines) แยกตามสัญญา
|
||||
CREATE TABLE disciplines (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
contract_id INT NOT NULL COMMENT 'ผูกกับสัญญา',
|
||||
discipline_code VARCHAR(10) NOT NULL COMMENT 'รหัสสาขา (เช่น GEN, STR)',
|
||||
code_name_th VARCHAR(255) COMMENT 'ชื่อไทย',
|
||||
code_name_en VARCHAR(255) COMMENT 'ชื่ออังกฤษ',
|
||||
is_active TINYINT(1) DEFAULT 1 COMMENT 'สถานะการใช้งาน',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
|
||||
UNIQUE KEY uk_discipline_contract (contract_id, discipline_code)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเก็บข้อมูลสาขางาน (Disciplines) ตาม Req 6B';
|
||||
|
||||
-- [NEW 6B] ตารางเก็บประเภทหนังสือย่อย (Sub Types) สำหรับ Mapping เลขรหัส
|
||||
CREATE TABLE correspondence_sub_types (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
contract_id INT NOT NULL COMMENT 'ผูกกับสัญญา',
|
||||
correspondence_type_id INT NOT NULL COMMENT 'ผูกกับประเภทเอกสารหลัก (เช่น RFA)',
|
||||
sub_type_code VARCHAR(20) NOT NULL COMMENT 'รหัสย่อย (เช่น MAT, SHP)',
|
||||
sub_type_name VARCHAR(255) COMMENT 'ชื่อประเภทหนังสือย่อย',
|
||||
sub_type_number VARCHAR(10) COMMENT 'เลขรหัสสำหรับ Running Number (เช่น 11, 22)',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types (id) ON DELETE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเก็บประเภทหนังสือย่อย (Sub Types) ตาม Req 6B';
|
||||
|
||||
-- หรือใช้ ALTER TABLE (แนะนำให้รันหลังสร้างตาราง disciplines เสร็จ)
|
||||
ALTER TABLE correspondences
|
||||
ADD COLUMN discipline_id INT NULL COMMENT 'สาขางาน (ถ้ามี)'
|
||||
AFTER correspondence_type_id;
|
||||
|
||||
ALTER TABLE correspondences
|
||||
ADD CONSTRAINT fk_corr_discipline FOREIGN KEY (discipline_id) REFERENCES disciplines (id) ON DELETE
|
||||
SET NULL;
|
||||
|
||||
-- ตาราง Master สำหรับสถานะ RFA
|
||||
CREATE TABLE rfa_status_codes (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
@@ -594,65 +599,75 @@ CREATE TABLE rfa_approve_codes (
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง Master สำหรับรหัสผลการอนุมัติ RFA';
|
||||
|
||||
CREATE TABLE rfas (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง (RFA Master ID)',
|
||||
id INT PRIMARY KEY COMMENT 'ID ของตาราง (RFA Master ID)', -- ❌ ไม่มี AUTO_INCREMENT
|
||||
rfa_type_id INT NOT NULL COMMENT 'ประเภท RFA',
|
||||
-- discipline_id INT NULL COMMENT 'สาขางาน (ถ้ามี)',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง',
|
||||
created_by INT COMMENT 'ผู้สร้าง',
|
||||
deleted_at DATETIME NULL COMMENT 'สำหรับ Soft Delete',
|
||||
FOREIGN KEY (rfa_type_id) REFERENCES rfa_types (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE SET NULL,
|
||||
-- CONSTRAINT fk_rfa_discipline FOREIGN KEY (discipline_id) REFERENCES disciplines (id) ON DELETE SET NULL,
|
||||
CONSTRAINT fk_rfas_parent FOREIGN KEY (id) REFERENCES correspondences (id) ON DELETE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "แม่" ของ RFA (มีความสัมพันธ์ 1 :N กับ rfa_revisions)';
|
||||
|
||||
ALTER TABLE rfas
|
||||
ADD COLUMN discipline_id INT NULL COMMENT 'สาขางาน (ถ้ามี)'
|
||||
AFTER rfa_type_id;
|
||||
|
||||
ALTER TABLE rfas
|
||||
ADD CONSTRAINT fk_rfa_discipline FOREIGN KEY (discipline_id) REFERENCES disciplines (id) ON DELETE
|
||||
SET NULL;
|
||||
|
||||
-- ตาราง "ลูก" เก็บประวัติ (Revisions) ของ rfas (1:N)
|
||||
CREATE TABLE rfa_revisions (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของ Revision',
|
||||
correspondence_id INT NOT NULL COMMENT 'Master ID ของ Correspondence',
|
||||
|
||||
rfa_id INT NOT NULL COMMENT 'Master ID ของ RFA',
|
||||
revision_number INT NOT NULL COMMENT 'หมายเลข Revision (0, 1, 2...)',
|
||||
revision_label VARCHAR(10) COMMENT 'Revision ที่แสดง (เช่น A, B, 1.1)',
|
||||
is_current BOOLEAN DEFAULT FALSE COMMENT '(1 = Revision ปัจจุบัน)',
|
||||
|
||||
-- ข้อมูลเฉพาะของ RFA Revision ที่ซับซ้อน
|
||||
rfa_status_code_id INT NOT NULL COMMENT 'สถานะ RFA',
|
||||
rfa_approve_code_id INT COMMENT 'ผลการอนุมัติ',
|
||||
title VARCHAR(255) NOT NULL COMMENT 'เรื่อง',
|
||||
subject VARCHAR(500) NOT NULL COMMENT 'หัวข้อเรื่อง',
|
||||
description TEXT COMMENT 'คำอธิบายการแก้ไขใน Revision นี้',
|
||||
body TEXT NULL COMMENT 'เนื้อความ (ถ้ามี)',
|
||||
remarks TEXT COMMENT 'หมายเหตุ',
|
||||
|
||||
document_date DATE COMMENT 'วันที่ในเอกสาร',
|
||||
issued_date DATE COMMENT 'วันที่ส่งขออนุมัติ',
|
||||
received_date DATETIME COMMENT 'วันที่ลงรับเอกสาร',
|
||||
due_date DATETIME COMMENT 'วันที่ครบกำหนด',
|
||||
approved_date DATE COMMENT 'วันที่อนุมัติ',
|
||||
description TEXT COMMENT 'คำอธิบายการแก้ไขใน Revision นี้',
|
||||
|
||||
-- Standard Meta Columns
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้างเอกสาร',
|
||||
created_by INT COMMENT 'ผู้สร้าง',
|
||||
updated_by INT COMMENT 'ผู้แก้ไขล่าสุด',
|
||||
FOREIGN KEY (correspondence_id) REFERENCES correspondences (id) ON DELETE CASCADE,
|
||||
|
||||
-- ส่วนของ JSON และ Schema Version
|
||||
details JSON NULL COMMENT 'RFA Specific Details',
|
||||
schema_version INT DEFAULT 1 COMMENT 'Version ของ JSON Schema',
|
||||
|
||||
-- Generated Virtual Columns (ดึงค่าจาก JSON โดยอัตโนมัติ)
|
||||
v_ref_drawing_count INT GENERATED ALWAYS AS (
|
||||
JSON_UNQUOTE(
|
||||
JSON_EXTRACT(details, '$.drawingCount')
|
||||
)
|
||||
) VIRTUAL,
|
||||
|
||||
FOREIGN KEY (rfa_id) REFERENCES rfas (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (rfa_status_code_id) REFERENCES rfa_status_codes (id),
|
||||
FOREIGN KEY (rfa_approve_code_id) REFERENCES rfa_approve_codes (id) ON DELETE
|
||||
SET NULL,
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL,
|
||||
FOREIGN KEY (updated_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL,
|
||||
UNIQUE KEY uq_rr_rev_number (rfa_id, revision_number),
|
||||
UNIQUE KEY uq_rr_current (rfa_id, is_current)
|
||||
FOREIGN KEY (rfa_approve_code_id) REFERENCES rfa_approve_codes (id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (created_by) REFERENCES users (user_id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (updated_by) REFERENCES users (user_id) ON DELETE SET NULL,
|
||||
UNIQUE KEY uq_rr_rev_number (rfa_id, revision_number),
|
||||
UNIQUE KEY uq_rr_current (rfa_id, is_current)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "ลูก" เก็บประวัติ (Revisions) ของ rfas (1 :N)';
|
||||
|
||||
-- ตารางเชื่อมระหว่าง rfa_revisions (ที่เป็นประเภท DWG) กับ shop_drawing_revisions (M:N)
|
||||
CREATE TABLE rfa_items (
|
||||
rfarev_correspondence_id INT COMMENT 'ID ของ RFA Revision',
|
||||
rfa_revision_id INT COMMENT 'ID ของ RFA Revision',
|
||||
shop_drawing_revision_id INT COMMENT 'ID ของ Shop Drawing Revision',
|
||||
PRIMARY KEY (
|
||||
rfarev_correspondence_id,
|
||||
rfa_revision_id,
|
||||
shop_drawing_revision_id
|
||||
),
|
||||
FOREIGN KEY (rfarev_correspondence_id) REFERENCES rfa_revisions (correspondence_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (rfa_revision_id) REFERENCES rfa_revisions (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions (id) ON DELETE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเชื่อมระหว่าง rfa_revisions (ที่เป็นประเภท DWG) กับ shop_drawing_revisions (M :N)';
|
||||
|
||||
@@ -1260,51 +1275,6 @@ CREATE TABLE backup_logs (
|
||||
error_message TEXT COMMENT 'ข้อความผิดพลาด (ถ้ามี)'
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางสำหรับบันทึกประวัติการสำรองข้อมูล';
|
||||
|
||||
-- 4.2 Virtual Columns for JSON Search (ตัวอย่างสำหรับ Correspondence)
|
||||
-- รองรับ: Backend Plan T2.1, Req 3.11.3
|
||||
-- เหตุผล: เพิ่มความเร็วในการ Search/Sort ข้อมูลที่อยู่ใน JSON details
|
||||
-- หมายเหตุ: ต้องมั่นใจว่า MariaDB เวอร์ชัน 11.8+ รองรับ Syntax นี้
|
||||
-- ตัวอย่าง: ดึง Project ID ที่อ้างอิงใน details ออกมาทำ Index
|
||||
ALTER TABLE correspondence_revisions
|
||||
ADD COLUMN v_ref_project_id INT GENERATED ALWAYS AS (
|
||||
JSON_UNQUOTE(
|
||||
JSON_EXTRACT(details, '$.projectId')
|
||||
)
|
||||
) VIRTUAL,
|
||||
ADD INDEX idx_corr_rev_v_project (v_ref_project_id);
|
||||
|
||||
-- ตัวอย่าง: ดึง Document Type ย่อยจาก details
|
||||
ALTER TABLE correspondence_revisions
|
||||
ADD COLUMN v_doc_subtype VARCHAR(50) GENERATED ALWAYS AS (
|
||||
JSON_UNQUOTE(JSON_EXTRACT(details, '$.subType'))
|
||||
) VIRTUAL,
|
||||
ADD INDEX idx_corr_rev_v_subtype (v_doc_subtype);
|
||||
|
||||
-- 2. ปรับปรุงตาราง correspondence_revisions
|
||||
-- เพิ่ม Virtual Columns และ Schema Version
|
||||
ALTER TABLE correspondence_revisions
|
||||
ADD COLUMN schema_version INT DEFAULT 1 COMMENT 'เวอร์ชันของ Schema ที่ใช้กับ details'
|
||||
AFTER details;
|
||||
|
||||
-- ทำแบบเดียวกันกับ RFA Revisions หากมีการเก็บ JSON details
|
||||
ALTER TABLE rfa_revisions
|
||||
ADD COLUMN details JSON NULL COMMENT 'RFA Specific Details'
|
||||
AFTER description;
|
||||
|
||||
ALTER TABLE rfa_revisions
|
||||
ADD COLUMN v_ref_drawing_count INT GENERATED ALWAYS AS (
|
||||
JSON_UNQUOTE(
|
||||
JSON_EXTRACT(details, '$.drawingCount')
|
||||
)
|
||||
) VIRTUAL;
|
||||
|
||||
ALTER TABLE rfa_revisions
|
||||
ADD COLUMN schema_version INT DEFAULT 1 COMMENT 'Version ของ JSON Schema'
|
||||
AFTER details;
|
||||
|
||||
CREATE INDEX idx_rfa_rev_v_drawing_count ON rfa_revisions (v_ref_drawing_count);
|
||||
|
||||
-- ... (ต่อท้ายไฟล์เดิม)
|
||||
-- ============================================================
|
||||
-- ส่วนที่ 11: Unified Workflow Engine (Phase 6A/Phase 3)
|
||||
-- ============================================================
|
||||
@@ -1390,6 +1360,13 @@ CREATE INDEX idx_wf_hist_user ON workflow_histories (action_by_user_id);
|
||||
-- =====================================================
|
||||
-- CREATE INDEXES
|
||||
-- =====================================================
|
||||
-- Indexes for correspondences
|
||||
CREATE INDEX idx_corr_type ON correspondences(correspondence_type_id);
|
||||
|
||||
CREATE INDEX idx_corr_project ON correspondences(project_id);
|
||||
|
||||
CREATE INDEX idx_rfa_rev_v_drawing_count ON rfa_revisions (v_ref_drawing_count);
|
||||
|
||||
-- Indexes for document_number_formats
|
||||
CREATE INDEX idx_document_number_formats_project ON document_number_formats (project_id);
|
||||
|
||||
@@ -1502,7 +1479,7 @@ SELECT c.id AS correspondence_id,
|
||||
cr.id AS revision_id,
|
||||
cr.revision_number,
|
||||
cr.revision_label,
|
||||
cr.title,
|
||||
cr.subject,
|
||||
cr.document_date,
|
||||
cr.issued_date,
|
||||
cr.received_date,
|
||||
@@ -1530,13 +1507,15 @@ WHERE cr.is_current = TRUE
|
||||
|
||||
-- View แสดง Revision "ปัจจุบัน" ของ rfa_revisions ทั้งหมด
|
||||
CREATE VIEW v_current_rfas AS
|
||||
SELECT r.id AS rfa_id,
|
||||
SELECT
|
||||
r.id AS rfa_id,
|
||||
r.rfa_type_id,
|
||||
rt.type_code AS rfa_type_code,
|
||||
rt.type_name_th AS rfa_type_name_th,
|
||||
rt.type_name_en AS rfa_type_name_en,
|
||||
rr.correspondence_id,
|
||||
c.correspondence_number,
|
||||
c.discipline_id, -- ✅ ดึงจาก Correspondences
|
||||
d.discipline_code, -- ✅ Join เพิ่มเพื่อแสดง code
|
||||
c.project_id,
|
||||
p.project_code,
|
||||
p.project_name,
|
||||
@@ -1545,7 +1524,7 @@ SELECT r.id AS rfa_id,
|
||||
rr.id AS revision_id,
|
||||
rr.revision_number,
|
||||
rr.revision_label,
|
||||
rr.title,
|
||||
rr.subject,
|
||||
rr.document_date,
|
||||
rr.issued_date,
|
||||
rr.received_date,
|
||||
@@ -1562,7 +1541,10 @@ SELECT r.id AS rfa_id,
|
||||
FROM rfas r
|
||||
INNER JOIN rfa_types rt ON r.rfa_type_id = rt.id
|
||||
INNER JOIN rfa_revisions rr ON r.id = rr.rfa_id
|
||||
INNER JOIN correspondences c ON rr.correspondence_id = c.id
|
||||
-- RFA uses shared primary key with correspondences (1:1)
|
||||
INNER JOIN correspondences c ON r.id = c.id
|
||||
-- [FIX 1] เพิ่มการ Join ตาราง disciplines
|
||||
LEFT JOIN disciplines d ON c.discipline_id = d.id
|
||||
INNER JOIN projects p ON c.project_id = p.id
|
||||
INNER JOIN organizations org ON c.originator_id = org.id
|
||||
INNER JOIN rfa_status_codes rsc ON rr.rfa_status_code_id = rsc.id
|
||||
@@ -1615,9 +1597,9 @@ SELECT -- 1. Workflow Instance Info
|
||||
ELSE 'N/A'
|
||||
END AS document_number,
|
||||
CASE
|
||||
WHEN wi.entity_type = 'rfa_revision' THEN rfa_rev.title
|
||||
WHEN wi.entity_type = 'rfa_revision' THEN rfa_rev.subject
|
||||
WHEN wi.entity_type = 'circulation' THEN circ.circulation_subject
|
||||
WHEN wi.entity_type = 'correspondence_revision' THEN corr_rev.title
|
||||
WHEN wi.entity_type = 'correspondence_revision' THEN corr_rev.subject
|
||||
ELSE 'Unknown Document'
|
||||
END AS subject,
|
||||
-- 4. Context Info (สำหรับ Filter สิทธิ์การมองเห็นที่ Backend)
|
||||
@@ -1628,7 +1610,7 @@ FROM workflow_instances wi
|
||||
JOIN workflow_definitions wd ON wi.definition_id = wd.id -- 5. Joins for RFA (ซับซ้อนหน่อยเพราะ RFA ผูกกับ Correspondence อีกที)
|
||||
LEFT JOIN rfa_revisions rfa_rev ON wi.entity_type = 'rfa_revision'
|
||||
AND wi.entity_id = CAST(rfa_rev.id AS CHAR)
|
||||
LEFT JOIN correspondences rfa_corr ON rfa_rev.correspondence_id = rfa_corr.id -- 6. Joins for Circulation
|
||||
LEFT JOIN correspondences rfa_corr ON rfa_rev.id = rfa_corr.id -- 6. Joins for Circulation
|
||||
LEFT JOIN circulations circ ON wi.entity_type = 'circulation'
|
||||
AND wi.entity_id = CAST(circ.id AS CHAR) -- 7. Joins for Correspondence
|
||||
LEFT JOIN correspondence_revisions corr_rev ON wi.entity_type = 'correspondence_revision'
|
||||
@@ -2902,7 +2902,7 @@ INSERT INTO `correspondence_revisions` (
|
||||
`revision_label`,
|
||||
`is_current`,
|
||||
`correspondence_status_id`,
|
||||
`title`,
|
||||
`subject`,
|
||||
`document_date`,
|
||||
`issued_date`,
|
||||
`received_date`,
|
||||
@@ -2937,23 +2937,21 @@ VALUES (
|
||||
INSERT INTO `rfas` (
|
||||
`id`,
|
||||
`rfa_type_id`,
|
||||
`discipline_id`,
|
||||
`created_at`,
|
||||
`created_by`,
|
||||
`deleted_at`
|
||||
)
|
||||
VALUES (1, 68, 75, '2025-12-06 05:40:02', 1, NULL);
|
||||
VALUES (2, 68, '2025-12-06 05:40:02', 1, NULL);
|
||||
|
||||
INSERT INTO `rfa_revisions` (
|
||||
`id`,
|
||||
`correspondence_id`,
|
||||
`rfa_id`,
|
||||
`revision_number`,
|
||||
`revision_label`,
|
||||
`is_current`,
|
||||
`rfa_status_code_id`,
|
||||
`rfa_approve_code_id`,
|
||||
`title`,
|
||||
`subject`,
|
||||
`document_date`,
|
||||
`issued_date`,
|
||||
`received_date`,
|
||||
@@ -2969,7 +2967,6 @@ VALUES (
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
'A',
|
||||
0,
|
||||
2,
|
||||
@@ -3223,3 +3220,4 @@ VALUES (
|
||||
NOW(),
|
||||
NOW()
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.5.1 - Permissions Seed Data (REORGANIZED)
|
||||
-- DMS v1.6.0 - Permissions Seed Data (REORGANIZED)
|
||||
-- File: specs/07-database/permissions-seed-data.sql
|
||||
-- Total Permissions: 85 (Reorganized with systematic ID allocation)
|
||||
-- Created: 2025-12-08
|
||||
-- Created: 2025-12-13
|
||||
-- ==========================================================
|
||||
-- Clear existing data
|
||||
TRUNCATE TABLE role_permissions;
|
||||
@@ -0,0 +1,62 @@
|
||||
# Schema v1.6.0 Migration & Document Number Fixes (2025-12-13)
|
||||
|
||||
## Task Summary
|
||||
This session focused on completing the migration to Schema v1.6.0 (Correspondence/RFA shared PK) and resolving critical bugs in the Document Numbering system.
|
||||
|
||||
### Status
|
||||
- **Schema Migration**: Completed (Backend & Frontend)
|
||||
- **Document Numbering**:
|
||||
- Preview Fixed (Recipient Code resolution)
|
||||
- Creation Fixed (Source data mapping)
|
||||
- Update Logic Fixed (Auto-regeneration on Draft edit)
|
||||
|
||||
## Walkthrough & Changes
|
||||
|
||||
### 1. Correspondence Module
|
||||
- **New Entity**: `CorrespondenceRecipient` to handle multiple recipients (TO/CC).
|
||||
- **Entity Update**: `Correspondence` now has a `recipients` relation.
|
||||
- **Entity Update**: `CorrespondenceRevision` renamed `title` to `subject`, added `body`, `remarks`, `dueDate`, `schemaVersion`.
|
||||
- **Service Update**: `create` method now saves recipients and maps new revision fields.
|
||||
- **DTO Update**: `CreateCorrespondenceDto` updated to support proper fields.
|
||||
|
||||
### 2. RFA Module
|
||||
- **Shared Primary Key**: `Rfa` entity now shares PK with `Correspondence`.
|
||||
- **Revision Update**: `RfaRevision` removed `correspondenceId` (access via `rfa.correspondence.id`), renamed `title` to `subject`, added new fields.
|
||||
- **Item Update**: `RfaItem` FK column renamed to `rfa_revision_id`.
|
||||
- **Service Update**: Only `RfaService` logic updated to handle shared PK and new field mappings. `findAll` query updated to join via `rfa.correspondence`.
|
||||
|
||||
### 3. Frontend Adaptation
|
||||
- **Type Definitions**: Updated `CorrespondenceRevision` and `RFA` types to match schema v1.6.0.
|
||||
- **Form Components**:
|
||||
- `CorrespondenceForm`: Renamed `title` to `subject`, added `body`, `remarks`, `dueDate`.
|
||||
- `RFAForm`: Renamed `title` to `subject`, added `body`, `remarks`.
|
||||
- **List & Detail Views**: Updated accessor keys (`title` -> `subject`) and added display sections for new fields (Body, Remarks) in Detail views.
|
||||
- **DTOs**: Updated `CreateCorrespondenceDto` and `CreateRFADto` to include new fields.
|
||||
|
||||
## Bug Fixes & Refinements (Session 2)
|
||||
|
||||
### Document Number Preview
|
||||
- **Issue**: Preview showed `--` for recipient code.
|
||||
- **Fix**:
|
||||
- Implemented `customTokens` support in `DocumentNumberingService`.
|
||||
- updated `CorrespondenceService.previewNextNumber` to manually resolve recipient code from `OrganizationRepository`.
|
||||
|
||||
### Correspondence Creation
|
||||
- **Issue**: Generated document number used incorrect placeholder.
|
||||
- **Fix**: Updated `create` method to extract recipient from `recipients` array instead of legacy `details` field.
|
||||
|
||||
### Edit Page Loading
|
||||
- **Issue**: "Failed to load" error on Edit page.
|
||||
- **Fix**: Corrected TypeORM relation path in `CorrespondenceService.findOne` from `recipients.organization` to properties `recipients.recipientOrganization`.
|
||||
|
||||
### Document Number Auto-Update
|
||||
- **Feature**: Automatically regenerate document number when editing a Draft.
|
||||
- **Implementation**: logic added to `update` method to re-calculate number if `type`, `discipline`, `project`, or `recipient` changes.
|
||||
|
||||
## Verification Results
|
||||
- **Backend Tests**: `correspondence.service.spec.ts` passed.
|
||||
- **Frontend Tests**: All 9 suites (113 tests) passed.
|
||||
- **Manual Verification**: Verified Preview, Creation, and Edit flows.
|
||||
|
||||
## Future Tasks
|
||||
- [ ] **Data Cleanup**: Migration script to fix existing document numbers with missing recipient codes (e.g., `คคง.--0001-2568` -> `คคง.-XYZ-0001-2568`).
|
||||
Reference in New Issue
Block a user