[CLAUDE] Docs: chốt session Tier 3 feature-complete + versioned workflow
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m33s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m33s
- Session log 2026-04-22-0300 (A→K): attachment, SignalR, form builder, PDF, dynamic + versioned workflow, nested menu, 3-panel permissions, seed master, brand identity, content polish, Gitea fix - STATUS: Tier 3 feature-complete snapshot + cumulative stats (24 tables, ~50 endpoints, 8 migrations); next-up = UAT + Email SMTP (blocked) + rotate creds + SQL backup schedule - HANDOFF: rewrite brief cho session mới — phase 5 prod done, Tier 3 đóng gói, quick sanity-check 2 app, versioned workflow quick ref, file active hiện trạng, git state - migration-todos: tick Tier 3 items (attachment/realtime/form builder/ PDF/dynamic+versioned workflow/nested menu) + thêm iter-3 versioned workflow section + post-launch list - schema-diagram: +5 table (Notifications, WorkflowTypeAssignments, WorkflowDefinitions, WorkflowSteps, WorkflowStepApprovers); indexes mới, cardinality FK restrict cho pinned policy, truy vấn tiêu biểu - workflow-contract: +section 7bis resolution order, 7ter admin designer flow, updated data model + code pointers Tier 3 - PROJECT-MAP: module map post-Tier-3 (3 box mới Notification/ Attachment/Branding + Infra/DevOps box), API namespace đầy đủ, architectural wins 5 điểm - contract-workflow skill: versioned workflow section, policy resolution code snippet, admin designer flow, code pointers Tier 3, tier 4+ backlog - gotchas +7 bẫy mới (#26-32): SignalR WebSocket headers, interceptor 2-phase pattern, LibreOffice mirror 404, PS 5.1 UTF-16 GITHUB_PATH, PS 5.1 diacritics parse, Dialog size TS, NavLink end query-params Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
353
docs/HANDOFF.md
353
docs/HANDOFF.md
@ -1,28 +1,29 @@
|
||||
# HANDOFF — Brief 5 phút cho session tiếp theo
|
||||
|
||||
**Last updated:** 2026-04-21 16:30 (cuối Phase 5.1 Security + Users Mgmt)
|
||||
**Last updated:** 2026-04-22 03:00 (post-Tier-3-feature-complete + versioned workflow)
|
||||
|
||||
## TL;DR
|
||||
|
||||
Tier 3 ERP features xong hết (Attachment, SignalR, Form builder, PDF, Versioned workflow, Nested menu, Permission layout). Prod live 3 domain. **Còn lại chủ yếu là UAT + SMTP + rotate creds**, không còn module kỹ thuật lớn nào chưa làm.
|
||||
|
||||
## Ở đâu rồi?
|
||||
|
||||
| Phase | Trạng thái |
|
||||
|---|---|
|
||||
| 0 Draft | ✅ Done |
|
||||
| 1 Alpha Core foundation | ✅ Done |
|
||||
| 1 Alpha Core đợt 2 (CRUD + Permission) | ✅ Done |
|
||||
| 2 Form Engine MVP | ✅ Done |
|
||||
| 2 Form Engine iteration 2 | 📝 Optional |
|
||||
| 3 Workflow MVP (9 phase + code gen) | ✅ Done |
|
||||
| 3 Workflow iteration 2 (SLA + notify + attachment) | 📝 Optional |
|
||||
| 4 Report MVP (Dashboard + Excel) | ✅ Done |
|
||||
| 4 Report iteration 2 | 📝 Optional |
|
||||
| 5 Prep (infra + scripts + guides + refresh token) | ✅ Done |
|
||||
| **5.1 Security + Users Mgmt (headers, lockout, Users CRUD)** | ✅ Done (IDOR + deps scan còn) |
|
||||
| 5 Deploy production (cần Gitea URL) | 📋 Next |
|
||||
| 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 |
|
||||
| 6+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future |
|
||||
|
||||
## Run nhanh
|
||||
|
||||
```powershell
|
||||
# Terminal 1 — API (auto seed 8 template lần đầu)
|
||||
# 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
|
||||
@ -34,144 +35,218 @@ cd fe-user && npm run dev # → http://localhost:8080
|
||||
|
||||
Login: `admin@solutionerp.local` / `Admin@123456`
|
||||
|
||||
Điểm cần test ngay (Phase 4 MVP):
|
||||
- **Admin `/dashboard`** → 5 KPI card + By Phase bar + Monthly chart + Top NCC/dự án
|
||||
- **Admin `/reports`** → filter phase/date → Export Excel .xlsx 10 cột có formula SUM
|
||||
- **fe-user `/contracts/new`** → tạo HĐ draft (Phase 2 DangSoanThao, SLA +7d)
|
||||
- **fe-user `/inbox`** → xem HĐ chờ role mình xử lý
|
||||
- **`/contracts/{id}`** → click "Duyệt → tiếp" chạy state machine. Phase 8 gen `MaHopDong` RG-001
|
||||
- **`/forms`** → render template .docx
|
||||
- **`/system/permissions`** → ma trận Role × MenuKey
|
||||
- **`/master/suppliers|projects|departments`** → CRUD
|
||||
## Quick sanity-check
|
||||
|
||||
## Cần làm kế tiếp (ưu tiên)
|
||||
**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
|
||||
|
||||
### A. Phase 5 — Production (tuần 12-13, item lớn nhất còn lại)
|
||||
**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
|
||||
|
||||
**Đọc trước:** `docs/changelog/migration-todos.md` section Phase 5.
|
||||
**Realtime check:**
|
||||
- Login 2 tab (admin + user) → user tạo comment / transition → admin nhận toast + bell +1
|
||||
|
||||
- [ ] `.gitea/workflows/deploy.yml` CI/CD build + deploy IIS
|
||||
- [ ] `scripts/deploy-iis.ps1` stop app pool → xcopy → start
|
||||
- [ ] Windows Server IIS + URL Rewrite + ARR (reverse proxy FE → .NET)
|
||||
- [ ] HTTPS cert via win-acme hoặc mua
|
||||
- [ ] `appsettings.Production.json` + user secrets + JWT secret rotation
|
||||
- [ ] Rate limiting middleware (auth endpoint 5 req/min/IP)
|
||||
- [ ] Security audit OWASP top 10
|
||||
- [ ] Health check endpoint `/health`
|
||||
- [ ] Serilog → file rolling daily retention 30d
|
||||
- [ ] SQL backup: daily full + 15min log
|
||||
- [ ] Runbook: restart, rollback migration, restore backup
|
||||
- [ ] UAT production 1 tuần với 2-3 user thật
|
||||
- [ ] Go-live checklist
|
||||
## Cần làm kế tiếp
|
||||
|
||||
### B. Polish iterations (optional — khi rảnh)
|
||||
### A. Hard blockers (chờ user / ops)
|
||||
|
||||
**Phase 2 iter 2:** convert 3 .doc qua Word COM `DisplayAlerts=0` hoặc LibreOffice, field spec JSON + form builder FE dynamic, `{{#loop}}` block support, PDF convert, FE upload template multipart.
|
||||
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`
|
||||
|
||||
**Phase 3 iter 2:** `SlaExpiryJob` BackgroundService auto-approve, email (MailKit) + in-app (SignalR) notify, upload attachment endpoint + FE multipart (`wwwroot/uploads/contracts/{id}/`), RowVersion concurrency, render HĐ docx khi tạo (merge TemplateId + DraftData + ContractClause).
|
||||
### B. Polish iterations (optional — khi UAT phát sinh)
|
||||
|
||||
**Phase 4 iter 2:** SLA overdue report by role/phase, PDF HĐ export (LibreOffice), dashboard user-specific (role tôi).
|
||||
- **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. Phase 2 iteration 2 (form engine polish)
|
||||
### C. Non-goals / parked
|
||||
|
||||
- Convert 3 file `.doc` qua Word COM `DisplayAlerts=0` + timeout, hoặc LibreOffice
|
||||
- Field spec JSON per template + dynamic form builder FE
|
||||
- `{{#loop}}...{{/loop}}` block support cho table lặp
|
||||
- PDF convert via LibreOffice headless
|
||||
- Admin upload template UI (multipart)
|
||||
|
||||
### D. Quick wins (không block phase)
|
||||
|
||||
- FE Users management + Roles CRUD (test permission với non-admin user thật)
|
||||
- Filter Inbox theo phase FE
|
||||
- Refresh token auto (FE axios interceptor retry 401)
|
||||
- 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) trước khi:**
|
||||
- Thêm package mới → check compat với .NET 10 (MediatR 14 fail → dùng 12)
|
||||
- Debug 404 API → kiểm Program.cs có persist không (Dropbox issue)
|
||||
- Expression tree error → tách switch ra ngoài LINQ
|
||||
- TS enum error → dùng const-object pattern (`erasableSyntaxOnly`)
|
||||
- Word COM stuck → kill + fallback LibreOffice
|
||||
- Migration lỗi → check 3 file đầy đủ (Designer + Migration + Snapshot)
|
||||
**Đọc [`gotchas.md`](gotchas.md) (26 bẫy) trước khi:**
|
||||
|
||||
## File đang active
|
||||
- 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)
|
||||
├── src/Backend/ (Clean Arch, 4 project, .NET 10)
|
||||
│ ├── SolutionErp.Domain/
|
||||
│ │ ├── Common/ BaseEntity, AuditableEntity
|
||||
│ │ ├── Contracts/ ContractType, ContractPhase, ApprovalDecision + **Contract, ContractApproval, ContractComment, ContractAttachment, ContractCodeSequence** ← Phase 3
|
||||
│ │ ├── Forms/ ContractTemplate, ContractClause ← Phase 2
|
||||
│ │ ├── Identity/ User, Role, MenuItem, Permission, AppRoles, MenuKeys
|
||||
│ │ └── Master/ Supplier, Project, Department, SupplierType
|
||||
│ │ ├── 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/ Exceptions, Behaviors, Interfaces, Models
|
||||
│ │ ├── Contracts/ ContractFeatures (8 CQRS), IContractWorkflowService, IContractCodeGenerator, DTOs ← Phase 3
|
||||
│ │ ├── Forms/ FormFeatures (List/Get/Render) ← Phase 2
|
||||
│ │ ├── Master/ Suppliers, Projects, Departments CQRS
|
||||
│ │ ├── Permissions/ GetMyMenuTree, matrix upsert
|
||||
│ │ └── Reports/ **DashboardStats, ExportContractsToExcel, IContractExcelExporter** ← Phase 4
|
||||
│ │ ├── 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 ← Phase 2
|
||||
│ │ ├── Identity/ JwtSettings, JwtTokenService
|
||||
│ │ ├── Persistence/ DbContext, DbInitializer, Interceptors, Migrations (**5**)
|
||||
│ │ ├── Reports/ **ContractExcelExporter** ← Phase 4
|
||||
│ │ └── Services/ DateTimeService, ContractWorkflowService, ContractCodeGenerator ← Phase 3
|
||||
│ │ ├── 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** (10 controller)
|
||||
│ ├── Middleware/ GlobalExceptionMiddleware
|
||||
│ ├── Services/ CurrentUserService, WebHostEnvironmentLocator
|
||||
│ └── wwwroot/templates/ 5 file .docx/.xlsx ← Phase 2
|
||||
├── fe-admin/ (11 page)
|
||||
│ └── src/pages/
|
||||
│ ├── LoginPage
|
||||
│ ├── DashboardPage ← Phase 4 rewrite (KPI cards + BarChart)
|
||||
│ ├── master/SuppliersPage, ProjectsPage, DepartmentsPage
|
||||
│ ├── system/PermissionsPage
|
||||
│ ├── forms/FormsPage ← Phase 2
|
||||
│ ├── contracts/ContractsListPage, ContractDetailPage ← Phase 3
|
||||
│ └── ReportsPage ← Phase 4
|
||||
├── fe-user/ (5 page)
|
||||
│ └── src/pages/
|
||||
│ ├── LoginPage
|
||||
│ ├── InboxPage ← Phase 3
|
||||
│ └── contracts/ContractCreatePage, ContractDetailPage, MyContractsPage ← Phase 3
|
||||
├── docs/ (35 file)
|
||||
│ ├── STATUS.md, HANDOFF.md, rules.md, architecture.md
|
||||
│ ├── CLAUDE.md, PROJECT-MAP.md
|
||||
│ ├── workflow-contract.md, forms-spec.md
|
||||
│ ├── database/{database-guide, schema-diagram}.md
|
||||
│ ├── 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) — deployment-iis, cicd, security-checklist, runbook ← Phase 5 prep
|
||||
│ ├── changelog/migration-todos.md + sessions/ (7 session log)
|
||||
│ └── gotchas.md
|
||||
├── scripts/ (5 file PS + py)
|
||||
│ ├── parse_forms.py, parse_workflow.py (Phase 0)
|
||||
│ ├── convert-doc-to-docx.ps1 (Phase 2)
|
||||
│ └── deploy-iis.ps1, backup-sql.ps1 ← Phase 5 prep
|
||||
├── .gitea/workflows/deploy.yml ← Phase 5 prep CI/CD template
|
||||
└── .claude/skills/ (3 skill — all full spec)
|
||||
│ ├── 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
|
||||
|
||||
```
|
||||
(sẽ là commit 8) — Phase 5 Prep (infra + scripts + guides + refresh token)
|
||||
fe7ad8e — Phase 4 Report MVP + docs consolidation
|
||||
7e957a7 — Phase 3 Workflow MVP
|
||||
5113e4c — Phase 2 Form Engine MVP
|
||||
54d6c9b — Phase 1.2 CRUD + Permission
|
||||
49a5f57 — Docs database-guide + flows
|
||||
702411f — Phase 1 foundation
|
||||
25dad7f — Phase 0 scaffold
|
||||
HEAD → main
|
||||
91b2da1 — PermissionsPage 3-panel layout (LATEST)
|
||||
f216169 — Admin Workflows tabs → sidebar menu items
|
||||
355bbe3 — Fix Dialog size TS (xl → lg)
|
||||
e7e5f2d — Versioned workflow entities + migration + designer
|
||||
4 session trước đó nằm trong STATUS table
|
||||
|
||||
Branch: main
|
||||
Remote: chưa (Gitea URL CẦN NGAY để Phase 5 go-live)
|
||||
Branch: main (tracking origin/main)
|
||||
Remote: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp.git
|
||||
```
|
||||
|
||||
## Credentials + URLs
|
||||
@ -180,23 +255,27 @@ Remote: chưa (Gitea URL CẦN NGAY để Phase 5 go-live)
|
||||
admin@solutionerp.local / Admin@123456
|
||||
```
|
||||
|
||||
- API: http://localhost:5443 (swagger `/swagger`)
|
||||
- Admin FE: http://localhost:8082
|
||||
- User FE: http://localhost:8080
|
||||
- SQL LocalDB: `(localdb)\MSSQLLocalDB` / Database=`SolutionErp_Dev`
|
||||
- API prod: https://api.huypham.vn — `/health/live`, `/health/ready`
|
||||
- Admin FE prod: https://admin.huypham.vn
|
||||
- User FE prod: https://user.huypham.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:**
|
||||
- Build pass 100% cả BE + FE
|
||||
- E2E test full 9-phase workflow end-to-end — mã HĐ gen đúng format RG-001
|
||||
- Docs đầy đủ: 26 file, session log mỗi chunk, gotchas tích lũy 17 pitfall
|
||||
- Cả 2 FE đều có Contract detail page + timeline + comment thread + state machine action
|
||||
- 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:**
|
||||
- SLA chỉ set deadline — không có job auto-approve (Phase 3.2)
|
||||
- Không có notification (email + in-app) — user phải F5 inbox
|
||||
- Form render chỉ MVP — loop table + PDF chưa có
|
||||
- Permission matrix chưa test thực với non-admin user
|
||||
- 3 file .doc chưa convert (carryover Phase 2)
|
||||
- Không có upload attachment endpoint (chỉ có entity + DTO)
|
||||
- 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
|
||||
|
||||
Reference in New Issue
Block a user