# HANDOFF — Brief 5 phút cho session tiếp theo **Last updated:** 2026-04-28 (Phase 7 — **Module Ngân sách (Budget) BE + 14 demo users Solutions thật**) ## TL;DR **Session 4 (28/04)** thêm 2 milestone lớn: ### A. Module Ngân sách (Budget) BE — migration 14, +4 bảng, +11 endpoint - 4 entity: `Budget` (Header) + `BudgetDetail` (flat row) + `BudgetApproval` (history) + `BudgetChangelog` (audit log). - Enum `BudgetPhase` 5 state (DangSoanThao→ChoCCM→ChoCEO→DaDuyet + TuChoi). - `BudgetPolicy.Default` hardcoded simple 3-step (Drafter→CCM→CEO) — chưa versioned (TODO khi user cần admin config UI). - Mã `NS-YYYYMM-XXXX` Random.Shared (chưa atomic — TODO khi format chính thức). - Link nullable: `Contract.BudgetId?` + `PE.BudgetId?` đã có FK + index, FE chưa wire form. - Menu seed `Budgets` root + 3 leaf (Bg_List/Bg_Create/Bg_Pending) order=27 icon Wallet. - Application: 11 CQRS handler ~340 LOC (Create/UpdateDraft/Transition/List/GetDetail/Delete + Detail CRUD auto-recompute TongNganSach + ListChangelogs). - Api: `BudgetsController` 11 endpoint REST. - **FE chưa làm — Priority 0 session 5.** ### B. 14 demo user Solutions thật - PRO 5 (TPB tra.bui + 4 NV) + CCM 7 (TPB ngocanh.huynh + 6 NV) + ISO 1 (chau.le) + CEO 1 (huy.duong). - Pwd `User@123456`. Reconcile pattern (gotcha #38 4-field rename). - Tổng 30 user (16 sample cũ giữ + 14 Solutions thật mới). **Tổng:** 51 DB tables, ~124 endpoints, 14 migrations, 38 gotchas, 5+ commit session 4 push lên Gitea. ## ⚠️ CẢNH BÁO session tiếp (Session 5) 1. **FE Budget pages CHƯA LÀM** — BE đã sẵn sàng nhưng chưa có page nào. Pattern: copy từ PE 3-panel List + Create + Detail tabs (Thông tin / Hạng mục) + WorkflowPanel timeline. Mirror sang fe-user. Thêm route `/budgets`, `/budgets/new`, `/budgets/:id`. Menu resolver `Bg_*` → URL. 2. **PE/Contract → Budget integration CHƯA WIRE** — BE đã có `BudgetId?` nullable FK trên cả 2 entity, FE form chưa thêm field "Ngân sách" select. Cần filter Budget theo `Phase=DaDuyet && NamNganSach=current && ProjectId match`. Tab Hạng mục có thể bonus cột "So với ngân sách". 3. **Chưa xóa binding cũ `.huypham.vn`** — vẫn active fallback. Sau 1-2 ngày verify stable → `.\migrate-domains.ps1 -RemoveOld -SkipCert` trên VPS. 4. **win-acme scheduled task "unhealthy"** — cert auto-renew có thể fail khi gần 2026-06-18. Fix: mở `wacs.exe` interactive → Manage Renewals → recreate task. 5. **PE feature gap carry over** (xem STATUS §C): - PE Workflow admin designer UI `/system/pe-workflows/:typeCode` - Section "Ý kiến 4 phòng ban" (Phê duyệt/CCM/MuaHàng/SM-PM) - Export phiếu PDF/Excel 6. **Login email** `admin@solutionerp.local` / `Admin@123456` — domain default chưa đổi sang `@solutions.com.vn` (chỉ demo user và rebrand cũ trong BackfillDemoEmail). 7. **Chú ý G-084:** VPS shared với VietReport — mọi reverse proxy / backend service mới phải dùng `127.0.0.1` + bind loopback IPv4 explicit. ## ⭐ Skills (.claude/skills/) — PHẢI dùng khi task khớp | Domain (3) | Ops (3) | |---|---| | `contract-workflow` — state machine + versioned WF | `dependency-audit-erp` — npm/dotnet CVE scan | | `form-engine` — render docx/xlsx + PDF | `ef-core-migration` — EF migration + 3-file rule | | `permission-matrix` — role × menu × CRUD | `iis-deploy-runbook` — 3 site IIS + win-acme + runner | **Audit cron:** `0 9 1 * *` (9:00 AM ngày 1 mỗi tháng). Workflow: `docs/rules.md §9.4`. Lần kế: **2026-05-01**. **Quy tắc:** KHÔNG bulk-clone repo skill 3rd party. Chỉ skill PROJECT-SPECIFIC. Đầy đủ: `docs/rules.md §9`. ## Ở đâu rồi? | Phase | Trạng thái | |---|---| | 0 Draft | ✅ Done | | 1 Alpha Core (foundation + đợt 2 CRUD + Permission) | ✅ Done | | 2 Form Engine MVP + iter 2 (upload UI + .doc auto-convert + PDF export) | ✅ Done | | 3 Workflow MVP (9 phase + code gen) + iter 2 (SLA job + attachment + notify) | ✅ Done | | 4 Report MVP (Dashboard + Excel) + user-specific dashboard | ✅ Done | | 5 Prep + 5.1 Security + Users Mgmt | ✅ Done | | **5 Deploy prod** (3 domain HTTPS live) | ✅ Done | | **Tier 3 (Attach + Realtime + Form builder + PDF + Versioned WF + Nested menu + Permission 3-panel)** | ✅ Done | | **Skill governance** (6 skill project-level + audit cron 1/tháng) | ✅ Done | | **3-panel List/Inbox/Thao tác + sidebar accordion + UserDashboard** | ✅ Done | | **4-bảng data model** (Header + 7 Details + Workflow + Changelog audit) | ✅ Done | | **Mã HĐ gen tại Create + backfill legacy** | ✅ Done | | **4 master catalogs** (Units/Materials/Services/WorkItems) + datalist autocomplete | ✅ Done | | **Roles VN labels (ShortName)** + Users dept/position + 13 demo users | ✅ Done | | **RolesPage CRUD** `/system/roles` + custom role admin | ✅ Done | | **7 demo HĐ varied phases** + details + comments + approvals workflow | ✅ Done | | **User-kind approver runtime guard** + Warning 20% SLA | ✅ Done | | **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 | | **PE polish iter 2** — flat layout + per-NCC attachments + readOnly Duyệt + email rebrand | ✅ Done | | **Domain rebrand huypham.vn → solutions.com.vn** — 3 subdomain + cert + CORS + FE bundle | ✅ Done | | **Module Ngân sách BE** — 4 bảng + 11 endpoint + workflow simple + 30 user | ✅ Done (FE TODO) | | **PE Workflow designer UI + Ý kiến 4 phòng ban + Export PDF** | 📝 Pending session 5+ | | **FE Budget pages + PE/Contract → Budget integration** | 📝 Priority 0 session 5 | | 8+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future | ## Run nhanh ```powershell # Terminal 1 — API (auto seed 12 role + 9 dept + 5 supplier + 3 project + 8 template + 7 workflow definition + 28 ContractType menu + 7 workflow menu) dotnet run --project src\Backend\SolutionErp.Api # Terminal 2 — Admin FE cd fe-admin && npm run dev # → http://localhost:8082 # Terminal 3 — User FE cd fe-user && npm run dev # → http://localhost:8080 ``` Login: `admin@solutionerp.local` / `Admin@123456` ## Quick sanity-check **Admin (:8082):** - `/dashboard` → "Của tôi" row 4 card + KPI cards + charts - `/contracts` → list toàn bộ, filter phase/supplier/project - `/contracts/new?type=5` → tạo HĐ Mua bán, pre-select type từ URL - `/contracts/{id}` → timeline + action dialog + attachments drag-drop + WorkflowSummaryCard - `/system/workflows` → 7-card landing (Thầu phụ/Giao khoán/NCC/Dịch vụ/Mua bán/NguyenTacNcc/NguyenTacDv) - `/system/workflows/MuaBan` → DefinitionCard active + history + "Tạo phiên bản mới" modal với Steps + Approvers (+Role / +User) - `/system/permissions` → 3-panel layout (Role list | Menu×CRUD matrix | Granted stats) - `/system/users` → Users CRUD + assign roles - `/forms` → upload .docx/.xlsx + render dialog Form↔JSON + Tải PDF **User (:8080):** - `/inbox?type=5` → HĐ Mua bán chờ role mình - `/my-contracts?type=2` → HĐ Thầu phụ của tôi - `/contracts/new?type=3` → tạo HĐ NCC - Sidebar nested: 📄 Hợp đồng → expand 7 type → expand "HĐ Mua bán" → Danh sách / Thao tác / Duyệt **Realtime check:** - Login 2 tab (admin + user) → user tạo comment / transition → admin nhận toast + bell +1 ## Cần làm kế tiếp ### 🔥 Priority 0 — Budget FE + PE/HD integration (session 5) Xem **STATUS.md §🔥 In Progress** đầy đủ (nhóm A/B/C/D/E). Tóm tắt: **A. Budget FE pages — copy pattern PE:** 1. `fe-admin/src/types/budget.ts` (types + enums BudgetPhase + ApprovalDecision reuse) 2. `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel `lg:grid-cols-[320px_1fr_360px]` — Panel 1 list + Panel 2 detail tabs + Panel 3 workflow timeline) 3. `fe-admin/src/pages/budgets/BudgetCreatePage.tsx` (form Header: tên/năm/dự án/phòng ban/người soạn) 4. `fe-admin/src/components/budgets/BudgetDetailTabs.tsx` (Thông tin / Hạng mục — flat row giống PE Details) 5. `fe-admin/src/components/budgets/BudgetWorkflowPanel.tsx` (Panel 3: timeline phase + ô comment + button Trình) 6. Mirror tất cả sang `fe-user/` 7. App.tsx routes `/budgets`, `/budgets/new`, `/budgets/:id` cả 2 app 8. Menu resolver `Bg_*` ở Layout: `Bg_List` → `/budgets`, `Bg_Pending` → `/budgets?phase=Pending`, `Bg_Create` → `/budgets/new` **B. PE/Contract → Budget integration:** 1. **PE form** thêm field `Ngân sách` select Budget (filter `Phase=DaDuyet && NamNganSach=current && ProjectId=peProjectId`). Lưu `PE.BudgetId`. 2. **Contract form** tương tự — link sang Budget cho đối chiếu chi phí. 3. PE Detail tab có thể thêm cột "So với ngân sách" — compute từ `BudgetDetail` tương ứng (match GroupCode + ItemCode) nếu có Budget link. **C. PE feature gap (carry over từ session 3):** 1. **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode` — mirror pattern `WorkflowsPage.tsx` + `WorkflowDesigner.tsx`. BE cần `PeWorkflowAdminFeatures.cs` + `PeWorkflowsController.cs`. Framework backend đã sẵn (3 bảng `PurchaseEvaluationWorkflow*` + `FromDefinition`), chỉ thiếu wire UI. 2. **Ý kiến 4 phòng ban** (Phê duyệt / P.CCM / P.MuaHàng / SM-PM) — Excel form có, entity chưa map. Cần design: 4 text field + signoff date, hoặc dùng Approvals với role-kind. 3. **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`. **D. Optional polish:** - Budget MaNganSach atomic sequence (hiện Random.Shared, format chốt sau) - Budget versioned workflow (admin config qua UI — hiện hardcoded `BudgetPolicy.Default`) - Payment terms PE tách field - Auto-map PE Details → Contract Details khi gen HĐ - Matrix Quotes bulk paste từ Excel **Đã xong trong session 4 (check STATUS Recently Done):** - ~~Module Ngân sách BE — 4 bảng + 11 endpoint + workflow simple~~ ✅ - ~~14 demo user Solutions thật (PRO 5 + CCM 7 + ISO 1 + CEO 1)~~ ✅ - ~~Docs cleanup + tái cấu trúc MD~~ ✅ ### A. Hard blockers (chờ user / ops) 1. **UAT thật 1 tuần với 2-3 user** — hard requirement từ roadmap. Kiến nghị: - User A: Drafter (QS/NV.PB) — tạo 3 HĐ mỗi type, đi hết 9 phase - User B: CCM — duyệt phase 6 - User C: BOD — duyệt phase 7 - Ghi bug / friction / đề xuất → backlog iter 2 2. **SMTP config** để bật Email outbox: ```json "Email": { "Host": "smtp.gmail.com", "Port": 587, "Username": "...", "Password": "...", "From": "noreply@solutionerp.local" } ``` Khi có → thêm `MailKit`, `IEmailSender`, hook vào `NotificationService.CreateAsync` ngay trước khi enqueue realtime push. 3. **Rotate credentials** — SA SQL password, vrapp password, JWT secret prod, Gitea runner registration token 4. **Schedule SQL backup** — `schtasks /create /tn "SolutionErp Backup" /tr "powershell -File C:\...\scripts\backup-sql.ps1" /sc DAILY /st 03:00` ### A1. Định kỳ — Skill audit **Cadence:** Mỗi đầu tháng (4 tuần). Lần audit kế tiếp: **2026-05-01**. Workflow xem `docs/rules.md §9.4`. Tóm tắt: 1. Cross-check 6 skill hiện có với STATUS / gotchas / migration-todos 2. Check repo nguồn 3rd party (alirezarezvani/claude-skills) có gì mới 3. Update / archive / add skill nếu cần 4. Log vào `docs/changelog/skill-audit-2026-05.md` Trigger: user nói "audit skill" hoặc tự chạy đầu Phase mới. ### B. Polish iterations (optional — khi UAT phát sinh) - **Roles CRUD** — admin tạo custom role ngoài 12 hardcoded (`Domain.Identity.AppRoles`) - **User-kind approver runtime** — data model `WorkflowStepApprover.Kind=User` + `AssignmentValue=userId` đã có, chỉ cần: ```csharp // ContractWorkflowService.TransitionAsync (bổ sung): var userApprovers = step.Approvers.Where(a => a.Kind == ApproverKind.User) .Select(a => Guid.Parse(a.AssignmentValue)); if (userApprovers.Any() && !userApprovers.Contains(actorUserId)) throw new ForbiddenException(); ``` - **Grant `Workflows.Read` cho non-admin role** trong PermissionsPage → menu Wf_* auto-visible (inheritance đã có) - **Warning notification 20% SLA** — job emit khi `SlaDeadline - now < sla * 0.2 && !SlaWarningSent`, set flag - **Reject → DangSoanThao E2E test** với 3 role khác nhau - **Deps scan CI** — `dotnet list package --vulnerable` + `npm audit --audit-level=high` ### C. Non-goals / parked - E-signature (VNPT CA / FPT CA) — Phase 6 - Bravo/SAP import NCC — Phase 6 - Mobile app — Phase 6 - AI OCR scan HĐ — Phase 6+ ## Lưu ý kỹ thuật quan trọng **Đọc [`gotchas.md`](gotchas.md) (38 bẫy) trước khi:** - Thêm package mới → .NET 10 compat (MediatR 14 fail → dùng 12.4.1) - Debug TS enum error → dùng const-object pattern (`erasableSyntaxOnly`) - Expression tree lỗi → tách switch ra ngoài LINQ - Deploy Windows Feature (WebSockets, etc.) → unlock section ở applicationHost (gotcha #25) - Workflow transition 403 → check `Contract.WorkflowDefinitionId` pin đúng không - Migration lỗi → 3 file đầy đủ (Designer + Migration + Snapshot) ## Versioned workflow — quick reference ``` 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 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ũ ✓ ``` 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 ``` ## Credentials + URLs ``` admin@solutionerp.local / Admin@123456 ← Admin (QTV) Demo users — 30 user (User@123456): ── 16 sample @solutionerp.local (giữ cho test legacy) ── bod.huynh, bod.le Tổng GĐ + Phó GĐ NĐUQ pm.nguyen GĐ Dự án FLOCK 01 (PM) ccm.tran, pro.pham, fin.do TPB CCM/PRO/FIN act.vu, equ.bui, hra.dang Kế toán trưởng / TPB EQU / TPB HRA qs.hoang, qs.ngo QS công trường (NV.PB) nv.cao, nv.dinh, nv.truong NV Cung ứng/Tài chính/CCM (NV.PB) bod.tran, pm.le Bonus NĐUQ + PM thứ 2 ── 14 Solutions thật @solutions.com.vn (session 4) ── PRO 5: tra.bui (TPB) + phuong.nguyen, binh.lethanh, danh.huynh, dat.tran (NV) CCM 7: ngocanh.huynh (TPB) + ha.dao, cuong.do, long.le, ha.nguyen, dung.nguyen, anh.nguyen (NV) ISO 1: chau.le CEO 1: huy.duong ⚠ Rotate ALL passwords trước UAT thật ``` - API prod: https://api.solutions.com.vn — `/health/live`, `/health/ready` - Admin FE prod: https://admin.solutions.com.vn - User FE prod: https://eoffice.solutions.com.vn - API dev: http://localhost:5443 — `/swagger` (Dev only) - Admin FE dev: http://localhost:8082 - User FE dev: http://localhost:8080 - SQL dev: `(localdb)\MSSQLLocalDB` / `SolutionErp_Dev` - SQL prod: `.\SQLEXPRESS` / `SolutionErp` / `vrapp` (⚠️ rotate) ## Đánh giá nhanh **Tốt:** - 3 domain HTTPS prod live, CI/CD xanh - Tier 3 feature-complete: attachment, realtime, form builder (upload + DynamicForm + PDF), versioned workflow (admin-configurable per ContractType, pin per contract), nested menu per type, 3-panel permissions - Clean-arch 3-project split đúng cho 2 cross-cutting service (realtime + document-converter) - 26 gotchas tích lũy, 8 session log, 40 docs — agent onboard nhanh - Invariant critical: "HĐ cũ giữ quy trình cũ" guaranteed by pinning (reference-based immutability, không snapshot copy) **Rủi ro còn:** - UAT thật chưa chạy → có thể phát hiện edge case missing - SMTP chưa có → notification chỉ in-app (toast + bell), không email - User-kind approver chưa enable guard runtime (designer cho pick, nhưng transition dùng Role fall-back) - Credentials chưa rotate - SQL backup chưa schedule Task Scheduler