eCourt-note/docs/requirement/gap-analysis.md
Your Name f4d46c7720 external-api: N10 API ดึงข้อมูลให้ระบบภายนอกด้วย API Key + ถอด F16 export CSV / N7 bookmark JSON แทนด้วย N10 — (1) endpoint เดียว POST /api/external/documents (JSON body {fileId และ/หรือ typeId — ส่งทั้งคู่ = AND เหลือเอกสารเดียว, filter:{type bookmarks|annotations, userId string|array, annotationTypes ค่า enum}}) ให้ backend e-Court เรียก server-to-server ผ่าน header x-api-key คืน {documents:[…]} รูปเดียวเสมอ — bundle ยุบชั้น field เอกสาร + annotations (พร้อม url deep link + replies) + bookmarks ระดับเดียวกัน, url เป็น URL เต็ม origin จาก request ผู้เรียก (x-forwarded-proto/host fallback host ตรง) + basePath (เดิม 2 GET query-param รวมเป็นเส้นเดียว 2026-09-24 · OR→AND + url relative→เต็ม + filter.types→annotationTypes กันสับสนกับ filter.type 2026-09-25) (2) lib/external-api-auth.ts — requireExternalApiKey เทียบ SHA-256 + crypto.timingSafeEqual, env EXTERNAL_API_KEY ไม่ตั้ง/ว่าง = 401 fail closed, ข้อความ 401 เดียวกันกัน enumerate + externalApiError คืน JSON {"error": ไทย} ใช้ร่วมทุก route — module DB-free ให้ tests/lib/external-api-auth.test.ts (5 tests) รันได้ไม่ต้องมี DATABASE_URL (3) lib/external-api.ts parseQueryBody strict กัน typo เงียบ ๆ (field นอก 3 ตัว = 400, annotationTypes ค่านอก enum = 400 บอกค่าที่รับ) + loadDocumentBundles bulk inArray = 3 query ต่อ request ไม่ว่ากลุ่มกี่ไฟล์ กรอง userIds/annotationTypes ใน SQL เรียง F15/N5 (4) route: auth ก่อนแตะ DB + ครอบ try/catch ทุก DB call ล้ม = log ฝั่ง server + 500 JSON ตาม contract ไม่ปล่อยเป็น 500 ของ framework, read-only ไม่ publish SSE ไม่ revalidatePath ไม่มี CORS, REDACTION รวมในผลลัพธ์ (5) ถอด F16/N7 ตามคำขอผู้ใช้ 2026-09-25 (N10 ครอบคลุมข้อมูลชุดเดียวกันพร้อม auth): ลบ app/api/annotations/export-csv + app/api/bookmarks/export + utils/csv.ts + tests/utils/csv.test.ts + ปุ่มส่งออก 2 ปุ่มบนหน้าสรุป + ปุ่ม JSON ใน sidebar + รูป requirement 1.png/2.png (บรรทัดอ้างถึงใน gap-analysis.md เปลี่ยนเป็น historical note) (6) docs sync ครบ: PLAN-API.md แผนฉบับเต็ม 9 รอบ + PLAN-FEAT.md §7 N10 + PLAN-BOOKMARK-PDF.md/gap-analysis.md 5.3.14 เปลี่ยนตอบด้วย N10 + CLAUDE.md + README (env/ตัวอย่าง curl/troubleshooting) + .env.example + .claude/rules/data-layer.md — ผ่าน code review 2 รอบ 2026-09-25: แก้ 500 JSON ตอน DB ล้ม + ถอด fan-out ต่อไฟล์เป็น bulk + ถอด as cast แทน type guard (tsc + vitest 149/149) (คำขอผู้ใช้ 2026-09-25)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-25 12:02:42 +07:00

23 KiB
Raw Blame History

รายงานเทียบ Requirement กับโปรเจกต์ (Gap Analysis)

  • วันที่ตรวจสอบ: 2026-09-14
  • อัปเดตล่าสุด: 2026-09-17 — ปิด gap 4 ข้อ: 5.3.11 ✅ (N5), 5.3.12 ✅ (N6), 5.3.14 ✅ (API ส่งออก bookmark เป็น JSON), 5.3.15 ✅ (export PDF ของ F8 มี bookmark ติดไป) · 2026-09-15 — แก้ไขข้อความข้อ 5.3.18–5.3.25 ตามที่เจ้าของเอกสารยืนยันใหม่
  • เอกสาร requirement ต้นทาง: docs/requirement/1.png, docs/requirement/2.png (ข้อกำหนดระบบบันทึกความเห็นของกรรมการ — Judges' Notes System — รูปทั้งสองถูกถอดออกจาก repo 2026-09-25 ตามคำขอผู้ใช้ ดูต่อได้จาก git history ก่อนหน้านี้)
  • โค้ดที่ใช้เทียบ: branch forgejo-dev — ข้อ 5.3.11–5.3.15 อัปเดตตามโค้ดล่าสุด 2026-09-17 (รวม N5–N6 commit a020e96 และ N7 → JSON export) · ตรวจครั้งแรก ณ commit b3b884c (implement ครบตาม PLAN.md + PLAN-FEAT.md แล้ว ยกเว้น F11 ที่ถูกถอดออก)
  • ช่วงเลขข้อ (ยืนยันโดยเจ้าของเอกสาร): ภาพที่ 1 = ข้อ 5.3.1–5.3.6 / ภาพที่ 2 = ข้อ 5.3.7–5.3.25

⚠️ หมายเหตุการอ่าน requirement: สำนวนภาษาไทยบางคำอาจคลาดเคลื่อนเล็กน้อยจากต้นฉบับ แต่สาระของทุกข้อชัดเจน — การอ่านครั้งแรกสับสนเพราะเลขข้อเป็นเลขอารบิก (5.3.X) ที่ OCR อ่านเป็นอักษรไทย ช่วงเลขข้อได้รับยืนยันจากเจ้าของเอกสารแล้ว และการตรวจซ้ำด้วยการสแกนตำแหน่งบรรทัด + อ่านเลขข้อรายบรรทัดยืนยันว่า จำนวนข้อ map ตรง 1:1 ครบทั้ง 19 ข้อ (10 ข้อครึ่งบน + 9 ข้อครึ่งล่าง รวม 5.3.7–5.3.25) — การจับคู่เลข ↔ เนื้อหาในตารางจึงเป็นที่ยืนยันแล้วทั้งหมด จนถึงฉบับแก้ไข 2026-09-15 ที่เจ้าของเอกสารให้ข้อความข้อ 5.3.18–5.3.25 ฉบับถูกต้อง: HTML5 แยกจากข้อ Tablet/iPad ออกเป็นข้อ 5.3.19 ของตัวเอง (ข้อถัดมาเลื่อนลง 1 ลำดับ), เพิ่มข้อสิทธิการใช้งานตามระบบปกครอง (5.3.23) และเชื่อมโยงกับระบบปกครอง (5.3.25) — ข้อเดิมเรื่อง API ระบบอื่น, มาตรฐานความมั่นคงปลอดภัย และ Availability 99.5% ไม่ปรากฏในฉบับแก้ไข

สรุปผล

โปรเจกต์ judes-note ตอบแกน functional ของ requirement ได้ค่อนข้างเต็ม — การ annotate บนเอกสาร PDF, bookmark ต่อหน้าเอกสาร, Text Box + Freehand Drawing, ลบ/แก้ไขความเห็น, แสดงผลรายการ, ใช้งานหลายคนพร้อมกันแบบ realtime, responsive และรองรับ tablet/iPad

แต่ requirement ฉบับนี้เขียนสำหรับระบบ production เต็มรูปแบบ ขณะที่ judes-note เป็น MVP เฟสแรกตามขอบเขตใน CLAUDE.md / docs/PLAN.md — ข้อที่ขาดส่วนใหญ่จึงแบ่งได้เป็น 2 กลุ่ม: (1) ของที่ตั้งใจไม่ทำในเฟสแรก (auth, integration) และ (2) ของที่เกือบมีแต่ต่างรายละเอียด (ลบ bookmark ทีละรายการ) รวมถึง (3) ของใหม่ที่ไม่เคยอยู่ในแผน (รองรับไฟล์รูปภาพ)

สถานะ ความหมาย
✅ มีและตรงตาม requirement
⚠️ มีบางส่วน / ใกล้เคียงแต่ต่างรายละเอียด
❌ ไม่มีในโปรเจกต์

1. ภาพที่ 1 — ข้อ 5.3.1–5.3.6 (คุณลักษณะหลักของระบบ)

5.3 พัฒนาระบบบันทึกความเห็นของกรรมการ (Judges' Notes System) มีคุณลักษณะดังต่อไปนี้

Requirement สถานะ รายละเอียดในโปรเจกต์
5.3.1 เรียกดูเอกสารที่เกี่ยวข้องและตรวจสอบจากระบบงานคดีปกครองได้โดยตรง ⚠️ ตัว viewer แสดงไฟล์ PDF ที่ระบุใน DB ได้ แต่ไม่มีการเชื่อมต่อระบบงานคดีปกครอง (ไม่มี integration/API ดึงเอกสารโดยตรง) — อัปโหลดไฟล์เองได้แล้ว (N4) แต่ไม่ใช่การดึงจากระบบคดีปกครอง — ผูกกับ gap 5.3.16 (integrate) และ 5.3.25 (เชื่อมโยงระบบปกครอง)
5.3.2 ระบบต้องไม่สามารถแก้ไขไฟล์ต้นฉบับได้ (Non-Destructive) ✅ เป็น invariant หลักของโปรเจกต์ (CLAUDE.md ข้อ 1): annotation เก็บใน DB เป็นพิกัด % เท่านั้น, ไฟล์ PDF ใน public/ ถูกอ่านอย่างเดียวผ่าน path guard (lib/server-pdf.ts), export PDF (F8) สร้างไฟล์ใหม่จากสำเนาในหน่วยความจำ (pdf-lib load แล้ว save คืน bytes ใหม่) — ไม่เขียนทับต้นฉบับเด็ดขาด
5.3.3 จัดเก็บข้อมูล Bookmark แยกจากเอกสารโดยเก็บไว้ในฐานข้อมูล และสามารถนำข้อมูลดังกล่าวมาแสดงได้ ✅ เป็นสถาปัตยกรรมแกนกลางของโปรเจกต์ (invariant #1–2): bookmark เก็บใน PostgreSQL ตาราง bookmarks เป็นพิกัด/ข้อมูลล้วน (pageIndex, ชื่อ, โครงสร้าง parent_id) แยกจากไฟล์ PDF ใน public/ — นำกลับมาแสดงได้ทั้งแท็บ Bookmarks ใน sidebar (scroll ไปหน้านั้น), หน้าสรุป F15 และ export
5.3.4 รูปแบบเอกสารที่รองรับได้ — ไฟล์เอกสาร PDF และไฟล์รูปภาพ (jpg, jpeg, png, tif) เป็นอย่างน้อย ✅ รองรับครบทุกนามสกุลแล้ว (N3 — แผน docs/PLAN-IMAGE.md, 2026-09-15): รูปคือ "หน้าเอกสาร" แสดง <img> แทน canvas + annotate ครบทุกชนิด + bookmark + realtime + export PDF ฝังรูป/CSV; TIFF รองรับทั้งหลายเฟรม (decode ด้วย utif2) และ EXIF orientation ตอน export; อัปโหลดไฟล์ PDF/รูปผ่านหน้ารายการได้ (N4)
5.3.5 บันทึกความเห็น (Bookmark) ทั้งแบบกรอกข้อความ (Text Box) และเขียนด้วยมือ (Freehand Drawing) ✅ TEXTBOX (F17) + DRAW freehand ดินสอ/ไฮไลต์เตอร์ + รองรับสไตลัส pressure (F7)
5.3.6 เพิ่ม ลบ แก้ไขความเห็นในกล่องข้อความได้ ✅ TEXTBOX (F17): สร้างกล่องข้อความ + แก้ไขข้อความในกล่องโดยตรง (editor รองรับตัวหนาบางส่วน — rich text) + ลบ/ย้าย/ปรับขนาด ของตัวเอง (F1, F13)

2. ภาพที่ 2 — ข้อ 5.3.7–5.3.25 (รายละเอียด bookmark + ข้อกำหนดระบบ)

Requirement สถานะ รายละเอียดในโปรเจกต์
5.3.7 เพิ่ม แก้ไข ลบ ข้อความที่เขียนหรือวาดได้ เช่น สีหรือขนาด ✅ ครบทั้งวงจร: สร้าง annotation ทุกชนิด (HIGHLIGHT/DRAW/SHAPE/TEXTBOX/STAMP) + แก้ไขสี/ความหนา/ขนาด ผ่านแผง selection (F1 — AnnotationSelectionLayer: แถบสี + ความหนา, TEXTBOX ปรับ fontSize ได้) + ย้าย/ปรับขนาด + F13 แก้ไขข้อความ + ลบของตัวเอง + F19 version history
5.3.8 ข้อมูลบันทึก bookmark ต้องอ้างถึงไฟล์เอกสาร หน้าเอกสาร วันที่บันทึก และผู้บันทึก ✅ ตาราง bookmarks มีครบทั้ง 4: file_id (FK → ไฟล์เอกสาร), page_index (หน้าเอกสาร), created_at (วันที่บันทึก), user_id (ผู้บันทึก) — นำมาแสดงในแท็บ Bookmarks, หน้าสรุป F15 และ export
5.3.9 กำหนดความเป็นส่วนตัวของ bookmark: ส่วนบุคคล (Private) / กลุ่ม (Group) ❌ ไม่มี Private/Group visibility — ทุกคนเห็นทุกรายการ (ไม่มี auth/roles โดยเจตนา)
5.3.10 แสดง bookmark ของเอกสารแต่ละไฟล์ หรือชุดของเอกสารได้ ✅ ครบทั้งสองแบบ — รายไฟล์: แท็บ Bookmarks ใน sidebar (ผูก file_id) + หน้าสรุป F15; ชุดของเอกสาร: กลุ่มตาม type_id จากลิงก์ e-Court (N9) — หน้า /groups/[typeId] การ์ดแต่ละไฟล์หุบ/กางดู bookmark+annotation ทั้งไฟล์รวมทุกไฟล์ในกลุ่ม เรียงตามหน้า กดแถวเด้งไปตำแหน่งนั้น (2026-09-23)
5.3.11 แสดง bookmark ตามลำดับหน้าได้ ✅ ทำแล้ว (2026-09-16, N5): แท็บ "ที่คั่นหน้า" เรียงตาม หน้า → ตำแหน่งบนหน้า (yOffset) → เวลาสร้าง ทั้ง root ของต้นไม้และลูกในแม่เดียวกัน — ลำดับเดียวกันใช้ทุกที่: PDF outline ตอน export (F8), ผลค้นหา (N6), ส่งออก JSON (N7)
5.3.12 สามารถกำหนดเงื่อนไขการค้นหา bookmarks ได้ ✅ ทำแล้ว (2026-09-16, N6): block ค้นหาเฉพาะแท็บ "ที่คั่นหน้า" — คำค้น (ชื่อ+โน้ต) + เงื่อนไข ช่วงหน้า / ผู้บันทึก / ช่วงวันที่บันทึก ผสมกันได้ + ปุ่มล้างเงื่อนไข (Server Action searchBookmarks — แผน docs/PLAN-BOOKMARK.md)
5.3.13 แสดงผลรายการหน้าของเอกสารที่ bookmark ไว้ ✅ แท็บ Bookmarks ใน sidebar + หน้าสรุป (F15)
5.3.14 จัดทำชุด API ดึงข้อมูล bookmark สำหรับเชื่อมต่อระบบอื่น ✅ ปัจจุบันตอบด้วย N10 API (2026-09-25): POST /api/external/documents (auth API Key x-api-key) คืน bookmark พร้อม annotation ทั้งเอกสาร/ทั้งกลุ่ม พร้อม filter ผู้บันทึก/ชนิด — เดิมเคยเป็น GET /api/bookmarks/export?fileId= (2026-09-17) แล้วถูกถอด 2026-09-25 ตามคำขอผู้ใช้ เพราะ N10 ครอบคลุมข้อมูลชุดเดียวกันพร้อม auth
5.3.15 ส่งออก (Export) รายการ bookmark เป็น PDF ✅ export PDF ของ F8 (app/api/annotations/export/route.ts) ฝัง bookmark เป็น PDF outline ติดไปกับไฟล์ (ต้นไม้ 3 ระดับ เรียงตามหน้า) — เจ้าของเอกสารยืนยัน (2026-09-17) ถือว่าตอบข้อนี้แล้ว · หมายเหตุ: รายงาน PDF แยกต่างหากของ N7 เคยทำแล้วถูกเปลี่ยนเป็นส่งออก JSON ตามคำขอผู้ใช้ (2026-09-17)
5.3.16 หน้าจอเชื่อมต่อกับระบบอื่น (Integrate) เป็น modal หรือ iframe ❌ เป็น standalone Next.js app — ไม่มีโหมด embed
5.3.17 รองรับ Web Browser: Google Chrome, Microsoft Edge, Safari ✅ Web app มาตรฐาน — ทดสอบ desktop + iOS/Android แล้ว
5.3.18 ใช้งานบน Tablet, iPad ✅ Touch support เต็มรูปแบบ: ไฮไลต์ด้วย custom selection ลาก→ปล่อย=สร้างทันที (hooks/useCustomSelection.ts — แทนปุ่มลอยของ commit b3b884c ที่ถอดออกแล้ว), ลาก handles, วาดด้วยนิ้ว
5.3.19 รองรับการพัฒนาโปรแกรมแบบ Web Application ที่สนับสนุนเทคโนโลยี HTML5 หรือดีกว่า ✅ เป็น Web Application (Next.js 14) สร้างบนเทคโนโลยี HTML5 ทั้งหมด: Canvas 2D (render PDF ผ่าน pdfjs), SVG (InkLayer), Server-Sent Events/EventSource (realtime), HTTP Cookie (mock login e-Court), Pointer Events + pressure (สไตลัส) — ไม่พึ่ง plugin เดิม เช่น Flash/Java Applet
5.3.20 Responsive รองรับแสดงผลได้ทุกความละเอียดหน้าจอ ✅ sidebar จอกลาง/จอเล็ก, PDF fit จอเล็ก, ปุ่มขนาด touch-44px (commit 1c2f4c8)
5.3.21 ใช้งานหลายผู้ใช้พร้อมกัน (Multi-user) จากหลายเครื่อง ✅ Realtime sync ผ่าน SSE (hooks/useAnnotationRealtime.ts) — แก้ไข/ลบ ของใครของมันบนไฟล์เดียวกันได้พร้อมกัน
5.3.22 การรับรองตัวผู้ใช้งาน (Authentication) ✅ ทำแล้วเป็น mock (2026-09-17): หน้า /login dropdown ผู้ใช้ user1–user5 + รหัสผ่านกลาง Demo1234 → ตั้ง cookie oacCase ตาม format จริงของ e-Court (userId = u_userid ต่างกันต่อคน, userName = u_userlogin) + middleware.ts บังคับทุกหน้า + ปุ่มออกจากระบบ — auth จริงเทียบระบบศาลยังไม่ทำ
5.3.23 สิทธิการใช้งานเป็นไปตามระบบปกครอง ❌ ไม่มีระบบสิทธิ์ (roles/permissions) — login เป็น mock ยังไม่ผูกสิทธิ์ตามระบบปกครอง (ต้อง auth จริง 5.3.22 ก่อน)
5.3.24 ติดตั้ง On-Premise บน Server ภายใน หรือ Cloud ⚠️ สถาปัตยกรรม Next.js + PostgreSQL deploy ได้ทั้งสองรูปแบบทางเทคนิค แต่ไม่มีข้อกำหนด/packaging พิเศษ (หมายเหตุ: SSE pub/sub เป็น in-memory — รันหลาย instance ต้องเพิ่ม Redis/LISTEN-NOTIFY ก่อน)
5.3.25 ระบบที่พัฒนาสามารถเชื่อมโยงกับระบบปกครองได้ ❌ เป็น standalone Next.js app — ยังไม่มี integration เชื่อมกับระบบงานคดีปกครอง (ผูกกับ gap 5.3.1 เรียกเอกสารโดยตรง และ 5.3.16 โหมด integrate) — ด้านข้อมูลออกมี JSON export รอรับแล้ว (5.3.14)

3. สรุป Gap รายกลุ่ม

กลุ่ม A — ของที่ out of scope โดยเจตนาตามแผนเฟสแรก

ข้อที่ต้องเปลี่ยนขอบเขตโปรเจกต์ + ออกแบบเพิ่มก่อน implement:

  • Authentication ผู้ใช้งาน + สิทธิการใช้งานตามระบบปกครอง (5.3.22, 5.3.23)
  • Private/Group visibility ของ bookmark (5.3.9)
  • ชุด API สำหรับระบบภายนอก (5.3.14) — ปิดแล้ว: ปัจจุบันตอบด้วย N10 API POST /api/external/documents (API Key) ครอบทั้ง bookmark+annotation+replies — เดิม GET /api/bookmarks/export (2026-09-17) ถูกถอด 2026-09-25 (ดูตาราง 5.3.14)
  • โหมด Integrate แบบ modal/iframe (5.3.16)
  • เชื่อมโยงกับระบบงานคดีปกครอง — ทั้งเรียกเอกสารโดยตรงและเชื่อมต่อระบบ (5.3.1, 5.3.25)

กลุ่ม B — ฟังก์ชันที่มีอยู่แล้ว ต่อยอดเล็กน้อยได้เลย

งานขนาดเล็ก–กลาง ไม่กระทบสถาปัตยกรรม — ปิดครบทั้งกลุ่มแล้ว (2026-09-16–17) เก็บรายการไว้เป็นประวัติ:

  • ค้นหา bookmark พร้อมเงื่อนไข (5.3.12) — ทำแล้ว (2026-09-16, N6): คำค้น (ชื่อ/โน้ต) + ช่วงหน้า/ผู้บันทึก/ช่วงวันที่ ในแท็บ "ที่คั่นหน้า"
  • เรียง bookmark ตามลำดับหน้า (5.3.11) — ทำแล้ว (2026-09-16, N5): เรียง หน้า → ตำแหน่งบนหน้า → เวลาสร้าง ทั้งต้นไม้ + ใช้ลำดับเดียวกันใน export PDF outline
  • รายงานรายการ bookmark เป็น PDF (5.3.15) — ปิดแล้ว (2026-09-17): เจ้าของเอกสารถือว่า export PDF ของ F8 ที่ฝัง bookmark เป็น outline ตอบข้อนี้แล้ว; งาน N7 ที่ทำไว้ (รายงาน PDF แยก) เปลี่ยนเป็นส่งออก JSON แทน (ซึ่งไปปิด 5.3.14 พอดี)

กลุ่ม C — ของใหม่ที่ไม่เคยอยู่ในแผน

  • รองรับไฟล์รูปภาพ jpg/jpeg/png/tif (5.3.4) — ทำแล้ว (2026-09-15, N3 + N4 ตามแผน docs/PLAN-IMAGE.md): รูปคือ "หน้าเอกสาร" (layers เดิมซ้อนบน <img> พิกัด % ใช้ของเดิมได้ทันที) + TIFF หลายเฟรม + EXIF orientation + export PDF ฝังรูป + อัปโหลดผ่านหน้ารายการ
  • ชุดของเอกสาร (document set) + แสดง bookmark รวมหลายไฟล์ (5.3.10) — ทำแล้ว (2026-09-23, N9 ตามแผน docs/PLAN-DOCSET.md): กลุ่มตาม files.type_id จากลิงก์ e-Court (ไม่มีตารางกลุ่ม — จัดใน UI) + หน้า /groups/[typeId] กางดู bookmark+annotation รวมทุกไฟล์ของกลุ่ม

กลุ่ม D — infrastructure (ระยะยาว)

  • On-Premise/Cloud packaging (5.3.24) — รวมถึงเตรียม multi-instance สำหรับ SSE

4. ข้อเสนอแนะลำดับความสำคัญ

  1. ทำกลุ่ม B ก่อน — ทำเสร็จแล้ว (2026-09-16–17): N5+N6 ปิด 5.3.11/5.3.12, 5.3.15 ปิดด้วย export PDF ของ F8 (bookmark เป็น outline), 5.3.14 ปิดด้วย JSON export — สิ่งที่เหลืออยู่ในกลุ่ม A/C/D
  2. ตัดสินใจเรื่องรูปภาพ (กลุ่ม C) — ตัดสินใจและทำเสร็จแล้ว (2026-09-15): 5.3.4 ครบทุกนามสกุลตาม N3 + อัปโหลดไฟล์ (N4)
  3. กลุ่ม A ตามด้วย D — ต้องอัปเดต docs/PLAN.md ขยายขอบเขตอย่างเป็นทางการก่อน implement ตามกระบวนการของโปรเจกต์