[CLAUDE] Phase2: Form Engine MVP + docs (gotchas, skill, handoff)
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>
This commit is contained in:
155
docs/HANDOFF.md
Normal file
155
docs/HANDOFF.md
Normal file
@ -0,0 +1,155 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user