diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 1bd4f2f..82e3f68 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,15 +1,18 @@ # HANDOFF — Brief 5 phút cho session tiếp theo -**Last updated:** 2026-04-23 22:30 (post-RolesPage + 7 demo HĐ + clear pending — UAT-ready 100%) +**Last updated:** 2026-04-23 (Phase 6 — PurchaseEvaluation module E2E) ## TL;DR -**UAT-ready 100%.** Tier 3 ERP + 4-bảng overhaul + 4 master catalogs + -Roles VN + RolesPage CRUD + User-kind approver runtime + Warning 20% SLA -+ Edit detail row inline. 36 DB tables, ~93 endpoints, 11 migrations. -Demo data đầy đủ: **15 NCC + 8 Project + 7 [DEMO] HĐ (varied phases/ -details/approvals/comments) + 13 demo users + 60 master catalog items.** -Còn lại chỉ blockers user/ops: UAT thật + SMTP + rotate creds. +**Module Duyệt NCC (tiền-HĐ) E2E.** 2 quy trình A/B config được admin +(tái dùng framework versioned workflow), 10 bảng mới (7 core + 3 +workflow config), 17 endpoint mới, 3 FE page × 2 app + PeDetailTabs +5-tab + PeWorkflowPanel timeline. Kế thừa HĐ 1-click từ phiếu DaDuyet: +Gen Contract draft với SupplierId/ProjectId/GiaTri kế thừa, link 2 +chiều PE.ContractId. + +**Tổng:** 46 DB tables, ~110 endpoints, 12 migrations. Còn blockers +user/ops cũ: UAT thật + SMTP + rotate creds. ## ⭐ Skills (.claude/skills/) — PHẢI dùng khi task khớp @@ -47,6 +50,7 @@ Còn lại chỉ blockers user/ops: UAT thật + SMTP + rotate creds. | **Edit detail row inline** (7 typed Update commands + EditRowDialog) | ✅ Done | | **Master expand 15 NCC + 8 Project** + backfill demo HĐ diverse | ✅ Done | | **Deps audit script** (`scripts/deps-audit.ps1`) | ✅ Done | +| **Module Duyệt NCC (tiền-HĐ) E2E** — 10 bảng + 2 workflow + Kế thừa HĐ | ✅ Done | | 6+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future | ## Run nhanh diff --git a/docs/STATUS.md b/docs/STATUS.md index 142b90d..0ca0d42 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -2,9 +2,9 @@ > **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`. -**Last updated:** 2026-04-23 22:30 (post-RolesPage + 7 demo HĐ + clear pending — UAT-ready 100%) +**Last updated:** 2026-04-23 (Phase 6 — PurchaseEvaluation module E2E, migration 12, 46 DB tables) -## 📍 Phase hiện tại: **Pending tasks cleared — UAT-ready** — Prod live, 36 DB tables, ~93 endpoints, 11 migrations, 15 NCC + 8 Project + 7 demo HĐ + 13 demo users + 4 master catalogs. Chỉ còn blockers user/ops: UAT thật + Email outbox (chờ SMTP) + rotate creds. +## 📍 Phase hiện tại: **Module Duyệt NCC (tiền-HĐ) live E2E** — Prod live 3 domain, 46 DB tables (+10 PE), ~110 endpoints (+17 PE), 12 migrations. 2 quy trình Duyệt NCC config được admin (QT-DN-A 3-step / QT-DN-B 5-step). Kế thừa HĐ 1-click từ phiếu DaDuyet. ### 🌐 Production URLs @@ -22,6 +22,10 @@ _(không có — Tier 3 + skill governance đóng gói xong, chờ UAT + chờ c | Ngày | Ai | Task | Commit | |---|---|---|---| +| 2026-04-23 | Claude | **Kế thừa HĐ từ phiếu PE** — `CreateContractFromEvaluationCommand` guard DaDuyet + SelectedSupplier + ContractId=null → tạo Contract draft với SupplierId/ProjectId/GiaTri kế thừa. Link 2 chiều PE.ContractId. 2 endpoint mới (approved-pending-contract + create-contract). FE PeDetailTabs InfoTab banner emerald + CreateContractDialog pick ContractType 7 loại. | `a385d70` | +| 2026-04-23 | Claude | **PE FE — 2 app pages (List/Create/Detail 3-panel)** — Types + PurchaseEvaluationsListPage 3-panel + PurchaseEvaluationCreatePage + PeDetailTabs (5 tab: Thông tin/NCC/Hạng mục+Quote matrix/Duyệt/Lịch sử) + PeWorkflowPanel timeline. Menu resolver Pe_* → /purchase-evaluations?type=N. fe-user mirror. TS build pass cả 2 app. | commit Phase 3 | +| 2026-04-23 | Claude | **PE App+Api CQRS** — ~900 dòng: Create/UpdateDraft/Transition/List/Inbox/GetDetail bundle/Delete + Supplier CRUD + Detail CRUD + Quote Upsert + SelectWinner + Changelog list. PurchaseEvaluationWorkflowService policy-based guard + notification push. PurchaseEvaluationsController ~15 endpoint. | commit Phase 2 BE | +| 2026-04-23 | Claude | **PurchaseEvaluation module — Domain+Infra (migration 12)** — 10 bảng mới (7 core: Header+Suppliers+Details+Quotes+Approvals+Changelogs+Attachments + 3 workflow config: Definitions/Steps/StepApprovers). 2 enum (PEType A/B, PEPhase 7 state + TuChoi). PurchaseEvaluationPolicy + Registry + FromDefinition. Seed 13 menu Pe_*/PeWf_* + 2 WorkflowDefinition v01 (QT-DN-A 3-step, QT-DN-B 5-step). | `2c6f0ca` | | 2026-04-23 | Claude | **Mở rộng master data + backfill demo HĐ** — SeedDemoMasterDataAsync per-Code idempotent (5→15 NCC + 3→8 Project). DemoSupplierByType/DemoProjectByType maps đa dạng theo loại HĐ. BackfillDemoContractsSupplierProjectAsync update [DEMO] HĐ supplier+project nếu mismatch. Match business: ThauPhu↔NTP, NCC↔NCC, DV↔DV. | `bcdc007` | | 2026-04-23 | Claude | **Edit detail row inline + deps audit script** — 7 typed UpdateXxxDetailCommand BE (ChangelogAction.Update log) + 7 PUT endpoints. FE ContractDetailsTab: ActionBtns (Pencil + Trash) + EditRowDialog reuse FIELDS_BY_TYPE config + buildPayload + populate form từ row data. Mirror fe-admin. `scripts/deps-audit.ps1` chạy dotnet+npm scan, color output, -FailOnHigh CI gate. | `e53cd3a` | | 2026-04-23 | Claude | **User-kind approver runtime guard + Warning 20% SLA** — WorkflowPolicy +UserTransitions parallel dict (default null cho Standard/SkipCcm, populated qua FromDefinition khi WorkflowStepApprover Kind=User). IsTransitionAllowed signature update accept actorUserId, fallback User-kind nếu Role không match. SlaExpiryJob.ProcessWarningsAsync mới — pull HĐ !SlaWarningSent && remaining ≤ 20% × default SLA → notify Drafter via NotificationType.SlaWarning + set flag tránh spam. | `4edcd58` | @@ -111,13 +115,13 @@ Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1 ## 📊 Thông số cumulative -| | P0 | P1f | P1.2 | P2 | P3 | P4 | P5prep | Tier3 | +Toolkit/Catalogs/Roles | **+RolesPg+Demo+Pending** | -|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| -| BE LOC | 0 | ~400 | ~1500 | ~1900 | ~2700 | ~3100 | ~3300 | ~4800 | ~7800 | **~8800** | -| DB tables | 0 | 7 | 12 | 14 | 19 | 19 | 19 | 24 | 36 | **36** (no schema change) | -| API endpoints | 0 | 4 | 20 | 23 | 31 | 33 | 35 | ~50 | ~80 | **~93** (+3 Roles CRUD +7 PUT Detail) | -| Migrations | 0 | 1 | 3 | 4 | 5 | 5 | 5 | 8 | 11 | 11 | -| FE pages | 0 | 2 | 6 | 7 | 14 | 16 | 16 | ~20 | ~22 | **~23** (+RolesPage) | +| | P0 | P1f | P1.2 | P2 | P3 | P4 | P5prep | Tier3 | +Toolkit | +RolesPg+Demo | **+PE module** | +|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| +| BE LOC | 0 | ~400 | ~1500 | ~1900 | ~2700 | ~3100 | ~3300 | ~4800 | ~7800 | ~8800 | **~11100** | +| DB tables | 0 | 7 | 12 | 14 | 19 | 19 | 19 | 24 | 36 | 36 | **46** (+10 PE) | +| API endpoints | 0 | 4 | 20 | 23 | 31 | 33 | 35 | ~50 | ~80 | ~93 | **~110** (+17 PE) | +| Migrations | 0 | 1 | 3 | 4 | 5 | 5 | 5 | 8 | 11 | 11 | **12** | +| FE pages | 0 | 2 | 6 | 7 | 14 | 16 | 16 | ~20 | ~22 | ~23 | **~26** (+3 PE pages × 2 app) | | FE components | — | — | — | — | — | — | — | many | many+ | +EditRowDialog (refactor ActionBtns) | | Scripts PS | 0 | 0 | 0 | 1 | 1 | 1 | 3 | 4 | 4 | **5** (+deps-audit.ps1) | | CI/CD workflow | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | diff --git a/docs/changelog/migration-todos.md b/docs/changelog/migration-todos.md index d6141e6..55d1b6e 100644 --- a/docs/changelog/migration-todos.md +++ b/docs/changelog/migration-todos.md @@ -296,6 +296,20 @@ - [x] **Seed master data** — 9 dept + 5 supplier + 3 project + MyDashboard — `6197c84` - [x] **Brand identity** — #1F7DC1 palette + Be Vietnam Pro + Solutions logo — `4abb559`..`bf1fbe3` +## Phase 6 — Module Duyệt NCC (tiền-HĐ) ✅ Done + +- [x] **Migration 12 AddPurchaseEvaluations** — 10 bảng: PurchaseEvaluations + Suppliers + Details + Quotes + Approvals + Changelogs + Attachments + WorkflowDefinitions + WorkflowSteps + WorkflowStepApprovers +- [x] **Domain** — 2 enum (Type A/B, Phase 7 state) + Policy record + Registry + FromDefinition builder (mirror WorkflowPolicyRegistry HĐ) +- [x] **Seed** — 13 menu Pe_*/PeWf_* + 2 WorkflowDefinition v01 (QT-DN-A 3-step, QT-DN-B 5-step) +- [x] **Application CQRS** — ~900 dòng: Create/Update/Transition/List/Inbox/Get/Delete + Supplier CRUD + Detail CRUD + Quote Upsert + SelectWinner + Changelog +- [x] **PurchaseEvaluationWorkflowService** — policy-based guard + approval + notification + changelog +- [x] **PurchaseEvaluationsController** — 17 endpoint REST +- [x] **FE 2 app** — Types + PurchaseEvaluationsListPage 3-panel + PurchaseEvaluationCreatePage + PeDetailTabs (5 tab) + PeWorkflowPanel + Menu resolver Pe_* +- [x] **Kế thừa HĐ** — CreateContractFromEvaluationCommand guard DaDuyet + SelectedSupplier + !ContractId → gen Contract draft kế thừa Supplier/Project/GiaTri/DraftData. FE CreateContractDialog pick ContractType 7 loại. Link 2 chiều PE.ContractId. +- [ ] **PE Workflow admin designer UI** — `/system/pe-workflows/:typeCode` (framework đã sẵn, mirror `/system/workflows/:typeCode`) — optional +- [ ] **PE Attachments upload** (pattern reuse ContractAttachmentFeatures) — optional +- [ ] **Auto-map PE Details → Contract Details per-type** khi gen HĐ — phức tạp vì 7 ContractType schema khác nhau, user điền lại manual — optional + ## Post-launch (Phase 6+ — future) - [ ] **Email outbox** (MailKit + SMTP) — blocked chờ SMTP config diff --git a/docs/changelog/sessions/2026-04-23-2300-purchase-evaluations.md b/docs/changelog/sessions/2026-04-23-2300-purchase-evaluations.md new file mode 100644 index 0000000..2545258 --- /dev/null +++ b/docs/changelog/sessions/2026-04-23-2300-purchase-evaluations.md @@ -0,0 +1,144 @@ +# Session 2026-04-23 ~23:00 — Module Duyệt NCC (tiền-HĐ) E2E + +**Focus:** Build module mới "Quy trình chọn Thầu phụ - NCC" từ user spec +(Excel form trình duyệt so sánh giá + 2 flowchart A/B). Đây là đầu vào +của HĐ — phiếu duyệt xong kế thừa làm HĐ cho NCC đó. + +4 commit (`2c6f0ca` → `a385d70`), 1 migration (12), ~2500 LOC BE + FE. + +## User input + +**2 file từ user:** +1. **Excel form** "BẢNG TỔNG HỢP TRÌNH DUYỆT SO SÁNH GIÁ" — dự án SOVI, + gói thầu Cung cấp bê tông, so sánh 4 NCC × hạng mục (nhóm A.I Bê tông, + A.II Phụ gia, A.III Bơm, A.IV Vận chuyển) + ý kiến 4 phòng ban + D + Điều kiện TT + E Thông tin liên hệ +2. **Flowchart** 2 quy trình: + - A "Duyệt NCC" (3 step): Purchasing → CCM → CEO + - B "Duyệt NCC - Phương án" (5 step): Purchasing → Dự án → CCM → + CEO (duyệt PA) → CEO (duyệt NCC) + +**User confirm:** +- Menu: Quy trình chọn Thầu phụ - NCC → Duyệt NCC / Duyệt NCC Phương Án, + mỗi cái 3 sub (Danh sách / Thao tác / Duyệt) +- Kế thừa HĐ: user click "Tạo HĐ" → list phiếu đã duyệt → chọn → kế thừa +- Mã phiếu: tính sau (auto gen PE-YYYYMM-XXXX tạm) +- Tách Quotes ra bảng riêng (row-based) +- "7 bảng core" (thực tế 7 + 3 workflow config tách riêng vì Phase enum khác) +- "Config quy trình y như HĐ" (admin tự config version mới) + +## Design + +**10 bảng mới (migration 12 `AddPurchaseEvaluations`):** + +Core 7: +1. `PurchaseEvaluations` — Header (Type enum A/B, Phase 7 state, WorkflowDefinitionId + pinned, SelectedSupplierId, PaymentTerms JSON, ContractId? FK kế thừa) +2. `PurchaseEvaluationSuppliers` — N:M NCC tham gia + contact + payment term per NCC +3. `PurchaseEvaluationDetails` — hạng mục so sánh + ngân sách (GroupCode A.I/II/III/IV) +4. `PurchaseEvaluationQuotes` — báo giá per NCC per Detail + IsSelected flag (matrix cell) +5. `PurchaseEvaluationApprovals` — workflow history +6. `PurchaseEvaluationChangelogs` — audit log unified +7. `PurchaseEvaluationAttachments` — file upload (báo giá + spec + phiếu export) + +Workflow config 3: +8. `PurchaseEvaluationWorkflowDefinitions` — versioned per Type (A/B), UK(Code, Version) +9. `PurchaseEvaluationWorkflowSteps` — Order + Phase + Name + SlaDays +10. `PurchaseEvaluationWorkflowStepApprovers` — Kind (Role/User) + AssignmentValue + +**Phase enum (PurchaseEvaluationPhase, 7 state + TuChoi):** +- 1 DangSoanThao / 2 ChoPurchasing / 3 ChoDuAn (chỉ B) / 4 ChoCCM +- 5 ChoCEODuyetPA (chỉ B) / 6 ChoCEODuyetNCC / 7 DaDuyet / 99 TuChoi + +**Policy default (hardcoded fallback khi admin chưa author DB):** +- A NccOnly: DangSoanThao → ChoPurchasing (PRO) → ChoCCM (CCM) → ChoCEODuyetNCC (BOD) → DaDuyet +- B NccWithPlan: DangSoanThao → ChoPurchasing (PRO) → ChoDuAn (PM) → ChoCCM (CCM) → ChoCEODuyetPA (BOD) → ChoCEODuyetNCC (BOD) → DaDuyet +- SLA default: soạn 3d, step 2d, CEO 1d +- Reject path mọi phase → DangSoanThao + +**Kế thừa HĐ flow:** +- Phiếu DaDuyet + SelectedSupplierId + !ContractId → banner emerald FE +- Click "Tạo HĐ từ phiếu" → dialog pick ContractType 7 loại + TenHopDong + bypass flag +- POST `/api/purchase-evaluations/{id}/create-contract` +- BE: verify → clone Supplier/Project/DepartmentId/GiaTri(sum details) → gen MaHopDong + ngay → pin ContractWorkflowDefinition[Type] → log Changelog cả 2 bảng → link + 2 chiều PE.ContractId = contract.Id +- Navigate `/contracts/{newId}` + +## Commits + +### 1. `2c6f0ca` — Domain+Infra (migration 12) + +- 10 entity files ở `Domain/PurchaseEvaluations/` +- 1 EF config file (10 configuration class) +- Policy + Registry + FromDefinition mirror HĐ +- MenuKeys +Pe_* + PeWorkflows constants +- DbInitializer seed 13 menu + 2 WorkflowDefinition v01 + +### 2. `(commit 2)` — App+Api CQRS + +- `IPurchaseEvaluationWorkflowService` + `PurchaseEvaluationWorkflowService` impl +- 4 Features file (~900 LOC): + - `PurchaseEvaluationFeatures.cs` — Create/Update/Transition/List/Inbox/Get/Delete/Changelog + - `PurchaseEvaluationSupplierFeatures.cs` — Add/Update/Remove supplier + - `PurchaseEvaluationDetailFeatures.cs` — Add/Update/Delete hạng mục + Upsert/Delete Quote + SelectWinner + - `PurchaseEvaluationDtos.cs` — DTO records cho GetBundle +- `PurchaseEvaluationsController.cs` — 15 endpoint REST +- DI register + +### 3. `(commit 3)` — FE 2 app + +- `types/purchaseEvaluation.ts` — PEType/Phase enum + DTOs (copy-share) +- `pages/pe/PurchaseEvaluationsListPage.tsx` — 3-panel: list | detail tabs | workflow +- `pages/pe/PurchaseEvaluationCreatePage.tsx` — form create/edit header +- `components/pe/PeDetailTabs.tsx` — 5 tab + 4 dialog (AddSupplier/EditSupplier/DetailDialog/QuoteDialog) + matrix clickable +- `components/pe/PeWorkflowPanel.tsx` — timeline + nextPhase buttons +- Menu resolver Layout.tsx: `Pe__` + `PeWf_` (admin only) +- App.tsx 3 route mới +- MenuKeys.ts +PurchaseEvaluations + PeWorkflows +- fe-user mirror (cùng pages, no admin hidden items) + +### 4. `a385d70` — Kế thừa HĐ (Phase 4) + +- `CreateContractFromEvaluationFeatures.cs` — Command + Query (list approved pending) +- 2 endpoint: `GET /approved-pending-contract` + `POST /{id}/create-contract` +- PeDetailTabs InfoTab: banner emerald + `CreateContractDialog` pick ContractType + +## Build results + +- Backend: 0 error, 2 pre-existing warning (DocxRenderer) — build pass +- fe-admin + fe-user: `tsc --noEmit` 0 error + +## Skip MVP (tương lai) + +- [ ] PE Workflow admin designer UI `/system/pe-workflows/:typeCode` (framework + đã có, mirror `/system/workflows/:typeCode`) +- [ ] PE Attachments upload endpoint + FE drag-drop (pattern reuse ContractAttachment) +- [ ] Auto-map PE Details → Contract Details per-type khi gen HĐ (phức tạp + vì 7 ContractType schema khác nhau) +- [ ] Demo data PE (1-2 phiếu sample cho UAT) + +## Stats + +| | Trước session | Sau session | Δ | +|---|---|---|---| +| BE LOC | ~8800 | ~11100 | +2300 | +| DB tables | 36 | 46 | +10 | +| Migrations | 11 | 12 | +1 | +| API endpoints | ~93 | ~110 | +17 | +| FE pages | ~23 | ~26 | +3 (× 2 app) | +| Commits session | — | 4 | `2c6f0ca` → `a385d70` | + +## Notes + +1. **Workflow config tách bảng riêng** thay vì share WorkflowDefinition với HĐ + — vì Phase enum khác (PurchaseEvaluationPhase vs ContractPhase). Code + duplication ~250 dòng (FromDefinition builder) nhưng design clean. +2. **Quote Dialog matrix UX** — click cell → popup nhập giá + IsSelected + per hạng mục (cho phép mỗi hạng mục NCC khác). `SelectWinner` riêng set + winner tổng thể (trường hợp 1 NCC thắng toàn bộ). +3. **Kế thừa HĐ non-copy details** — PE detail schema flat (GroupCode/NoiDung/ + KhoiLuong/DonGia...) khác 7 ContractType details schemas — user điền + lại manual. Link qua PE.ContractId cho reference. +4. **MaPhieu format PE-YYYYMM-XXXX** — tạm random. Có thể đổi format sau + (vd theo dự án: `{ProjectCode}/PE/{seq}`) — user confirm format sau. diff --git a/docs/database/schema-diagram.md b/docs/database/schema-diagram.md index a48bf20..9acc7f6 100644 --- a/docs/database/schema-diagram.md +++ b/docs/database/schema-diagram.md @@ -480,8 +480,9 @@ COMMIT; | **9** | **`AddContractDetailsAndChangelog`** | **7 ContractType-specific Details + ContractChangelogs (unified audit log)** | | **10** | **`AddMasterCatalogs`** | **UnitsOfMeasure, MaterialItems, ServiceItems, WorkItems** | | **11** | **`AddRoleShortNameAndUserDepartment`** | **+Role.ShortName + User.DepartmentId/Position (cột thêm, không bảng mới)** | +| **12** | **`AddPurchaseEvaluations`** | **10 bảng module Duyệt NCC: PurchaseEvaluations + Suppliers + Details + Quotes + Approvals + Changelogs + Attachments + WorkflowDefinitions + WorkflowSteps + WorkflowStepApprovers** | -Tổng: **36 bảng** (+ `__EFMigrationsHistory` hệ thống). +Tổng: **46 bảng** (+ `__EFMigrationsHistory` hệ thống). ## 8bis. Bảng mới sau Migration 9-11 @@ -566,7 +567,65 @@ Common: `AuditableEntity`, `IX__Code` UNIQUE filtered `IsDeleted=0`, - Runtime guard hiện tại chỉ dùng Role-kind (User-kind data model ready, enable iter sau) ``` -## 10. Liên quan +## 11. PurchaseEvaluation module (Migration 12 — 10 bảng mới) + +Module tiền-HĐ: phiếu trình duyệt so sánh giá N NCC × M hạng mục. +Sau khi DaDuyet → user click "Tạo HĐ từ phiếu" → gen Contract draft +kế thừa Supplier/Project/GiaTri, link qua `PurchaseEvaluation.ContractId`. + +### Core (7 bảng): + +| Bảng | Mục đích | +|---|---| +| `PurchaseEvaluations` | Header. MaPhieu auto PE-YYYYMM-XXXX, Type enum (1=DuyetNcc A, 2=DuyetNccPhuongAn B), Phase (7 state + TuChoi), WorkflowDefinitionId pinned at create, SelectedSupplierId (winner), PaymentTerms JSON (D section form), ContractId? FK kế thừa. AuditableEntity. | +| `PurchaseEvaluationSuppliers` | N:M Phiếu × Supplier. DisplayName ("TGN-30 ngày"), ContactName/Email/Phone (E section), PaymentTermText per NCC, Note (chip "ĐÃ CHỐT SO SÁNH LẦN 1/2"), Order. UK(EvaluationId, SupplierId). | +| `PurchaseEvaluationDetails` | Hạng mục so sánh. GroupCode (A.I/II/III/IV), GroupName (Bê tông/Phụ gia...), ItemCode, NoiDung, ĐơnViTinh, KhoiLuongNganSach/ThiCong, DonGiaNganSach, ThanhTienNganSach. | +| `PurchaseEvaluationQuotes` | Báo giá per NCC per Detail (matrix cell). FK Detail + Supplier-row, BgVat/ChuaVat/ThanhTien, IsSelected flag, Note. UK(DetailId, SupplierId). | +| `PurchaseEvaluationApprovals` | Workflow history (giống ContractApprovals). FromPhase/ToPhase/Decision/Comment/ApprovedAt. | +| `PurchaseEvaluationChangelogs` | Audit log unified (EntityType: Header/Supplier/Detail/Quote/Workflow/Attachment + Action: Insert/Update/Delete/Transition). | +| `PurchaseEvaluationAttachments` | File upload — báo giá NCC gửi, bản vẽ, phiếu export. Purpose enum. | + +### Workflow config (3 bảng — tái dùng pattern HĐ versioned): + +| Bảng | Mục đích | +|---|---| +| `PurchaseEvaluationWorkflowDefinitions` | Versioned definition per Type. Code+Version UNIQUE, IsActive (1 per Type). Seed v01: QT-DN-A (3-step) + QT-DN-B (5-step). | +| `PurchaseEvaluationWorkflowSteps` | Ordered steps: Order+Phase+Name+SlaDays. | +| `PurchaseEvaluationWorkflowStepApprovers` | Role/User kind + AssignmentValue (reuse WorkflowApproverKind enum từ HĐ). | + +### State machine PE Phase: + +``` +A (NccOnly 3-step): + DangSoanThao → ChoPurchasing → ChoCCM → ChoCEODuyetNCC → DaDuyet + bất kỳ phase duyệt reject → DangSoanThao + DangSoanThao → TuChoi (cancel) + +B (NccWithPlan 5-step): + DangSoanThao → ChoPurchasing → ChoDuAn → ChoCCM → ChoCEODuyetPA → ChoCEODuyetNCC → DaDuyet + Role mapping: Drafter/DeptManager → Procurement (PRO) → ProjectManager (PM) → CostControl (CCM) → Director (BOD) +``` + +### Kế thừa HĐ flow: + +``` +PE.Phase=DaDuyet && SelectedSupplierId && !ContractId + → user FE click "Tạo HĐ từ phiếu" + → pick ContractType (1-7) + TenHopDong + bypassCCM flag + → POST /api/purchase-evaluations/{id}/create-contract + → CreateContractFromEvaluationCommand: + 1. Verify PE state + 2. new Contract { SupplierId=PE.Selected, ProjectId=PE.Project, ... } + 3. GiaTri = sum(PE.Details.ThanhTienNganSach) + 4. DraftData = PE.PaymentTerms (carry) + 5. WorkflowDefinitionId = active ContractWorkflowDefinition[Type] + 6. Gen MaHopDong (ContractCodeGenerator SERIALIZABLE) + 7. PE.ContractId = contract.Id (link 2 chiều) + 8. Changelog cả 2 bảng + → navigate /contracts/{newId} +``` + +## 12. Liên quan - [`database-guide.md`](database-guide.md) — conventions + migration workflow + cheatsheet đầy đủ - [`../architecture.md`](../architecture.md) — layered architecture + data flow