Files
admin 1564f8648d
CI / CD Pipeline / build (push) Successful in 4m10s
CI / CD Pipeline / deploy (push) Successful in 3m52s
690524:1919 ADR-028-228-migration #04
2026-05-24 19:19:46 +07:00

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 เพิ่ม column ai_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-flight GET /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:e2b 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-check import_transactions (document_number + batch_id + status != FAILED) ก่อน enqueue → 409 พร้อม existingJobId ถ้าซ้ำ (FR-001b); (3) enqueue ไปยัง ai-batch queue
  • T014 [US1] เพิ่ม POST /api/ai/jobs endpoint ใน backend/src/modules/ai/ai.controller.ts (JwtAuthGuard + CaslAbilityGuard + Idempotency-Key header validation)
  • T015 [P] [US1] เพิ่ม GET /api/ai/jobs/:jobId endpoint ใน 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/review endpoint ใน backend/src/modules/migration/migration-review.controller.ts (JwtAuthGuard + CaslAbilityGuard migration.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] สร้าง ReviewQueueTable component ใน 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