# 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 `<datalist>` 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_<Code> 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_<Code>` leaf dưới group `Workflows`. Layout resolvePath `Wf_<Code>` → `/system/workflows/<code>`. 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` |
