- เพิ่ม POST /api/ai/jobs + GET /api/ai/jobs/:jobId endpoints (FR-001, FR-002) - เพิ่ม BullMQ Worker MigrateDocumentWorker + OCR auto-detect (FR-003, FR-004) - เพิ่ม cleanup-temp-files + expire-pending-reviews workers (FR-005, FR-005a/b) - สร้าง SQL deltas: tags, correspondence_tags, alter migration_review_queue (FR-006, ADR-009) - เพิ่ม MigrationReviewService.commitRecord() + SELECT FOR UPDATE (FR-007, FR-007a) - เพิ่ม CASL permission migration.commit + MigrationReviewController (FR-007) - สร้าง TagsModule + TagsService + TagsController (US3) - สร้าง Migration Review Queue frontend page + ReviewQueueTable (US2) - อัปเดต n8n guide: deterministic Idempotency-Key + token pre-flight (FR-001a, FR-010a/b) - สร้าง spec.md, plan.md, tasks.md, data-model.md, contracts/, quickstart.md - สร้าง ADR-028 document + validation-report.md (PASS 32/32 tasks, 173/173 tests)
10 KiB
// File: specs/200-fullstacks/228-migration-arch-refactor/tasks.md // Change Log: // - 2026-05-22: Generated from plan.md + spec.md for ADR-028 Migration Architecture Refactor
Tasks: ADR-028 Migration Architecture Refactor
Branch: 228-migration-arch-refactor | Generated: 2026-05-22
Total Tasks: 32 | Parallel Opportunities: 12
Updated: 2026-05-22 — เพิ่ม 2 tasks จาก quizme session (FR-001a/b, FR-005a/b, FR-007a, FR-010a/b)
Phase 1: Setup
- T001 สร้าง SQL delta file
specs/03-Data-and-Storage/deltas/2026-05-22-create-tags-tables.sqlตาม data-model.md (tables:tags,correspondence_tags) - T001b สร้าง SQL delta file
specs/03-Data-and-Storage/deltas/2026-05-22-alter-migration-review-queue.sqlเพิ่ม columnai_job_id VARCHAR(36) NULLในmigration_review_queue(ADR-009 — ตาราง migration_review_queue สร้างโดย 03-04 SQL แต่ไม่มี column นี้) - T002 Apply SQL delta ทั้งสอง (T001, T001b) ใน staging database และ verify schema ถูกต้อง
- T003 สร้าง NestJS module skeleton
backend/src/modules/tags/tags.module.ts - T004 สร้าง BullMQ job type constant
migrate-documentในbackend/src/common/constants/bullmq.constants.ts - T004b อัปเดต n8n Node 0 "Set Configuration" ใน
specs/03-Data-and-Storage/03-05-n8n-migration-setup-guide.md— (1) Idempotency-Key format deterministic:{batchId}:{documentNumber}ไม่ใช่ random UUID (FR-001a); (2) token pre-flightGET /api/auth/meก่อน process records (FR-010a); (3) 401 mid-batch handler → write TOKEN_EXPIRED ลง migration_progress + resumable (FR-010b)
Phase 2: Foundational (Blocking Prerequisites)
- T005 สร้าง TypeORM Entity
Tagในbackend/src/modules/tags/entities/tag.entity.ts(fields: id, publicId UUIDv7, projectId, tagName, colorCode, description, createdBy, timestamps, deletedAt) - T006 [P] สร้าง TypeORM Entity
CorrespondenceTagในbackend/src/modules/tags/entities/correspondence-tag.entity.ts(fields: correspondenceId, tagId, isAiSuggested, confidence, createdBy, createdAt) - T007 สร้าง DTO
SubmitAiJobDtoในbackend/src/modules/ai/dto/submit-ai-job.dto.ts(type: 'migrate-document', payload: MigrateDocumentPayload) พร้อม class-validator decorators - T008 [P] สร้าง DTO
AiJobResultDtoในbackend/src/modules/ai/dto/ai-job-result.dto.ts(isValid, confidence, category, summary, suggestedTags, ocrMethod, processingTimeMs)
Phase 3: US1 — n8n Submits AI Job via BullMQ (P1 — Blocking)
Story Goal: n8n สามารถส่ง PDF ผ่าน POST /api/ai/jobs และ poll ผลลัพธ์ได้
Independent Test: curl -X POST /api/ai/jobs พร้อม test PDF → poll จนได้ status: completed + AI JSON output
- T009 [US1] สร้าง BullMQ Worker
MigrateDocumentWorkerในbackend/src/modules/ai/workers/migrate-document.worker.ts— Step 1: fetch temp file from StorageService - T010 [P] [US1] เพิ่ม OCR routing logic ใน Worker — PyMuPDF Fast Path (chars > 100) หรือ PaddleOCR Slow Path — เรียกผ่าน OCR Service HTTP API (ไม่ใช่ direct Ollama)
- T011 [P] [US1] เพิ่ม gemma4:e4b inference ใน Worker — System Prompt + User Prompt สำหรับ metadata extraction + classification + tagging
- T012 [US1] เพิ่ม JSON validation + error handling ใน Worker (ADR-007) — ถ้า AI output ไม่ถูก format → mark job failed + log ใน
ai_audit_logs - T013 [US1] เพิ่ม
submitMigrationJob()method ในbackend/src/modules/ai/ai.service.ts— (1) Idempotency-Key check; (2) double-checkimport_transactions(document_number + batch_id + status != FAILED) ก่อน enqueue → 409 พร้อม existingJobId ถ้าซ้ำ (FR-001b); (3) enqueue ไปยัง ai-batch queue - T014 [US1] เพิ่ม
POST /api/ai/jobsendpoint ในbackend/src/modules/ai/ai.controller.ts(JwtAuthGuard + CaslAbilityGuard + Idempotency-Key header validation) - T015 [P] [US1] เพิ่ม
GET /api/ai/jobs/:jobIdendpoint ในbackend/src/modules/ai/ai.controller.ts(JwtAuthGuard + status + result retrieval) - T016 [US1] เพิ่ม Scheduled BullMQ job
cleanup-temp-filesในbackend/src/modules/ai/workers/cleanup-temp-files.worker.ts— ลบ temp attachments ที่ครบ 24h + ไม่มี commit ยกเว้น files ที่ถูก reference โดย migration_review_queue.status = PENDING (FR-005a) - T016b [P] [US1] สร้าง Scheduled BullMQ job
expire-pending-reviewsในbackend/src/modules/migration/workers/expire-pending-reviews.worker.ts— รันรายวัน: auto-expire PENDING records ที่ไม่มี action ภายใน 30 วัน → status = EXPIRED + cleanup temp file + BullMQ notification job แจ้ง Admin (FR-005b)
Phase 4: US3 — Schema Setup: Tags Tables (P1 — Parallel กับ US1)
Story Goal: tags และ correspondence_tags พร้อมใช้งานสำหรับ AI Tag Extraction
Independent Test: เรียก POST /api/tags สร้าง tag → link ไป correspondence → ตรวจ correspondence_tags table
- T017 [P] [US3] สร้าง
TagsServiceในbackend/src/modules/tags/tags.service.ts(methods: create, findByProject, normalize, linkToCorrespondence) - T018 [P] [US3] สร้าง
TagsControllerในbackend/src/modules/tags/tags.controller.ts(GET /api/tags?projectId=, POST /api/tags) พร้อม CASL guard - T019 [US3] Register
TagsModuleในbackend/src/app.module.tsและ add entities ใน TypeORM config
Phase 5: US2 — Migration Review Queue Frontend (P2)
Story Goal: Document Controller/Admin เห็น review queue และ Execute Import ได้
Independent Test: Login ด้วย DOCUMENT_CONTROLLER → เข้า /migration/review → เห็น PENDING records → Execute Import → ตรวจ Correspondence สร้างสำเร็จ
- T020a [US2] สร้าง
MigrationReviewService.commitRecord()ในbackend/src/modules/migration/migration-review.service.ts— (1)SELECT FOR UPDATEบน migration_review_queue record → ถ้า status ไม่ใช่ PENDING → 409 ALREADY_PROCESSING (FR-007a); (2) update status เป็น PROCESSING; (3) สร้าง Correspondence, ย้าย temp attachment เป็น permanent, link tags, update import_transactions - T020b [US2] เพิ่ม
POST /api/ai/migration/reviewendpoint ในbackend/src/modules/migration/migration-review.controller.ts(JwtAuthGuard + CaslAbilityGuardmigration.commit+ Idempotency-Key) เรียกMigrationReviewService.commitRecord() - T021 [P] [US2] เพิ่ม CASL permission
migration.commitสำหรับ role DOCUMENT_CONTROLLER, ADMIN, SUPERADMIN ในbackend/src/common/casl/ability.factory.ts - T022 [P] [US2] สร้าง TypeScript types สำหรับ Migration Review ใน
frontend/types/dto/migration/migration-review.dto.ts - T023 [P] [US2] สร้าง frontend hook
useMigrationReview()ในfrontend/hooks/use-migration-review.ts(TanStack Query — fetch migration_review_queue + mutation execute import) - T024 [US2] สร้าง Migration Review Queue page
frontend/app/(dashboard)/migration/review/page.tsx(table: document_number, confidence, category, status, suggested_tags, actions) - T025 [US2] สร้าง
ReviewQueueTablecomponent ในfrontend/components/migration/review-queue-table.tsx— รวม Tag Review (is_new highlight, approve/map/reject)
Phase 6: US4 — Post-Migration Cleanup Script (P3)
Story Goal: ลบ migration tables ชั่วคราวหลัง Gate #3 ผ่าน (ยกเว้น import_transactions)
Independent Test: รัน cleanup script → ตรวจ 5 ตาราง drop แล้ว แต่ import_transactions ยังอยู่
- T026 [US4] สร้าง SQL cleanup script
specs/03-Data-and-Storage/deltas/2026-05-22-drop-migration-tables.rollback.sqlสำหรับ restore (ถ้าจำเป็น) - T027 [US4] สร้าง SQL cleanup script
specs/03-Data-and-Storage/deltas/2026-05-22-drop-migration-tables.sql— DROP TABLE IF EXISTS สำหรับ 5 ตาราง (explicit comment:import_transactionsไม่ drop)
Phase 7: Polish & Cross-Cutting
- T028 สร้าง ADR-028 document ใน
specs/06-Decision-Records/ADR-028-migration-architecture-refactor.md— document ทุก decision จาก session นี้ (n8n→BullMQ, gemma4:e4b, PyMuPDF/PaddleOCR, token 7d, RBAC, table retention)
Dependencies Graph
T001 → T002 (schema must apply before entities work)
T005, T006 → T017, T018, T019 (entities before service/controller)
T007, T008 → T013, T014, T015 (DTOs before service/endpoints)
T009 → T010 → T011 → T012 (Worker steps sequential)
T013, T014, T015 → T009 (Service before Worker registration)
T016 (independent)
T016b (independent, parallel กับ T016)
T019 → (tags available for Worker)
T020a → T020b → T024, T025 (service → controller → frontend)
T021 → T020b (CASL permission before controller endpoint)
T028 (independent — can do last)
Parallel Execution Opportunities
Group A (Phase 2 — can run in parallel):
- T005 + T006 + T007 + T008
Group B (US1 — can run in parallel after T009):
- T010 + T011 (OCR routing + AI inference, different concerns)
- T014 + T015 (POST + GET endpoints, same controller different methods)
Group C (US2 — can run in parallel after T020):
- T022 + T023 (types + hook)
- T021 (CASL permission, different file)
Group D (US3 — parallel กับ US1 entirely):
- T017 + T018 (service + controller)
Implementation Strategy
MVP Scope (Phase 1-3 + Phase 4):
- SQL delta apply + Tags entities
POST /api/ai/jobs+GET /api/ai/jobs/:jobId+ BullMQ Worker- n8n สามารถรัน Migration ได้โดยผ่าน BullMQ (ตรง ADR-023A)
Full Scope (+ Phase 5-7):
- Migration Review Queue Frontend
- Post-migration cleanup
- ADR-028 documentation