From f24acb699aa98adfc861b3af35599371756fba8f Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Thu, 30 Apr 2026 01:10:03 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Docs:=20compact=203=20file=20core=20?= =?UTF-8?q?(-273=20d=C3=B2ng=20t=E1=BB=95ng)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STATUS.md (-52 dòng, -27%): archive 51 row Recently Done Phase 0-7 cũ → changelog/recently-done-archive-2026-04.md (file mới) Giữ 12 row mới nhất Phase 8/Session 5 + pointer archive. HANDOFF.md (-147 dòng, -32%): bỏ 3 section duplicate - Versioned workflow quick ref → cross-ref workflow-contract.md §7bis - File đang active (90 dòng tree) → cross-ref PROJECT-MAP.md - Git state snapshot stale → cross-ref `git log --oneline -10` migration-todos.md (-74 dòng, -35%): collapse Phase 6 iter 1+2 + Phase 7 done parts thành 4 dòng paragraph. Giữ Phase 8/9 active + skill audit. Quy tắc compact (rules.md §6 implicit): - Recently Done > 30 row → archive cũ vào changelog/recently-done-archive-{YYYY-MM}.md - Phase done >= 1 tháng → collapse thành 1 paragraph + cross-ref session log - Section duplicate file khác → cross-ref thay vì copy Commit MD-only → CI skip (path filter gotcha #41). Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/HANDOFF.md | 154 +----------------- docs/STATUS.md | 57 +------ docs/changelog/migration-todos.md | 95 ++--------- .../recently-done-archive-2026-04.md | 61 +++++++ 4 files changed, 79 insertions(+), 288 deletions(-) create mode 100644 docs/changelog/recently-done-archive-2026-04.md diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 170a326..70d2839 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -253,159 +253,13 @@ Trigger: user nói "audit skill" hoặc tự chạy đầu Phase mới. - Workflow transition 403 → check `Contract.WorkflowDefinitionId` pin đúng không - Migration lỗi → 3 file đầy đủ (Designer + Migration + Snapshot) -## Versioned workflow — quick reference +## Versioned workflow — quick ref -``` -Contract.WorkflowDefinitionId (nullable Guid FK) - → pin tại `CreateContractCommandHandler` = WorkflowDefinitions.Single(d => d.ContractType == c.Type && d.IsActive) - → ContractWorkflowService.LoadAsync(contractId): - if contract.WorkflowDefinitionId != null: - def = db.WorkflowDefinitions.Include(Steps.Approvers).First(wfId) - return WorkflowPolicyRegistry.FromDefinition(def) - else if admin override ở WorkflowTypeAssignments: - return Registry.ByName(override.PolicyName) - else: - return Registry.For(contract.Type) // hardcoded Standard/SkipCcm +`Contract.WorkflowDefinitionId` pin tại Create. `ContractWorkflowService.LoadAsync` resolve order: pinned def → admin override → hardcoded Registry.For(type). Invariant: HĐ cũ giữ policy cũ qua FK Restrict. Detail: [`workflow-contract.md §7bis`](workflow-contract.md). -Admin tạo version mới: - POST /api/workflows - body: { code, name, contractType, steps: [{ order, phase, name, slaDays, approvers: [{ kind, assignmentValue }] }] } - → auto increment Version = max(Version where Code==code) + 1 - → deactivate old IsActive trong cùng ContractType (atomic) - → HĐ cũ Đà PIN WorkflowDefinitionId = old Id → vẫn chạy policy cũ ✓ -``` +## File đang active -Invariants: -- `UNIQUE (Code, Version)` per WorkflowDefinitions -- **Chỉ 1 IsActive=true per ContractType** tại 1 thời điểm -- `Contract.WorkflowDefinitionId` KHÔNG cascade khi xóa WorkflowDefinition → protect history - -## File đang active (hiện trạng) - -``` -SOLUTION_ERP/ -├── src/Backend/ (Clean Arch, 4 project, .NET 10) -│ ├── SolutionErp.Domain/ -│ │ ├── Common/ BaseEntity, AuditableEntity -│ │ ├── Contracts/ ContractType, ContractPhase, ApprovalDecision, -│ │ │ Contract (+WorkflowDefinitionId), ContractApproval, -│ │ │ ContractComment, ContractAttachment, ContractCodeSequence, -│ │ │ **WorkflowPolicy** (record + registry + FromDefinition), -│ │ │ **WorkflowDefinition** (Code+Version+IsActive+ContractType), -│ │ │ **WorkflowStep** (Order+Phase+Name+SlaDays), -│ │ │ **WorkflowStepApprover** (Kind=Role|User, AssignmentValue), -│ │ │ **WorkflowTypeAssignment** (admin override legacy) -│ │ ├── Forms/ ContractTemplate (+FieldSpec JSON), ContractClause -│ │ ├── Identity/ User, Role, MenuItem, Permission, AppRoles, -│ │ │ **MenuKeys** (+ContractTypeCodes, ContractTypeGroup/List/Create/Pending helpers, WorkflowTypeLeaf) -│ │ ├── Master/ Supplier (+SupplierType), Project, Department -│ │ └── Notifications/ **Notification** (+NotificationType enum) -│ ├── SolutionErp.Application/ -│ │ ├── Auth/ Login, Refresh, Me -│ │ ├── Common/ -│ │ │ └── Interfaces/ IApplicationDbContext, ICurrentUser, IDateTime, -│ │ │ IJwtTokenService, **IFileStorage**, **IDocumentConverter**, -│ │ │ **IRealtimeNotifier**, **INotificationService** -│ │ ├── Contracts/ ContractFeatures, IContractWorkflowService, -│ │ │ **ContractAttachmentFeatures** (Upload/Download/Delete CQRS), -│ │ │ **WorkflowAdminFeatures** (Overview + CreateNewVersion) -│ │ ├── Forms/ FormFeatures (List/Get/Render/**Upload/Update/Delete/ExportPdf**) -│ │ ├── Master/ Suppliers, Projects, Departments CQRS -│ │ ├── **Notifications/** NotificationFeatures (List/UnreadCount/MarkRead/MarkAllRead) -│ │ ├── Permissions/ GetMyMenuTree (**+inherit Contracts/Workflows**) -│ │ └── Reports/ DashboardStats, ExportToExcel, **MyDashboard** -│ ├── SolutionErp.Infrastructure/ -│ │ ├── Forms/ DocxRenderer, XlsxRenderer, FormRenderer, -│ │ │ **LibreOfficeDocumentConverter** -│ │ ├── Identity/ JwtSettings, JwtTokenService -│ │ ├── Persistence/ -│ │ │ ├── Interceptors/ AuditingInterceptor, **NotificationPushInterceptor** -│ │ │ └── Migrations/ 8 migrations -│ │ ├── Reports/ ContractExcelExporter -│ │ ├── **Storage/** LocalFileStorage (path-traversal guard) -│ │ └── Services/ DateTimeService, **ContractWorkflowService (load pinned def)**, -│ │ ContractCodeGenerator, **NotificationService** -│ └── SolutionErp.Api/ -│ ├── Authorization/ MenuPermissionHandler + Requirement -│ ├── Controllers/ Auth, Suppliers, Projects, Departments, Menus, -│ │ Roles, Permissions, Forms, Contracts, Reports, -│ │ Users, **Notifications**, **Workflows** -│ ├── **Hubs/** NotificationHub (/hubs/notifications) -│ ├── Middleware/ GlobalExceptionMiddleware -│ ├── **Realtime/** SignalRNotifier -│ ├── Services/ CurrentUserService, WebHostEnvironmentLocator -│ └── wwwroot/templates/ .docx/.xlsx templates -├── fe-admin/ (~18 page) -│ └── src/ -│ ├── pages/ -│ │ ├── LoginPage, DashboardPage (MyDashboardRow) -│ │ ├── master/ Suppliers, Projects, Departments -│ │ ├── system/ **PermissionsPage (3-panel)**, **WorkflowsPage (URL-driven)**, Users -│ │ ├── forms/ FormsPage (upload + Form/JSON + PDF) -│ │ ├── contracts/ List, Detail (+Attachments), **Create** -│ │ └── ReportsPage -│ ├── components/ Layout (recursive menu + filterForAdmin), -│ │ TopBar, NotificationBell, UserMenu, SlaTimer, -│ │ EmptyState, PhaseBadge, WorkflowSummaryCard, -│ │ ContractAttachmentsSection, DynamicForm, -│ │ **WorkflowDesigner** (Steps + Approvers modal) -│ └── lib/ api.ts, realtime.ts, cn.ts -├── fe-user/ (~10 page) -│ └── src/ -│ ├── pages/ Login, Inbox (+?type filter), -│ │ contracts/{Create, Detail, MyContracts} -│ ├── components/ Layout (recursive + filterForUser + USER_FIXED_TOP), -│ │ NotificationBell, ContractAttachmentsSection, SlaTimer -│ └── lib/ realtime.ts (same singleton pattern) -├── docs/ (~40 file) -│ ├── STATUS, HANDOFF, rules, architecture, CLAUDE, PROJECT-MAP (6) -│ ├── workflow-contract, forms-spec (2) -│ ├── database/{database-guide, schema-diagram} (2) -│ ├── flows/ (7 file — README + 6 flow) -│ ├── guides/ (4 file) -│ ├── changelog/migration-todos + sessions/ (8 session log) -│ └── gotchas (26 pitfall) -├── scripts/ (5 PS + py) -│ ├── parse_forms, parse_workflow (Phase 0) -│ ├── convert-doc-to-docx (Phase 2) -│ ├── deploy-iis, backup-sql (Phase 5) -│ └── install-libreoffice (Tier 3) -├── .gitea/workflows/deploy.yml CI/CD Windows self-hosted runner -└── .claude/skills/ 3 skill (contract-workflow, form-engine, permission-matrix) -``` - -## Git state - -``` -HEAD → main -bcdc007 — Infra: Mở rộng seed master (15 NCC + 8 Project) + backfill demo HĐ (LATEST) -e53cd3a — App+Api+FE+Scripts: Edit detail row inline + deps audit helper -4edcd58 — Domain+Infra: User-kind approver runtime guard + Warning 20% SLA -8bc9565 — Infra: SeedDemoContractsAsync — 7 HĐ varied phases UAT-ready -072ad6d — App+Api+FE-Admin: RolesPage CRUD (/system/roles) -ff5e35f — Docs: chốt session 2026-04-23 chiều -ae59cfe — FE-Admin: UsersPage dept/position + RoleShortName VN -330d529 — Domain+App+Infra: Role ShortName + User Dept/Position + 13 demo users (migration 11) -39031ca — FE: ContractDetailsPreview cho create mode -16e24ed — FE: Admin CatalogsPage CRUD + Details datalist autocomplete -e27c547 — Domain+App+Api: 4 master catalogs cho Details (migration 10) -51449d6 — App+Infra: Mã HĐ gen ngay tại CreateContract + backfill legacy -7f26ff9 — Edit/Xóa luôn hiện, mờ khi != DangSoanThao -8c4b4da — 2-panel layout cho Thao tác -ad0652d — Bỏ tabs, Chi tiết+Lịch sử 7/3 grid -b3762af — Panel 2 tabs (Tổng quan/Chi tiết/Lịch sử) -e684455 — App+Api: 7 Details CRUD endpoints + Changelogs query -71c035d — App+Infra: IChangelogService -70810e1 — Domain+Infra: 7 Details + ContractChangelog (migration 9) -d326e80 — FE-User: tách Tổng quan thành /dashboard riêng -89c7e88 — FE-User: 3-panel InboxPage -b75448e — 3-panel layout cho danh sách HĐ -7ea3957 — Sidebar accordion menu loại HĐ -d43d2c0 — Docs: chốt session 2026-04-23 — skill governance - -Branch: main (tracking origin/main) -Remote: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp.git -``` +Cấu trúc thư mục + file map: [`PROJECT-MAP.md`](PROJECT-MAP.md). Git state: `git log --oneline -10`. ## Credentials + URLs diff --git a/docs/STATUS.md b/docs/STATUS.md index 3542085..c05b0a4 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -57,60 +57,9 @@ | 2026-04-29 | Claude | **PE Detail UI restructure theo spec form PHIẾU TRÌNH KÝ** — 4 section đánh số match form chính thức: "1. Thông tin gói thầu" (a/b chỉ Tên + Dự án) / "2. Chọn NCC/TP" (a NCC chọn / b Ngân sách / c Giá chào thầu auto-compute từ winner quotes / d Bản so sánh embed GeneralAttachments) / "3. NCC/TP tham gia" / "4. Hạng mục + Báo giá". FormRow helper (label 176px + value flex) thay cho dl grid 2-col cũ. | `7e36241` | | 2026-04-29 | Claude | **PE/Contract → Budget integration + cột "So với ngân sách"** — BE: `BudgetSummaryDto` shared (PE & Contract DetailBundle), Create/Update PE+Contract commands + `BudgetId?` validate cùng Project + Phase=DaDuyet. `CreateContractFromEvaluation` carry forward pe.BudgetId → contract.BudgetId. FE: PE & Contract Create form + Select "Ngân sách" filter Phase=DaDuyet + Project match. PE InfoTab + Contract Edit display Budget link clickable. PE ItemsTab matrix + cột "NS link · Δ" — match per-row qua key `groupCode\|itemCode`, fetch /budgets/{id} riêng + footer aggregate (xanh dưới / đỏ vượt / xám khớp). | `61e5d4d` | | 2026-04-29 | Claude | **Budget FE 3-panel pages cả 2 app** — `types/budget.ts` (BudgetPhase 5-state enum + DTO) + `BudgetsListPage` 3-panel `[340px_1fr_360px]` + filter Phase + Năm + alias `?phase=Pending` + readOnly mode menu Duyệt + `BudgetCreatePage` form Header + `BudgetDetailTabs` flat (Section Thông tin Header + Section Hạng mục table CRUD inline auto-compute ThanhTien=KL×ĐG) + `BudgetWorkflowPanel` Panel 3 timeline + dialog comment + Approvals/Changelog. Mirror fe-user. App.tsx 3 route + Layout resolver `Bg_*`. TS build pass cả 2 app. | `df12fb1` | -| 2026-04-28 | Claude | **Module Ngân sách (Budget) BE — 4 bảng + workflow simple 3-step** — Migration 14 `AddBudgets`. Domain: `Budget` (Header — MaNganSach `NS-YYYYMM-XXXX`, NamNganSach, ProjectId/DepartmentId, DrafterUserId, TongNganSach auto-sum, SlaDeadline) + `BudgetDetail` (flat row pattern: GroupCode/Name + ItemCode + NoiDung + DonViTinh + KhoiLuong/DonGia/ThanhTien) + `BudgetApproval` (workflow history reuse `ApprovalDecision`) + `BudgetChangelog` (`BudgetEntityType` Header/Detail/Workflow). Enum `BudgetPhase` 5 state (DangSoanThao→ChoCCM→ChoCEO→DaDuyet + TuChoi). `BudgetPolicy.Default` hardcoded 3-step (Drafter→CCM→CEO). Application: 11 CQRS handler (~340 LOC: Create/UpdateDraft/Transition/List/GetDetail/Delete + Detail CRUD auto-recompute TongNganSach + ListChangelogs). Api: `BudgetsController` 11 endpoint. Link: Contract.BudgetId? + PE.BudgetId? nullable FK + index. Menu seed `Budgets` root + 3 leaf (Bg_List/Create/Pending) order=27 icon Wallet. **FE chưa làm** (next session). | `a05c57b` | -| 2026-04-28 | Claude | **14 demo users Solutions company thật** — PRO 5 (TPB tra.bui + 4 NV: phuong/binh/danh/dat) + CCM 7 (TPB ngocanh.huynh + 6 NV: ha.dao/cuong.do/long.le/ha.nguyen/dung.nguyen/anh.nguyen) + ISO 1 (chau.le) + CEO 1 (huy.duong). Pattern reconcile per-user try-catch (gotcha #38 4-field rename). Pwd `User@123456`. Tổng 30 user (16 sample cũ + 14 Solutions thật). Test login E2E pass. | `8097892` | -| 2026-04-28 | Claude | **Docs cleanup + chốt session 3** — Tái cấu trúc MD: archive raw dump (forms-spec-raw, workflow-raw) → `_archive/`, compact `migration-todos.md` collapse Phase 0-5+Tier3 cũ, update `CLAUDE.md` modules table + skills 6 (3 domain + 3 ops), `flows/` thêm PE ref architecture, audit `gotchas.md` (38 pitfall — thêm #34 NavLink query string + #35 menu inheritance + #36 Vite env rebuild + #37 mutex accordion family + #38 Identity 4-field rename). Session log `2026-04-23-2200-roles-demo-pending-cleanup.md` + `2026-04-24-chot-session-3-pe-polish.md`. | `309dcd9` · `e71e0eb` · `e65578a` | -| 2026-04-24 | Claude | **PE polish — Demo seed + MaPhieu atomic + Pe_* perm defaults** — Migration 13 `AddPurchaseEvaluationCodeSequences` (Prefix PK, mirror ContractCodeSequences). `IPurchaseEvaluationCodeGenerator` + impl SERIALIZABLE — format `PE/{YYYY}/{A\|B}/{Seq:D3}`. Replace Random.Shared trong CreatePEHandler. `SeedDemoPurchaseEvaluationsAsync` 4 phiếu varied (A-001 DangSoanThao, A-002 ChoCEODuyetNCC + 9 quotes, A-003 DaDuyet PaymentTerms JSON, B-001 ChoDuAn 5-step). `SeedPurchaseEvaluationPermissionDefaultsAsync` 7 role × 9 menu key — Drafter/DeptManager/Procurement Create+Update, các role duyệt R+U, DeptManager thêm Delete. | `c48ac21` | -| 2026-04-24 | Claude | **Rebrand 3 domain huypham.vn → solutions.com.vn E2E** — 18 file repo (FE env + scripts + CI/CD + docs + skill + code comments). Viết `scripts/migrate-domains.ps1` (ASCII-only gotcha #30) chạy trên VPS: 3 HTTP binding mới + 3 cert Let's Encrypt (HTTP-01 via SelfHosting) + auto HTTPS 443 + redirect. CI/CD auto-deploy commit `66c1a5c+b93dacf`: appsettings.Production.json CORS mới + FE bundle `VITE_API_BASE_URL=api.solutions.com.vn`. E2E verified: `/api/purchase-evaluations` 401, CORS preflight OK, FE dist có domain mới. URL cũ fallback. Claude SSH tự chạy (không cần user RDP). | `66c1a5c` · `b93dacf` | -| 2026-04-23 | Claude | **SeedDemoUsersAsync robust reconcile + 16 demo users** — Reconcile pattern (per-user try-catch, fix drift dept/position/role nếu user existing). 13 → 16 demo (+bod.tran NĐUQ thứ 2, +pm.le PM thứ 2, +nv.truong NV CCM). Detailed log created/fixed/failed counts. Resolves prod issue: chỉ thấy admin user vì old skip-if-exists fail silent. | `a667665` | -| 2026-04-23 | Claude | **G-084 hardening** — localhost → 127.0.0.1 trong `deploy-iis.ps1` + skill `iis-deploy-runbook`. Thêm gotcha #33 (IPv4/IPv6 port hijack) ref VietReport incident + 3 rules (reverse-proxy IP literal / backend loopback IPv4 explicit / service dependency). SOLUTION_ERP risk thấp (API in-process IIS, no ARR proxy) nhưng chuẩn hóa cho tương lai. | `3990066` | -| 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` | -| 2026-04-23 | Claude | **SeedDemoContractsAsync — 7 demo HĐ varied phases** — Idempotent (skip nếu [DEMO] tồn tại). 7 HĐ covering 7 ContractType + final phases (DangSoanThao/DangGopY/DangInKy/DangTrinhKy/DaPhatHanh) + 14 Details rows + ~30 Approvals workflow history + 2 Comments demo. ApproverUserId mapping đúng role (CCM→ccm.tran, BOD→bod.huynh, HRA→hra.dang). Mã HĐ auto gen RG-001. | `8bc9565` | -| 2026-04-23 | Claude | **RolesPage CRUD `/system/roles`** — BE: CreateRole regex Name validation, UpdateRole CHỈ ShortName/Description (Name FK không đổi), DeleteRole block AppRoles.All + count UserRoles > 0. 3 endpoint POST/PUT/DELETE Authorize Admin. FE: 5-column table + Loại badge (Mặc định/Tùy chỉnh) + Edit dialog Name disabled + Delete with HARDCODED_ROLES guard + Banner amber FK warning + Create dialog regex pattern HTML5. | `072ad6d` | -| 2026-04-23 | Claude | **Roles VN labels (ShortName) + Users dept/position + 13 demo users** — Migration 11 `AddRoleShortNameAndUserDepartment`. Role thêm ShortName max 50 (QTV/BOD/CCM/PRO/FIN/...) + Description full VN. User thêm DepartmentId FK Restrict + Position. Idempotent backfill 12 roles VN labels. Seed 13 demo users (bod/pm/ccm/pro/fin/act/equ/hra TPB + 4 Drafter), pwd `User@123456`. FE UsersPage column Phòng ban + Chức vụ + edit dialog mới + roles checkbox "ShortName — Full". PermissionsPage Panel 1 2-line per role. | `330d529` + `ae59cfe` | -| 2026-04-23 | Claude | **4 master catalogs cho Details + datalist autocomplete** — Migration 10 `AddMasterCatalogs`: UnitsOfMeasure (20 seed) + MaterialItems (15) + ServiceItems (10) + WorkItems (15). CQRS CRUD 13 endpoint, Admin role POST/PUT/DELETE. Menu mới `Catalogs` group + 4 leaves dưới Master. FE Admin CatalogsPage generic 4-tab CRUD `/master/catalogs/:kind`. FE Details Add form HTML5 `` per field + smart-fill (pick code → autofill name + defaultUnit). DB 32→36 bảng. | `e27c547` + `16e24ed` | -| 2026-04-23 | Claude | **Mã HĐ gen ngay tại CreateContract + backfill HĐ legacy** — `CreateContractCommandHandler` call `codeGenerator.GenerateAsync` trước `db.Contracts.Add`. TransitionAsync giữ defensive `if MaHopDong null gen` cho legacy. `BackfillContractCodesAsync` trong DbInitializer chạy startup, idempotent (NULL count → skip nếu 0). Trade-off: gap sequence khi reject nhưng user có mã ngay đầu để reference giấy tờ. | `51449d6` | -| 2026-04-23 | Claude | **"Thao tác" 2-panel + Edit/Xóa hover + Detail preview** — `ContractCreatePage` rewrite: Panel 1 List HĐ theo type + button "+ Thêm mới" cuối. Panel 2 ContractHeaderForm (new) hoặc ContractEditForm (edit) + Chi tiết section. URL state ?type/?id/?mode=new. Action buttons row Panel 1: Edit ✏ + Xóa 🗑 luôn hiện, mờ + disabled khi Phase != DangSoanThao. ContractDetailsPreview cho create mode show table headers + lock icon. | `8c4b4da` + `ec0c983` + `501b4de` + `7f26ff9` + `39031ca` | -| 2026-04-23 | Claude | **Panel 2 layout: tabs → 7/3 grid (UX iter 2)** — Bỏ tabs Tổng quan/Chi tiết/Lịch sử. Render flat: Tổng quan (Info+Comments+Attachments) ở trên, dưới grid lg:grid-cols-10 (Chi tiết 7 cột + Lịch sử Changelog 3 cột). | `b3762af` (tabs) → `ad0652d` (grid) | -| 2026-04-23 | Claude | **4-bảng data model overhaul (Header+Details+Workflow+Changelog)** — Migration 9 `AddContractDetailsAndChangelog`: 7 ContractType-specific Details bảng + 1 ContractChangelog unified audit log. IChangelogService 5 method, wired vào CreateContract+UpdateDraft+AddComment+Upload/Delete/Transition. CQRS 9 endpoint mới (GetBundle+7 Add+Delete+ListChangelogs). FE ContractDetailsTab + ContractChangelogsTab. DB 24→32 bảng. | `70810e1` + `71c035d` + `e684455` | -| 2026-04-23 | Claude | **3-panel layout HĐ (List/Detail/Workflow) + Inbox + sidebar accordion + UserDashboard fix** — MyContractsPage + ContractsListPage + InboxPage 3-panel `lg:grid-cols-[320px_1fr_360px]`, `?id=` URL state, mobile fallback fullpage. Sidebar accordion qua AccordionContext (chỉ 1 Ct_ expand). Tách "Tổng quan" → /dashboard riêng (fix bug trùng /inbox), UserDashboardPage 5-card "Của tôi" + recent contracts. | `b75448e` + `89c7e88` + `7ea3957` + `d326e80` | -| 2026-04-23 | Claude | **Skill governance + audit định kỳ** — `docs/rules.md §9` mới (6 skill bảng, nguyên tắc tạo project-specific, format SKILL.md bắt buộc, workflow audit 7 bước, 4 anti-patterns). Cron task `solution-erp-skill-audit-monthly` fire 9:00 AM ngày 1 mỗi tháng (next 2026-05-01) — self-contained prompt cold-start, auto-refresh stale nhỏ + đề xuất add/archive cho human approve, log vào `docs/changelog/skill-audit-{YYYY-MM}.md`, ABORT nếu repo dirty. Touch-points: CLAUDE.md callout + HANDOFF A1 + migration-todos checkbox + skill scope commit | `b904a25` | -| 2026-04-23 | Claude | **3 skill ops project-specific** — Khảo sát alirezarezvani/claude-skills, quyết định KHÔNG bulk-clone (skill global đã cover phần generic, repo còn lại doc-dump không có when-to-use). Viết 3 skill mới encode SOLUTION_ERP-only: `dependency-audit-erp` (npm/dotnet CVE scan respect MediatR 12.4.1 + Swashbuckle 6.9.0 pin), `ef-core-migration` (8 migration history + 3-file rule + DesignTimeDbContextFactory + 6 pitfalls cụ thể), `iis-deploy-runbook` (3 IIS site + win-acme + NSSM gitea-runner + LibreOffice + debug playbook 500/502/SignalR). Total skill project-level = 6 (3 domain + 3 ops) | `661f859` | -| 2026-04-22 | Claude | **PermissionsPage 3-panel layout** — Grid `lg:grid-cols-[280px_1fr_300px]`: Panel 1 Role list click-to-select (active ring-brand), Panel 2 Menu×CRUD matrix sticky thead + search + column bulk-toggle + brand-tinted hover, Panel 3 Granted progress bar + CRUD breakdown color badges (slate/emerald/amber/red) + Tip | `91b2da1` | -| 2026-04-22 | Claude | **Admin Workflows tabs → sidebar menu items** — Seed 7 `Wf_` leaf dưới group `Workflows`. Layout resolvePath `Wf_` → `/system/workflows/`. WorkflowsPage bỏ tab bar, URL param drives type selection. Landing 7-card grid khi click top-level `Quy trình HĐ`. Inheritance: `Workflows.Read` perm → tất cả 7 leaves auto-visible. | `f216169` | -| 2026-04-22 | Claude | **Versioned workflow per ContractType** — 3 entity mới: WorkflowDefinition (Code+Version+IsActive+ContractType), WorkflowStep (Order+Phase+Name+SlaDays), WorkflowStepApprover (Role/User + AssignmentValue). Contract.WorkflowDefinitionId nullable FK pin tại create. Migration `AddVersionedWorkflows`. Seed v01 per 7 ContractType. `WorkflowPolicyRegistry.FromDefinition()` build runtime policy từ DB. ContractWorkflowService load pinned definition. Admin `/system/workflows/:typeCode` Designer modal (create new version, clone, add/remove step, +Role/+User approvers). POST /api/workflows auto-increment Version + deactivate old. Invariant: HĐ cũ pin v01 giữ nguyên khi v02 active. E2E verified: QT-MB-v02 active, HĐ cũ vẫn chạy v01. | `e7e5f2d` + `355bbe3` | -| 2026-04-21 | Claude | **Nested sidebar menu fe-user** — 7 ContractType × 3 actions (Danh sách/Thao tác/Duyệt), nested 3-level. Admin hide `Ct_*`. Layout recursive MenuNodeRenderer. MyContracts + Inbox filter `?type=X` | `5e0f380` + `48e91fe` | -| 2026-04-21 | Claude | **Seed master data + MyDashboard widgets** — DbInitializer seed 9 departments (PM/QS/CCM/PRO/FIN/ACT/EQU/HRA/BOD) + 5 demo suppliers + 3 demo projects idempotent. MyDashboard endpoint role-aware: DraftsInProgress / PendingMyApproval / DueSoon / Overdue / DraftsTotalValue. FE "Của tôi" row 4 card hover-interactive, admin auto-hide nếu = 0 | `6197c84` | -| 2026-04-21 | Claude | **Dynamic workflow policy per ContractType** — Domain WorkflowPolicy record + registry (Standard 8-phase cho Thầu phụ/Giao khoán/NCC; SkipCcm 7-phase cho Dịch vụ/Mua bán/Nguyên tắc). ContractWorkflowService dùng policy.ForContract(c). FE xóa NEXT_PHASES hardcoded, dùng contract.workflow.nextPhases BE trả. WorkflowSummaryCard timeline visual. Gotcha #21 resolved | `cae4d84` | -| 2026-04-21 | Claude | **PDF export + .doc/.xls auto-convert + DynamicForm** — LibreOffice 25.8.6 VPS, IDocumentConverter shell soffice `--convert-to pdf/docx/xlsx` timeout+temp isolation. Admin upload .doc auto-convert .docx. DynamicForm parse FieldSpec JSON render inputs (text/textarea/number/date/currency/select). Form↔JSON toggle. E2E verified PDF 488KB/126 pages | `e459097` + `6bbd894` | -| 2026-04-21 | Claude | **Form template builder CRUD** — Admin tự upload `.docx/.xlsx` qua UI (không cần dev). BE multipart + FormCode regex unique + FieldSpec JSON validation + soft delete via IsActive. FE FormsPage upload dialog + row actions render/edit/delete. E2E verified | `166d26c` | -| 2026-04-21 | Claude | **Fix Gitea 500 sau Install Web-WebSockets** — appcmd unlock section webSocket. Gotcha #25 | `c52186b` | -| 2026-04-21 | Claude | **SignalR realtime notifications E2E** — 3-project clean-arch: IRealtimeNotifier (App) + SignalRNotifier (Api) + NotificationPushInterceptor (Infra SaveChanges hook). Hub `/hubs/notifications` JWT `?access_token=` query (WebSocket headers limit). FE singleton lib/realtime.ts auto-reconnect + toast + query invalidation. IIS WebSocket module enabled | `ea9ab5e` | -| 2026-04-21 | Claude | **Attachment upload E2E** — IFileStorage + LocalFileStorage (path-traversal guard) + CQRS Upload/Download/Delete + 3 endpoint (multipart, stream, DELETE) + FE ContractAttachmentsSection drag-drop + purpose selector + icon-per-MIME + auth-blob download + confirm delete. Wired 2 ContractDetailPage | `c8d0070` + `dc3f09b` | -| 2026-04-21 | Claude | **Content polish** — typography 14px + leading 1.55 + tracking-tight + PageHeader border-b + Button shadow+active + Input inset shadow + DataTable rounded-xl UPPERCASE header brand hover | `346bd5d` | -| 2026-04-21 | Claude | **Brand identity từ Solutions logo** — pixel-sampled #1F7DC1 → palette brand-50..900 + accent red + Be Vietnam Pro (Vietnamese-first) + favicon 'S' crop + apple-touch-icon + login gradient brand | `4abb559` + `bf1fbe3` | -| 2026-04-21 | Claude | **Fix login Network Error** — SPA web.config HTTP→HTTPS redirect rule (CORS chỉ https) | `397eb36` | -| 2026-04-21 | Claude | **Notifications module E2E** — Domain entity + EF migration + Infra service + CQRS + API controller + FE bells wire real endpoint + ContractWorkflowService emit notification cho Drafter khi phase transition | `49c0ddc` | -| 2026-04-21 | Claude | **PermissionsPage iter 1** — search, stats badge, bulk column toggle, empty state | `6c0e206` | -| 2026-04-21 | Claude | **ERP shell** — TopBar + NotificationBell + UserMenu (avatar + role badges). Layout `[sidebar] [topbar + content]` | `2b6f91c` | -| 2026-04-21 | Claude | **Tier 1 UI polish** — SlaTimer (inline + full variant, 5 chỗ), Inbox stat cards, DataTable skeleton rows, EmptyState | `290936a`..`2e43799` | -| 2026-04-21 | Claude | **CI/CD deploy xanh E2E** — self-hosted Windows runner, single job build+deploy, fresh node_modules (Vite 8 rolldown binding), appsettings từ secrets, /health/live 200 sau deploy | `b40da1e` | -| 2026-04-21 | Claude | **VPS prod setup** — SQL DB (SQLEXPRESS), IIS sites (SolutionErp-Api/Admin/User), win-acme 3 Let's Encrypt + auto-renew, shared gitea-runner với VIETREPORT | `169e268`..`519ba85` | -| 2026-04-21 | Claude | **IDOR + SLA Job + Admin warning** — ContractsController filter theo role. SlaExpiryJob BackgroundService 15min auto-approve Decision=AutoApprove. DbInitializer warn khi admin vẫn default | `fba0754` | -| 2026-04-21 | Claude | **Phase 5.1 Security + Users Mgmt** — Security headers + Identity lockout + LoginHandler check + Users CQRS + UsersController + FE `/system/users` | `11e61c9` | -| 2026-04-21 | Claude | **Phase 5 Prep** — BE rate limit + health check + Serilog file + HSTS + scripts deploy-iis/backup-sql + .gitea/workflows/deploy.yml + 4 guides + FE refresh token queue pattern | `46a2cab` | -| 2026-04-21 | Claude | **Phase 4 Report MVP** — Dashboard KPI + Excel export + rules.md + architecture.md + schema-diagram.md + gotchas 26 pitfalls | `fe7ad8e` | -| 2026-04-21 | Claude | **Phase 3 Workflow MVP** — 9 phase state machine + gen mã HĐ RG-001 | `7e957a7` | -| 2026-04-21 | Claude | **Phase 2 Form Engine MVP** | `5113e4c` | -| 2026-04-21 | Claude | **Phase 1.2** — CRUD Master + Permission Matrix | `54d6c9b` | -| 2026-04-21 | Claude | **Phase 1 foundation** + Docs addition | `702411f` + `49a5f57` | -| 2026-04-21 | Claude | **Phase 0** | `25dad7f` | + + +> **51 row Phase 0-7 (2026-04-21..28) đã archive →** [`changelog/recently-done-archive-2026-04.md`](changelog/recently-done-archive-2026-04.md) Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1f](changelog/sessions/2026-04-21-1100-phase1-foundation.md) · [P1.2](changelog/sessions/2026-04-21-1130-phase1-cruds-permission.md) · [P2](changelog/sessions/2026-04-21-1200-phase2-form-engine.md) · [P3](changelog/sessions/2026-04-21-1330-phase3-workflow.md) · [P4](changelog/sessions/2026-04-21-1430-phase4-report.md) · [P5prep](changelog/sessions/2026-04-21-1530-phase5-prep.md) · [Tier 3](changelog/sessions/2026-04-22-0300-tier3-feature-complete.md) · [Skill gov](changelog/sessions/2026-04-23-0900-skill-governance.md) · [Toolkit+4-bảng+Roles VN](changelog/sessions/2026-04-23-1500-toolkit-data-roles.md) · [Roles+Demo+Pending](changelog/sessions/2026-04-23-2200-roles-demo-pending-cleanup.md) · [PE polish iter 2 + rebrand](changelog/sessions/2026-04-24-chot-session-3-pe-polish.md) · [Budget BE + 14 Solutions users](changelog/sessions/2026-04-28-chot-session-4-budget.md) · [**Budget FE + PE/HD-Budget + PE WF Designer + Tests Phase 1-2**](changelog/sessions/2026-04-29-chot-session-5-budget-fe-pe-tests.md) diff --git a/docs/changelog/migration-todos.md b/docs/changelog/migration-todos.md index ef7da9b..d1dd6ef 100644 --- a/docs/changelog/migration-todos.md +++ b/docs/changelog/migration-todos.md @@ -17,95 +17,22 @@ Detail chi tiết: `docs/changelog/sessions/2026-04-21-*.md` + `2026-04-22-0300-tier3-feature-complete.md` + `2026-04-23-*.md`. -## ✅ Phase 6 — Module Duyệt NCC (tiền-HĐ) — Done +## ✅ Phase 6-7 — PE Module + Budget BE — Done (2026-04-23..28) -### Iter 1 (2026-04-23) +- **Phase 6 iter 1+2**: Module Duyệt NCC tiền-HĐ — Migration 12+13, 10 bảng PE + WorkflowDefinitions, 2 type A/B, 17 endpoint, FE 3-panel cả 2 app, kế thừa HĐ qua `CreateContractFromEvaluationCommand`. UX polish iter 2 (flat layout, per-NCC attachments, readOnly mode Duyệt). Demo seed 4 phiếu varied + 7 role × 9 Pe_* permission defaults. +- **Domain rebrand**: 3 sub `.huypham.vn` → `.solutions.com.vn` E2E live HTTPS (cert + CORS + FE bundle). +- **Phase 7 — Budget BE**: Migration 14, 4 bảng Budgets + workflow simple 3-step hardcoded `BudgetPolicy.Default`, 11 endpoint, link nullable Contract.BudgetId/PE.BudgetId. **FE chưa làm** (Phase 8 done). +- **Phase 7 — 14 demo Solutions users**: PRO 5 + CCM 7 + ISO 1 + CEO 1, total 30 user (16 sample + 14 thật). -- [x] Migration 12 `AddPurchaseEvaluations` — 10 bảng (Header/Suppliers/Details/Quotes/Approvals/Changelogs/Attachments/WorkflowDefinitions/Steps/StepApprovers) -- [x] Domain — 2 enum (Type A/B, Phase 7-state) + Policy record + Registry + FromDefinition builder -- [x] Seed — 13 menu Pe_*/PeWf_* + 2 WorkflowDefinition v01 (QT-DN-A 3-step, QT-DN-B 5-step) -- [x] Application CQRS ~900 LOC — Create/Update/Transition/List/Inbox/Get/Delete + Supplier CRUD + Detail CRUD + Quote Upsert + SelectWinner + Changelog -- [x] PurchaseEvaluationWorkflowService — policy guard + approval + notification + changelog -- [x] PurchaseEvaluationsController — 17 endpoint REST -- [x] FE 2 app — Types + PurchaseEvaluationsListPage 3-panel + Create page + PeDetailTabs + PeWorkflowPanel + Menu resolver Pe_* -- [x] Kế thừa HĐ — `CreateContractFromEvaluationCommand` (guard DaDuyet + SelectedSupplier + !ContractId) → Contract draft. FE CreateContractDialog pick ContractType. -- [x] **Migration 13** `AddPurchaseEvaluationCodeSequences` — atomic MaPhieu sequence `PE/{YYYY}/{A|B}/{Seq:D3}` -- [x] Demo PE seed — 4 phiếu varied phase (A-001/A-002/A-003/B-001) + Pe_* permission defaults 7 role × 9 menu key +Session logs: `2026-04-23-2300-purchase-evaluations.md` · `2026-04-24-chot-session-3-pe-polish.md` · `2026-04-28-chot-session-4-budget.md`. -Session log: `2026-04-23-2300-purchase-evaluations.md` + `2026-04-24-1030-pe-polish-demo-maphieu-perms.md`. +3 task PE feature gap (Workflow Designer / Ý kiến 4 PB / Export PDF) → đã đóng 2/3 ở Phase 8 §C+D. Export PDF carry over Phase 9. -### Iter 2 — UX polish (2026-04-24) +### Pending migrations (chưa cần đến) -- [x] Rename menu "Phương Án" → "Giải pháp" + backfill DB (zero breaking change) -- [x] Menu tree inheritance extend Pe_*/PeWf_* (`GetMyMenuTreeQuery` + 4 root) -- [x] Accordion mutex Pe_* groups + sidebar w-72 + label nowrap -- [x] NavLink active check query string (queryMatches helper) — fix 2 leaf cùng highlight -- [x] PE detail flat layout: Panel 2 = 4 section (Thông tin/NCC/Hạng mục/**Bảng so sánh**), Panel 3 += Approvals + Changelog -- [x] Upload file đính kèm per-NCC (SupplierAttachmentsCell) + Bảng so sánh tổng (GeneralAttachmentsSection, supplierRowId=null) + enum `ComparisonTable=4` -- [x] readOnly mode menu "Duyệt" (pendingMe=1) — hide Sửa/Xóa/Thêm/Edit/Upload/Delete, giữ download + transition + comment -- [x] Contract: move Lịch sử điều chỉnh Panel 2 → Panel 3 (Chi tiết HĐ full-width) -- [x] Demo email rebrand `@solutionerp.local` → `@solutions.com.vn` + `BackfillUserEmailDomainAsync` (idempotent rename 4 field Email/NormalizedEmail/UserName/NormalizedUserName) - -Session log: `2026-04-24-chot-session-3-pe-polish.md`. - -### ✅ Domain rebrand `.huypham.vn` → `.solutions.com.vn` (2026-04-24) - -- [x] 18 file repo (FE env + scripts + CI/CD + docs + skill + code comments) -- [x] `scripts/migrate-domains.ps1` (ASCII-only #30) — 3 IIS binding + 3 cert Let's Encrypt + auto HTTPS + redirect -- [x] CI/CD auto rebuild BE CORS + FE bundle VITE_API_BASE_URL -- [x] E2E verified 3 domain live + preflight OK - -Sub: `api.solutions.com.vn` · `admin.solutions.com.vn` · `eoffice.solutions.com.vn`. Old `.huypham.vn` vẫn fallback (chưa remove). - -## 📝 Phase 7 — PE feature gap + Budget BE (Session 4 partial done) - -### A. PE feature gap (3 task MISSING — carry over session 5) - -- [ ] **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode` - - BE `Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs` (mirror `WorkflowAdminFeatures.cs`) - - `Api/Controllers/PeWorkflowsController.cs` - - FE `fe-admin/src/pages/system/PeWorkflowsPage.tsx` + `PeWorkflowDesigner.tsx` - - Route `/system/pe-workflows/:typeCode` (menu PeWf_* + resolver đã sẵn) -- [ ] **Ý kiến 4 phòng ban** (Phê duyệt / P.CCM / P.MuaHàng / SM-PM) ở tab Thông tin - - Option A: 4 text field + signoff date + UserId vào header - - Option B: dùng `PurchaseEvaluationApprovals` với roleKind extra field - - UX: 4 box sign-off như Excel mẫu -- [ ] **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx` - -### B. Optional polish - -- [ ] Auto-map PE Details → Contract per-type Details khi gen HĐ (phức tạp vì 7 schema khác nhau) -- [ ] Payment terms tách field từ JSON → 6 column (Tạm ứng/TT tạm/Quyết toán/Bảo hành/Hạn mức/Đánh giá) -- [ ] Matrix Quotes bulk paste từ Excel -- [ ] fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi" - -### C. Ops - -- [ ] Remove binding cũ `.huypham.vn` sau verify stable: `ssh vietreport-vps ; cd C:\solution-erp\scripts ; .\migrate-domains.ps1 -RemoveOld -SkipCert` -- [ ] win-acme scheduled task fix unhealthy (cert expire 2026-06-18) -- [ ] UAT thật 1 tuần với 2-3 user (30 demo user — 16 sample + 14 Solutions thật) -- [ ] SMTP config → Email outbox -- [ ] Rotate credentials (admin + 30 demo + SA + vrapp + JWT) -- [ ] Schedule SQL backup Task Scheduler - -### D. Module Ngân sách (Budget) — Session 4 ✅ partial done - -- [x] **Migration 14** `AddBudgets` — 4 bảng (Budgets/BudgetDetails/BudgetApprovals/BudgetChangelogs) + index BudgetId nullable trên Contract & PurchaseEvaluation -- [x] Domain — `Budget` (Header) + `BudgetDetail` (flat row) + `BudgetApproval` + `BudgetChangelog` + enum `BudgetPhase` 5-state + `BudgetEntityType` Header/Detail/Workflow -- [x] `BudgetPolicy.Default` hardcoded simple 3-step (Drafter→CCM→CEO + Reject từ ChoCCM/ChoCEO về DangSoanThao) -- [x] Application CQRS ~340 LOC — Create + UpdateDraft + Transition + List + GetDetail + Delete (only DangSoanThao/TuChoi) + Detail CRUD (auto-recompute TongNganSach) + ListChangelogs -- [x] `BudgetsController` 11 endpoint REST -- [x] Menu seed `Budgets` root + 3 leaf (Bg_List/Bg_Create/Bg_Pending) order=27 icon Wallet -- [x] **14 demo user Solutions thật** — PRO 5 + CCM 7 + ISO 1 + CEO 1 (pwd `User@123456`) - -Session log: `2026-04-28-chot-session-4-budget.md`. - -### E. Pending migrations - -- [ ] `AddPePaymentTermFields` (nếu chốt UX tách field — JSON blob → 6 column) -- [x] **`AddPurchaseEvaluationDepartmentOpinions`** ✅ migration 15 (S5) -- [ ] `AddBudgetCodeSequences` (nếu chốt format MaNganSach atomic — hiện Random.Shared) -- [ ] `AddBudgetVersionedWorkflow` (nếu user cần admin config UI thay vì hardcoded `BudgetPolicy.Default`) +- [ ] `AddPePaymentTermFields` — nếu chốt UX tách field (JSON → 6 column riêng) +- [ ] `AddBudgetCodeSequences` — atomic SERIALIZABLE khi chốt format MaNganSach (hiện Random.Shared) +- [ ] `AddBudgetVersionedWorkflow` — nếu user cần admin config UI thay hardcoded `BudgetPolicy.Default` ## ✅ Phase 8 — Budget FE + PE/HD integration (Session 5 done) diff --git a/docs/changelog/recently-done-archive-2026-04.md b/docs/changelog/recently-done-archive-2026-04.md new file mode 100644 index 0000000..685adda --- /dev/null +++ b/docs/changelog/recently-done-archive-2026-04.md @@ -0,0 +1,61 @@ +# Recently Done — Archive (Phase 0-7, 2026-04-21..28) + +> Archive từ `STATUS.md` Recently Done table sau khi Phase 8 chốt 2026-04-29. +> Giữ lại để tra cứu lịch sử commit ↔ feature mapping. Newest đã chuyển ngược lên top. + +| Ngày | Ai | Task | Commit | +|---|---|---|---| +| 2026-04-28 | Claude | **Module Ngân sách (Budget) BE — 4 bảng + workflow simple 3-step** — Migration 14 `AddBudgets`. Domain: `Budget` (Header — MaNganSach `NS-YYYYMM-XXXX`, NamNganSach, ProjectId/DepartmentId, DrafterUserId, TongNganSach auto-sum, SlaDeadline) + `BudgetDetail` (flat row pattern: GroupCode/Name + ItemCode + NoiDung + DonViTinh + KhoiLuong/DonGia/ThanhTien) + `BudgetApproval` (workflow history reuse `ApprovalDecision`) + `BudgetChangelog` (`BudgetEntityType` Header/Detail/Workflow). Enum `BudgetPhase` 5 state (DangSoanThao→ChoCCM→ChoCEO→DaDuyet + TuChoi). `BudgetPolicy.Default` hardcoded 3-step (Drafter→CCM→CEO). Application: 11 CQRS handler (~340 LOC: Create/UpdateDraft/Transition/List/GetDetail/Delete + Detail CRUD auto-recompute TongNganSach + ListChangelogs). Api: `BudgetsController` 11 endpoint. Link: Contract.BudgetId? + PE.BudgetId? nullable FK + index. Menu seed `Budgets` root + 3 leaf (Bg_List/Create/Pending) order=27 icon Wallet. **FE chưa làm** (next session). | `a05c57b` | +| 2026-04-28 | Claude | **14 demo users Solutions company thật** — PRO 5 (TPB tra.bui + 4 NV: phuong/binh/danh/dat) + CCM 7 (TPB ngocanh.huynh + 6 NV: ha.dao/cuong.do/long.le/ha.nguyen/dung.nguyen/anh.nguyen) + ISO 1 (chau.le) + CEO 1 (huy.duong). Pattern reconcile per-user try-catch (gotcha #38 4-field rename). Pwd `User@123456`. Tổng 30 user (16 sample cũ + 14 Solutions thật). Test login E2E pass. | `8097892` | +| 2026-04-28 | Claude | **Docs cleanup + chốt session 3** — Tái cấu trúc MD: archive raw dump (forms-spec-raw, workflow-raw) → `_archive/`, compact `migration-todos.md` collapse Phase 0-5+Tier3 cũ, update `CLAUDE.md` modules table + skills 6 (3 domain + 3 ops), `flows/` thêm PE ref architecture, audit `gotchas.md` (38 pitfall — thêm #34 NavLink query string + #35 menu inheritance + #36 Vite env rebuild + #37 mutex accordion family + #38 Identity 4-field rename). Session log `2026-04-23-2200-roles-demo-pending-cleanup.md` + `2026-04-24-chot-session-3-pe-polish.md`. | `309dcd9` · `e71e0eb` · `e65578a` | +| 2026-04-24 | Claude | **PE polish — Demo seed + MaPhieu atomic + Pe_* perm defaults** — Migration 13 `AddPurchaseEvaluationCodeSequences` (Prefix PK, mirror ContractCodeSequences). `IPurchaseEvaluationCodeGenerator` + impl SERIALIZABLE — format `PE/{YYYY}/{A\|B}/{Seq:D3}`. Replace Random.Shared trong CreatePEHandler. `SeedDemoPurchaseEvaluationsAsync` 4 phiếu varied (A-001 DangSoanThao, A-002 ChoCEODuyetNCC + 9 quotes, A-003 DaDuyet PaymentTerms JSON, B-001 ChoDuAn 5-step). `SeedPurchaseEvaluationPermissionDefaultsAsync` 7 role × 9 menu key — Drafter/DeptManager/Procurement Create+Update, các role duyệt R+U, DeptManager thêm Delete. | `c48ac21` | +| 2026-04-24 | Claude | **Rebrand 3 domain huypham.vn → solutions.com.vn E2E** — 18 file repo (FE env + scripts + CI/CD + docs + skill + code comments). Viết `scripts/migrate-domains.ps1` (ASCII-only gotcha #30) chạy trên VPS: 3 HTTP binding mới + 3 cert Let's Encrypt (HTTP-01 via SelfHosting) + auto HTTPS 443 + redirect. CI/CD auto-deploy commit `66c1a5c+b93dacf`: appsettings.Production.json CORS mới + FE bundle `VITE_API_BASE_URL=api.solutions.com.vn`. E2E verified: `/api/purchase-evaluations` 401, CORS preflight OK, FE dist có domain mới. URL cũ fallback. Claude SSH tự chạy (không cần user RDP). | `66c1a5c` · `b93dacf` | +| 2026-04-23 | Claude | **SeedDemoUsersAsync robust reconcile + 16 demo users** — Reconcile pattern (per-user try-catch, fix drift dept/position/role nếu user existing). 13 → 16 demo (+bod.tran NĐUQ thứ 2, +pm.le PM thứ 2, +nv.truong NV CCM). Detailed log created/fixed/failed counts. Resolves prod issue: chỉ thấy admin user vì old skip-if-exists fail silent. | `a667665` | +| 2026-04-23 | Claude | **G-084 hardening** — localhost → 127.0.0.1 trong `deploy-iis.ps1` + skill `iis-deploy-runbook`. Thêm gotcha #33 (IPv4/IPv6 port hijack) ref VietReport incident + 3 rules (reverse-proxy IP literal / backend loopback IPv4 explicit / service dependency). SOLUTION_ERP risk thấp (API in-process IIS, no ARR proxy) nhưng chuẩn hóa cho tương lai. | `3990066` | +| 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` | +| 2026-04-23 | Claude | **SeedDemoContractsAsync — 7 demo HĐ varied phases** — Idempotent (skip nếu [DEMO] tồn tại). 7 HĐ covering 7 ContractType + final phases (DangSoanThao/DangGopY/DangInKy/DangTrinhKy/DaPhatHanh) + 14 Details rows + ~30 Approvals workflow history + 2 Comments demo. ApproverUserId mapping đúng role (CCM→ccm.tran, BOD→bod.huynh, HRA→hra.dang). Mã HĐ auto gen RG-001. | `8bc9565` | +| 2026-04-23 | Claude | **RolesPage CRUD `/system/roles`** — BE: CreateRole regex Name validation, UpdateRole CHỈ ShortName/Description (Name FK không đổi), DeleteRole block AppRoles.All + count UserRoles > 0. 3 endpoint POST/PUT/DELETE Authorize Admin. FE: 5-column table + Loại badge (Mặc định/Tùy chỉnh) + Edit dialog Name disabled + Delete with HARDCODED_ROLES guard + Banner amber FK warning + Create dialog regex pattern HTML5. | `072ad6d` | +| 2026-04-23 | Claude | **Roles VN labels (ShortName) + Users dept/position + 13 demo users** — Migration 11 `AddRoleShortNameAndUserDepartment`. Role thêm ShortName max 50 (QTV/BOD/CCM/PRO/FIN/...) + Description full VN. User thêm DepartmentId FK Restrict + Position. Idempotent backfill 12 roles VN labels. Seed 13 demo users (bod/pm/ccm/pro/fin/act/equ/hra TPB + 4 Drafter), pwd `User@123456`. FE UsersPage column Phòng ban + Chức vụ + edit dialog mới + roles checkbox "ShortName — Full". PermissionsPage Panel 1 2-line per role. | `330d529` + `ae59cfe` | +| 2026-04-23 | Claude | **4 master catalogs cho Details + datalist autocomplete** — Migration 10 `AddMasterCatalogs`: UnitsOfMeasure (20 seed) + MaterialItems (15) + ServiceItems (10) + WorkItems (15). CQRS CRUD 13 endpoint, Admin role POST/PUT/DELETE. Menu mới `Catalogs` group + 4 leaves dưới Master. FE Admin CatalogsPage generic 4-tab CRUD `/master/catalogs/:kind`. FE Details Add form HTML5 `` per field + smart-fill (pick code → autofill name + defaultUnit). DB 32→36 bảng. | `e27c547` + `16e24ed` | +| 2026-04-23 | Claude | **Mã HĐ gen ngay tại CreateContract + backfill HĐ legacy** — `CreateContractCommandHandler` call `codeGenerator.GenerateAsync` trước `db.Contracts.Add`. TransitionAsync giữ defensive `if MaHopDong null gen` cho legacy. `BackfillContractCodesAsync` trong DbInitializer chạy startup, idempotent (NULL count → skip nếu 0). Trade-off: gap sequence khi reject nhưng user có mã ngay đầu để reference giấy tờ. | `51449d6` | +| 2026-04-23 | Claude | **"Thao tác" 2-panel + Edit/Xóa hover + Detail preview** — `ContractCreatePage` rewrite: Panel 1 List HĐ theo type + button "+ Thêm mới" cuối. Panel 2 ContractHeaderForm (new) hoặc ContractEditForm (edit) + Chi tiết section. URL state ?type/?id/?mode=new. Action buttons row Panel 1: Edit ✏ + Xóa 🗑 luôn hiện, mờ + disabled khi Phase != DangSoanThao. ContractDetailsPreview cho create mode show table headers + lock icon. | `8c4b4da` + `ec0c983` + `501b4de` + `7f26ff9` + `39031ca` | +| 2026-04-23 | Claude | **Panel 2 layout: tabs → 7/3 grid (UX iter 2)** — Bỏ tabs Tổng quan/Chi tiết/Lịch sử. Render flat: Tổng quan (Info+Comments+Attachments) ở trên, dưới grid lg:grid-cols-10 (Chi tiết 7 cột + Lịch sử Changelog 3 cột). | `b3762af` (tabs) → `ad0652d` (grid) | +| 2026-04-23 | Claude | **4-bảng data model overhaul (Header+Details+Workflow+Changelog)** — Migration 9 `AddContractDetailsAndChangelog`: 7 ContractType-specific Details bảng + 1 ContractChangelog unified audit log. IChangelogService 5 method, wired vào CreateContract+UpdateDraft+AddComment+Upload/Delete/Transition. CQRS 9 endpoint mới (GetBundle+7 Add+Delete+ListChangelogs). FE ContractDetailsTab + ContractChangelogsTab. DB 24→32 bảng. | `70810e1` + `71c035d` + `e684455` | +| 2026-04-23 | Claude | **3-panel layout HĐ (List/Detail/Workflow) + Inbox + sidebar accordion + UserDashboard fix** — MyContractsPage + ContractsListPage + InboxPage 3-panel `lg:grid-cols-[320px_1fr_360px]`, `?id=` URL state, mobile fallback fullpage. Sidebar accordion qua AccordionContext (chỉ 1 Ct_ expand). Tách "Tổng quan" → /dashboard riêng (fix bug trùng /inbox), UserDashboardPage 5-card "Của tôi" + recent contracts. | `b75448e` + `89c7e88` + `7ea3957` + `d326e80` | +| 2026-04-23 | Claude | **Skill governance + audit định kỳ** — `docs/rules.md §9` mới (6 skill bảng, nguyên tắc tạo project-specific, format SKILL.md bắt buộc, workflow audit 7 bước, 4 anti-patterns). Cron task `solution-erp-skill-audit-monthly` fire 9:00 AM ngày 1 mỗi tháng (next 2026-05-01) — self-contained prompt cold-start, auto-refresh stale nhỏ + đề xuất add/archive cho human approve, log vào `docs/changelog/skill-audit-{YYYY-MM}.md`, ABORT nếu repo dirty. Touch-points: CLAUDE.md callout + HANDOFF A1 + migration-todos checkbox + skill scope commit | `b904a25` | +| 2026-04-23 | Claude | **3 skill ops project-specific** — Khảo sát alirezarezvani/claude-skills, quyết định KHÔNG bulk-clone (skill global đã cover phần generic, repo còn lại doc-dump không có when-to-use). Viết 3 skill mới encode SOLUTION_ERP-only: `dependency-audit-erp` (npm/dotnet CVE scan respect MediatR 12.4.1 + Swashbuckle 6.9.0 pin), `ef-core-migration` (8 migration history + 3-file rule + DesignTimeDbContextFactory + 6 pitfalls cụ thể), `iis-deploy-runbook` (3 IIS site + win-acme + NSSM gitea-runner + LibreOffice + debug playbook 500/502/SignalR). Total skill project-level = 6 (3 domain + 3 ops) | `661f859` | +| 2026-04-22 | Claude | **PermissionsPage 3-panel layout** — Grid `lg:grid-cols-[280px_1fr_300px]`: Panel 1 Role list click-to-select (active ring-brand), Panel 2 Menu×CRUD matrix sticky thead + search + column bulk-toggle + brand-tinted hover, Panel 3 Granted progress bar + CRUD breakdown color badges (slate/emerald/amber/red) + Tip | `91b2da1` | +| 2026-04-22 | Claude | **Admin Workflows tabs → sidebar menu items** — Seed 7 `Wf_` leaf dưới group `Workflows`. Layout resolvePath `Wf_` → `/system/workflows/`. WorkflowsPage bỏ tab bar, URL param drives type selection. Landing 7-card grid khi click top-level `Quy trình HĐ`. Inheritance: `Workflows.Read` perm → tất cả 7 leaves auto-visible. | `f216169` | +| 2026-04-22 | Claude | **Versioned workflow per ContractType** — 3 entity mới: WorkflowDefinition (Code+Version+IsActive+ContractType), WorkflowStep (Order+Phase+Name+SlaDays), WorkflowStepApprover (Role/User + AssignmentValue). Contract.WorkflowDefinitionId nullable FK pin tại create. Migration `AddVersionedWorkflows`. Seed v01 per 7 ContractType. `WorkflowPolicyRegistry.FromDefinition()` build runtime policy từ DB. ContractWorkflowService load pinned definition. Admin `/system/workflows/:typeCode` Designer modal (create new version, clone, add/remove step, +Role/+User approvers). POST /api/workflows auto-increment Version + deactivate old. Invariant: HĐ cũ pin v01 giữ nguyên khi v02 active. E2E verified: QT-MB-v02 active, HĐ cũ vẫn chạy v01. | `e7e5f2d` + `355bbe3` | +| 2026-04-21 | Claude | **Nested sidebar menu fe-user** — 7 ContractType × 3 actions (Danh sách/Thao tác/Duyệt), nested 3-level. Admin hide `Ct_*`. Layout recursive MenuNodeRenderer. MyContracts + Inbox filter `?type=X` | `5e0f380` + `48e91fe` | +| 2026-04-21 | Claude | **Seed master data + MyDashboard widgets** — DbInitializer seed 9 departments (PM/QS/CCM/PRO/FIN/ACT/EQU/HRA/BOD) + 5 demo suppliers + 3 demo projects idempotent. MyDashboard endpoint role-aware: DraftsInProgress / PendingMyApproval / DueSoon / Overdue / DraftsTotalValue. FE "Của tôi" row 4 card hover-interactive, admin auto-hide nếu = 0 | `6197c84` | +| 2026-04-21 | Claude | **Dynamic workflow policy per ContractType** — Domain WorkflowPolicy record + registry (Standard 8-phase cho Thầu phụ/Giao khoán/NCC; SkipCcm 7-phase cho Dịch vụ/Mua bán/Nguyên tắc). ContractWorkflowService dùng policy.ForContract(c). FE xóa NEXT_PHASES hardcoded, dùng contract.workflow.nextPhases BE trả. WorkflowSummaryCard timeline visual. Gotcha #21 resolved | `cae4d84` | +| 2026-04-21 | Claude | **PDF export + .doc/.xls auto-convert + DynamicForm** — LibreOffice 25.8.6 VPS, IDocumentConverter shell soffice `--convert-to pdf/docx/xlsx` timeout+temp isolation. Admin upload .doc auto-convert .docx. DynamicForm parse FieldSpec JSON render inputs (text/textarea/number/date/currency/select). Form↔JSON toggle. E2E verified PDF 488KB/126 pages | `e459097` + `6bbd894` | +| 2026-04-21 | Claude | **Form template builder CRUD** — Admin tự upload `.docx/.xlsx` qua UI (không cần dev). BE multipart + FormCode regex unique + FieldSpec JSON validation + soft delete via IsActive. FE FormsPage upload dialog + row actions render/edit/delete. E2E verified | `166d26c` | +| 2026-04-21 | Claude | **Fix Gitea 500 sau Install Web-WebSockets** — appcmd unlock section webSocket. Gotcha #25 | `c52186b` | +| 2026-04-21 | Claude | **SignalR realtime notifications E2E** — 3-project clean-arch: IRealtimeNotifier (App) + SignalRNotifier (Api) + NotificationPushInterceptor (Infra SaveChanges hook). Hub `/hubs/notifications` JWT `?access_token=` query (WebSocket headers limit). FE singleton lib/realtime.ts auto-reconnect + toast + query invalidation. IIS WebSocket module enabled | `ea9ab5e` | +| 2026-04-21 | Claude | **Attachment upload E2E** — IFileStorage + LocalFileStorage (path-traversal guard) + CQRS Upload/Download/Delete + 3 endpoint (multipart, stream, DELETE) + FE ContractAttachmentsSection drag-drop + purpose selector + icon-per-MIME + auth-blob download + confirm delete. Wired 2 ContractDetailPage | `c8d0070` + `dc3f09b` | +| 2026-04-21 | Claude | **Content polish** — typography 14px + leading 1.55 + tracking-tight + PageHeader border-b + Button shadow+active + Input inset shadow + DataTable rounded-xl UPPERCASE header brand hover | `346bd5d` | +| 2026-04-21 | Claude | **Brand identity từ Solutions logo** — pixel-sampled #1F7DC1 → palette brand-50..900 + accent red + Be Vietnam Pro (Vietnamese-first) + favicon 'S' crop + apple-touch-icon + login gradient brand | `4abb559` + `bf1fbe3` | +| 2026-04-21 | Claude | **Fix login Network Error** — SPA web.config HTTP→HTTPS redirect rule (CORS chỉ https) | `397eb36` | +| 2026-04-21 | Claude | **Notifications module E2E** — Domain entity + EF migration + Infra service + CQRS + API controller + FE bells wire real endpoint + ContractWorkflowService emit notification cho Drafter khi phase transition | `49c0ddc` | +| 2026-04-21 | Claude | **PermissionsPage iter 1** — search, stats badge, bulk column toggle, empty state | `6c0e206` | +| 2026-04-21 | Claude | **ERP shell** — TopBar + NotificationBell + UserMenu (avatar + role badges). Layout `[sidebar] [topbar + content]` | `2b6f91c` | +| 2026-04-21 | Claude | **Tier 1 UI polish** — SlaTimer (inline + full variant, 5 chỗ), Inbox stat cards, DataTable skeleton rows, EmptyState | `290936a`..`2e43799` | +| 2026-04-21 | Claude | **CI/CD deploy xanh E2E** — self-hosted Windows runner, single job build+deploy, fresh node_modules (Vite 8 rolldown binding), appsettings từ secrets, /health/live 200 sau deploy | `b40da1e` | +| 2026-04-21 | Claude | **VPS prod setup** — SQL DB (SQLEXPRESS), IIS sites (SolutionErp-Api/Admin/User), win-acme 3 Let's Encrypt + auto-renew, shared gitea-runner với VIETREPORT | `169e268`..`519ba85` | +| 2026-04-21 | Claude | **IDOR + SLA Job + Admin warning** — ContractsController filter theo role. SlaExpiryJob BackgroundService 15min auto-approve Decision=AutoApprove. DbInitializer warn khi admin vẫn default | `fba0754` | +| 2026-04-21 | Claude | **Phase 5.1 Security + Users Mgmt** — Security headers + Identity lockout + LoginHandler check + Users CQRS + UsersController + FE `/system/users` | `11e61c9` | +| 2026-04-21 | Claude | **Phase 5 Prep** — BE rate limit + health check + Serilog file + HSTS + scripts deploy-iis/backup-sql + .gitea/workflows/deploy.yml + 4 guides + FE refresh token queue pattern | `46a2cab` | +| 2026-04-21 | Claude | **Phase 4 Report MVP** — Dashboard KPI + Excel export + rules.md + architecture.md + schema-diagram.md + gotchas 26 pitfalls | `fe7ad8e` | +| 2026-04-21 | Claude | **Phase 3 Workflow MVP** — 9 phase state machine + gen mã HĐ RG-001 | `7e957a7` | +| 2026-04-21 | Claude | **Phase 2 Form Engine MVP** | `5113e4c` | +| 2026-04-21 | Claude | **Phase 1.2** — CRUD Master + Permission Matrix | `54d6c9b` | +| 2026-04-21 | Claude | **Phase 1 foundation** + Docs addition | `702411f` + `49a5f57` | +| 2026-04-21 | Claude | **Phase 0** | `25dad7f` |