All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m47s
11 commit feature work (b75448e→ae59cfe) → docs sync. ## STATUS.md - Last updated 2026-04-23 16:00 - Phase header: Tier 3 + 4-bảng + master catalogs + roles VN - 7 Recently Done row mới (3-panel layout, 4-bảng overhaul, Thao tác 2-panel, Mã HĐ gen Create, master catalogs, roles VN demo users) - Cumulative table thêm cột "+Toolkit/Catalogs/Roles" (DB 36, endpoints ~80, migrations 11, commits ~47) - Session log link mới - Skill list count = 13 file ## HANDOFF.md - TL;DR cập nhật: 36 tables, 80 endpoints, 11 migrations - Phase table thêm 5 row Done (3-panel, 4-bảng, mã HĐ, master, roles) - Git state 18 commit gần nhất - Credentials block thêm 13 demo user (User@123456) — warn rotate trước UAT ## migration-todos.md Section "Session 2026-04-23 (chiều)" với 14 ticked checkbox + commit refs. ## schema-diagram.md - Header: 24 → 36 bảng - Migration table thêm row 9-11 (highlighted) - Section 8bis mới: chi tiết 7 Details + ContractChangelogs + 4 Catalogs + Role.ShortName + User.DepartmentId/Position ## Session log mới `docs/changelog/sessions/2026-04-23-1500-toolkit-data-roles.md` (~270 dòng) — outcome A→I, stats cumulative, 6 architectural decisions, next session priority. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
19 KiB
19 KiB
Migration To-dos — Atomic Roadmap
Mỗi item là 1 task atomic (~2-8h work). Tick
[x]khi xong. Link session log nếu có.
Phase 0 — Draft Scaffold (T1)
- Tạo cấu trúc thư mục
SOLUTION_ERP/ - Scaffold .NET 10 solution
SolutionErp.slnx - Scaffold 4 project:
SolutionErp.{Domain, Application, Infrastructure, Api} - Wire Clean Arch references (Api → App/Infra, Infra → App, App → Domain)
- Install NuGet base: MediatR, FluentValidation, AutoMapper, EF Core SqlServer, Identity, JWT, Swagger, Serilog
- Scaffold 2 React + Vite apps
fe-admin+fe-uservới TS template - Config vite.config.ts: port, strictPort, proxy
/api, alias@ - Pin Node
>=20trong package.json +.nvmrccho CI - Parse 8 form →
docs/forms-spec.md - Parse quy trình →
docs/workflow-contract.md - Viết
docs/{CLAUDE,STATUS,PROJECT-MAP}.md - Viết
docs/database/database-guide.md(conventions + schema + ERD + migration workflow) - Viết
docs/flows/— README + 6 flow doc (auth, permission, contract-create, contract-approve, form-render, sla-expiry) - Viết
.gitignore,README.md,global.json,docker-compose.yml - Tạo placeholder skill folders:
contract-workflow,form-engine,permission-matrix git init+ commit đầu (25dad7f)- Push Gitea remote (chờ URL từ user)
Phase 1 — Alpha Core (T2-4)
Foundation (đã xong Session 2)
Domain/Common/BaseEntity.cs(Id Guid, CreatedAt, UpdatedAt, CreatedBy, UpdatedBy)Domain/Common/AuditableEntity.cs(IsDeleted, DeletedAt, DeletedBy)Domain/Contracts/Enums:ContractType,ContractPhase(9 state),ApprovalDecisionDomain/Identity/User.cs(IdentityUser + FullName + RefreshToken + IsActive)Domain/Identity/Role.cs(IdentityRole + Description)Domain/Identity/AppRoles.cs— 12 role constantsApplication/Common/Interfaces/: IApplicationDbContext, ICurrentUser, IDateTime, IJwtTokenServiceApplication/Common/Exceptions/*Application/Common/Behaviors/ValidationBehavior.csApplication/DependencyInjection.cs— MediatR + FluentValidationInfrastructure/Persistence/ApplicationDbContext.cs : IdentityDbContextInfrastructure/Persistence/Interceptors/AuditingInterceptor.csInfrastructure/Persistence/DbInitializer.cs— seed 12 role + adminInfrastructure/Persistence/DesignTimeDbContextFactory.csInfrastructure/Identity/{JwtSettings, JwtTokenService}.csInfrastructure/Services/DateTimeService.csInfrastructure/DependencyInjection.csApi/Services/CurrentUserService.csApi/Middleware/GlobalExceptionMiddleware.csApi/Controllers/AuthController.cs(login, refresh, me, logout)Api/Program.cs(Serilog, JWT, CORS, Swagger, middleware)Api/appsettings.{json, Development.json}+launchSettings.json(port 5443)- Migration 1
Init+ apply toSolutionErp_DevLocalDB - FE: Vite config (Tailwind 4 + proxy + alias)
- FE:
src/{index.css, lib/api.ts, lib/cn.ts, types/auth.ts}cho 2 app - FE:
src/contexts/AuthContext.tsx,components/{ProtectedRoute, Layout}.tsx - FE:
components/ui/{Button, Input, Label}.tsx - FE:
pages/LoginPage.tsx,pages/DashboardPage.tsx(admin) +pages/InboxPage.tsx(user) - FE:
App.tsxvới Router + AuthProvider + Toaster - FE:
main.tsxvới QueryClient (TanStack Query) - E2E verified: login qua Vite proxy cả 2 app → JWT + user info
Phase 1 đợt 2 — CRUD master + Permission Matrix
Domain/Master/Supplier(+ SupplierType enum 5 loại) /Project/Department(AuditableEntity)- EF
IEntityTypeConfiguration<T>cho mỗi entity (unique Code + query filter IsDeleted) - CQRS CRUD: Create/Update/Delete/GetById/List (PagedResult) cho 3 entity
Api/Controllers/{SuppliersController, ProjectsController, DepartmentsController}- Migration 2:
AddMasterData Domain/Identity/MenuItem(Key PK, Label, ParentKey, Order, Icon) +MenuKeysconst classDomain/Identity/Permission(RoleId, MenuKey, CanRead/Create/Update/Delete)- Seed default menu tree + admin full access trong DbInitializer (mở rộng Tier 3: 28 Ct_* + 7 Wf_*)
Application/Permissions/Queries/GetMyMenuTreeQuery— resolve per-user + inherit Contracts/Workflows rootApi/Controllers/{MenusController, RolesController, PermissionsController}- Migration 3:
AddPermissions - Authorization handler
MenuPermissionHandler+ register policy{menu}.{action} - FE:
<PermissionGuard menuKey="Suppliers" action="Update">+usePermission()hook - FE Admin: 3 trang CRUD Supplier/Project/Department với DataTable + Dialog + search/sort/paging
- FE Admin: Permission Matrix grid page (role × menu × CRUD checkbox) — iter 1 + 3-panel iter 2
- FE Admin: Layout menu động từ
/api/menus/me+ recursive nested + filterForAdmin - FE User: trang "HĐ của tôi" list + filter
?type=X— Tier 3 - FE Admin: Users management page (tạo user + gán role + reset password + unlock)
- FE Admin: Roles CRUD — optional (12 role seed đủ dùng)
- Route guard theo role admin-only — PermissionGuard ở button level
Exit criteria Phase 1
- Admin login → tạo NCC/Project → gán permission menu
- User non-admin login → thấy menu theo role, không bị 403
- Tạo Contract draft → list hiển thị, filter role-aware
Phase 2 — Form Engine (T5-6)
MVP xong (Phase 2 iteration 1)
- Khảo sát: chọn OpenXml + ClosedXML (free, không cần license)
Domain/Forms/ContractTemplate(Id, FormCode, Name, ContractType, FileName, StoragePath, Format, FieldSpec JSON, IsActive)Domain/Forms/ContractClauseskeleton- EF config + Migration
AddForms Application/Forms/Services/IFormRendererinterfaceInfrastructure/Forms/DocxRenderer(OpenXml, handle placeholder split runs)Infrastructure/Forms/XlsxRenderer(ClosedXML)Application/Forms/FormFeatures.cs— List/Get/Render CQRSApi/Controllers/FormsController— GET templates, GET single, POST render- Copy 5 .docx/.xlsx template →
wwwroot/templates/ - Seed 8 ContractTemplate rows (5 IsActive=true, 3 chờ convert)
- FE admin:
FormsPage— list + render dialog điền JSON + download - E2E verified: render FO-002.05 → file .docx 482KB mở được bằng Word
Iteration 2 (Tier 3 — đã làm)
- Convert
.doc→.docx/.xls→.xlsxquaIDocumentConverter+ LibreOffice headless (thay Word COM, auto-convert khi admin upload) - FE user: form builder dynamic —
DynamicFormcomponent render từFieldSpecJSON (text/textarea/number/date/currency/select) - FE admin: upload template mới qua UI (POST multipart) + edit FieldSpec + delete (soft via IsActive)
- PDF convert via LibreOffice headless (
soffice --headless --convert-to pdf) —LibreOfficeDocumentConverter(timeout + per-request temp + isolated UserInstallation) - Format helpers: number →
VND, date →dd/MM/yyyy(render layer) - Support
{{#loop}}...{{/loop}}block cho table lặp (hạng mục HĐ giao khoán, PO) — optional - Lưu
ContractClause(FO-002.04) dạng rich text + TipTap/TinyMCE editor — optional - Import/export template (backup/restore) — optional
- Content preservation test (render → diff layout) — optional
Phase 3 — Workflow State Machine (T7-9)
MVP xong (iteration 1)
Domain/Contracts/Contract(Phase, SlaDeadline, BypassProcurementAndCCM, MaHopDong, DraftData, SlaWarningSent)Domain/Contracts/ContractApproval(FromPhase, ToPhase, ApproverUserId, Decision, Comment)Domain/Contracts/ContractComment+ContractAttachment(+ AttachmentPurpose enum)Domain/Contracts/ContractCodeSequence(Prefix PK, LastSeq)- EF config + unique MaHopDong filtered + indexes Phase/Supplier/Project/SlaDeadline + cascade delete
- DbSets (5) +
IApplicationDbContextupdate - Migration
AddContractsWorkflow Application/Contracts/Services/IContractWorkflowService+IContractCodeGeneratorInfrastructure/Services/ContractWorkflowService— adjacency 9 phase + role guard + Admin bypass + system actor + bypass CCM (Chủ đầu tư)Infrastructure/Services/ContractCodeGenerator— 7 format RG-001 + transaction SERIALIZABLE- CQRS: Create/UpdateDraft/Transition/AddComment/List/Inbox/GetDetail/Delete (8 feature)
Api/Controllers/ContractsController— 8 endpoint REST- FE admin: ContractsListPage + ContractDetailPage (timeline + action dialog)
- FE user: InboxPage + ContractCreatePage + ContractDetailPage + MyContractsPage
- PhaseBadge component + color map
- E2E verified: tạo HĐ → chạy 9 phase → gen mã
FLOCK 01/HĐGK/SOL&PVL2026/01
Iteration 2 (polish — Tier 3 + Notification)
Infrastructure/HostedServices/SlaExpiryJob— check mỗi 15min, auto-approve quá hạn với Decision=AutoApprove (+30s delay startup)- E2E test với non-admin user (Drafter role) — IDOR filter verified
- Admin password warning log khi vẫn dùng default
Infrastructure/Services/NotificationService— in-app + emit (email đợi SMTP)- SignalR hub cho real-time notification badge —
/hubs/notifications+ interceptor auto-push - Upload attachment endpoint (multipart) + FE drag-drop UI (
wwwroot/uploads/contracts/{id}/) — IFileStorage + path-traversal guard - Filter Inbox theo type ở FE (
?type=X) - Render HĐ template docx/xlsx → PDF export (LibreOffice)
- Warning notification khi còn 20% SLA —
SlaWarningSentflag đã có - MediatR
AuditBehavior— log mọi command (ngoài ContractApprovals) - RowVersion optimistic concurrency (2 user race → 409)
- Render HĐ docx lúc tạo (merge TemplateId + DraftData + ContractClause appendix)
- E2E test: reject → quay về DangSoanThao với multi-role
- Email notification (MailKit + SMTP) — blocked chờ user config
Iteration 3 (Versioned workflow — Tier 3)
Domain/Contracts/WorkflowDefinition(Code + Version + IsActive + ContractType + Description)Domain/Contracts/WorkflowStep(Order + Phase + Name + SlaDays)Domain/Contracts/WorkflowStepApprover(Kind: Role|User + AssignmentValue)Contract.WorkflowDefinitionIdnullable FK pin tại create time- Migration
AddVersionedWorkflows+ seed v01 cho 7 ContractType WorkflowPolicyRegistry.FromDefinition()— runtime policy build từ DBContractWorkflowService— load pinned def → FromDefinition → guardWorkflowAdminFeatures— GetOverview + CreateNewVersion (auto-increment Version + deactivate old)- FE admin
/system/workflows/:typeCode— DefinitionCard + history + Designer modal - Designer: Steps repeatable, per-step phase/name/SLA, +Role / +User approver select
- Clone-from-version button cho starting point
- Invariants: UNIQUE (Code, Version), 1 IsActive per ContractType, no cascade FK
- E2E: create QT-MB-v02 → v01 archived → HĐ mới pin v02 → HĐ cũ pin v01 giữ nguyên
- Runtime enable User-kind approver trong TransitionAsync guard (data model ready)
Phase 4 — Reporting + Polish (T10-11)
MVP xong (iteration 1)
- Dashboard admin: 5 KPI (total/active/overdue/published this month/total value) + by phase + top 5 NCC + top 5 dự án + 12 tháng
- Excel export HĐ theo filter (phase/supplier/project/date range) qua ClosedXML
- BE
GetDashboardStatsQuery+ExportContractsToExcelCommand+ ReportsController - FE
DashboardPagerewrite vớiBarCharttự build (Tailwind only, không thư viện ngoài) - FE
ReportsPagefilter + export - Docs consolidation:
rules.md+architecture.md+database/schema-diagram.md+ gotchas update
Iteration 2 (Tier 3 + optional)
- Dashboard user-specific (
MyDashboardendpoint — DraftsInProgress / PendingMyApproval / DueSoon / Overdue / DraftsTotalValue) + FE "Của tôi" row 4 card - UX polish: skeleton loader DataTable, empty state có action, error boundary recovery
- Content polish: typography 14px + leading 1.55 + tracking-tight + PageHeader + Button + Input + DataTable
- Brand identity: #1F7DC1 palette + Be Vietnam Pro font + Solutions logo
- SLA overdue report (by role / phase, export Excel)
- Contract audit log export (từng HĐ ra PDF)
- Chart library recharts (nếu cần chart phức tạp)
- Accessibility: keyboard nav, focus trap modal, aria labels
- Dark mode
- Performance: explicit index DB cho query hot đã identify
- Tài liệu user guide: quy trình tạo HĐ + duyệt
- UAT với 5-10 HĐ dữ liệu thật từ bộ phận Cung ứng
Phase 5 — Production (T12-13)
Prep xong (code + scripts + docs)
docs/guides/cicd.md— CI/CD runbook- Gitea Actions workflow
.gitea/workflows/deploy.yml— build .NET + 2 FE, deploy IIS qua WinRM - Pin Node
.nvmrc20 (gotcha #5) scripts/deploy-iis.ps1— stop pool → backup → xcopy → start → health checkscripts/backup-sql.ps1— daily BACKUP DATABASE + COMPRESSION + retention 30dappsettings.Production.jsontemplate + user secrets pattern- Rate limiting (built-in .NET 10) — auth-login 5/min + global 300/min
- Health check
/health/live+/health/ready(DB probe) - Serilog File sink rolling daily retention 30d
- HSTS production (1 year)
docs/guides/deployment-iis.md— setup lần đầu + troubleshootingdocs/guides/security-checklist.md— OWASP top 10docs/guides/runbook.md— operations (restart, rollback, restore)- FE refresh token auto interceptor (queue pattern cả 2 app)
Deploy thật
- Windows Server setup: IIS + URL Rewrite + ARR (reverse proxy FE → IIS)
- SQL Server prod (SQLEXPRESS) + vrapp db_owner
- HTTPS certificate (Let's Encrypt qua win-acme — 3 cert + auto-renew)
- Gitea remote setup + push all commits
- Set Gitea Actions secrets (JWT_SECRET, DB_CONNECTION — deploy local via runner)
- Enable Gitea runner (Windows self-hosted, shared với VIETREPORT)
- Test CI/CD workflow — xanh E2E, /health/live 200 sau deploy
- UAT production 1 tuần với 2-3 user thật ← hard blocker còn lại
- SQL Task Scheduler trigger backup-sql.ps1 (script có sẵn, chưa schedule)
- Go-live checklist: rotate creds + backup plan + on-call contact
Phase 5.1 Security hardening + Users Mgmt
- Security headers middleware (X-Content-Type-Options, X-Frame-Options, CSP, Referrer-Policy, Permissions-Policy)
- Identity account lockout (5 fail → 15min, config-driven)
- Password policy config-driven (default 8 dev, override
Identity:Password:RequiredLengthprod) - LoginCommand: check IsLockedOutAsync + AccessFailedAsync + reset on success
- BE Users management: CQRS 8 feature + UsersController 7 endpoint (Users.Read/Create/Update policies)
- FE admin
/system/users: list + create + assign roles + reset password + unlock + toggle active - IDOR check ContractsController — user Drafter chỉ xem HĐ mình tạo hoặc role eligible phase (
ListContractsQueryHandler+GetContractQueryHandler) - Admin mặc định warning log (
DbInitializer.WarnDefaultAdminPasswordAsync) - Dependencies scan vào CI (
dotnet list package --vulnerable --include-transitive,npm audit --audit-level=high) - BE Roles CRUD (Create/Rename/Delete custom role) + FE
/system/roles— optional, 12 role seed đủ dùng
Skill governance (recurring)
Quy tắc: xem docs/rules.md §9. Audit định kỳ mỗi đầu tháng — workflow §9.4.
- Setup ban đầu — 6 skill (3 domain + 3 ops), rules §9, HANDOFF section A1 ←
661f859+ - Audit 2026-05-01 — log
docs/changelog/skill-audit-2026-05.md - Audit 2026-06-01
- Audit 2026-07-01
- (lập lại mỗi tháng đầu)
Session 2026-04-23 (chiều) — Toolkit + 4-bảng + Master Catalogs + Roles VN
- 3-panel layout HĐ list/inbox/thao tác (commits b75448e/89c7e88/8c4b4da)
- Sidebar accordion menu loại HĐ (
7ea3957) - Tách Tổng quan → /dashboard riêng fix bug trùng /inbox (
d326e80) - 4-bảng overhaul Header/7 Details/Workflow/Changelog (Migration 9,
70810e1) - IChangelogService + integrate vào CRUD/Workflow handlers (
71c035d) - Details CRUD endpoints + Changelogs query (
e684455) - FE Panel 2 7/3 grid (Chi tiết + Lịch sử inline,
ad0652d) - Edit/Xóa hover row Panel 1 Thao tác (mờ khi != DangSoanThao,
7f26ff9) - Mã HĐ gen ngay tại Create + backfill legacy (
51449d6) - 4 master catalogs Units/Materials/Services/WorkItems (Migration 10,
e27c547) - Admin CatalogsPage + datalist autocomplete trong Details form (
16e24ed) - Roles VN labels ShortName + Description backfill (Migration 11,
330d529) - Users +DepartmentId/Position + 13 demo users seed (
330d529) - FE UsersPage dept dropdown + position field + role badge ShortName (
ae59cfe)
Tier 3 ERP (Session 2026-04-22) — feature-complete
- Attachment upload E2E — IFileStorage + CQRS + FE drag-drop (gotcha path-traversal) —
c8d0070 - SignalR realtime notifications — 3-project clean-arch split + JWT
?access_token=+ auto-reconnect —ea9ab5e - Form template builder CRUD — Upload/Update/Delete + FieldSpec JSON editor —
166d26c - PDF export + DynamicForm + .doc auto-convert — LibreOffice headless per-request temp —
6bbd894+e459097 - Dynamic workflow policy — Standard/SkipCcm registry theo ContractType —
cae4d84 - Versioned workflow — WorkflowDefinition + Steps + Approvers pinned per Contract —
e7e5f2d - Admin workflow designer — per-type page + Designer modal + clone —
e7e5f2d - Nested sidebar menu fe-user — 7 type × 3 action + admin/user split —
5e0f380 - Workflows tabs → sidebar menu — 7 Wf_ leaves + URL-driven —
f216169 - PermissionsPage 3-panel layout — Role list | Menu×CRUD | Granted stats —
91b2da1 - Seed master data — 9 dept + 5 supplier + 3 project + MyDashboard —
6197c84 - Brand identity — #1F7DC1 palette + Be Vietnam Pro + Solutions logo —
4abb559..bf1fbe3
Post-launch (Phase 6+ — future)
- Email outbox (MailKit + SMTP) — blocked chờ SMTP config
- Roles CRUD — admin tạo custom role ngoài 12 hardcoded
- User-kind approver runtime — data model có, guard cần wire
- E-signature integration (VNPT CA hoặc FPT CA)
- Tích hợp Bravo / SAP ERP import NCC
- Mobile app (React Native?) cho BOD duyệt ngoài giờ
- AI: gợi ý điền form dựa HĐ cũ, OCR scan HĐ đối tác
- Multi-tenant nếu có công ty thứ 2