[CLAUDE] Docs: compact 3 file core (-273 dòng tổng)
STATUS.md (-52 dòng, -27%): archive 51 row Recently Done Phase 0-7 cũ
→ changelog/recently-done-archive-2026-04.md (file mới)
Giữ 12 row mới nhất Phase 8/Session 5 + pointer archive.
HANDOFF.md (-147 dòng, -32%): bỏ 3 section duplicate
- Versioned workflow quick ref → cross-ref workflow-contract.md §7bis
- File đang active (90 dòng tree) → cross-ref PROJECT-MAP.md
- Git state snapshot stale → cross-ref `git log --oneline -10`
migration-todos.md (-74 dòng, -35%): collapse Phase 6 iter 1+2 + Phase 7
done parts thành 4 dòng paragraph. Giữ Phase 8/9 active + skill audit.
Quy tắc compact (rules.md §6 implicit):
- Recently Done > 30 row → archive cũ vào changelog/recently-done-archive-{YYYY-MM}.md
- Phase done >= 1 tháng → collapse thành 1 paragraph + cross-ref session log
- Section duplicate file khác → cross-ref thay vì copy
Commit MD-only → CI skip (path filter gotcha #41).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
154
docs/HANDOFF.md
154
docs/HANDOFF.md
@ -253,159 +253,13 @@ Trigger: user nói "audit skill" hoặc tự chạy đầu Phase mới.
|
||||
- Workflow transition 403 → check `Contract.WorkflowDefinitionId` pin đúng không
|
||||
- Migration lỗi → 3 file đầy đủ (Designer + Migration + Snapshot)
|
||||
|
||||
## Versioned workflow — quick reference
|
||||
## Versioned workflow — quick ref
|
||||
|
||||
```
|
||||
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
|
||||
`Contract.WorkflowDefinitionId` pin tại Create. `ContractWorkflowService.LoadAsync` resolve order: pinned def → admin override → hardcoded Registry.For(type). Invariant: HĐ cũ giữ policy cũ qua FK Restrict. Detail: [`workflow-contract.md §7bis`](workflow-contract.md).
|
||||
|
||||
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ũ ✓
|
||||
```
|
||||
## File đang active
|
||||
|
||||
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)
|
||||
│ ├── 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
|
||||
```
|
||||
Cấu trúc thư mục + file map: [`PROJECT-MAP.md`](PROJECT-MAP.md). Git state: `git log --oneline -10`.
|
||||
|
||||
## Credentials + URLs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user