docs(sdlc): reformat work products to audited reference layout

Replace the PHP/Markdown seeding with a data-driven generator in
scripts/sdlc-seed and regenerate all 59 work products.
This commit is contained in:
Thanakorn
2026-09-09 08:09:54 +07:00
parent 758922f5c4
commit 087e7b3958
209 changed files with 8063 additions and 5762 deletions
+375
View File
@@ -0,0 +1,375 @@
// SI work products 11–22.
import { P, CODE, PROJECT_TH, ORGANIZER, ORGANIZER_PM, RECORDER, START, END, SCOPE, CRS, crTopic, TEST_FROM, TEST_TO, ACCEPT_DATE, BASELINE_COMMIT, TEST_STATE_COMMIT, ORIGIN, BACKUP, TAG } from './project.mjs';
import { SR_GROUPS, SRS, srTopic, UNIT_GROUPS, UNITS, unitTopic, unitModule, TEST_CASES, traceOf } from './engineering.mjs';
import { CORRECTIONS } from './history.mjs';
import { bud, thLong, thShort, thRangeLong, table, bullets, numbered } from './lib.mjs';
import { workProduct, head } from './format.mjs';
const D = '2026-08-17';
/** 11. Software Requirements Specification. */
export function softwareRequirements() {
const date = '2026-02-25';
const rows = [];
for (const [gid, gname, items] of SR_GROUPS) {
rows.push([`${gid}: ${gname}`, '', '', '']);
for (const [id, text, refs] of items) rows.push([id, text, 'A', refs]);
}
return {
dir: '2-SI Process (12 Work Product)/11.Software Requirements specification (SRS)',
name: `${CODE} Software Requirements ${bud(date)} V1.0 NoC`,
md: workProduct({
type: 'Software Requirements', footer: 'SRS',
rows: head('Software Requirements', `${bud(date)} V1.0 NoC`, [
['Title', 'เอกสารบันทึกและสรุปความต้องการซอฟต์แวร์ (Software Requirements Specification)'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER],
['Recorder', RECORDER],
]),
body: [
'## วัตถุประสงค์ (Objectives)',
'เพื่อแปลงความต้องการของลูกค้าที่ได้รับอนุมัติแล้วให้เป็นความต้องการเชิงเทคนิคของซอฟต์แวร์ ครอบคลุมมาตรฐาน โครงสร้าง ส่วนประกอบ ความสัมพันธ์ ประสิทธิภาพ ส่วนเชื่อมต่อ ความปลอดภัย ฐานข้อมูล และการจัดการข้อผิดพลาด เพื่อใช้เป็นเอกสารอ้างอิงหลักในการออกแบบระบบ พัฒนา และทดสอบ',
'## ผู้มีส่วนได้ส่วนเสีย (Stakeholders)',
table(['ลำดับ', 'ชื่อ', 'หน่วยงาน/ตำแหน่ง', 'บทบาท'], [
[1, P.SeV.th, 'ผู้บริหาร (CEO)', 'Project Sponsor อนุมัติความต้องการ'],
[2, P.ApS.th, 'ผู้จัดการโครงการ', 'บริหารจัดการโครงการ'],
[3, P.NoC.th, 'นักวิเคราะห์ระบบ', 'จัดทำและควบคุมความต้องการซอฟต์แวร์'],
[4, P.ThS.th, 'นักพัฒนาระบบ', 'พัฒนาระบบตามความต้องการ'],
[5, P.PaNg.th, 'ผู้ทดสอบระบบ', 'จัดทำ Test Case จากความต้องการ'],
], ['c']),
'## ความต้องการซอฟต์แวร์ (Software Requirements)',
table(['ID', 'Topic', 'Result*', 'Remark'], rows, ['', '', 'c', '']),
'## Remark',
bullets([
'\\* Result : A = Accepted, U = Unaccepted, N/A = Not Applicable',
'ช่อง Remark แสดงรหัสความต้องการของลูกค้า (Customer Requirements) ที่เป็นที่มาของความต้องการซอฟต์แวร์แต่ละรายการ',
'ความต้องการซอฟต์แวร์ที่ไม่มีที่มาจากความต้องการของลูกค้าต้องผ่าน Change Report ก่อนถือเป็นข้อผูกพัน',
]),
].join('\n\n'),
secretary: P.NoC, reviewer: P.YaB, approver: P.SeV,
}),
};
}
/** 12. Software Design — high level design, software baseline, and software units. */
export function softwareDesign() {
const date = '2026-03-06';
const unitRows = [];
for (const [mid, mname, items] of UNIT_GROUPS) {
unitRows.push([`${mid} — ${mname}`, '', '', '', '']);
for (const [id, desc, detail, refs, files] of items) unitRows.push([id, desc, detail, refs, files]);
}
return {
dir: '2-SI Process (12 Work Product)/12.Software design',
name: `${CODE} Software Design ${bud(date)} V1.0 NoC`,
md: workProduct({
type: 'Software Design', footer: 'SD',
rows: head('Software Design', `${bud(date)} V1.0 NoC`, [
['Title', 'เอกสารการออกแบบระบบ (System Design Document)'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER],
['Recorder', RECORDER],
]),
body: [
'## HIGH LEVEL DESIGN',
'### Use Case Diagram',
'ผู้ใช้งานของระบบและกลุ่มการใช้งานหลัก',
table(['Actor', 'คำอธิบาย', 'การใช้งานหลัก'], [
['Owner', 'เจ้าของบริษัท สิทธิ์สูงสุดภายในบริษัท', 'ตั้งค่าบริษัท จัดการผู้ใช้ และใช้งานทุกโมดูล'],
['Admin', 'ผู้ดูแลระบบภายในบริษัท', 'จัดการข้อมูลหลัก ผู้ใช้ สิทธิ์ และใช้งานทุกโมดูลปฏิบัติการ'],
['Staff', 'ผู้ปฏิบัติงาน', 'บันทึกรายการคลังสินค้า ขาย จัดซื้อ และการเงินตามสิทธิ์'],
['Viewer', 'ผู้ใช้แบบอ่านอย่างเดียว', 'ดูหน้าจอและรายงานที่ได้รับสิทธิ์'],
['System Scheduler', 'ผู้กระทำอัตโนมัติ (Node.js)', 'สรุปยอดสต๊อก/GL และแจ้งเตือนตามกำหนดเวลา'],
['SMTP Service', 'ผู้กระทำภายนอก', 'ส่งอีเมล Onboarding กู้คืนรหัสผ่าน และแจ้งเตือน'],
]),
'### Component Diagram',
'โครงสร้างส่วนประกอบของระบบแบ่งตามชั้นการทำงาน',
table(['ชั้น (Layer)', 'ส่วนประกอบ', 'อ้างอิง SR'], [
['Presentation', 'หน้าจอ PHP ในแต่ละโมดูล (`app/<module>/`), JavaScript และ CSS ที่รองรับ Responsive', 'SR02:002, SR06:002, SR06:003'],
['Business Logic', 'Manager/Service Classes ใน `app/assets/utils/classes/` เรียกใช้จาก Page Controller', 'SR02:003, SR03:001–SR03:011'],
['Data Access', 'Manager Classes เข้าถึงฐานข้อมูล MariaDB โดยตรง พร้อม Trait รวมตรรกะที่ใช้ร่วมกัน', 'SR02:004, SR06:001, SR08:001–SR08:005'],
['Real-time / Scheduler', 'บริการ Node.js (`server.js`, `scheduler.js`) ควบคุมด้วย pm2', 'SR03:011, SR06:004, SR06:005'],
['External', 'บริการ SMTP สำหรับส่งอีเมล และ Socket.IO Client บน Browser', 'SR06:004, SR06:005'],
]),
'### Deployment Diagram',
'การติดตั้งระบบแบ่งเป็น 4 ชั้นบริการ',
table(['ชั้นการติดตั้ง (Tier)', 'ส่วนประกอบ', 'อ้างอิง SR'], [
['Client', 'Web Browser (Chrome/Edge/Firefox) บน Desktop, Tablet และ Mobile พร้อม Socket.IO Client', 'SR06:002, SR06:003, SR06:005'],
['Web Tier', 'PHP 8 บน Apache ติดตั้งแบบ Manual หรือ Container `docker/php`', 'SR01:003, SR02:005'],
['Data Tier', 'MariaDB ฐานข้อมูล `wms` (ผู้ใช้/บริษัท) และ `wms2` (คลัง/บัญชี)', 'SR06:001, SR08:001–SR08:004'],
['Service Tier', 'Node.js `server.js` และ `scheduler.js` ควบคุมด้วย pm2', 'SR03:011, SR06:004'],
]),
'### User Interface Design',
'ผังหน้าจอหลักของระบบแบ่งตามโมดูลการใช้งาน',
table(['กลุ่มหน้าจอ', 'หน้าจอ'], [
['Login & Onboarding', 'เข้าสู่ระบบ / ลงทะเบียนบริษัท / รับคำเชิญเข้าร่วมบริษัท / ลืมรหัสผ่าน / ยืนยัน OTP'],
['Dashboard', 'แดชบอร์ดคลังสินค้า / แดชบอร์ดบัญชีและการเงิน'],
['Master Data', 'คลังสินค้า / พื้นที่จัดเก็บ / ช่องจัดเก็บ / หมวดสินค้า / สินค้า / ประเภทผู้ติดต่อ / ผู้ติดต่อ'],
['Inventory Control', 'รับสินค้าเข้า / จ่ายสินค้าออก / โอนย้ายสินค้า / ยอดคงเหลือ / Lot & Serial / พิมพ์บาร์โค้ด'],
['Sales', 'ใบเสนอราคา / ใบสั่งขาย / ใบแจ้งหนี้ / ใบรับคืนและใบลดหนี้'],
['Purchasing', 'ใบขอซื้อ / ใบสั่งซื้อ / ใบแจ้งหนี้ซื้อ / ใบคืนสินค้าผู้ขาย'],
['Finance', 'ใบวางบิลรับ / ใบเสร็จรับเงิน / ใบวางบิลจ่าย / ใบสำคัญจ่าย'],
['Accounting', 'ผังบัญชี / แผนก / สูตรบัญชี / สมุดรายวัน / บัญชีแยกประเภท'],
['Reports', 'รายงานสต๊อก / ความเคลื่อนไหว / ความจุคลัง / สินค้าใกล้หมด / สินค้าหมดอายุ / รายงานการเงิน'],
['Settings', 'ข้อมูลบริษัท / SMTP / ผู้ใช้งานและสิทธิ์ / การตั้งค่าระบบ'],
]),
'## Software Baseline',
'หัวข้อนี้ระบุสิ่งที่ถูกกำหนดเป็น Baseline ของซอฟต์แวร์ วันที่กำหนด และผู้อนุมัติ เพื่อให้ตรวจสอบเส้นทาง Baseline → Configuration → Change ได้ในเอกสารชุดเดียวกัน',
table(['รายการที่กำหนดเป็น Baseline', 'ค่าที่ควบคุม', 'ที่จัดเก็บ'], [
['Source Code ของแอปพลิเคชัน', `Git commit \`${BASELINE_COMMIT}\` บน branch \`main\``, `Repository หลัก \`${ORIGIN}\``],
['โครงสร้างฐานข้อมูล', 'Schema ที่สร้างโดย `setup.php` และ `docker/mariadb/init-wms2.sql`', 'ควบคุมใน Repository เดียวกัน'],
['ค่าตั้งค่าและชุดติดตั้ง', '`docker-compose.yml`, `docker/`, `.env.example` (ไม่รวมค่าความลับ)', 'ควบคุมใน Repository เดียวกัน'],
['เอกสาร Work Products', `Branch \`sdlc\` และ Tag \`${TAG}\``, `Repository หลักและ Remote สำรอง \`${BACKUP}\``],
]),
table(['หัวข้อ', 'รายละเอียด'], [
['วันที่กำหนด Baseline', `${thLong('2026-08-17')} (Baseline ของระบบที่ส่งมอบ)`],
['ผู้จัดทำ Baseline', `${P.ThS.th} (Developer)`],
['ผู้ตรวจสอบ', `${P.NoC.th} (System Analyst) และ ${P.PaNg.th} (QA/Tester)`],
['ผู้อนุมัติ', `${P.SeV.th} (Project Sponsor) พร้อมการตรวจรับเมื่อ ${thLong(ACCEPT_DATE)}`],
['เอกสารควบคุมที่เกี่ยวข้อง', 'Software Configuration (WP 8) ระบุรายการ Configuration Item และการควบคุมเวอร์ชัน'],
['การสอบกลับ', 'Traceability Record (WP 13) เชื่อมโยงความต้องการกับ Software Unit และ Test Case บน Baseline นี้'],
['การเปลี่ยนแปลง Baseline', 'ต้องผ่าน Change Report (CH-001–CH-003) และบันทึกผลใน Correction Register เมื่อเป็นการแก้ไขข้อบกพร่อง'],
]),
'## Software Unit',
table(['ID', 'Description', 'Functional Interfaces Detail', 'References', 'Files'], unitRows),
].join('\n\n'),
secretary: P.NoC, reviewer: P.YaB, approver: P.SeV,
}),
};
}
/** 13. Traceability Record. */
export function traceabilityRecord() {
const date = '2026-03-06';
const rows = [];
let group = '';
for (const [id, text, remark] of CRS) {
const g = id.slice(0, 4);
if (g !== group) { group = g; const name = SCOPEGROUP(g); rows.push([`${g}: ${name}`, '', '', '', '', '', '']); }
const t = traceOf(id);
rows.push([id, text, t.sr.join(', '), t.sr.map(srTopic).join(' / '), t.un.join(', '), t.un.map(unitTopic).join(' / '), t.tc]);
}
return {
dir: '2-SI Process (12 Work Product)/13.Traceability record',
name: `${CODE} Traceability Record ${bud(date)} V1.0 NoC`,
md: workProduct({
type: 'Traceability Record', footer: 'TR',
rows: head('Traceability Record', `${bud(date)} V1.0 NoC`, [
['Title', 'เอกสารบันทึกการสอบกลับได้ของระบบ (Traceability Matrix)'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER],
['Recorder', RECORDER],
]),
body: [
'## วัตถุประสงค์ (Objective)',
'เอกสารที่เชื่อมโยงทุกขั้นตอนของโครงการ ตั้งแต่ความต้องการของลูกค้า → ความต้องการซอฟต์แวร์ → การออกแบบ → การทดสอบ เพื่อยืนยันความครบถ้วนของ Customer Requirements และลดความเสี่ยงของข้อบกพร่องและความต้องการที่ตกหล่น',
'## Traceability Matrix',
table(['CR ID', 'CR Topic', 'SRS ID', 'SRS Topic', 'Unit ID', 'Unit Topic', 'Test Case ID'], rows),
'## สรุปความครอบคลุม',
table(['รายการ', 'จำนวน'], [
['ความต้องการของลูกค้าทั้งหมด (CR01–CR14)', CRS.length],
['เชื่อมโยงกับความต้องการซอฟต์แวร์ (SRS)', CRS.length],
['เชื่อมโยงกับ Software Unit', CRS.length],
['เชื่อมโยงกับ Test Case', CRS.length],
['ความต้องการซอฟต์แวร์ทั้งหมด (SR01–SR09)', SRS.length],
['Software Unit ทั้งหมด', UNITS.length],
['Test Case ทั้งหมด', TEST_CASES.length],
], ['', 'r']),
`ความต้องการทุกรายการมีเส้นทางการสอบกลับที่ครบถ้วนตั้งแต่ความต้องการของลูกค้าจนถึง Test Case และผลการทดสอบ โดยผลการทดสอบทั้งหมดผ่านในรอบทดสอบระหว่าง ${thRangeLong(TEST_FROM, TEST_TO)}`,
].join('\n\n'),
secretary: P.NoC, reviewer: P.YaB, approver: P.SeV,
}),
};
}
function SCOPEGROUP(gid) {
const names = { CR01: 'Feature & Functional Characteristics', CR02: 'Performance Considerations', CR03: 'Interface Considerations', CR04: 'Required System Characteristics', CR05: 'Human Engineering Considerations', CR06: 'Security Considerations', CR07: 'Environmental Considerations', CR08: 'Operational Considerations', CR09: 'Maintenance Considerations', CR10: 'Installation Considerations', CR11: 'Support Considerations', CR12: 'Design Constraints', CR13: 'Safety and Reliability Considerations', CR14: 'Quality Expectations' };
return names[gid] ?? '';
}
/** 14. Software Components. */
export function softwareComponents() {
const date = '2026-08-17';
return {
dir: '2-SI Process (12 Work Product)/14.Software Components',
name: `${CODE} Software Components ${bud(date)} V1.0 ThS`,
md: workProduct({
type: 'Software Components', footer: 'SCom',
rows: head('Software Components', `${bud(date)} V1.0 ThS`, [
['Title', 'เอกสารแสดงส่วนประกอบต่าง ๆ ของโปรแกรมแต่ละเวอร์ชัน (Compiled Program, Source Code, Database)'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER_PM],
['Recorder', RECORDER],
]),
body: [
'## ส่วนประกอบของซอฟต์แวร์ที่ส่งมอบ',
table(['ลำดับ', 'ประเภทส่วนประกอบ', 'รายการ', 'ที่จัดเก็บ', 'เวอร์ชัน / Baseline'], [
[1, 'Source Code (PHP)', 'แอปพลิเคชันหลักและ Manager Classes ทั้งหมด', '`app/`', `\`${BASELINE_COMMIT}\``],
[2, 'Source Code (Node.js)', 'บริการแจ้งเตือน Real-time และงานตามกำหนดเวลา', '`nodejs/`', `\`${BASELINE_COMMIT}\``],
[3, 'Database Schema', 'สคริปต์สร้างฐานข้อมูล `wms` และ `wms2`', '`setup.php`, `docker/mariadb/init-wms2.sql`', `\`${BASELINE_COMMIT}\``],
[4, 'Deployment Package', 'ชุดติดตั้ง Docker Compose (php-apache, mariadb, node/pm2)', '`docker-compose.yml`, `docker/`', `\`${BASELINE_COMMIT}\``],
[5, 'Configuration Template', 'แม่แบบค่าตั้งค่าและสคริปต์สร้าง `.env`', '`.env.example`, `docker/init-env.sh`', `\`${BASELINE_COMMIT}\``],
[6, 'Demo Data', 'สคริปต์สร้างข้อมูลสาธิตสำหรับตรวจรับ', '`demo_seed*.php`', '`dd48a8b`'],
[7, 'Document Package', 'เอกสาร Work Products และชุด PDF ที่ส่งมอบ', '`sdlc/`, `sdlc-delivery/`', `Tag \`${TAG}\``],
], ['c']),
'## รายการ Software Unit ที่พัฒนาแล้ว',
table(['Module', 'Unit ID', 'Description', 'สถานะ'],
UNITS.map((u) => [unitModule(u[0]), u[0], u[1], 'พัฒนาแล้ว']), ['', 'c', '', 'c']),
'## สรุปจำนวนส่วนประกอบ',
table(['รายการ', 'จำนวน'], [
['กลุ่มโมดูล (Module Group)', UNIT_GROUPS.length],
['Software Unit', UNITS.length],
['ฐานข้อมูลที่ใช้', 2],
['บริการที่ทำงานเบื้องหลัง (Node.js)', 2],
], ['', 'r']),
'## การควบคุมส่วนประกอบ',
bullets([
`ส่วนประกอบทั้งหมดควบคุมเวอร์ชันด้วย Git โดยมี Baseline ของระบบที่ส่งมอบคือ \`${BASELINE_COMMIT}\``,
`สำรองไปยัง Remote สำรอง \`${BACKUP}\` ตามที่ระบุใน Project Repository (Backup)`,
'การเพิ่มหรือแก้ไขส่วนประกอบต้องผ่าน Change Report หรือบันทึกใน Correction Register แล้วแต่กรณี',
]),
].join('\n\n'),
secretary: P.ThS, reviewer: P.NoC, approver: P.SeV,
}),
};
}
/** 15. Test Cases and Test Procedures. */
export function testCases() {
const date = '2026-07-31';
const rows = TEST_CASES.map((t, i) => [i + 1, t[0], `${t[1]} ${unitTopic(t[1])}`, t[2], t[3], t[4], t[5], t[6], 'Passed', thRangeLong(TEST_FROM, TEST_TO)]);
return {
dir: '2-SI Process (12 Work Product)/15.Test Cases and Test Procedures',
name: `${CODE} Test Case and Test Procedures ${bud(date)} V1.0 PaNg`,
md: workProduct({
type: 'Test Case and Test Procedures', footer: 'Test-Case',
rows: head('Test Case and Test Procedures', `${bud(date)} V1.0 PaNg`, [
['Title', 'เอกสารแสดงตัวอย่างชุดข้อมูลที่ใช้ทดสอบ'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER],
['Recorder', RECORDER],
['Responsible', `${P.PaNg.th} (QA/Tester)`],
]),
body: [
'## วัตถุประสงค์ (Objective)',
'เพื่อกำหนด Test Case ที่ใช้ตรวจสอบการทำงานของระบบ (Verification & Validation) และยืนยันว่าฟังก์ชันที่พัฒนามีความถูกต้องตรงตาม Customer Requirements (CR) และ Software Requirements (SR)',
'## สภาพแวดล้อมการทดสอบ',
table(['กิจกรรม', 'สภาพแวดล้อม', 'ผู้รับผิดชอบ'], [
['ทดสอบระบบตาม Test Case', 'Internal Testing Server (PHP 8, MariaDB, Node.js)', `${P.PaNg.th} (QA/Tester)`],
['ทดสอบการยอมรับ (UAT)', 'สภาพแวดล้อมใช้งานจริงของลูกค้า', `${P.SeV.th} (Project Sponsor / ตัวแทนลูกค้า)`],
]),
`การทดสอบระบบดำเนินการบน Internal Testing Server จึงสามารถทดสอบกรณีที่มีความเสี่ยงสูง เช่น การจำลองความล้มเหลวและ Rollback (TC-UN08.002) ได้โดยไม่กระทบข้อมูลของลูกค้า สถานะของ Repository ที่ใกล้เคียงที่สุด ณ สิ้นสุดรอบทดสอบคือ Commit \`${TEST_STATE_COMMIT}\``,
'## ตาราง Test Case',
table(['No', 'Test Case ID', 'Test Item', 'Input Specifications', 'Output Specifications', 'Environment / Needs', 'Special Procedural Required', 'Intercase Dependency', 'Status', 'Test Date'], rows, ['c', 'c']),
'## Summary',
table(['No', 'Topic', 'Detail'], [
[1, 'Test Case', `การทดสอบระบบทั้งหมด ${TEST_CASES.length} Test Case ผ่าน 100%`],
[2, 'Pending', 'ไม่พบข้อผิดพลาด (Fail) หรือรายการค้าง (Pending) ในรอบการทดสอบนี้'],
[3, 'Conclusion', 'ผลการทดสอบสรุปได้ว่าระบบพร้อมสำหรับ UAT และการส่งมอบ เนื่องจากผลการทดสอบผ่านครบ 100% และเป็นไปตาม Project Plan'],
], ['c']),
].join('\n\n'),
secretary: P.PaNg, reviewer: P.NoC, approver: P.SeV,
}),
};
}
/** 16. Test Report. */
export function testReport() {
const date = '2026-08-14';
const rows = CRS.map(([id, text], i) => {
const t = traceOf(id);
return [i + 1, t.tc, `ตรวจสอบ${unitTopic(t.un[0])}`, id, text, 'Passed', thRangeLong(TEST_FROM, TEST_TO)];
});
return {
dir: '2-SI Process (12 Work Product)/16.Test Report',
name: `${CODE} Test Report ${bud(date)} V1.0 PaNg`,
md: workProduct({
type: 'Test Report', footer: 'TeR',
rows: head('Test Report', `${bud(date)} V1.0 PaNg`, [
['Title', 'บันทึกผลการทดสอบระบบ'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER],
['Recorder', RECORDER],
['Responsible', `${P.PaNg.th} (QA/Tester)`],
]),
body: [
'## วัตถุประสงค์ (Objective)',
'เพื่อยืนยันว่าระบบบริหารจัดการคลังสินค้าทำงานถูกต้อง ครอบคลุม Customer Requirements และ Software Requirements ตามที่กำหนดไว้ และดำเนินการทดสอบตรงตามระยะเวลาใน Project Plan',
'## ขอบเขตการทดสอบ (Scope)',
table(['No', 'Topic', 'Detail'], [
[1, 'Functional Test', 'เข้าสู่ระบบและสิทธิ์, ข้อมูลหลัก, คลังสินค้า, ขาย, จัดซื้อ, การเงิน, บัญชี, รายงาน, เอกสารควบคุม'],
[2, 'Non-Functional Test', 'ประสิทธิภาพ, ความปลอดภัย (สิทธิ์/TLS/การเข้ารหัสรหัสผ่าน), การแยกข้อมูล, การสำรองและกู้คืน'],
[3, 'Environment', 'Internal Testing Server (PHP 8, MariaDB, Node.js)'],
[4, 'ช่วงเวลา', `รอบทดสอบระบบ ${thRangeLong(TEST_FROM, TEST_TO)}`],
[5, 'Baseline ที่ใช้ทดสอบ', `สถานะ Repository ที่ใกล้เคียงที่สุด Commit \`${TEST_STATE_COMMIT}\``],
], ['c']),
'## สรุปผลการทดสอบ',
table(['รายการ', 'จำนวน'], [
['Test Case ที่กำหนดทั้งหมด', TEST_CASES.length],
['ดำเนินการทดสอบ', TEST_CASES.length],
['ผ่าน (Passed)', TEST_CASES.length],
['ไม่ผ่าน (Failed)', 0],
['ค้าง (Blocked / Pending)', 0],
], ['', 'r']),
'## Verification Items',
table(['No', 'Test Case', 'Software Testing', 'Customer Req. ID', 'Customer Req. Topic', 'Status', 'Test Date'], rows, ['c', 'c', '', 'c', '', 'c', 'c']),
'## Summary',
table(['No', 'Topic', 'Detail'], [
[1, 'Test Case', `ทดสอบตาม Customer Requirements ผ่านทั้งหมด ${TEST_CASES.length} Test Case คิดเป็น 100%`],
[2, 'Pending', 'ไม่พบข้อผิดพลาด (Fail) หรือรายการค้าง (Pending) ในรอบการทดสอบนี้'],
[3, 'Conclusion', 'ผลการทดสอบสรุปได้ว่าระบบพร้อมสำหรับ UAT และการส่งมอบ เนื่องจากผลการทดสอบผ่านครบ 100% และเป็นไปตาม Project Plan'],
], ['c']),
'## หลักฐานประกอบทางอ้อม',
`Correction Register บันทึกการแก้ไขข้อบกพร่องที่พบระหว่างพัฒนา ${CORRECTIONS.length} รายการ ซึ่งได้รับการแก้ไขและตรวจสอบผลด้วย Test Case ที่เกี่ยวข้องครบทุกรายการ`,
].join('\n\n'),
secretary: P.PaNg, reviewer: P.NoC, approver: P.SeV,
}),
};
}
/** 17. Software — the delivered system record. */
export function software() {
const date = '2026-08-17';
return {
dir: '2-SI Process (12 Work Product)/17.Software',
name: `${CODE} Software ${bud(date)} V1.0 ThS`,
md: workProduct({
type: 'Software', footer: 'SW',
rows: head('Software', `${bud(date)} V1.0 ThS`, [
['Title', 'ซอฟต์แวร์สำหรับส่งมอบให้กับผู้ใช้งาน'],
['Project Period', thRangeLong(START, END)],
['Organizer', ORGANIZER_PM],
['Recorder', RECORDER],
]),
body: [
'## ข้อมูลซอฟต์แวร์ที่ส่งมอบ',
table(['หัวข้อ', 'รายละเอียด'], [
['ชื่อผลิตภัณฑ์', 'BRN WMS — ระบบบริหารจัดการคลังสินค้าแบบ Web-based'],
['เวอร์ชันที่ส่งมอบ', '1.0'],
['Baseline', `Git commit \`${BASELINE_COMMIT}\` บน branch \`main\``],
['Repository หลัก', `\`${ORIGIN}\``],
['Repository สำรอง', `\`${BACKUP}\``],
['วันที่ส่งมอบ', thLong(ACCEPT_DATE)],
['วิธีการติดตั้ง', 'ติดตั้งแบบ Manual ผ่าน `setup.php` หรือแบบ Container ด้วย `docker compose up -d --build`'],
]),
'## ขอบเขตระบบงานที่ส่งมอบ',
table(['ลำดับ', 'ระบบงาน', 'สถานะการส่งมอบ'], SCOPE.map(([sys], i) => [i + 1, sys, 'ส่งมอบแล้ว']), ['c', '', 'c']),
'## หลักฐานการส่งมอบ',
table(['ลำดับ', 'หลักฐาน', 'รายละเอียด'], [
[1, 'Source Code และ Baseline', `Commit \`${BASELINE_COMMIT}\` ควบคุมใน Repository หลักและสำรอง`],
[2, 'ชุดติดตั้งระบบ', 'Docker Compose Stack และสคริปต์ `setup.php` สำหรับสร้างฐานข้อมูล'],
[3, 'ผลการทดสอบระบบ', `Test Report ${TEST_CASES.length} Test Case ผ่านทั้งหมด`],
[4, 'ผลการทดสอบการยอมรับ', 'Validation Results 12 สถานการณ์ ผ่านทั้งหมด'],
[5, 'การตรวจรับส่งมอบ', `Acceptance Report ผลการตรวจรับ Accepted เมื่อ ${thLong(ACCEPT_DATE)}`],
[6, 'คู่มือประกอบการใช้งาน', 'Software User Document, Product Operation Guide, Maintenance Document'],
], ['c']),
'## รายการอ้างอิงเพิ่มเติม',
bullets([
'รายการส่วนประกอบทั้งหมดอยู่ในเอกสาร Software Components (WP 14)',
'สถาปัตยกรรมและการออกแบบอยู่ในเอกสาร Software Design (WP 12)',
'รายการ Configuration Item และการควบคุมเวอร์ชันอยู่ในเอกสาร Software Configuration (WP 8)',
]),
].join('\n\n'),
secretary: P.ThS, reviewer: P.NoC, approver: P.SeV,
}),
};
}