Files
lcbp3/docs/workflow.bak
2025-11-17 22:09:01 +07:00

193 lines
10 KiB
Plaintext

## Workflow ระดับ Project (correspondence_routing_steps, technical_doc_workflows): คือ "การเดินทาง" ของเอกสาร ระหว่างองค์กร (เช่น จากผู้รับเหมา -> ไปยังที่ปรึกษา -> ไปยังเจ้าของโครงการ)
## Workflow ระดับ Organization (Circulation): คือ "การแจกจ่าย" เอกสาร ภายในองค์กรของคุณเอง หลังจากที่คุณได้รับเอกสารนั้นมาแล้ว (เช่น เอกสารมาถึง Document Control แล้วต้องส่งต่อให้ใครบ้างในบริษัท)
circulation_templates: ตารางหลักสำหรับเก็บชื่อแม่แบบ
circulation_template_assignees: ตารางสำหรับเก็บ "รายชื่อผู้รับผิดชอบ" ที่ถูกกำหนดไว้ในแต่ละแม่แบบ
Workflow การทำงานใน Frontend
1. หน้า Admin Panel: จะต้องมีเมนูใหม่สำหรับให้ Admin หรือผู้มีสิทธิ์ เข้าไป สร้าง/แก้ไข/ลบ แม่แบบใบเวียน (circulation_templates) สำหรับองค์กรของตนเองได้
2. หน้าที่สร้างใบเวียน (Create Circulation Dialog):
* ที่ด้านบนสุดของฟอร์ม จะมี Dropdown ใหม่ ปรากฏขึ้นมา เขียนว่า "ใช้แม่แบบ (Use Template)"
* ใน Dropdown นี้ จะแสดงรายชื่อแม่แบบทั้งหมดที่องค์กรนั้นๆ สร้างไว้
* เมื่อผู้ใช้เลือกแม่แบบ:
** ระบบจะยิง API ไปดึงรายชื่อผู้รับผิดชอบจากตาราง circulation_template_assignees
** จากนั้น JavaScript จะทำการเติมข้อมูล (Auto-populate) ลงในช่อง "Main", "Action", และ "Information" ให้โดยอัตโนมัติ
* ผู้ใช้ยังสามารถ แก้ไข/เพิ่มเติม/ลบ รายชื่อผู้รับผิดชอบได้ตามต้องการ ก่อนที่จะกดสร้างใบเวียนจริง
การจัดการข้อมูล JSON จะเกิดขึ้นใน 3 ส่วนหลักๆ คือ Backend, Frontend, และ Database ครับ
## 1. การจัดการในฝั่ง Backend (NestJS)
นี่คือส่วนที่ทำหน้าที่หลักในการสร้างและอ่านข้อมูล JSON อย่างเป็นระบบและปลอดภัย
1.1 การแก้ไข Entity
เราจะแก้ไข Correspondence entity โดยเพิ่มคอลัมน์ details เข้าไป และลบ Entity ย่อยๆ ที่ไม่ใช้ออก
src/correspondences/entities/correspondence.entity.ts
@Entity('correspondences')
export class Correspondence {
// ... (คอลัมน์เดิมทั้งหมด: id, document_number, title, etc.)
@Column({
type: 'json', // ◀️ กำหนดประเภทข้อมูลเป็น JSON
nullable: true,
comment: 'เก็บข้อมูลเฉพาะของเอกสารแต่ละประเภทในรูปแบบ JSON'
})
details: any; // ◀️ ใช้ type 'any' หรือสร้าง Interface/Type ที่ซับซ้อนขึ้น
}
1.2 การสร้าง DTOs สำหรับแต่ละประเภทเอกสาร
เพื่อรักษาความถูกต้องของข้อมูล (Validation) เราจะสร้าง DTO แยกสำหรับเอกสารแต่ละประเภท
ตัวอย่าง src/correspondences/dto/create-letter.dto.ts:
TypeScript
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
// DTO สำหรับข้อมูลใน details ของ Letter
class LetterDetailsDto {
@ApiProperty()
@IsString()
@IsNotEmpty()
attention_to: string;
@ApiProperty()
@IsString()
@IsNotEmpty()
signatory_name: string;
}
// DTO หลักสำหรับสร้าง Letter
export class CreateLetterDto {
@ApiProperty({ description: "ข้อมูลพื้นฐานของเอกสาร" })
@ValidateNested() // ◀️ บอกให้ class-validator ตรวจสอบ object ข้างในด้วย
@Type(() => CreateCorrespondenceDto) // ◀️ ใช้ DTO พื้นฐานร่วมกัน
base_data: CreateCorrespondenceDto;
@ApiProperty({ description: "ข้อมูลเฉพาะของ Letter" })
@ValidateNested()
@Type(() => LetterDetailsDto)
details: LetterDetailsDto;
}
1.3 การสร้าง API Endpoint และ Logic ใน Service
เราจะสร้าง Endpoint แยกสำหรับสร้างเอกสารแต่ละประเภทเพื่อความชัดเจน
ใน CorrespondencesController:
TypeScript
@Post('letter')
@ApiOperation({ summary: 'Create a new Letter' })
createLetter(@Body() createLetterDto: CreateLetterDto, @Req() req: Request) {
const user = req.user as any;
return this.correspondencesService.createTypedCorrespondence(
createLetterDto.base_data,
createLetterDto.details,
user
);
}
ใน CorrespondencesService:
TypeScript
async createTypedCorrespondence(baseData: CreateCorrespondenceDto, details: any, user: User): Promise<Correspondence> {
// ... (โค้ดตรวจสอบสิทธิ์เหมือนเดิม)
const newCorrespondence = this.correspondenceRepository.create({
...baseData, // ข้อมูลพื้นฐาน (เลขที่เอกสาร, ชื่อเรื่อง, etc.)
details: details, // ◀️ นำ object ของ details มาใส่ในคอลัมน์ JSON โดยตรง
created_by_user_id: user.user_id,
originator_org_id: user.org_id,
status_id: 1, // 'Draft'
});
return this.correspondenceRepository.save(newCorrespondence);
}
## 2. การจัดการในฝั่ง Frontend (Next.js / React)
Frontend จะทำหน้าที่แสดงฟอร์มที่ถูกต้องตามประเภทเอกสาร และส่งข้อมูลในรูปแบบที่ Backend ต้องการ
2.1 การแสดงฟอร์มแบบไดนามิก (Dynamic Forms)
ในหน้า "Create Correspondence" เมื่อผู้ใช้เลือกประเภทเอกสารจาก Dropdown เราจะใช้ State เพื่อแสดงฟอร์มที่ถูกต้อง
TypeScript
const [docType, setDocType] = useState('LETTER');
// ...
const renderDetailFields = () => {
switch (docType) {
case 'LETTER':
return (
<>
{/* ฟิลด์สำหรับ Attention To, Signatory */}
</>
);
case 'RFI':
return (
<>
{/* ฟิลด์สำหรับ Question, Required By Date */}
</>
);
default:
return null;
}
}
return (
<form>
{/* ฟิลด์พื้นฐาน (Document Number, Title) */}
{/* Dropdown เลือกประเภทเอกสาร */}
{renderDetailFields()} {/* ◀️ แสดงฟิลด์เฉพาะทางที่นี่ */}
</form>
);
2.2 การส่งข้อมูล
เมื่อผู้ใช้กด Submit เราจะรวบรวมข้อมูลจากฟอร์มให้เป็นโครงสร้าง JSON ที่ Backend ต้องการ
JavaScript
const handleSubmit = () => {
// รวบรวมข้อมูลพื้นฐาน
const base_data = {
document_number: '...',
title: '...',
// ...
};
// รวบรวมข้อมูลเฉพาะทาง
const details = {
attention_to: '...',
signatory_name: '...',
};
// ส่งข้อมูลไปที่ API Endpoint ที่ถูกต้อง
fetch('/api/correspondences/letter', {
method: 'POST',
body: JSON.stringify({ base_data, details }),
});
}
## 3. การจัดการในระดับฐานข้อมูล (MariaDB)
แม้ว่าเราจะไม่ค่อยได้ Query ข้อมูล JSON โดยตรงผ่าน SQL บ่อยนัก แต่ก็สามารถทำได้เมื่อจำเป็น (เช่น สำหรับการทำรายงานที่ซับซ้อน)
ตัวอย่าง: ค้นหาเอกสาร Letter ทั้งหมดที่ส่งถึง "Mr. John Doe"
SQL
SELECT
corr_id,
document_number,
details
FROM
correspondences
WHERE
type_id = (SELECT type_id FROM correspondence_types WHERE type_code = 'LETTER') -- กรองเฉพาะ Letter
AND JSON_VALUE(details, '$.attention_to') = 'Mr. John Doe'; -- ◀️ ค้นหาค่าใน JSON
การจัดการข้อมูลด้วยวิธีนี้จะทำให้ระบบของคุณมีความ