User request: 'Chot lai toan bo MD de sang session moi'. Session 3 (2026-04-24) — ~15 commit feat/fix PE module + domain migration: - Domain 3 subdomain huypham.vn → solutions.com.vn E2E live - PE rename 'Phuong An' → 'Giai phap' + backfill DB - Menu tree inheritance extend Pe_*/PeWf_* - Accordion mutex Pe_* + sidebar w-72 + label nowrap - NavLink queryMatches (fix 2 leaf cung highlight) - PE detail flat layout: Panel 2 = 4 section, Panel 3 + approvals/history - Upload file dinh kem per-NCC (SupplierAttachmentsCell) + Bang so sanh tong - readOnly mode menu 'Duyet' (pendingMe=1) - HD move Lich su dieu chinh → Panel 3 - Demo email rebrand @solutionerp.local → @solutions.com.vn + BackfillUserEmailDomain Docs updated (6 file): - STATUS.md: +9 row Recently Done session 3. In Progress tick 10+ done. Phase hien tai = 'UX polish hoan thien, UAT-ready'. - HANDOFF.md: TL;DR session 3 summary. Priority 0 = 3 task MISSING cuoi (Designer UI, Y kien 4 phong ban, Export PDF). Login email moi. - gotchas.md: +5 entry (#34 NavLink query, #35 menu inheritance extend, #36 Vite env rebuild, #37 PS 5.1 ASCII, #38 Identity rename 4 field) + checklist debug +5 entry. - ef-core-migration SKILL: migration 13 AddPurchaseEvaluationCodeSequences + Phase 6 update section (ComparisonTable enum + BackfillUserEmail). - skills/README: ef-core-migration 13 migration label updated. - docs/changelog/sessions/2026-04-24-chot-session-3-pe-polish.md: session log 15 commit + bugs + stats + next priorities session 4. Memory project_solution_erp.md: Phase 6 iter 2 DONE. Domain rebrand DONE. Session 4 priority 3 PE gap remaining. Stats: 47 DB tables (+1 MaPhieu seq), ~113 endpoint (+3 PE attachments), 13 migrations, 38 gotchas, ~85 commits total.
22 KiB
HANDOFF — Brief 5 phút cho session tiếp theo
Last updated: 2026-04-24 chiều (Phase 6 — PE polish iter 2 + domain rebrand hoàn tất, UAT-ready)
TL;DR
PE module UX polish gần complete. Session 3 (24/04) apply 10 commit fix tất cả UX friction user báo:
- Rename menu "Phương Án" → "Giải pháp"
- Menu tree inheritance Pe_/PeWf_ (fix bug children không hiện)
- Accordion mutex 2 PE group + sidebar w-72 nowrap label
- NavLink active check query string (fix 2 leaf cùng highlight)
- PE detail flat layout: Panel 2 = 4 section (Thông tin/NCC/Hạng mục/Bảng so sánh), Panel 3 thêm Duyệt + Lịch sử thay đổi
- Upload file đính kèm per-NCC (SupplierAttachmentsCell) + Bảng so sánh tổng
- readOnly mode cho menu "Duyệt" (pendingMe=1)
- HĐ: move Lịch sử điều chỉnh Panel 2 → Panel 3
- Demo email rebrand
@solutionerp.local → @solutions.com.vnvới backfill
Domain migration (session 2): 3 subdomain .huypham.vn → .solutions.com.vn
live E2E — api/admin/eoffice.solutions.com.vn. Cert Let's Encrypt + CORS +
FE bundle VITE_API_BASE_URL đều đã apply.
Tổng: 47 DB tables, ~113 endpoints, 13 migrations, 33 gotchas, 20+ commit session 3 push lên Gitea.
⚠️ CẢNH BÁO session tiếp (Session 4)
- Chưa xóa binding cũ
.huypham.vn— vẫn active fallback. Sau 1-2 ngày verify stable →.\migrate-domains.ps1 -RemoveOld -SkipCerttrên VPS. - win-acme scheduled task "unhealthy" — cert auto-renew có thể fail
khi gần 2026-06-18. Fix: mở
wacs.exeinteractive → Manage Renewals → recreate task. - PE còn 3 task MISSING cho feature-complete (xem STATUS §A):
- PE Workflow admin designer UI
/system/pe-workflows/:typeCode - Auto-map PE Details → Contract 7 per-type Details khi gen HĐ
- Section "Ý kiến 4 phòng ban" (Phê duyệt/CCM/MuaHàng/SM-PM)
- PE Workflow admin designer UI
- Login email mới
admin@solutions.com.vn/Admin@123456— old@solutionerp.localđã bị rename 401. - 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 |
| 6+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future |
Run nhanh
# 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 — PE feature gap (session 4)
Xem STATUS.md §🔥 In Progress đầy đủ (nhóm A/B/C/D). 3 task MISSING cuối:
- PE Workflow admin designer UI
/system/pe-workflows/:typeCode— mirror patternWorkflowsPage.tsx+WorkflowDesigner.tsx. BE cầnPeWorkflowAdminFeatures.cs(GetOverview + CreateNewVersion) +PeWorkflowsController.cs. Framework backend đã sẵn (3 bảngPurchaseEvaluationWorkflow*+FromDefinitionbuilder), chỉ thiếu wire UI. - Ý 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.
- Export phiếu PDF/Excel — tái dùng
IDocumentConverter+ templatePE-TrinhDuyet.docx. - Payment terms tách field từ JSON blob → 6 field riêng (optional UX polish).
- Auto-map PE Details → Contract Details khi gen HĐ (optional nâng cấp).
Đã xong trong session 3 (check STATUS Recently Done):
PE Attachments upload✅ (per-NCC + Bảng so sánh tổng)Menu tree inheritance Pe_/PeWf_✅Accordion mutex + sidebar width + label nowrap✅NavLink query active check✅PE detail flat layout + readOnly mode✅HĐ move Lịch sử điều chỉnh → Panel 3✅Menu rename Phương Án → Giải pháp✅Demo email rebrand solutionerp.local → solutions.com.vn✅
A. Hard blockers (chờ user / ops)
- 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
- SMTP config để bật Email outbox:
Khi có → thêm
"Email": { "Host": "smtp.gmail.com", "Port": 587, "Username": "...", "Password": "...", "From": "noreply@solutionerp.local" }MailKit,IEmailSender, hook vàoNotificationService.CreateAsyncngay trước khi enqueue realtime push. - Rotate credentials — SA SQL password, vrapp password, JWT secret prod, Gitea runner registration token
- 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:
- Cross-check 6 skill hiện có với STATUS / gotchas / migration-todos
- Check repo nguồn 3rd party (alirezarezvani/claude-skills) có gì mới
- Update / archive / add skill nếu cần
- 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:// 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.Readcho 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 (26 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.WorkflowDefinitionIdpin đú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.WorkflowDefinitionIdKHÔ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 (User@123456):
bod.huynh@solutionerp.local Tổng GĐ (BOD)
bod.le@solutionerp.local Phó GĐ NĐUQ
pm.nguyen@solutionerp.local GĐ Dự án FLOCK 01 (PM)
ccm.tran@solutionerp.local TPB Kiểm soát chi phí (CCM + TPB)
pro.pham@solutionerp.local TPB Cung ứng (PRO + TPB)
fin.do@solutionerp.local TPB Tài chính (FIN + TPB)
act.vu@solutionerp.local Kế toán trưởng (ACT + TPB)
equ.bui@solutionerp.local TPB Thiết bị (EQU + TPB)
hra.dang@solutionerp.local TPB HRA (HRA + TPB)
qs.hoang, qs.ngo QS công trường (NV.PB)
nv.cao, nv.dinh NV Cung ứng/Tài chính (NV.PB)
⚠ 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