251118:1300 ปรับปรุง Project requirement

This commit is contained in:
admin
2025-11-18 13:01:23 +07:00
parent 693dd7f074
commit 7c1c5e3c99
20 changed files with 15426 additions and 13926 deletions

483
Documnets/0.html Normal file
View File

@@ -0,0 +1,483 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LCBP3-DMS V1.4.1 Project Infographic</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f4f7f6;
}
.chart-container {
position: relative;
width: 100%;
max-width: 600px;
margin-left: auto;
margin-right: auto;
height: 350px;
max-height: 400px;
}
@media (max-width: 768px) {
.chart-container {
height: 300px;
max-height: 350px;
}
}
.stat-card {
background-color: #004AAD;
color: white;
border-left: 5px solid #FFC107;
}
.kpi-value {
font-size: 2.5rem;
line-height: 1.2;
}
.section-card {
background-color: white;
border-radius: 0.75rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
margin-bottom: 2rem;
overflow: hidden;
}
.section-header {
background-color: #002F6C;
color: white;
padding: 1.5rem;
}
.section-content {
padding: 1.5rem;
}
.flow-box {
border: 2px solid #007BFF;
background-color: #B3D7FF;
color: #002F6C;
padding: 0.75rem;
border-radius: 0.5rem;
text-align: center;
font-weight: 600;
box-shadow: 0 4px 6px rgba(0, 75, 173, 0.1);
}
.flow-arrow {
font-size: 2rem;
color: #004AAD;
align-self: center;
margin: 0 0.5rem;
}
.timeline-item {
position: relative;
padding-left: 2.5rem;
padding-bottom: 2rem;
border-left: 4px solid #007BFF;
}
.timeline-dot {
position: absolute;
left: -11px;
top: 0;
height: 20px;
width: 20px;
background-color: #FFC107;
border: 3px solid #004AAD;
border-radius: 50%;
}
.rbac-level {
border: 2px dashed;
padding: 1rem;
border-radius: 0.5rem;
margin-top: 1rem;
text-align: center;
}
</style>
</head>
<body class="antialiased">
<header class="bg-white shadow-md sticky top-0 z-50">
<nav class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<div class="flex-shrink-0 flex items-center">
<span class="text-2xl font-bold text-[#002F6C]">LCBP3-DMS</span>
<span class="ml-2 text-xl font-semibold text-[#007BFF]">V1.4.1 Project Overview</span>
</div>
<div class="hidden md:block">
<div class="ml-10 flex items-baseline space-x-4">
<a href="#kpi" class="text-gray-600 hover:text-[#007BFF] px-3 py-2 rounded-md text-sm font-medium">KPIs</a>
<a href="#architecture" class="text-gray-600 hover:text-[#007BFF] px-3 py-2 rounded-md text-sm font-medium">Architecture</a>
<a href="#roadmap" class="text-gray-600 hover:text-[#007BFF] px-3 py-2 rounded-md text-sm font-medium">Roadmap</a>
<a href="#security" class="text-gray-600 hover:text-[#007BFF] px-3 py-2 rounded-md text-sm font-medium">Security</a>
<a href="#stats" class="text-gray-600 hover:text-[#007BFF] px-3 py-2 rounded-md text-sm font-medium">Stats</a>
</div>
</div>
</div>
</nav>
</header>
<main class="max-w-7xl mx-auto p-4 md:p-8 mt-8">
<section id="intro" class="section-card">
<div class="section-header">
<h1 class="text-3xl font-bold">Project Overview: LCBP3 Document Management System (V1.4.1)</h1>
</div>
<div class="section-content">
<p class="text-lg text-gray-700">
นี่คือภาพรวมของระบบบริหารจัดการเอกสารโครงการ (DMS) V1.4.1
ที่กำลังพัฒนาสำหรับโครงการแหลมฉบังเฟส 3 (LCBP3)
เป้าหมายหลักคือการสร้างเว็บแอปพลิเคชั่นที่ทันสมัย ปลอดภัย
และมีประสิทธิภาพสูงเพื่อจัดการและควบคุมการสื่อสารด้วยเอกสารที่ซับซ้อน
ลดการใช้กระดาษ และเพิ่มความสะดวกในการทำงานร่วมกันระหว่างองค์กร
</p>
</div>
</section>
<section id="kpi" class="mb-8">
<h2 class="text-3xl font-bold text-gray-800 mb-6">Key Performance Indicators (KPIs)</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="stat-card p-6 rounded-lg shadow-lg">
<h3 class="text-lg font-semibold uppercase tracking-wider">API Response Time</h3>
<p class="kpi-value font-bold mt-2">&lt; 200<span class="text-xl">ms</span></p>
<p class="text-sm opacity-90">(90th Percentile)</p>
</div>
<div class="stat-card p-6 rounded-lg shadow-lg">
<h3 class="text-lg font-semibold uppercase tracking-wider">Search Performance</h3>
<p class="kpi-value font-bold mt-2">&lt; 500<span class="text-xl">ms</span></p>
<p class="text-sm opacity-90">(Elasticsearch)</p>
</div>
<div class="stat-card p-6 rounded-lg shadow-lg">
<h3 class="text-lg font-semibold uppercase tracking-wider">File Upload (50MB)</h3>
<p class="kpi-value font-bold mt-2">&lt; 30<span class="text-xl">s</span></p>
<p class="text-sm opacity-90">(Inc. Virus Scan)</p>
</div>
<div class="stat-card p-6 rounded-lg shadow-lg">
<h3 class="text-lg font-semibold uppercase tracking-wider">Cache Hit Ratio</h3>
<p class="kpi-value font-bold mt-2">&gt; 80<span class="text-xl">%</span></p>
<p class="text-sm opacity-90">(Redis)</p>
</div>
</div>
</section>
<section id="architecture" class="section-card">
<div class="section-header">
<h2 class="text-3xl font-bold">System Architecture & Technology Stack</h2>
</div>
<div class="section-content">
<p class="text-lg text-gray-700 mb-6">
สถาปัตยกรรมระบบเป็นแบบ API-First ที่ทำงานบน QNAP Container Station (Docker)
โดยมีการแบ่งส่วนบริการ (Services) อย่างชัดเจน
เพื่อความสะดวกในการจัดการและบำรุงรักษา
</p>
<div class="border-2 border-gray-200 rounded-lg p-4">
<div class="flex flex-col md:flex-row md:items-center justify-center space-y-4 md:space-y-0 md:space-x-4">
<div class="flow-box bg-[#FFC107] border-[#004AAD]">Internet User</div>
<div class="flow-arrow hidden md:block"></div>
<div class="flow-arrow md:hidden text-center"></div>
<div class="flow-box">QNAP (WAN)</div>
<div class="flow-arrow hidden md:block"></div>
<div class="flow-arrow md:hidden text-center"></div>
<div class="flow-box bg-green-100 border-green-500 text-green-800">Nginx Proxy Manager</div>
</div>
<div class="border-t-2 border-dashed border-gray-400 my-6"></div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 class="text-xl font-semibold text-center text-[#002F6C] mb-4">Public Facing Services (ผ่าน NPM)</h3>
<div class="space-y-3">
<div class="flow-box">Frontend (Next.js)</div>
<div class="flow-box">Backend (NestJS)</div>
<div class="flow-box">Gitea (Git)</div>
<div class="flow-box">n8n (Automation)</div>
</div>
</div>
<div>
<h3 class="text-xl font-semibold text-center text-[#002F6C] mb-4">Internal Services (Backend เรียกใช้)</h3>
<div class="space-y-3">
<div class="flow-box bg-gray-200 border-gray-400 text-gray-800">MariaDB (Database)</div>
<div class="flow-box bg-gray-200 border-gray-400 text-gray-800">Redis (Cache)</div>
<div class="flow-box bg-gray-200 border-gray-400 text-gray-800">Elasticsearch (Search)</div>
<div class="flow-box bg-gray-200 border-gray-400 text-gray-800">ClamAV (Virus Scan)</div>
</div>
</div>
</div>
</div>
</div>
</section>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<section id="roadmap" class="section-card">
<div class="section-header">
<h2 class="text-3xl font-bold">Development Roadmap</h2>
</div>
<div class="section-content">
<p class="text-lg text-gray-700 mb-6">
แผนการพัฒนาถูกแบ่งออกเป็น Phase (Backend) และ Sprints (Frontend)
เพื่อให้สามารถส่งมอบงานได้อย่างต่อเนื่องและเป็นระบบ
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 class="text-xl font-semibold text-[#002F6C] mb-4">Backend (NestJS)</h3>
<div class="relative">
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Phase 0-1: Setup & Core</h4>
<p class="text-sm text-gray-600">Infrastructure, DB Schema, ORM</p>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Phase 2-3: Auth & RBAC</h4>
<p class="text-sm text-gray-600">JWT, Passport, CASL 4-Level</p>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Phase 4-5: Core Features</h4>
<p class="text-sm text-gray-600">Document Upload, RFA Workflow</p>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Phase 6-8: Integration & Deploy</h4>
<p class="text-sm text-gray-600">Search, Cache, Notification, Deploy</p>
</div>
</div>
</div>
<div>
<h3 class="text-xl font-semibold text-[#002F6C] mb-4">Frontend (Next.js)</h3>
<div class="relative">
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Sprint 1-2: Setup & Auth</h4>
<p class="text-sm text-gray-600">shadcn/ui, NextAuth, Layout</p>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Sprint 3: Dashboard</h4>
<p class="text-sm text-gray-600">Charts (Recharts), KPIs</p>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Sprint 4-5: Document Module</h4>
<p class="text-sm text-gray-600">TanStack Table, Upload, Search</p>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<h4 class="font-bold">Sprint 6-7: Workflow & Deploy</h4>
<p class="text-sm text-gray-600">RFA Forms, Testing, Deploy</p>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="security" class="section-card">
<div class="section-header">
<h2 class="text-3xl font-bold">Feature Focus: 4-Level RBAC</h2>
</div>
<div class="section-content">
<p class="text-lg text-gray-700 mb-6">
ระบบควบคุมสิทธิ์ (RBAC) เป็นหัวใจสำคัญของความปลอดภัย
โดยใช้สถาปัตยกรรม 4 ระดับ (4-Level) เพื่อการควบคุมที่ละเอียดสูงสุด
</p>
<div class="rbac-level border-[#002F6C]">
<span class="font-bold text-lg text-[#002F6C]">🌍 Level 1: Global</span>
<p class="text-sm text-gray-600">(Super Admin, System Settings)</p>
<div class="rbac-level border-[#004AAD]">
<span class="font-bold text-lg text-[#004AAD]">🏢 Level 2: Organization</span>
<p class="text-sm text-gray-600">(Org Admin, Manage Users & Projects)</p>
<div class="rbac-level border-[#007BFF]">
<span class="font-bold text-lg text-[#007BFF]">🏗️ Level 3: Project</span>
<p class="text-sm text-gray-600">(Project Manager, View All Project Docs)</p>
<div class="rbac-level border-[#B3D7FF]">
<span class="font-bold text-lg text-[#002F6C]">📄 Level 4: Contract</span>
<p class="text-sm text-gray-600">(Contractor, Access Own Contract Docs Only)</p>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<section id="stats" class="section-card">
<div class="section-header">
<h2 class="text-3xl font-bold">Document Statistics (Mockup Data)</h2>
</div>
<div class="section-content">
<p class="text-lg text-gray-700 mb-6">
Dashboard จะแสดงสถิติเอกสารแบบ Real-time
(อ้างอิงจาก View: `v_document_statistics` ในฐานข้อมูล)
เพื่อช่วยในการติดตามและบริหารจัดการโครงการ
</p>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div>
<h3 class="text-xl font-semibold text-center text-[#002F6C] mb-4">เอกสารตามประเภท (By Type)</h3>
<p class="text-sm text-center text-gray-600 mb-4">
แสดงจำนวนเอกสารทั้งหมดโดยแบ่งตามประเภทหลัก
ช่วยให้เห็นภาพรวมของเอกสารในระบบ
</p>
<div class="chart-container">
<canvas id="docTypeChart"></canvas>
</div>
</div>
<div>
<h3 class="text-xl font-semibold text-center text-[#002F6C] mb-4">สถานะเอกสาร (By Status)</h3>
<p class="text-sm text-center text-gray-600 mb-4">
แสดงสัดส่วนของสถานะเอกสารในปัจจุบัน
(เช่น ร่าง, รออนุมัติ, อนุมัติแล้ว) เพื่อติดตาม Workflow
</p>
<div class="chart-container">
<canvas id="docStatusChart"></canvas>
</div>
</div>
</div>
</div>
</section>
</main>
<footer class="text-center p-6 text-gray-600 text-sm">
LCBP3-DMS V1.4.1 Infographic | Generated on: <span id="generation-date"></span>
</footer>
<script>
document.getElementById('generation-date').textContent = new Date().toLocaleDateString('en-US', {
year: 'numeric', month: 'long', day: 'numeric'
});
const wrapLabel = (label) => {
const maxChars = 16;
if (typeof label === 'string' && label.length > maxChars) {
const words = label.split(' ');
const lines = [];
let currentLine = '';
for (const word of words) {
if ((currentLine + word).length > maxChars) {
lines.push(currentLine.trim());
currentLine = '';
}
currentLine += word + ' ';
}
lines.push(currentLine.trim());
return lines;
}
return label;
};
const tooltipTitleCallback = (tooltipItems) => {
const item = tooltipItems[0];
let label = item.chart.data.labels[item.dataIndex];
if (Array.isArray(label)) {
return label.join(' ');
} else {
return label;
}
};
const sharedChartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
title: tooltipTitleCallback
}
},
legend: {
labels: {
font: {
family: "'Inter', sans-serif"
}
}
}
},
scales: {
x: {
ticks: {
font: {
family: "'Inter', sans-serif"
}
}
},
y: {
ticks: {
font: {
family: "'Inter', sans-serif"
}
}
}
}
};
const docTypeCtx = document.getElementById('docTypeChart').getContext('2d');
const docTypeChart = new Chart(docTypeCtx, {
type: 'bar',
data: {
labels: [
'Correspondence (RFA)',
'Shop Drawing',
'Contract Drawing',
wrapLabel('Technical Specification'),
'Method Statement'
],
datasets: [{
label: 'จำนวนเอกสาร',
data: [120, 190, 75, 45, 88],
backgroundColor: [
'#004AAD',
'#007BFF',
'#B3D7FF',
'#002F6C',
'#FFC107'
],
borderColor: '#ffffff',
borderWidth: 1
}]
},
options: { ...sharedChartOptions }
});
const docStatusCtx = document.getElementById('docStatusChart').getContext('2d');
const docStatusChart = new Chart(docStatusCtx, {
type: 'doughnut',
data: {
labels: ['Draft', 'Pending Approval', 'Approved', 'Rejected'],
datasets: [{
label: 'สถานะเอกสาร',
data: [30, 45, 150, 15],
backgroundColor: [
'#B3D7FF',
'#FFC107',
'#007BFF',
'#D9363E'
],
hoverOffset: 4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
title: tooltipTitleCallback
}
},
legend: {
position: 'bottom',
labels: {
font: {
family: "'Inter', sans-serif"
}
}
}
}
}
});
</script>
</body>
</html>

220
Documnets/Git_command.md Normal file
View File

@@ -0,0 +1,220 @@
# **คำสั่งตั้งค่า Gitea ใหม่ทั้งหมด + คำสั่งใช้งานประจำวัน / แก้ปัญหา / branch”**
---
📘 Git + Gitea (QNAP / Container Station) Cheat Sheet
คู่มือนี้รวบรวม:
- คำสั่งตั้งค่า Gitea ใหม่ทั้งหมด
- คำสั่งใช้งาน Git ประจำวัน
- การแก้ไขปัญหา repository
- การทำงานกับ branch
- การ reset / clone / merge / rebase
---
## 🧩 SECTION 1 การตั้งค่า Gitea ใหม่ทั้งหมด
🔹 1) เคลียร์ host key เดิม ใช้เมื่อ Gitea ถูก reset ใหม่ หรือ IP / key เปลี่ยน
```bash
ssh-keygen -R "[git.np-dms.work]:2222"
```
🔹 2) เชื่อมต่อครั้งแรก (จะมีคำถาม fingerprint)
```bash
ssh -T git@git.np-dms.work -p 2222
```
🔹 3) แสดง SSH public key เพื่อเพิ่มใน Gitea
```bash
cat /root/.ssh/id_ed25519.pub
cat /root/.ssh/id_rsa.pub
```
🔹 4) เพิ่ม remote ใหม่ (หากยังไม่ได้เพิ่ม)
```bash
git remote add origin ssh://git@git.np-dms.work:2222/np-dms/lcbp3.git
```
🔹 5) ลบ remote เดิมหากผิด
```bash
git remote remove origin
```
🔹 6) Push ครั้งแรกหลังตั้งค่า
```bash
git push -u origin main
```
🔹 7) Clone repo ใหม่ทั้งหมด
```bash
git clone ssh://git@git.np-dms.work:2222/np-dms/lcbp3.git
```
---
## 🧩 SECTION 2 คำสั่ง Git ใช้งานประจำวัน
🟦 ตรวจสอบสถานะงาน
```bash
git status
```
🟦 ดูว่าแก้ไฟล์อะไรไป
```bash
git diff
```
🟦 เพิ่มไฟล์ทั้งหมด
```bash
git add .
```
🟦 Commit การแก้ไข
```bash
git commit -m "message"
```
🟦 Push
```bash
git push
```
🟦 Pull (ดึงงานล่าสุด)
```bash
git pull
```
---
## 🧩 SECTION 3 ทำงานกับ Branch
### ดู branch ทั้งหมด
```bash
git branch
```
### สร้าง branch ใหม่
```bash
git checkout -b feature/login-page
```
### สลับ branch
```bash
git checkout main
```
### ส่ง branch ขึ้น Gitea
```bash
git push -u origin feature/login-page
```
### ลบ branch ในเครื่อง
```bash
git branch -d feature/login-page
```
### ลบ branch บน Gitea
```bash
git push origin --delete feature/login-page
```
### Merge branch → main
```bash
git checkout main
git pull
git merge feature/login-page
git push
```
### Rebase เพื่อให้ history สวย
```bash
git checkout feature/login-page
git rebase main
git checkout main
git merge feature/login-page
git push
```
---
## 🧩 SECTION 4 แก้ไขปัญหา Repo
🔴 (1) Reset repo ทั้งหมดให้เหมือน remote
⚠ ใช้เมื่อไฟล์ในเครื่องพัง หรือแก้จนเละ
```bash
git fetch --all
git reset --hard origin/main
```
🔴 (2) แก้ปัญหา conflict ตอน pull
```bash
git pull --rebase
```
🔴 (3) ดู remote ว่าชี้ไปทางไหน
```bash
git remote -v
```
🔴 (4) เปลี่ยน remote ใหม่
```bash
git remote remove origin
git remote add origin ssh://git@git.np-dms.work:2222/np-dms/lcbp3.git
```
🔴 (5) Commit message ผิด แก้ใหม่
```bash
git commit --amend
```
🔴 (6) ย้อน commit ล่าสุด (ไม่ลบไฟล์)
```bash
git reset --soft HEAD~1
```
🔴 (7) ดู log แบบสรุป
```bash
git log --oneline --graph
```
🔴 (8) Clone repo ใหม่ทั้งหมด (เมื่อพังหนัก)
```bash
rm -rf lcbp3
git clone ssh://git@git.np-dms.work:2222/np-dms/lcbp3.git
```
---
## 📌 END
```

View File

@@ -0,0 +1,91 @@
# การติดตั้ง Gitea ใน Docker
* user id ของ gites:
* uid=1000(git) gid=1000(git) groups=1000(git)
## กำหนดสิทธิ
```bash
chown -R 1000:1000 /share/Container/gitea/
[/share/Container/git] # ls -l /share/Container/gitea/etc/app.ini
[/share/Container/git] # setfacl -R -m u:1000:rwx /share/Container/gitea/
[/share/Container/git] # setfacl -R -m u:70:rwx /share/Container/git/postgres/
getfacl /share/Container/git/etc/app.ini
chown -R 1000:1000 /share/Container/gitea/
ล้าง
setfacl -R -b /share/Container/gitea/
chgrp -R administrators /share/Container/gitea/
chown -R 1000:1000 /share/Container/gitea/etc /share/Container/gitea/lib /share/Container/gitea/backup
setfacl -m u:1000:rwx -m g:1000:rwx /share/Container/gitea/etc /share/Container/gitea/lib /share/Container/gitea/backup
```
## Docker file
```yml
# File: share/Container/git/docker-compose.yml
# DMS Container v1_4_1 : แยก service และ folder, Application name: git, Servive:gitea
networks:
lcbp3:
external: true
giteanet:
external: true
name: gitnet
services:
gitea:
image: gitea/gitea:latest-rootless
container_name: gitea
restart: always
stdin_open: true
tty: true
environment:
# ---- File ownership in QNAP ----
USER_UID: "1000"
USER_GID: "1000"
TZ: Asia/Bangkok
# ---- Server / Reverse proxy (NPM) ----
GITEA__server__ROOT_URL: https://git.np-dms.work/
GITEA__server__DOMAIN: git.np-dms.work
GITEA__server__SSH_DOMAIN: git.np-dms.work
GITEA__server__START_SSH_SERVER: "true"
GITEA__server__SSH_PORT: "22"
GITEA__server__SSH_LISTEN_PORT: "22"
GITEA__server__LFS_START_SERVER: "true"
GITEA__server__HTTP_ADDR: "0.0.0.0"
GITEA__server__HTTP_PORT: "3000"
GITEA__server__TRUSTED_PROXIES: "127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
# --- การตั้งค่าฐานข้อมูล
GITEA__database__DB_TYPE: mysql
GITEA__database__HOST: mariadb:3306
GITEA__database__NAME: "gitea"
GITEA__database__USER: "gitea"
GITEA__database__PASSWD: "Center#2025"
# --- repos
GITEA__repository__ROOT: /var/lib/gitea/git/repositories
DISABLE_HTTP_GIT: "false"
ENABLE_BASIC_AUTHENTICATION: "true"
# --- Enable Package Registry ---
GITEA__packages__ENABLED: "true"
GITEA__packages__REGISTRY__ENABLED: "true"
GITEA__packages__REGISTRY__STORAGE_TYPE: local
GITEA__packages__REGISTRY__STORAGE_PATH: /data/registry
# Optional: lock install after setup (เปลี่ยนเป็น true เมื่อจบ onboarding)
GITEA__security__INSTALL_LOCK: "true"
volumes:
- /share/Container/gitea/backup:/backup
- /share/Container/gitea/etc:/etc/gitea
- /share/Container/gitea/lib:/var/lib/gitea
# ให้ repo root ใช้จาก /share/dms-data/gitea_repos
- /share/dms-data/gitea_repos:/var/lib/gitea/git/repositories
- /share/dms-data/gitea_registry:/data/registry
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3003:3000" # HTTP (ไปหลัง NPM)
- "2222:22" # SSH สำหรับ git clone/push
networks:
- lcbp3
- giteanet
```

View File

@@ -0,0 +1,138 @@
# การติดตั้ง MAriaDB และ PHPMyAdmin ใน Docker
* user id ของ mariadb:
* uid=0(root) gid=0(root) groups=0(root)
## กำหนดสิทธิ
```bash
chown -R 999:999 /share/Container/mariadb/init
chmod 755 /share/Container/mariadb/init
setfacl -R -m u:999:r-x /share/Container/mariadb/init
setfacl -R -d -m u:999:r-x /share/Container/mariadb/init
chown -R 33:33 /share/Container/pma/tmp
chmod 755 /share/Container/pma/tmp
setfacl -R -m u:33:rwx /share/Container/pma/tmp
setfacl -R -d -m u:33:rwx /share/Container/pma/tmp
chown -R 33:33 /share/dms-data/logs/pma
chmod 755 /share/dms-data/logs/pma
setfacl -R -m u:33:rwx /share/dms-data/logs/pma
setfacl -R -d -m u:33:rwx /share/dms-data/logs/pma
setfacl -R -m u:1000:rwx /share/Container/gitea
setfacl -R -m u:1000:rwx /share/dms-data/gitea_repos
setfacl -R -m u:1000:rwx /share/dms-data/gitea_registry
```
## เพิ่ม database & user สำหรับ Nginx Proxy Manager (NPM)
```bash
docker exec -it mariadb mysql -u root -p
CREATE DATABASE npm;
CREATE USER 'npm'@'%' IDENTIFIED BY 'npm';
GRANT ALL PRIVILEGES ON npm.* TO 'npm'@'%';
FLUSH PRIVILEGES;
```
## เพิ่ม database & user สำหรับ Gitea
```bash
docker exec -it mariadb mysql -u root -p
CREATE DATABASE gitea CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
CREATE USER 'gitea'@'%' IDENTIFIED BY 'Center#2025';
GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'%';
FLUSH PRIVILEGES;
```
## Docker file
```yml
# File: share/Container/mariadb/docker-compose.yml
# DMS Container v1_4_1 : แยก service และ folder,Application name: lcbp3-db, Servive: mariadb, pma
x-restart: &restart_policy
restart: unless-stopped
x-logging: &default_logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
services:
mariadb:
<<: [*restart_policy, *default_logging]
image: mariadb:11.8
container_name: mariadb
stdin_open: true
tty: true
deploy:
resources:
limits:
cpus: "2.0"
memory: 4G
reservations:
cpus: "0.5"
memory: 1G
environment:
MYSQL_ROOT_PASSWORD: "Center#2025"
MYSQL_DATABASE: "lcbp3"
MYSQL_USER: "center"
MYSQL_PASSWORD: "Center#2025"
TZ: "Asia/Bangkok"
ports:
- "3306:3306"
volumes:
- "/share/Container/mariadb/data:/var/lib/mysql"
- "/share/Container/mariadb/my.cnf:/etc/mysql/conf.d/my.cnf:ro"
- "/share/Container/mariadb/init:/docker-entrypoint-initdb.d:ro"
- "/share/dms-data/mariadb/backup:/backup"
healthcheck:
test:
["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -pCenter#2025 || exit 1"]
interval: 10s
timeout: 5s
retries: 15
networks:
lcbp3: {}
pma:
<<: [*restart_policy, *default_logging]
image: phpmyadmin:5-apache
container_name: pma
stdin_open: true
tty: true
deploy:
resources:
limits:
cpus: "0.25"
memory: 256M
environment:
TZ: "Asia/Bangkok"
PMA_HOST: "mariadb"
PMA_PORT: "3306"
PMA_ABSOLUTE_URI: "https://pma.np-dms.work/"
UPLOAD_LIMIT: "1G"
MEMORY_LIMIT: "512M"
ports:
- "89:80"
# expose:
# - "80"
volumes:
- "/share/Container/pma/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php:ro"
- "/share/Container/pma/zzz-custom.ini:/usr/local/etc/php/conf.d/zzz-custom.ini:ro"
- "/share/Container/pma/tmp:/var/lib/phpmyadmin/tmp:rw"
- "/share/dms-data/logs/pma:/var/log/apache2"
depends_on:
mariadb:
condition: service_healthy
networks:
lcbp3: {}
networks:
lcbp3:
external: true
```

99
Documnets/NPM_setting.md Normal file
View File

@@ -0,0 +1,99 @@
# การติดตั้ง Nginx Proxy Manager (NPM) ใน Docker
* ค่าเริ่มต้นคือ:Email: [admin@example.com] Password: changeme
* user id ของ NPM:
* uid=0(root) gid=0(root) groups=0(root)
---
## กำหนดสิทธิ
```bash
# ตรวจสอบ user id ของ NPM
docker exec -it npm id
chown -R 0:0 /share/Container/npm
setfacl -R -m u:0:rwx /share/Container/npm
```
## Note: Configurations
| Domain Names | Forward Hostname | IP Forward Port | Cache Assets | Block Common Exploits | Websockets | Force SSL | HTTP/2 | SupportHSTS Enabled |
| :----------------------------- | :--------------- | :-------------- | :----------- | :-------------------- | :--------- | :-------- | :----- | :------------------ |
| backend.np-dms.work | backend | 3000 | [ ] | [x] | [ ] | [x] | [x] | [ ] |
| lcbp3.np-dms.work | frontend | 3000 | [x] | [x] | [x] | [x] | [x] | [ ] |
| db.np-dms.work | mariadb | 3306 | [x] | [x] | [x] | [x] | [x] | [ ] |
| git.np-dms.work | gitea | 3000 | [x] | [x] | [x] | [x] | [x] | [ ] |
| n8n.np-dms.work | n8n | 5678 | [x] | [x] | [x] | [x] | [x] | [ ] |
| npm.np-dms.work | npm | 81 | [ ] | [x] | [x] | [x] | [x] | [ ] |
| pma.np-dms.work | pma | 80 | [x] | [x] | [ ] | [x] | [x] | [ ] |
| np-dms.work, [www.np-dms.work] | localhost | 80 | [x] | [x] | [ ] | [x] | [x] | [ ] |
## Docker file
```yml
# File: share/Container/npm/docker-compose-npm.yml
# DMS Container v1_4_1 แยก service และ folder, Application name: lcbp3-npm, Servive:npm
x-restart: &restart_policy
restart: unless-stopped
x-logging: &default_logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
services:
npm:
<<: [*restart_policy, *default_logging]
image: jc21/nginx-proxy-manager:latest
container_name: npm
stdin_open: true
tty: true
deploy:
resources:
limits:
cpus: "1.0" # 50% CPU
memory: 512M
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "81:81" # NPM Admin UI
environment:
TZ: "Asia/Bangkok"
DB_MYSQL_HOST: "mariadb"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
# Uncomment this if IPv6 is not enabled on your host
DISABLE_IPV6: "true"
networks:
- lcbp3
- giteanet
volumes:
- "/share/Container/npm/data:/data"
- "/share/dms-data/logs/npm:/data/logs" # <-- เพิ่ม logging volume
- "/share/Container/npm/letsencrypt:/etc/letsencrypt"
- "/share/Container/npm/custom:/data/nginx/custom" # <-- สำคัญสำหรับ http_top.conf
# - "/share/Container/lcbp3/npm/landing:/data/landing:ro"
landing:
image: nginx:1.27-alpine
container_name: landing
restart: unless-stopped
volumes:
- "/share/Container/npm/landing:/usr/share/nginx/html:ro"
networks:
- lcbp3
networks:
lcbp3:
external: true
giteanet:
external: true
name: gitnet
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,673 @@
# 📝 **Documents Management System Version 1.4.1: Application Requirements Specification (ปรับปรุงโดย deepseek)**
**ปรับปรุงตามการ review และข้อเสนอแนะล่าสุด*
## 📌**1. วัตถุประสงค์**
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System)ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
- **เสริม:** ปรับปรุงความปลอดภัยของระบบด้วยมาตรการป้องกันที่ทันสมัย
- **เสริม:** เพิ่มความทนทานของระบบด้วยกลไก resilience patterns
- **เสริม:** สร้างระบบ monitoring และ observability ที่ครอบคลุม
## 🛠️**2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)**
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
- **2.1. Infrastructure & Environment:**
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
- Development Environment: VS Code on Windows 11
- Domain: np-dms.work, <www.np-dms.work>
- ip: 159.192.126.103
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
- Data Storage: /share/dms-data บน QNAP
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
- **2.2. การจัดการ Configuration:**
- ใช้ docker-compose.yml สำหรับ environment variables ตามข้อจำกัดของ QNAP
- **แต่ต้องมี mechanism สำหรับจัดการ sensitive secrets อย่างปลอดภัย** โดยใช้:
- Docker secrets (ถ้ารองรับ)
- External secret management (Hashicorp Vault) หรือ
- Encrypted environment variables
- Development environment ยังใช้ .env ได้ แต่ต้องไม่ commit เข้า version control
- ต้องมี configuration validation during application startup
- ต้องแยก configuration ตาม environment (development, staging, production)
- **2.3. Code Hosting:**
- Application name: git
- Service: Gitea (Self-hosted on QNAP)
- Service name: gitea
- Domain: git.np-dms.work
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
- **2.4. Backend / Data Platform:**
- Application name: lcbp3-backend
- Service: NestJS
- Service name: backend
- Domain: backend.np-dms.work
- Framework: NestJS (Node.js, TypeScript, ESM)
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
- **2.5. Database:**
- Application name: lcbp3-db
- Service: mariadb:10.11
- Service name: mariadb
- Domain: db.np-dms.work
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
- **2.6. Database management:**
- Application name: lcbp3-db
- Service: phpmyadmin:5-apache
- Service name: pma
- Domain: pma.np-dms.work
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
- **2.7. Frontend:**
- Application name: lcbp3-frontend
- Service: next.js
- Service name: frontend
- Domain: lcbp3.np-dms.work
- Framework: Next.js (App Router, React, TypeScript, ESM)
- Styling: Tailwind CSS + PostCSS
- Component Library: shadcn/ui
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
- **2.8. Workflow automation:**
- Application name: lcbp3-n8n
- Service: n8nio/n8n:latest
- Service name: n8n
- Domain: n8n.np-dms.work
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
- **2.9. Reverse Proxy:**
- Application name: lcbp3-npm
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
- Service name: npm
- Domain: npm.np-dms.work
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
- **2.10. การจัดการตรรกะทางธุรกิจ (Business Logic Implementation):**
- 2.10.1. ตรรกะทางธุรกิจที่ซับซ้อนทั้งหมด (เช่น การเปลี่ยนสถานะ Workflow [cite: 3.5.4, 3.6.5], การบังคับใช้สิทธิ์ [cite: 4.4], การตรวจสอบ Deadline [cite: 3.2.5]) **จะถูกจัดการในฝั่ง Backend (NestJS)** [cite: 2.3] เพื่อให้สามารถบำรุงรักษาและทดสอบได้ง่าย (Testability)
- 2.10.2. **จะไม่มีการใช้ SQL Triggers** เพื่อป้องกันตรรกะซ่อนเร้น (Hidden Logic) และความซับซ้อนในการดีบัก
- 2.10.3. **การจัดการเลขที่เอกสาร:** ใช้ **application-level locking** (Redis distributed lock) แทน stored procedure เพื่อป้องกัน race condition และให้ง่ายต่อการทดสอบและบำรุงรักษา
- **2.11 Data Migration และ Schema Versioning:**
- ต้องมี database migration scripts สำหรับทุก schema change โดยใช้ TypeORM migrations
- ต้องรองรับ rollback ของ migration ได้
- ต้องมี data seeding strategy สำหรับ environment ต่างๆ (development, staging, production)
- ต้องมี version compatibility between schema versions
- Migration scripts ต้องผ่านการทดสอบใน staging environment ก่อน production
- ต้องมี database backup ก่อนทำ migration ใน production
- **2.12 กลยุทธ์ความทนทานและการจัดการข้อผิดพลาด (Resilience & Error Handling Strategy)**
- 2.12.1 Circuit Breaker Pattern: ใช้สำหรับ external service calls (Email, LINE, Elasticsearch)
- 2.12.2 Retry Mechanism: ด้วย exponential backoff สำหรับ transient failures
- 2.12.3 Fallback Strategies: Graceful degradation เมื่อบริการภายนอกล้มเหลว
- 2.12.4 Error Handling: Error messages ต้องไม่เปิดเผยข้อมูล sensitive
- 2.12.5 Monitoring: Centralized error monitoring และ alerting system
## **📦 3. ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)**
- **3.1. การจัดการโครงสร้างโครงการและองค์กร**
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
- 3.1.3. องค์กร (Organizations):
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
- **3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)**
- 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects), รองรับ To (ผู้รับหลัก) และ CC (ผู้รับสำเนา) หลายองค์กร
- 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
- 3.2.3. การสร้างเอกสาร (Correspondence):
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
- 3.2.4. การอ้างอิงและจัดกลุ่ม:
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
- 3.2.5. Correspondence Routing & Workflow
- 3.2.5.1 Routing Templates (แม่แบบการส่งต่อ)
- ผู้ดูแลระบบต้องสามารถสร้างแม่แบบการส่งต่อได้
- แม่แบบสามารถเป็นแบบทั่วไป (ใช้ได้ทุกโครงการ) หรือเฉพาะโครงการ
- แต่ละแม่แบบประกอบด้วยลำดับขั้นตอนการส่งต่อ
- การส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Wouting ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
- 3.2.5.2 Routing Steps (ขั้นตอนการส่งต่อ) แต่ละขั้นตอนในแม่แบบต้องกำหนด:
- **ลำดับขั้นตอน** (Sequence)
- **องค์กรผู้รับ** (To Organization)
- **วัตถุประสงค์** (Purpose): เพื่ออนุมัติ (FOR_APPROVAL), เพื่อตรวจสอบ (FOR_REVIEW), เพื่อทราบ (FOR_INFORMATION), เพื่อดำเนินการ (FOR_ACTION)
- **ระยะเวลาที่คาดหวัง** (Expected Duration)
- 3.2.5.3 Actual Routing Execution (การส่งต่อจริง) เมื่อสร้างเอกสารและเลือกใช้แม่แบบ ระบบต้อง:
- สร้างลำดับการส่งต่อตามแม่แบบ
- ติดตามสถานะของแต่ละขั้นตอน: ส่งแล้ว (SENT), กำลังดำเนินการ (IN_PROGRESS), ดำเนินการแล้ว (ACTIONED), ส่งต่อแล้ว (FORWARDED), ตอบกลับแล้ว (REPLIED)
- ระบุวันครบกำหนด (Due Date) สำหรับแต่ละขั้นตอน
- บันทึกผู้ดำเนินการและเวลาที่ดำเนินการ
- 3.2.5.4 Routing Flexibility (ความยืดหยุ่น)
- สามารถข้ามขั้นตอนได้ในกรณีพิเศษ (โดยผู้มีสิทธิ์)
- สามารถส่งกลับขั้นตอนก่อนหน้าได้
- สามารถเพิ่มความคิดเห็นในแต่ละขั้นตอน
- แจ้งเตือนอัตโนมัติเมื่อถึงขั้นตอนใหม่หรือใกล้ครบกำหนด
- 3.2.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่เป็นผู้รับได้
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
- **3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)**
- 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
- 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
- 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
- **3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)**
- 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
- 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
- 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
- **3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)**
- 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
- 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
- Request for Drawing Approval (RFA_DWG)
- Request for Document Approval (RFA_DOC)
- Request for Method statement Approval (RFA_MES)
- Request for Material Approval (RFA_MAT)
- 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
- 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA_DWG):
- เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
- Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
- ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
- 3.5.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
- ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
- 3.5.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
- **3.6.การจัดการเอกสารนำส่ง (Transmittals)**
- 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
- 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
- 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
- 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
- **3.7. ใบเวียนเอกสาร (Circulation Sheet)**
- 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
- 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
- 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
- 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
- ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
- ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
- ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
- 3.7.5. การติดตามงาน:
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
- **3.8. ประวัติการแก้ไข (Revisions):** ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
- **3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)**
- เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) [cite: 2.1]
- ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง attachments (ตารางกลาง)
- ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น correspondence_attachments, circulation_attachments, shop_drawing_revision_attachments ,และ contracy_drawing_attachments
- สถาปัตยกรรมแบบรวมศูนย์นี้ แทนที่ แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
- **3.9.6 ความปลอดภัยของการจัดเก็บไฟล์:**
- ต้องมีการ scan virus สำหรับไฟล์ที่อัปโหลดทั้งหมด โดยใช้ ClamAV หรือบริการ third-party
- จำกัดประเภทไฟล์ที่อนุญาต: PDF, DWG, DOCX, XLSX, ZIP (ต้องระบุรายการที่ชัดเจน)
- ขนาดไฟล์สูงสุด: 50MB ต่อไฟล์
- ไฟล์ต้องถูกเก็บนอก web root และเข้าถึงได้ผ่าน authenticated endpoint เท่านั้น
- ต้องมี file integrity check (checksum) เพื่อป้องกันการแก้ไขไฟล์
- Download links ต้องมี expiration time (default: 24 ชั่วโมง)
- ต้องบันทึก audit log ทุกครั้งที่มีการดาวน์โหลดไฟล์สำคัญ
- **3.10. การจัดการเลขที่เอกสาร (Document Numbering):**
- 3.10.1. ระบบต้องสามารถสร้างเลขที่เอกสาร (เช่น correspondence_number) ได้โดยอัตโนมัติ
- 3.10.2. การนับเลข Running Number (SEQ) จะต้องนับแยกตาม Key ดังนี้: **โครงการ (Project)**, **องค์กรผู้ส่ง (Originator Organization)**, **ประเภทเอกสาร (Document Type)** และ **ปีปัจจุบัน (Year)**
- 3.10.3. ผู้ดูแลระบบ (Admin) ต้องสามารถกำหนด "รูปแบบ" (Format Template) ของเลขที่เอกสารได้ (เช่น {ORG_CODE}-{TYPE_CODE}-{YEAR_SHORT}-{SEQ:4}) โดยกำหนดแยกตามโครงการและประเภทเอกสาร
- 3.10.4. **ใช้ application-level locking** (Redis distributed lock) แทน stored procedure เพื่อป้องกัน race condition
- 3.10.5. ต้องมี retry mechanism และ fallback strategy เมื่อการ generate เลขที่เอกสารล้มเหลว
- **3.11 การจัดการ JSON Details**
- **3.11.1 วัตถุประสงค์**
- จัดเก็บข้อมูลแบบไดนามิกที่เฉพาะเจาะจงกับแต่ละประเภทของเอกสาร
- รองรับการขยายตัวของระบบโดยไม่ต้องเปลี่ยนแปลง database schema
- จัดการ metadata และข้อมูลประกอบสำหรับ correspondence, routing, และ workflows
- **3.11.2 โครงสร้าง JSON Schema**
ระบบต้องมี predefined JSON schemas สำหรับประเภทเอกสารต่างๆ:
- **3.11.2.1 Correspondence Types**
- **GENERIC**: ข้อมูลพื้นฐานสำหรับเอกสารทั่วไป
- **RFI**: รายละเอียดคำถามและข้อมูลทางเทคนิค
- **RFA**: ข้อมูลการขออนุมัติแบบและวัสดุ
- **TRANSMITTAL**: รายการเอกสารที่ส่งต่อ
- **LETTER**: ข้อมูลจดหมายทางการ
- **EMAIL**: ข้อมูลอีเมล
- **3.11.2.2 Routing Types**
- **ROUTING_TEMPLATE**: กฎและเงื่อนไขการส่งต่อ
- **ROUTING_INSTANCE**: สถานะและประวัติการส่งต่อ
- **ROUTING_ACTION**: การดำเนินการในแต่ละขั้นตอน
- **3.11.2.3 Audit Types**
- **AUDIT_LOG**: ข้อมูลการตรวจสอบ
- **SECURITY_SCAN**: ผลการตรวจสอบความปลอดภัย
- **3.11.3 Validation Rules**
- ต้องมี JSON schema validation สำหรับแต่ละประเภท
- ต้องรองรับ versioning ของ schema
- ต้องมี default values สำหรับ field ที่ไม่บังคับ
- ต้องตรวจสอบ data types และ format ให้ถูกต้อง
- **3.11.4 Performance Requirements**
- JSON field ต้องมีขนาดไม่เกิน 50KB
- ต้องรองรับ indexing สำหรับ field ที่ใช้ค้นหาบ่อย
- ต้องมี compression สำหรับ JSON ขนาดใหญ่
- **3.11.5 Security Requirements**
- ต้อง sanitize JSON input เพื่อป้องกัน injection attacks
- ต้อง validate JSON structure ก่อนบันทึก
- ต้อง encrypt sensitive data ใน JSON fields
## **🔐 4. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)**
- **4.1. ภาพรวม:** ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
- **4.2. ลำดับชั้นของสิทธิ์ (Permission Hierarchy)**
- Global: สิทธิ์สูงสุดของระบบ
- Organization: สิทธิ์ภายในองค์กร เป็นสิทธิ์พื้นฐานของผู้ใช้
- Project: สิทธิ์เฉพาะในโครงการ จะถูกพิจารณาเมื่อผู้ใช้อยู่ในโครงการนั้น
- Contract: สิทธิ์เฉพาะในสัญญา จะถูกพิจารณาเมื่อผู้ใช้อยู่ในสัญญานั้น (สัญญาเป็นส่วนหนึ่งของโครงการ)
กฎการบังคับใช้: เมื่อตรวจสอบสิทธิ์ ระบบจะพิจารณาสิทธิ์จากทุกระดับที่ผู้ใช้มี และใช้ สิทธิ์ที่มากที่สุด (Most Permissive) เป็นตัวตัดสิน
ตัวอย่าง: ผู้ใช้ A เป็น Viewer ในองค์กร แต่ถูกมอบหมายเป็น Editor ในโครงการ X เมื่ออยู่ในโครงการ X ผู้ใช้ A จะมีสิทธิ์แก้ไขได้
- **4.3. การกำหนดบทบาท (Roles) และขอบเขต (Scope)**
| บทบาท (Role) | ขอบเขต (Scope) | คำอธิบาย | สิทธิ์หลัก (Key Permissions) |
| :------------------- | :------------- | :---------------------- | :------------------------------------------------------------------------------------- |
| **Superadmin** | Global | ผู้ดูแลระบบสูงสุด | ทำทุกอย่างในระบบ, จัดการองค์กร, จัดการข้อมูลหลักระดับ Global |
| **Org Admin** | Organization | ผู้ดูแลองค์กร | จัดการผู้ใช้ในองค์กร, จัดการบทบาท/สิทธิ์ภายในองค์กร, ดูรายงานขององค์กร |
| **Document Control** | Organization | ควบคุมเอกสารขององค์กร | เพิ่ม/แก้ไข/ลบเอกสาร, กำหนดสิทธิ์เอกสารภายในองค์กร |
| **Editor** | Organization | ผู้แก้ไขเอกสารขององค์กร | เพิ่ม/แก้ไขเอกสารที่ได้รับมอบหมาย |
| **Viewer** | Organization | ผู้ดูเอกสารขององค์กร | ดูเอกสารที่มีสิทธิ์เข้าถึง |
| **Project Manager** | Project | ผู้จัดการโครงการ | จัดการสมาชิกในโครงการ (เพิ่ม/ลบ/มอบบทบาท), สร้าง/จัดการสัญญาในโครงการ, ดูรายงานโครงการ |
| **Contract Admin** | Contract | ผู้ดูแลสัญญา | จัดการสมาชิกในสัญญา, สร้าง/จัดการข้อมูลหลักเฉพาะสัญญา (ถ้ามี), อนุมัติเอกสารในสัญญา |
- **4.4. กระบวนการเริ่มต้นใช้งาน (Onboarding Workflow) ที่สมบูรณ์**
- **4.4.1. สร้างองค์กร (Organization)**
- **Superadmin** สร้างองค์กรใหม่ (เช่น บริษัท A)
- **Superadmin** แต่งตั้งผู้ใช้อย่างน้อย 1 คนให้เป็น **Org Admin** หรือ **Document Control** ของบริษัท A
- **4.4.2. เพิ่มผู้ใช้ในองค์กร**
- **Org Admin** ของบริษัท A เพิ่มผู้ใช้อื่นๆ (Editor, Viewer) เข้ามาในองค์กรของตน
- **4.4.3. มอบหมายผู้ใช้ให้กับโครงการ (Project)**
- **Project Manager** ของโครงการ X (ซึ่งอาจมาจากบริษัท A หรือบริษัทอื่น) ทำการ "เชิญ" หรือ "มอบหมาย" ผู้ใช้จากองค์กรต่างๆ ที่เกี่ยวข้องเข้ามาในโครงการ X
- ในขั้นตอนนี้ **Project Manager** จะกำหนด **บทบาทระดับโครงการ** (เช่น Project Member, หรืออาจไม่มีบทบาทพิเศษ ให้ใช้สิทธิ์จากระดับองค์กรไปก่อน)
- **4.4.4. เมอบหมายผู้ใช้ให้กับสัญญา (Contract)**
- **Contract Admin** ของสัญญา Y (ซึ่งเป็นส่วนหนึ่งของโครงการ X) ทำการเลือกผู้ใช้ที่อยู่ในโครงการ X แล้ว มอบหมายให้เข้ามาในสัญญา Y
- ในขั้นตอนนี้ **Contract Admin** จะกำหนด **บทบาทระดับสัญญา** (เช่น Contract Member) และสิทธิ์เฉพาะที่จำเป็น
- **4.4.5 Security Onboarding:**
- ต้องบังคับเปลี่ยน password ครั้งแรกสำหรับผู้ใช้ใหม่
- ต้องมี security awareness training สำหรับผู้ใช้ที่มีสิทธิ์สูง
- ต้องมี process สำหรับการรีเซ็ต password ที่ปลอดภัย
- ต้องบันทึก audit log ทุกครั้งที่มีการเปลี่ยนแปลง permissions
- **4.5. การจัดการข้อมูลหลัก (Master Data Management) ที่แบ่งตามระดับ**
| ข้อมูลหลัก | ผู้มีสิทธิ์จัดการ | ระดับ |
| :---------------------------------- | :------------------------------ | :--------------------------------- |
| ประเภทเอกสาร (Correspondence, RFA) | **Superadmin** | Global |
| สถานะเอกสาร (Draft, Approved, etc.) | **Superadmin** | Global |
| หมวดหมู่แบบ (Shop Drawing) | **Project Manager** | Project (สร้างใหม่ได้ภายในโครงการ) |
| Tags | **Org Admin / Project Manager** | Organization / Project |
| บทบาทและสิทธิ์ (Custom Roles) | **Superadmin / Org Admin** | Global / Organization |
| Document Numbering Formats | **Superadmin / Admin** | Global / Organization |
## **👥 5. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)**
- **5.1. Layout หลัก:** หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Document Control/เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
- Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวข้องกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
- Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
- **5.2. หน้า Landing Page:** เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
- **5.3. หน้า Dashboard:** เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
- การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
- ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
- Security Metrics: แสดงจำนวน files scanned, security incidents, failed login attempts
- **5.4. การติดตามสถานะ:** องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
- **5.5. การจัดการข้อมูลส่วนตัว (Profile Page):** ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
- **5.6. การจัดการเอกสารทางเทคนิค (RFA & Workflow):** ผู้ใช้สามารถดู RFA ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ Document Control ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ Document Control ขึ้นไป
- **5.7. การจัดการใบเวียนเอกสาร (Circulation):** ผู้ใช้สามารถดู Circulation ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว,ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ Document Control ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ Document Control ขึ้นไป
- **5.8. การจัดการเอกสารนำส่ง (Transmittals):** ผู้ใช้สามารถดู Transmittals ในรูปแบบรายการทั้งหมดได้ในหน้าเดียว
- **5.9. ข้อกำหนด UI/UX การแนบไฟล์ (File Attachment UX):**
- ระบบต้องรองรับการอัปโหลดไฟล์หลายไฟล์พร้อมกัน (Multi-file upload) เช่น การลากและวาง (Drag-and-Drop)
- ในหน้าอัปโหลด (เช่น สร้าง RFA หรือ Correspondence) ผู้ใช้ต้องสามารถกำหนดได้ว่าไฟล์ใดเป็น "เอกสารหลัก" (Main Document เช่น PDF) และไฟล์ใดเป็น "เอกสารแนบประกอบ" (Supporting Attachments เช่น .dwg, .docx, .zip)
- **Security Feedback:** แสดง security warnings สำหรับ file types ที่เสี่ยงหรือ files ที่ fail virus scan
- **File Type Indicators:** แสดง file type icons และ security status
## **6. ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)**
- **6.1. การบันทึกการกระทำ (Audit Log):** ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
- **6.1.1 ขอบเขตการบันทึก Audit Log:**
- ทุกการสร้าง/แก้ไข/ลบ ข้อมูลสำคัญ (correspondences, RFAs, drawings, users, permissions)
- ทุกการเข้าถึงข้อมูล sensitive (user data, financial information)
- ทุกการเปลี่ยนสถานะ workflow (status transitions)
- ทุกการดาวน์โหลดไฟล์สำคัญ (contract documents, financial reports)
- ทุกการเปลี่ยนแปลง permission และ role assignment
- ทุกการล็อกอินที่สำเร็จและล้มเหลว
- ทุกการส่งคำขอ API ที่สำคัญ
- **6.1.2 ข้อมูลที่ต้องบันทึกใน Audit Log:**
- ผู้ใช้งาน (user_id)
- การกระทำ (action)
- ชนิดของ entity (entity_type)
- ID ของ entity (entity_id)
- ข้อมูลก่อนการเปลี่ยนแปลง (old_values) - สำหรับ update operations
- ข้อมูลหลังการเปลี่ยนแปลง (new_values) - สำหรับ update operations
- IP address
- User agent
- Timestamp
- Request ID สำหรับ tracing
- **6.2. การค้นหา (Search):** ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสาร **correspondence**, **rfa**, **shop_drawing**, **contract-drawing**, **transmittal** และ **ใบเวียน (Circulations)** จากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
- **6.3. การทำรายงาน (Reporting):** สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
- **6.4. ประสิทธิภาพ (Performance):** มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
- **6.4.1 ตัวชี้วัดประสิทธิภาพ:**
- **API Response Time:** < 200ms (90th percentile) สำหรับ operation ทั่วไป
- **Search Query Performance:** < 500ms สำหรับการค้นหาขั้นสูง
- **File Upload Performance:** < 30 seconds สำหรับไฟล์ขนาด 50MB
- **Concurrent Users:** รองรับผู้ใช้พร้อมกันอย่างน้อย 100 คน
- **Database Connection Pool:** ขนาดเหมาะสมกับ workload (default: min 5, max 20 connections)
- **Cache Hit Ratio:** > 80% สำหรับ cached data
- **Application Startup Time:** < 30 seconds
- **6.4.2 Caching Strategy:**
- **Master Data Cache:** Roles, Permissions, Organizations, Project metadata (TTL: 1 hour)
- **User Session Cache:** User permissions และ profile data (TTL: 30 minutes)
- **Search Result Cache:** Frequently searched queries (TTL: 15 minutes)
- **File Metadata Cache:** Attachment metadata (TTL: 1 hour)
- **Document Cache:** Frequently accessed document metadata (TTL: 30 minutes)
- **ต้องมี cache invalidation strategy ที่ชัดเจน:**
- Invalidate on update/delete operations
- Time-based expiration
- Manual cache clearance สำหรับ admin operations
- ใช้ Redis เป็น distributed cache backend
- ต้องมี cache monitoring (hit/miss ratios)
- **6.5. ความปลอดภัย (Security):**
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
- **6.5.1 Rate Limiting Strategy:**
- **Anonymous Endpoints:** 100 requests/hour ต่อ IP address
- **Authenticated Endpoints:**
- Viewer: 500 requests/hour
- Editor: 1000 requests/hour
- Document Control: 2000 requests/hour
- Admin/Superadmin: 5000 requests/hour
- **File Upload Endpoints:** 50 requests/hour ต่อ user
- **Search Endpoints:** 500 requests/hour ต่อ user
- **Authentication Endpoints:** 10 requests/minute ต่อ IP address
- **ต้องมี mechanism สำหรับยกเว้น rate limiting สำหรับ trusted services**
- ต้องบันทึก log เมื่อมีการ trigger rate limiting
- **6.5.2 Error Handling และ Resilience:**
- ต้องมี circuit breaker pattern สำหรับ external service calls
- ต้องมี retry mechanism ด้วย exponential backoff
- ต้องมี graceful degradation เมื่อบริการภายนอกล้มเหลว
- Error messages ต้องไม่เปิดเผยข้อมูล sensitive
- **6.5.3 Input Validation:**
- ต้องมี input validation ทั้งฝั่ง client และ server (defense in depth)
- ต้องป้องกัน OWASP Top 10 vulnerabilities:
- SQL Injection (ใช้ parameterized queries ผ่าน ORM)
- XSS (input sanitization และ output encoding)
- CSRF (CSRF tokens สำหรับ state-changing operations)
- ต้อง validate file uploads:
- File type (white-list approach)
- File size
- File content (magic number verification)
- ต้อง sanitize user inputs ก่อนแสดงผลใน UI
- ต้องใช้ content security policy (CSP) headers
- ต้องมี request size limits เพื่อป้องกัน DoS attacks
- **6.5.4 Session และ Token Management:**
- **JWT token expiration:** 8 hours สำหรับ access token
- **Refresh token expiration:** 7 days
- **Refresh token mechanism:** ต้องรองรับ token rotation และ revocation
- **Token revocation on logout:** ต้องบันทึก revoked tokens จนกว่าจะ expire
- **Concurrent session management:**
- จำกัดจำนวน session พร้อมกันได้ (default: 5 devices)
- ต้องแจ้งเตือนเมื่อมี login จาก device/location ใหม่
- **Device fingerprinting:** สำหรับ security และ audit purposes
- **Password policy:**
- ความยาวขั้นต่ำ: 8 characters
- ต้องมี uppercase, lowercase, number, special character
- ต้องเปลี่ยน password ทุก 90 วัน
- ต้องป้องกันการใช้ password ที่เคยใช้มาแล้ว 5 ครั้งล่าสุด
- **6.6. การสำรองข้อมูลและการกู้คืน (Backup & Recovery):**
- ระบบจะต้องมีกลไกการสำรองข้อมูลอัตโนมัติสำหรับฐานข้อมูล MariaDB [cite: 2.4] และไฟล์เอกสารทั้งหมดใน /share/dms-data [cite: 2.1] (เช่น ใช้ HBS 3 ของ QNAP หรือสคริปต์สำรองข้อมูล) อย่างน้อยวันละ 1 ครั้ง
- ต้องมีแผนการกู้คืนระบบ (Disaster Recovery Plan) ในกรณีที่ Server หลัก (QNAP) ใช้งานไม่ได้
- **6.6.1 ขั้นตอนการกู้คืน:**
- **Database Restoration Procedure:**
- สร้างจาก full backup ล่าสุด
- Apply transaction logs ถึง point-in-time ที่ต้องการ
- Verify data integrity post-restoration
- **File Storage Restoration Procedure:**
- Restore จาก QNAP snapshot หรือ backup
- Verify file integrity และ permissions
- **Application Redeployment Procedure:**
- Deploy จาก version ล่าสุดที่รู้ว่าทำงานได้
- Verify application health
- **Data Integrity Verification Post-Recovery:**
- Run data consistency checks
- Verify critical business data
- **Recovery Time Objective (RTO):** < 4 ชั่วโมง
- **Recovery Point Objective (RPO):** < 1 ชั่วโมง
- **6.7. กลยุทธ์การแจ้งเตือน (Notification Strategy):**
- **6.7.1 ระบบจะส่งการแจ้งเตือน (ผ่าน Email หรือ Line [cite: 2.7]) เมื่อมีการกระทำที่สำคัญ** ดังนี้:
1. เมื่อมีเอกสารใหม่ (Correspondence, RFA) ถูกส่งมาถึงองค์กรณ์ของเรา
2. เมื่อมีใบเวียน (Circulation) ใหม่ มอบหมายงานมาที่เรา
3. (ทางเลือก) เมื่อเอกสารที่เราส่งไป ถูกดำเนินการ (เช่น อนุมัติ/ปฏิเสธ)
4. (ทางเลือก) เมื่อใกล้ถึงวันครบกำหนด (Deadline) [cite: 3.2.5, 3.6.6, 3.7.5]
- **6.7.2 Notification Delivery Guarantees:**
- **At-least-once delivery:** สำหรับ important notifications
- **Retry mechanism:** ด้วย exponential backoff (max 3 retries)
- **Dead letter queue:** สำหรับ notifications ที่ส่งไม่สำเร็จหลังจาก retries
- **Delivery status tracking:** ต้องบันทึกสถานะการส่ง notifications
- **Fallback channels:** ถ้า Email ล้มเหลว ให้ส่งผ่าน SYSTEM notification
- **Notification preferences:** ผู้ใช้ต้องสามารถกำหนด channel preferences ได้
- **6.8. Monitoring และ Observability**
- **6.8.1 Application Monitoring:**
- **Health checks:** /health endpoint สำหรับ load balancer
- **Metrics collection:** Response times, error rates, throughput
- **Distributed tracing:** สำหรับ request tracing across services
- **Log aggregation:** Structured logging ด้วย JSON format
- **Alerting:** สำหรับ critical errors และ performance degradation
- **6.8.2 Business Metrics:**
- จำนวน documents created ต่อวัน
- Workflow completion rates
- User activity metrics
- System utilization rates
- Search query performance
- **6.8.3 Security Monitoring:**
- Failed login attempts
- Rate limiting triggers
- Virus scan results
- File download activities
- Permission changes
- **6.9 JSON Processing & Validation**
- **6.9.1 JSON Schema Management**
- ต้องมี centralized JSON schema registry
- ต้องรองรับ schema versioning และ migration
- ต้องมี schema validation during runtime
- **6.9.2 Performance Optimization**
- **Caching:** Cache parsed JSON structures
- **Compression:** ใช้ compression สำหรับ JSON ขนาดใหญ่
- **Indexing:** Support JSON path indexing สำหรับ query
- **6.9.3 Error Handling**
- ต้องมี graceful degradation เมื่อ JSON validation ล้มเหลว
- ต้องมี default fallback values
- ต้องบันทึก error logs สำหรับ validation failures
---
## **7. ข้อกำหนดด้านการทดสอบ (Testing Requirements)**
- **7.1. Unit Testing:**
- ต้องมี unit tests สำหรับ business logic ทั้งหมด
- Code coverage อย่างน้อย 70% สำหรับ backend services
- ต้องทดสอบ RBAC permission logic ทุกระดับ
- **7.2. Integration Testing:**
- ทดสอบการทำงานร่วมกันของ modules
- ทดสอบ database migrations และ data integrity
- ทดสอบ API endpoints ด้วย realistic data
- **7.3. End-to-End Testing:**
- ทดสอบ complete user workflows
- ทดสอบ document lifecycle จาก creation ถึง archival
- ทดสอบ cross-module integrations
- **7.4. Security Testing:**
- **Penetration Testing:** ทดสอบ OWASP Top 10 vulnerabilities
- **Security Audit:** Review code สำหรับ security flaws
- **Virus Scanning Test:** ทดสอบ file upload security
- **Rate Limiting Test:** ทดสอบ rate limiting functionality
- **7.5. Performance Testing:**
- **Load Testing:** ทดสอบด้วย realistic workloads
- **Stress Testing:** หา breaking points ของระบบ
- **Endurance Testing:** ทดสอบการทำงานต่อเนื่องเป็นเวลานาน
- **7.6. Disaster Recovery Testing:**
- ทดสอบ backup และ restoration procedures
- ทดสอบ failover mechanisms
- ทดสอบ data integrity หลังการ recovery
---
## **8. ข้อกำหนดด้านการบำรุงรักษา (Maintenance Requirements)**
- **8.1. Log Retention:**
- Audit logs: 7 ปี
- Application logs: 1 ปี
- Performance metrics: 2 ปี
- **8.2. Monitoring และ Alerting:**
- ต้องมี proactive monitoring สำหรับ critical systems
- ต้องมี alerting สำหรับ security incidents
- ต้องมี performance degradation alerts
- **8.3. Patch Management:**
- ต้องมี process สำหรับ security patches
- ต้องทดสอบ patches ใน staging environment
- ต้องมี rollback plan สำหรับ failed updates
- **8.4. Capacity Planning:**
- ต้อง monitor resource utilization
- ต้องมี scaling strategy สำหรับ growth
- ต้องมี performance baselines และ trending
---
## **9. ข้อกำหนดด้านการปฏิบัติตามกฎระเบียบ (Compliance Requirements)**
- **9.1. Data Privacy:**
- ต้องปฏิบัติตามกฎหมายคุ้มครองข้อมูลส่วนบุคคล
- ต้องมี data retention policies
- ต้องมี data deletion procedures
- **9.2. Audit Compliance:**
- ต้องรองรับ internal และ external audits
- ต้องมี comprehensive audit trails
- ต้องมี reporting capabilities สำหรับ compliance
- **9.3. Security Standards:**
- ต้องปฏิบัติตาม organizational security policies
- ต้องมี security incident response plan
- ต้องมี regular security assessments
---
## **10. ข้อกำหนดด้าน Testing Strategy**
### **10.1 Testing Gates แต่ละ Phase**
ทุก Phase ต้องผ่านการทดสอบต่อไปนี้ก่อนดำเนินการ Phase ถัดไป:
#### **10.1.1 Unit Testing Requirements**
- Code coverage อย่างน้อย 80% สำหรับ components ที่พัฒนาใน Phase
- ทดสอบ business logic ทั้งหมด
- ทดสอบ error scenarios และ edge cases
#### **10.1.2 Integration Testing Requirements**
- ทดสอบการทำงานร่วมกันของ modules ใน Phase
- ทดสอบ database operations
- ทดสอบ external service integrations
#### **10.1.3 Security Testing Requirements**
- ทดสอบ security vulnerabilities
- ทดสอบ permission และ access control
- ทดสอบ input validation
#### **10.1.4 Performance Testing Requirements**
- ทดสอบ response time ตามเป้าหมาย
- ทดสอบภายใต้ load ที่คาดหมาย
- ทดสอบ memory usage และ resource utilization
### **10.2 Testing Automation**
- ต้องมี automated test pipelines
- ต้องมี test reports และ metrics
- ต้องมี regression testing
---
## **📋 สรุปการปรับปรุงจากเวอร์ชันก่อนหน้า**
### **Security Enhancements:**
1. **File Upload Security** - Virus scanning, file type validation, access controls
2. **Input Validation** - OWASP Top 10 protection, XSS/CSRF prevention
3. **Rate Limiting** - Comprehensive rate limiting strategy
4. **Secrets Management** - Secure handling of sensitive configuration
### **Architecture Improvements:**
1. **Document Numbering** - Changed from Stored Procedure to Application-level Locking
2. **Resilience Patterns** - Circuit breaker, retry mechanisms, fallback strategies
3. **Monitoring & Observability** - Health checks, metrics, distributed tracing
4. **Caching Strategy** - Comprehensive caching with proper invalidation
### **Performance Targets:**
1. **API Response Time** - < 200ms (90th percentile)
2. **Search Performance** - < 500ms
3. **File Upload** - < 30 seconds for 50MB files
4. **Cache Hit Ratio** - > 80%
### **Operational Excellence:**
1. **Disaster Recovery** - RTO < 4 hours, RPO < 1 hour
2. **Backup Procedures** - Comprehensive backup and restoration
3. **Security Testing** - Penetration testing and security audits
4. **Performance Testing** - Load testing with realistic workloads
เอกสารนี้สะท้อนถึงความมุ่งมั่นในการสร้างระบบที่มีความปลอดภัย, มีความทนทาน, และมีประสิทธิภาพสูง พร้อมรองรับการเติบโตในอนาคตและความต้องการทางธุรกิจที่เปลี่ยนแปลงไป
**หมายเหตุ:** Requirements นี้จะถูกทบทวนและปรับปรุงเป็นระยะตาม feedback จากทีมพัฒนาและความต้องการทางธุรกิจที่เปลี่ยนแปลงไป
## **Document Control:**
- Document for Application Requirements Specification DMS v1.4.1
- Version: 1.4.1
- Date: 2025-11-16
- Author: System Architecture Team
- Status: FINAL
- Classification: Internal Technical Documentation
---
_End of Requirements Specification

119
Documnets/Securities.md Normal file
View File

@@ -0,0 +1,119 @@
สวัสดีครับ! การตั้งค่า Network Segmentation และ Firewall Rules เป็นขั้นตอนที่ฉลาดมากครับ โดยเฉพาะเมื่อคุณมี Services ที่ต้องเปิดสู่ Public (เช่น `lcbp3.np-dms.work`) และ Services ภายใน (เช่น `db.np-dms.work`)
สำหรับอุปกรณ์ Omada (ER7206 + OC200) กลยุทธ์หลักคือการใช้ **VLANs (Virtual LANs)** เพื่อแบ่งกลุ่มอุปกรณ์ และใช้ **Firewall ACLs (Access Control Lists)** เพื่อควบคุมการจราจรระหว่างกลุ่มเหล่านั้น
นี่คือคำแนะนำตามแนวทาง "Zero Trust" ที่ปรับให้เข้ากับสถาปัตยกรรมของคุณครับ
---
## 1. 🌐 การแบ่งส่วนเครือข่าย (VLAN Segmentation)
ใน Omada Controller (OC200) ให้คุณไปที่ `Settings > Wired Networks > LAN` และสร้างเครือข่ายย่อย (VLANs) ดังนี้:
* **VLAN 1 (Default): Management**
* **IP Range:** 192.168.1.x
* **วัตถุประสงค์:** ใช้สำหรับอุปกรณ์ Network (ER7206, OC200, Switches) และ PC ของผู้ดูแลระบบ (Admin) เท่านั้น
* **VLAN 10: Servers (DMZ)**
* **IP Range:** 192.168.10.x
* **วัตถุประสงค์:** นี่คือ VLAN ที่คุณจะเสียบสาย LAN ของ **QNAP NAS** ครับ QNAP จะได้รับ IP ในกลุ่มนี้ (เช่น `192.168.10.100`)
* **VLAN 20: Office / Trusted**
* **IP Range:** 192.168.20.x
* **วัตถุประสงค์:** สำหรับ PC, Notebook, และ Wi-Fi ของพนักงานทั่วไปที่ต้องเข้าใช้งานระบบ (เช่น `lcbp3.np-dms.work`)
* **VLAN 30: Guests / Untrusted**
* **IP Range:** 192.168.30.x
* **วัตถุประสงค์:** สำหรับ Wi-Fi แขก (Guest) ห้ามเข้าถึงเครือข่ายภายในโดยเด็ดขาด
**การตั้งค่า Port Switch:**
หลังจากสร้าง VLANs แล้ว ให้ไปที่ `Devices` > เลือก Switch ของคุณ > `Ports` > กำหนด Port Profile:
* Port ที่เสียบ QNAP NAS: ตั้งค่า Profile เป็น **VLAN 10**
* Port ที่เสียบ PC พนักงาน: ตั้งค่า Profile เป็น **VLAN 20**
---
## 2. 🔥 Firewall Rules (ACLs)
นี่คือหัวใจสำคัญครับ ไปที่ `Settings > Network Security > ACL (Access Control)`
กฎของ Firewall จะทำงานจากบนลงล่าง (ข้อ 1 ทำก่อนข้อ 2)
### A. กฎการห้าม (Deny Rules) - สำคัญที่สุด
**กฎข้อ 1: บล็อก Guest (VLAN 30) ไม่ให้ยุ่งกับใคร**
* **Name:** Isolate-Guests
* **Policy:** Deny
* **Source:** `Network` -> `VLAN 30`
* **Destination:** `Network` -> `VLAN 1`, `VLAN 10`, `VLAN 20`
* *(กฎนี้จะทำให้ Guest ออกอินเทอร์เน็ตได้อย่างเดียว แต่คุยข้าม VLAN ไม่ได้)*
**กฎข้อ 2: บล็อก Server (VLAN 10) ไม่ให้โจมตีคนอื่น**
* **Name:** Isolate-Servers
* **Policy:** Deny
* **Source:** `Network` -> `VLAN 10`
* **Destination:** `Network` -> `VLAN 20`
* *(กฎนี้ป้องกันไม่ให้ Server (QNAP) ที่อาจถูกแฮก เริ่มเชื่อมต่อไปยัง PC ของพนักงาน (VLAN 20) เพื่อแพร่กระจาย Malware)*
**กฎข้อ 3: บล็อก Office ไม่ให้เข้าหน้า Admin**
* **Name:** Block-Office-to-Management
* **Policy:** Deny
* **Source:** `Network` -> `VLAN 20`
* **Destination:** `Network` -> `VLAN 1`
* *(ป้องกันไม่ให้พนักงานทั่วไปเข้าหน้าตั้งค่า Router หรือ Controller)*
### B. กฎการอนุญาต (Allow Rules)
**กฎข้อ 4: อนุญาตให้ Office (VLAN 20) ใช้งาน Services ที่จำเป็น**
* **Name:** Allow-Office-to-Services
* **Policy:** Allow
* **Source:** `Network` -> `VLAN 20`
* **Destination:** `IP Group` -> (สร้าง Group ชื่อ `QNAP_Services` ชี้ไปที่ `192.168.10.100` (IP ของ QNAP))
* **Port:** `Service` -> (สร้าง Port Group ชื่อ `Web_Services`):
* TCP 443 (HTTPS - สำหรับทุก Service เช่น lcbp3, git, pma)
* TCP 80 (HTTP - สำหรับ NPM redirect)
* TCP 81 (NPM Admin UI)
* TCP 2222 (Gitea SSH)
* (ไม่จำเป็นต้องเปิด Port 3000, 3003, 5678, 89 เพราะ NPM จัดการให้แล้ว)
### C. กฎสุดท้าย (Default)
Omada มักจะมีกฎ "Allow All" อยู่ล่างสุด ให้ปล่อยไว้ หรือถ้าคุณต้องการความปลอดภัยสูงสุด (Zero Trust) ให้เปลี่ยนกฎสุดท้ายเป็น "Deny All" (แต่ต้องมั่นใจว่ากฎ Allow ของคุณครอบคลุมทั้งหมดแล้ว)
---
## 3. 🚪 Port Forwarding (การเปิด Service สู่สาธารณะ)
ส่วนนี้ไม่ใช่ Firewall ACL แต่จำเป็นเพื่อให้คนนอกเข้าใช้งานได้ครับ
ไปที่ `Settings > Transmission > Port Forwarding`
สร้างกฎเพื่อส่งต่อการจราจรจาก WAN (อินเทอร์เน็ต) ไปยัง Nginx Proxy Manager (NPM) ที่อยู่บน QNAP (VLAN 10)
* **Name:** Allow-NPM-HTTPS
* **External Port:** 443
* **Internal Port:** 443
* **Internal IP:** `192.168.10.100` (IP ของ QNAP)
* **Protocol:** TCP
* **Name:** Allow-NPM-HTTP (สำหรับ Let's Encrypt)
* **External Port:** 80
* **Internal Port:** 80
* **Internal IP:** `192.168.10.100` (IP ของ QNAP)
* **Protocol:** TCP
### สรุปผังการเชื่อมต่อ
1. **ผู้ใช้ภายนอก** -> `https://lcbp3.np-dms.work`
2. **ER7206** รับที่ Port 443
3. **Port Forwarding** ส่งต่อไปยัง `192.168.10.100:443` (QNAP NPM)
4. **NPM** (บน QNAP) ส่งต่อไปยัง `backend:3000` หรือ `frontend:3000` ภายใน Docker
5. **ผู้ใช้ภายใน (Office)** -> `https://lcbp3.np-dms.work`
6. **Firewall ACL** (กฎข้อ 4) อนุญาตให้ VLAN 20 คุยกับ `192.168.10.100:443`
7. (ขั้นตอนที่ 3-4 ทำงานเหมือนเดิม)
การตั้งค่าตามนี้จะช่วยแยกส่วน Server ของคุณออกจากเครือข่ายพนักงานอย่างชัดเจน ซึ่งปลอดภัยกว่าการวางทุกอย่างไว้ในวง LAN เดียวกันมากครับ

View File

@@ -0,0 +1,143 @@
# การติดตั้ง Nginx Proxy Manager (NPM) ใน Docker
---
## **📝 คำอธิบายและข้อควรพิจารณา**
* 1 Redis (Service: cache)
* Image: redis:7-alpine มีขนาดเล็กและทันสมัย
* Port: ไม่ได้ expose port 6379 ออกมาที่ Host QNAP เพราะตามสถาปัตยกรรม Service backend (NestJS) จะคุยกับ cache (Redis) ผ่าน lcbp3 network ภายในโดยตรง ซึ่งปลอดภัยกว่าครับ
* Volume: map data ไปที่ /share/Container/cache/data เผื่อใช้ Redis ในการทำ Persistent Cache (ถ้าต้องการแค่ Locking อาจจะไม่จำเป็นต้อง map volume ก็ได้ครับ)
* User ID: Image redis:7-alpine รันด้วย user redis (UID 999)
* 2 Elasticsearch (Service: search)
* Image: elasticsearch:8.11.1 ผมเลือกเวอร์ชัน 8 ที่ใหม่และระบุชัดเจน (ไม่ใช้ latest) เพื่อความเสถียรครับ
* Port: ไม่ได้ expose port 9200 ออกมาที่ Host เช่นกัน เพราะ NPM_setting.md ระบุว่า npm (Nginx Proxy Manager) จะ forward search.np-dms.work ไปยัง service search ที่ port 9200 ผ่าน lcbp3 network ครับ
* Environment (สำคัญมาก):
* discovery.type: "single-node": ต้องมี ไม่อย่างนั้น Elasticsearch V.8 จะไม่ยอม start ถ้าไม่พบ node อื่นใน cluster
* xpack.security.enabled: "false": เพื่อความสะดวกในการพัฒนาระยะแรก NestJS จะได้เชื่อมต่อ API port 9200 ได้เลย (หากเปิดใช้งานจะต้องตั้งค่า SSL และ Token ซึ่งซับซ้อนกว่ามาก)
* ES_JAVA_OPTS: "-Xms1g -Xmx1g": เป็น Best Practice ที่ต้องกำหนด Heap Size ให้ Elasticsearch (ในที่นี้คือ 1GB)
* User ID: Image elasticsearch รันด้วย user elasticsearch (UID 1000)
---
## กำหนดสิทธิ
```bash
# สร้าง Directory
mkdir -p /share/Container/services/cache/data
mkdir -p /share/Container/services/search/data
# กำหนดสิทธิ์ให้ตรงกับ User ID ใน Container
# Redis (UID 999)
chown -R 999:999 /share/Container/services/cache/data
chmod -R 750 /share/Container/services/cache/data
# Elasticsearch (UID 1000)
chown -R 1000:1000 /share/Container/services/search/data
chmod -R 750 /share/Container/services/search/data
```
## Docker file
```yml
# File: /share/Container/services/docker-compose.yml (หรือไฟล์ที่คุณใช้รวม)
# DMS Container v1_4_1: เพิ่ม Application name: services, Services 'cache' (Redis) และ 'search' (Elasticsearch)
x-restart: &restart_policy
restart: unless-stopped
x-logging: &default_logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
networks:
lcbp3:
external: true
services:
# ----------------------------------------------------------------
# 1. Redis (สำหรับ Caching และ Distributed Lock)
# Service Name: cache (ตามที่ NPM และ Backend Plan อ้างอิง)
# ----------------------------------------------------------------
cache:
<<: [*restart_policy, *default_logging]
image: redis:7-alpine # ใช้ Alpine image เพื่อให้มีขนาดเล็ก
container_name: cache
stdin_open: true
tty: true
deploy:
resources:
limits:
cpus: "1.0"
memory: 2G # Redis เป็น in-memory, ให้ memory เพียงพอต่อการใช้งาน
reservations:
cpus: "0.25"
memory: 512M
environment:
TZ: "Asia/Bangkok"
networks:
- lcbp3 # เชื่อมต่อ network ภายในเท่านั้น
volumes:
- "/share/Container/cache/data:/data" # Map volume สำหรับเก็บข้อมูล (ถ้าต้องการ persistence)
healthcheck:
test: ["CMD", "redis-cli", "ping"] # ตรวจสอบว่า service พร้อมใช้งาน
interval: 10s
timeout: 5s
retries: 5
# ----------------------------------------------------------------
# 2. Elasticsearch (สำหรับ Advanced Search)
# Service Name: search (ตามที่ NPM และ Backend Plan อ้างอิง)
# ----------------------------------------------------------------
search:
<<: [*restart_policy, *default_logging]
image: elasticsearch:8.11.1 # แนะนำให้ระบุเวอร์ชันชัดเจน (V.8)
container_name: search
stdin_open: true
tty: true
deploy:
resources:
limits:
cpus: "2.0" # Elasticsearch ใช้ CPU และ Memory ค่อนข้างหนัก
memory: 4G
reservations:
cpus: "0.5"
memory: 2G
environment:
TZ: "Asia/Bangkok"
# --- Critical Settings for Single-Node ---
discovery.type: "single-node" # สำคัญมาก: กำหนดให้รันแบบ 1 node
# --- Security (Disable for Development) ---
# ปิด xpack security เพื่อให้ NestJS เชื่อมต่อง่าย (backend -> search:9200)
# หากเป็น Production จริง ควรเปิดใช้งานและตั้งค่า token/cert ครับ
xpack.security.enabled: "false"
# --- Performance Tuning ---
# กำหนด Heap size (1GB) ให้เหมาะสมกับ memory limit (4GB)
ES_JAVA_OPTS: "-Xms1g -Xmx1g"
networks:
- lcbp3 # เชื่อมต่อ network ภายใน (NPM จะ proxy port 9200 จากภายนอก)
volumes:
- "/share/Container/search/data:/usr/share/elasticsearch/data" # Map volume สำหรับเก็บ data/indices
healthcheck:
# รอจนกว่า cluster health จะเป็น yellow หรือ green
test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q '\"status\":\"green\"\\|\\\"status\":\"yellow\"'"]
interval: 30s
timeout: 10s
retries: 5
```

91
Documnets/n8n_setting.md Normal file
View File

@@ -0,0 +1,91 @@
# การติดตั้ง n8n ใน Docker
* user id ของ gites:
* uid=1000(node) gid=1000(node) groups=1000(node)
## กำหนดสิทธิ
```bash
# สำหรับ n8n volumes
chown -R 1000:1000 /share/Container/n8n
chmod -R 755 /share/Container/n8n
```
## Docker file
```yml
# File: share/Container/n8n/docker-compose.yml
# DMS Container v1_4_1 แยก service และ folder, Application name:n8n service n8n
x-restart: &restart_policy
restart: unless-stopped
x-logging: &default_logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
services:
n8n:
<<: [*restart_policy, *default_logging]
image: n8nio/n8n:latest
container_name: n8n
stdin_open: true
tty: true
deploy:
resources:
limits:
cpus: "1.5"
memory: 2G
reservations:
cpus: "0.25"
memory: 512M
environment:
TZ: "Asia/Bangkok"
NODE_ENV: "production"
# N8N_PATH: "/n8n/"
N8N_PUBLIC_URL: "https://n8n.np-dms.work/"
WEBHOOK_URL: "https://n8n.np-dms.work/"
N8N_EDITOR_BASE_URL: "https://n8n.np-dms.work/"
N8N_PROTOCOL: "https"
N8N_HOST: "n8n.np-dms.work"
N8N_PORT: 5678
N8N_PROXY_HOPS: "1"
N8N_DIAGNOSTICS_ENABLED: 'false'
N8N_SECURE_COOKIE: 'true'
N8N_ENCRYPTION_KEY: "9AAIB7Da9DW1qAhJE5/Bz4SnbQjeAngI"
N8N_BASIC_AUTH_ACTIVE: 'true'
N8N_BASIC_AUTH_USER: admin
N8N_BASIC_AUTH_PASSWORD: Center#2025
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: 'true'
GENERIC_TIMEZONE: "Asia/Bangkok"
DB_TYPE: mysqldb
DB_MYSQLDB_DATABASE: "n8n"
DB_MYSQLDB_USER: "center"
DB_MYSQLDB_PASSWORD: "Center#2025"
DB_MYSQLDB_HOST: "mariadb"
DB_MYSQLDB_PORT: 3306
ports:
- "5678:5678"
networks:
lcbp3: {}
volumes:
- "/share/Container/n8n:/home/node/.n8n"
- "/share/Container/n8n/cache:/home/node/.cache"
- "/share/Container/n8n/scripts:/scripts"
- "/share/Container/n8n/data:/data"
- "/var/run/docker.sock:/var/run/docker.sock"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5678/"]
# test: ["CMD", "curl", "-f", "http://127.0.0.1:5678/ || exit 1"]
interval: 15s
timeout: 5s
retries: 30
networks:
lcbp3:
external: true
```

View File

@@ -0,0 +1,120 @@
# **🗺️ แผนผัง Network Architecture & Firewall (LCBP3-DMS)**
แผนผังนี้แสดงการแบ่งส่วนเครือข่าย (VLANs) และกฎ Firewall (ACLs) สำหรับ TP-Link Omada (ER7206/OC200) เพื่อรักษาความปลอดภัยของ QNAP NAS และ Docker Services
## **1\. แผนผังการเชื่อมต่อ (Connection Flow Diagram)**
graph TD
direction TB
subgraph Flow1 \[\<b\>การเชื่อมต่อจากภายนอก (Public WAN)\</b\>\]
User\[ผู้ใช้งานภายนอก (Internet)\]
end
subgraph Router \[\<b\>Router (ER7206)\</b\> \- Gateway\]
User \-- "Port 80/443 (HTTPS/HTTP)" \--\> ER7206
ER7206(\<b\>Port Forwarding\</b\>\<br/\>TCP 80 \-\> 192.168.10.100:80\<br/\>TCP 443 \-\> 192.168.10.100:443)
end
subgraph VLANs \[\<b\>เครือข่ายภายใน (VLANs & Firewall Rules)\</b\>\]
direction LR
subgraph VLAN10 \[\<b\>VLAN 10: Servers (DMZ)\</b\>\<br/\>192.168.10.x\]
QNAP\[\<b\>QNAP NAS (192.168.10.100)\</b\>\]
end
subgraph VLAN20 \[\<b\>VLAN 20: Office\</b\>\<br/\>192.168.20.x\]
OfficePC\[PC พนักงาน/Wi-Fi\]
end
subgraph VLAN30 \[\<b\>VLAN 30: Guests\</b\>\<br/\>192.168.30.x\]
GuestPC\[Guest Wi-Fi\]
end
subgraph Firewall \[\<b\>Firewall ACLs (ควบคุมโดย OC200)\</b\>\]
direction TB
rule1(\<b\>Rule 1: DENY\</b\>\<br/\>Guest (VLAN 30\) \-\> All VLANs)
rule2(\<b\>Rule 2: DENY\</b\>\<br/\>Server (VLAN 10\) \-\> Office (VLAN 20))
rule3(\<b\>Rule 3: ALLOW\</b\>\<br/\>Office (VLAN 20\) \-\> QNAP (192.168.10.100)\<br/\>Ports: 443, 80, 81, 2222\)
end
%% \--- แสดงผล Firewall Rules \---
GuestPC \-.x|rule1| QNAP
QNAP \-.x|rule2| OfficePC
OfficePC \-- "\[https://lcbp3.np-dms.work\](https://lcbp3.np-dms.work)" \--\>|rule3| QNAP
end
%% \--- เชื่อมต่อ Router กับ QNAP \---
ER7206 \--\> QNAP
subgraph Docker \[\<b\>Docker Network 'lcbp3' (ภายใน QNAP)\</b\>\]
direction TB
subgraph PublicServices \[Services ที่ NPM เปิดสู่ภายนอก\]
direction LR
NPM\[\<b\>NPM (Nginx Proxy Manager)\</b\>\<br/\>รับการจราจรจาก QNAP\]
Frontend(frontend:3000)
Backend(backend:3000)
Gitea(gitea:3000)
PMA(pma:80)
N8N(n8n:5678)
end
subgraph InternalServices \[Internal Services (Backend เรียกใช้เท่านั้น)\]
direction LR
DB(mariadb:3306)
Cache(cache:6379)
Search(search:9200)
end
%% \--- การเชื่อมต่อภายใน Docker \---
NPM \-- "lcbp3.np-dms.work" \--\> Frontend
NPM \-- "backend.np-dms.work" \--\> Backend
NPM \-- "git.np-dms.work" \--\> Gitea
NPM \-- "pma.np-dms.work" \--\> PMA
NPM \-- "n8n.np-dms.work" \--\> N8N
Backend \-- "lcbp3 Network" \--\> DB
Backend \-- "lcbp3 Network" \--\> Cache
Backend \-- "lcbp3 Network" \--\> Search
end
%% \--- เชื่อมต่อ QNAP กับ Docker \---
QNAP \--\> NPM
%% \--- Styling \---
classDef default fill:\#f9f9f9,stroke:\#333,stroke-width:2px;
classDef router fill:\#e6f7ff,stroke:\#0056b3,stroke-width:2px;
classDef vlan fill:\#fffbe6,stroke:\#d46b08,stroke-width:2px;
classDef docker fill:\#e6ffed,stroke:\#096dd9,stroke-width:2px;
classDef internal fill:\#f0f0f0,stroke:\#595959,stroke-width:2px,stroke-dasharray: 5 5;
classDef fw fill:\#fff0f0,stroke:\#d9363e,stroke-width:2px,stroke-dasharray: 3 3;
class Router,ER7206 router;
class VLANs,VLAN10,VLAN20,VLAN30 vlan;
class Docker,PublicServices,InternalServices docker;
class DB,Cache,Search internal;
class Firewall,rule1,rule2,rule3 fw;
## **2\. สรุปการตั้งค่า Firewall ACLs (สำหรับ Omada OC200)**
นี่คือรายการกฎ (Rules) ที่คุณต้องสร้างใน Settings \> Network Security \> ACL (เรียงลำดับจากบนลงล่าง):
| ลำดับ | Name | Policy | Source | Destination | Ports |
| :---- | :---- | :---- | :---- | :---- | :---- |
| **1** | Isolate-Guests | **Deny** | Network \-\> VLAN 30 (Guests) | Network \-\> VLAN 1, 10, 20 | All |
| **2** | Isolate-Servers | **Deny** | Network \-\> VLAN 10 (Servers) | Network \-\> VLAN 20 (Office) | All |
| **3** | Block-Office-to-Mgmt | **Deny** | Network \-\> VLAN 20 (Office) | Network \-\> VLAN 1 (Mgmt) | All |
| **4** | Allow-Office-to-Services | **Allow** | Network \-\> VLAN 20 (Office) | IP Group \-\> QNAP\_Services (192.168.10.100) | Port Group \-\> Web\_Services (443, 80, 81, 2222\) |
| **5** | (Default) | Allow | Any | Any | All |
## **3\. สรุปการตั้งค่า Port Forwarding (สำหรับ Omada ER7206)**
นี่คือรายการกฎที่คุณต้องสร้างใน Settings \> Transmission \> Port Forwarding:
| Name | External Port | Internal IP | Internal Port | Protocol |
| :---- | :---- | :---- | :---- | :---- |
| Allow-NPM-HTTPS | 443 | 192.168.10.100 | 443 | TCP |
| Allow-NPM-HTTP | 80 | 192.168.10.100 | 80 | TCP |