251213:1509 Docunment Number Businee Rule not correct
Some checks failed
Spec Validation / validate-markdown (push) Has been cancelled
Spec Validation / validate-diagrams (push) Has been cancelled
Spec Validation / check-todos (push) Has been cancelled

This commit is contained in:
admin
2025-12-13 15:09:01 +07:00
parent d964546c8d
commit ec35521258
64 changed files with 11956 additions and 223 deletions

View File

@@ -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 |

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
```

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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 (องค์กร, โครงการ, สัญญา)**

View File

@@ -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'

View File

@@ -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()
);

View File

@@ -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;

View File

@@ -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`).