Backend Forms:
- Domain/Forms: ContractTemplate (FormCode, Name, ContractType, FileName, StoragePath, Format, FieldSpec JSON, IsActive) + ContractClause
- EF config voi unique FormCode + query filter IsDeleted
- DbSets + IApplicationDbContext update
- Migration AddForms (bang 14 total)
- Packages: DocumentFormat.OpenXml 3.x + ClosedXML 0.105+
- Application/Forms:
- IFormRenderer interface + RenderResult record
- FormFeatures.cs: List/Get/Render CQRS
- IWebHostEnvironmentLocator (abstract IWebHostEnvironment)
- Infrastructure/Forms:
- DocxRenderer: OpenXml-based placeholder {{field}} replace, handle split runs (gom text tat ca <w:t> trong paragraph, replace, gan lai text dau + clear rest)
- XlsxRenderer: ClosedXML cell value replace
- FormRenderer router theo format docx/xlsx
- Api:
- FormsController: GET /templates (filter type, onlyActive), GET /templates/{id}, POST /templates/{id}/render (return file)
- WebHostEnvironmentLocator impl
- DbInitializer SeedContractTemplatesAsync: seed 8 template metadata, IsActive=true chi khi file ton tai
Templates vat ly:
- Copy 5 .docx/.xlsx tu FORM/ sang wwwroot/templates/
- 3 .doc (FO-002.02/03/06) chua convert: IsActive=false (Word COM bi stuck luc test, can retry voi DisplayAlerts=0 hoac LibreOffice)
- scripts/convert-doc-to-docx.ps1 (Word COM automation)
Frontend fe-admin:
- types/forms.ts: ContractTemplate + ContractTypeLabel
- pages/forms/FormsPage.tsx: list templates + Render dialog (paste JSON data → download .docx/.xlsx)
- Route /forms them vao App.tsx
Bug fix:
- SpaceProcessingModeValues namespace: wrap EnumValue<> full path
- SaveAs2($path, 16) thay vi SaveAs([ref], [ref]) — PowerShell type issue
- Word COM stuck: kill process, skip .doc cho MVP
Docs (theo yeu cau user):
- docs/gotchas.md MOI: 17 pitfalls nhom theo tech stack / EF Core / OpenXml / JSON / dev workflow
- .claude/skills/form-engine/SKILL.md: placeholder → full spec (algorithm + code pointers + API + limitations)
- .claude/skills/permission-matrix/SKILL.md: placeholder → full spec (BE policy + FE guard + seed + pitfalls)
- docs/HANDOFF.md MOI: brief 5 phut cho session sau (run quickstart + where we are + next steps + file tree + gotchas ref)
- docs/STATUS.md: update cumulative stats + next up Phase 3
- docs/changelog/migration-todos.md: tick Phase 2 iteration 1 items + add iteration 2 list
- docs/changelog/sessions/2026-04-21-1200-phase2-form-engine.md: session log
- CLAUDE.md root: them reference den gotchas + HANDOFF
E2E verified:
- GET /api/forms/templates (onlyActive=false) → 8 templates
- POST /api/forms/templates/{FO-002.05}/render voi data dict → HTTP 200 + file .docx 482KB (Microsoft Word 2007+ OK)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
156 lines
6.3 KiB
Markdown
156 lines
6.3 KiB
Markdown
# HANDOFF — Brief 5 phút cho session tiếp theo
|
||
|
||
**Last updated:** 2026-04-21 12:00 (cuối Phase 2 MVP)
|
||
|
||
## Ở đâ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 (9 phase state machine) | 📋 Next |
|
||
| 4 Report + Polish | 📋 Queue |
|
||
| 5 Production (CI/CD IIS) | 📋 Queue |
|
||
|
||
## Run nhanh
|
||
|
||
```powershell
|
||
# Terminal 1 — API (auto seed 8 template lần đầu)
|
||
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`
|
||
|
||
Điểm cần test ngay:
|
||
- `/forms` → render FO-002.05 → download .docx (Phase 2 MVP)
|
||
- `/system/permissions` → chọn role → tick matrix
|
||
- `/master/suppliers|projects|departments` → CRUD
|
||
|
||
## Cần làm kế tiếp (ưu tiên)
|
||
|
||
### A. Phase 3 — Workflow (item lớn, ~3 tuần work)
|
||
|
||
**Đọc trước:**
|
||
1. [`workflow-contract.md`](workflow-contract.md) — spec 9 phase + role matrix
|
||
2. [`flows/contract-approval-flow.md`](flows/contract-approval-flow.md) — sequence diagram
|
||
3. [`flows/sla-expiry-flow.md`](flows/sla-expiry-flow.md) — BackgroundService auto-approve
|
||
4. [`forms-spec.md#RG-001`](forms-spec.md) — format mã HĐ
|
||
|
||
**Deliverable chính:**
|
||
- Entity: `Contract` (Phase, SlaDeadline, BypassProcurementAndCCM, DraftData) + `ContractApproval` + `ContractComment` + `ContractAttachment`
|
||
- `IContractWorkflowService.TransitionAsync()` — state guard (9 phase adjacency) + role guard
|
||
- `IContractCodeGenerator` (implement RG-001) với transaction SERIALIZABLE + `ContractCodeSequences` table
|
||
- `SlaExpiryJob` BackgroundService — auto-approve HĐ quá hạn mỗi 15 phút
|
||
- `INotificationService` — email (MailKit) + in-app
|
||
- API `POST /api/contracts/{id}/transitions`
|
||
- FE `/inbox` (list HĐ chờ tôi xử lý theo role × phase)
|
||
- FE `/contracts/{id}` detail — timeline 9 phase, approval panel, comment thread, attachment upload
|
||
|
||
### B. Phase 2 iteration 2 (nếu user muốn polish Form Engine)
|
||
|
||
- Convert 3 file `.doc` (retry Word COM với timeout OR LibreOffice)
|
||
- Field spec JSON → dynamic form builder
|
||
- `{{#loop}}...{{/loop}}` support
|
||
- PDF convert
|
||
- FE upload template UI
|
||
|
||
### C. Quick wins (không block phase)
|
||
|
||
- FE Users management + Roles CRUD (test permission với non-admin role)
|
||
- fe-user sync menu động (đang hardcode)
|
||
|
||
## 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)
|
||
|
||
## File đang active
|
||
|
||
```
|
||
SOLUTION_ERP/
|
||
├── src/Backend/ (Clean Arch, 4 project, .NET 10)
|
||
│ ├── SolutionErp.Domain/
|
||
│ │ ├── Common/ BaseEntity, AuditableEntity
|
||
│ │ ├── Contracts/ ContractType, ContractPhase, ApprovalDecision
|
||
│ │ ├── Forms/ ContractTemplate, ContractClause ← Phase 2
|
||
│ │ ├── Identity/ User, Role, MenuItem, Permission, AppRoles, MenuKeys
|
||
│ │ └── Master/ Supplier, Project, Department, SupplierType
|
||
│ ├── SolutionErp.Application/
|
||
│ │ ├── Auth/ Login, Refresh, Me
|
||
│ │ ├── Common/ Exceptions, Behaviors, Interfaces, Models
|
||
│ │ ├── Forms/ FormFeatures (List/Get/Render) ← Phase 2
|
||
│ │ ├── Master/ Suppliers, Projects, Departments CQRS
|
||
│ │ └── Permissions/ GetMyMenuTree, matrix upsert
|
||
│ ├── SolutionErp.Infrastructure/
|
||
│ │ ├── Forms/ DocxRenderer, XlsxRenderer, FormRenderer ← Phase 2
|
||
│ │ ├── Identity/ JwtSettings, JwtTokenService
|
||
│ │ ├── Persistence/ DbContext, DbInitializer, Interceptors, Migrations (4)
|
||
│ │ └── Services/ DateTimeService
|
||
│ └── SolutionErp.Api/
|
||
│ ├── Authorization/ MenuPermissionHandler + Requirement
|
||
│ ├── Controllers/ Auth, Suppliers, Projects, Departments, Menus, Roles, Permissions, Forms
|
||
│ ├── Middleware/ GlobalExceptionMiddleware
|
||
│ ├── Services/ CurrentUserService, WebHostEnvironmentLocator
|
||
│ └── wwwroot/templates/ 5 file .docx/.xlsx ← Phase 2
|
||
├── fe-admin/ (7 page)
|
||
│ └── src/pages/
|
||
│ ├── LoginPage
|
||
│ ├── DashboardPage
|
||
│ ├── master/SuppliersPage, ProjectsPage, DepartmentsPage
|
||
│ ├── system/PermissionsPage
|
||
│ └── forms/FormsPage ← Phase 2
|
||
├── fe-user/ (2 page — Login + Inbox placeholder)
|
||
├── docs/ (24 file — STATUS, PROJECT-MAP, workflow, forms-spec, database-guide, 6 flow, gotchas, 4 session log, 1 handoff)
|
||
└── .claude/skills/ (3 skill — contract-workflow placeholder, form-engine + permission-matrix full spec)
|
||
```
|
||
|
||
## Git state
|
||
|
||
```
|
||
49a5f57..(sẽ là commit 5) — Phase 2 MVP
|
||
54d6c9b — Phase 1.2 CRUD + Permission
|
||
49a5f57 — Docs database-guide + flows
|
||
702411f — Phase 1 foundation
|
||
25dad7f — Phase 0 scaffold
|
||
|
||
Branch: main
|
||
Remote: chưa (Gitea URL chờ user)
|
||
```
|
||
|
||
## Credentials + URLs
|
||
|
||
```
|
||
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`
|
||
|
||
## Đánh giá nhanh
|
||
|
||
**Tốt:**
|
||
- Build pass 100% cả BE + FE
|
||
- E2E test: login + CRUD + render template đều pass
|
||
- Docs đầy đủ: 24 file, có session log mỗi chunk, gotchas library tích lũy
|
||
|
||
**Rủi ro:**
|
||
- fe-user còn thô — Phase 3 phải build inbox
|
||
- Form render chỉ MVP — loop table + PDF chưa có
|
||
- Permission matrix chưa test thực với non-admin user
|