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>
11 KiB
Session 2026-04-23 ~15:00 — Toolkit + 4-bảng overhaul + master data + roles VN
Focus: Sang phiên 2 trong ngày — UX redesign toàn bộ surface HĐ (3-panel List/Detail/Workflow + Inbox + Thao tác), data model overhaul 4-bảng (Header/Details/Workflow/Changelog), master catalogs cho Details, chi tiết Users/Departments/Roles VN.
11 commit (b75448e → ae59cfe), 2 migration (9 + 10 + 11), DB 24→36 bảng.
Outcomes
A. 3-panel layout cho List/Inbox (UX) ✓
MyContractsPage(fe-user):lg:grid-cols-[320px_1fr_360px]— Panel 1 List + search + filter | Panel 2 Detail content | Panel 3 Workflow + Lịch sử duyệtContractsListPage(fe-admin): same pattern + Pagination compactInboxPage(fe-user): same + 4 StatPill inline (Cần xử lý / Sắp QH / Quá hạn / Giá trị) + vai trò amber banner- URL state
?id=selected — bookmarkable, refresh giữ - Mobile fallback (<lg): click row → fullpage
/contracts/:id - Components reuse:
ContractDetailContent+WorkflowHistoryPanel - Commits:
b75448e,89c7e88
B. Sidebar accordion cho 7 loại HĐ ✓
- Chỉ 1 group
Ct_<Code>expand cùng lúc (accordion) - Auto-expand theo URL
?type=Xqua useEffect + AccordionContext - Highlight active group: bg-slate-50 + text-slate-900
- Commit:
7ea3957
C. Tách "Tổng quan" → /dashboard riêng (fix bug trùng /inbox) ✓
UserDashboardPagemới: 5-card "Của tôi" (DraftsInProgress / Pending / DueSoon / Overdue / TotalValue) + section HĐ gần đây- Layout resolvePath: Dashboard → /dashboard (không trùng Hộp thư)
- App route: / redirect → /dashboard
- Commit:
d326e80
D. Data model 4-bảng overhaul (Tier 3 follow-up) ✓
User decision Option B: bảng riêng cho mỗi loại HĐ.
Migration 9 — AddContractDetailsAndChangelog:
- 7 Details bảng: ThauPhuDetails, GiaoKhoanDetails, NhaCungCapDetails,
DichVuDetails, MuaBanDetails, NguyenTacNccDetails, NguyenTacDvDetails
- Common base: ContractId FK Cascade, Order, ThanhTien decimal(18,2), GhiChu, audit fields
- Schema chuyên biệt per loại HĐ (vd MuaBan có ThueVAT, NguyenTac có DonGiaToiThieu/ToiDa)
- 1 ContractChangelogs bảng — unified audit log:
- EntityType enum: Contract | Detail | Workflow | Comment | Attachment
- Action enum: Insert | Update | Delete | Transition
- PhaseAtChange + UserName denormalize + FieldChangesJson + ContextNote
- DB 24 → 32 bảng
IChangelogService (App + Infra):
- 5 method: LogContractChange / LogDetailChange / LogWorkflowTransition / LogCommentAdded / LogAttachment
- Wired vào: CreateContract + UpdateContractDraft (with diff) + AddComment + Upload/Delete Attachment + ContractWorkflowService.Transition
CQRS + API:
- GetContractDetailsQuery dispatch theo Type → bundle 7 lists
- 7 typed AddXxxDetailCommand handler (Insert + log changelog)
- DeleteContractDetailCommand generic (dispatch theo Type)
- ListContractChangelogsQuery (read-only, desc CreatedAt, top 200)
- 9 endpoints mới ContractsController
Commits: 70810e1, 71c035d, e684455
E. FE Panel 2 — tabs → 7/3 grid layout (UX iter 2) ✓
Iter 1 (b3762af): Tabs Tổng quan / Chi tiết / Lịch sử
Iter 2 (ad0652d): Bỏ tabs, hiển thị flat:
- Tổng quan content (Info + Comments + Attachments) ở trên
- Bên dưới grid 7-3: [Chi tiết Tab] [Lịch sử Changelog Tab]
ContractDetailsTab:
- 7 table renderers per type (HEADERS_BY_TYPE + DeleteBtn)
- AddRowForm với FIELDS_BY_TYPE (5-7 field per type)
- buildPayload auto compute thanhTien (SL × DonGia × (1+VAT/100) cho MuaBan)
- canEdit chỉ khi Phase=DangSoanThao
ContractChangelogsTab:
- Render unified timeline desc CreatedAt
- Icon + tone color theo EntityType
- Expandable detail row hiển thị FieldChangesJson (Cũ → Mới)
F. "Thao tác" — 2-panel + Edit/Xóa hover + Mở fullpage ✓
ContractCreatePage rewrite:
- 2-panel: Panel 1 List HĐ theo type + button "+ Thêm mới" cuối | Panel 2 Header form (new/edit) + Chi tiết section
- URL state: ?type / ?id / ?mode=new
- Empty state khi chưa chọn
- Action buttons hover row: Edit ✏ + Xóa 🗑 (luôn hiện, mờ khi Phase != DangSoanThao + tooltip "Chỉ sửa được khi Đang soạn thảo")
- ContractDetailsPreview cho create mode — show table headers + lock icon + disabled add button (user thấy structure trước khi tạo Header)
Commits: 8c4b4da, ec0c983, 501b4de, 7f26ff9, 39031ca
G. Mã HĐ gen ngay tại Create + backfill ✓
User feedback: HĐ phải có mã ngay khi tạo, không đợi DangDongDau.
CreateContractCommandHandler: gen mã trước khidb.Contracts.Add— GenerateAsync chạy SERIALIZABLE riêng, entity chưa tracked nên không bị save kèm- TransitionAsync giữ defensive
if (MaHopDong is null) gencho legacy BackfillContractCodesAsynctrong DbInitializer — chạy 1 lần startup, idempotent (count NULL → skip nếu 0), log success/failed
Commit: 51449d6
H. 4 master catalogs cho Details (migration 10) ✓
User feedback: thêm Master Data cho phần Chi tiết.
Domain entities (4 mới):
UnitOfMeasure(UnitsOfMeasure) — m2, kg, ngc, ...MaterialItem(MaterialItems) — Code, Name, Category (NhomSP), DefaultUnit, Specification, OriginCountry, IsActiveServiceItem(ServiceItems) — vận chuyển, bảo trì, tư vấn, ...WorkItem(WorkItems) — đào móng, đổ bê tông, xây tường, ...
Common pattern: AuditableEntity, Code unique, Category index, IsActive.
Migration 10 — AddMasterCatalogs: DB 32 → 36 bảng.
Seed defaults idempotent:
- 20 UnitsOfMeasure (m2/m3/kg/tan/l/cai/bo/goi/ngc/h/ca/...)
- 15 MaterialItems demo (xi măng PCB40, cát vàng, đá 1x2, thép D10, ...)
- 10 ServiceItems demo (vận chuyển, bảo trì, tư vấn, kiểm định, ...)
- 15 WorkItems demo (đào móng, đổ bê tông, xây tường, lát gạch, ...)
CQRS: CatalogsFeatures.cs (~290 dòng) — 4 catalog × 5 handlers (List + Create + Update + Delete + unique code guard).
Controller: 13 endpoints — GET open cho mọi role (autocomplete); POST/PUT/DELETE Admin role only.
Menu mới (5):
- Catalogs group "Danh mục chi tiết" dưới Master
- 4 leaves: Đơn vị tính / Vật tư SP / Dịch vụ / Hạng mục công việc
FE Admin CatalogsPage: 1 page generic, URL /master/catalogs/:kind,
4 sub-tabs (units/materials/services/work-items), per-kind FIELDS config,
form Dialog với input/textarea/checkbox.
FE Details Add form datalist autocomplete:
- Fetch 4 catalogs qua TanStack Query (cache 'catalogs')
- HTML5
<datalist>per relevant field (donViTinh/maSP/tenSP/hangMuc/...) - Smart-fill: user pick code → autofill name + defaultUnit (sibling fields) qua handleFieldChange
I. Roles VN labels + Users dept/position + 13 demo users (migration 11) ✓
Entity changes:
Role+ShortName(max 50) — Mã viết tắt VNUser+DepartmentIdGuid? FK Departments (Restrict) +Position
Migration 11 — AddRoleShortNameAndUserDepartment: thêm cột, không
table mới. DB vẫn 36 bảng.
12 roles VN labels (idempotent backfill nếu existing role thiếu):
| Code | Short | Description |
|---|---|---|
| Admin | QTV | Quản trị viên hệ thống |
| Drafter | NV.PB | Nhân viên phòng ban (soạn HĐ) |
| DeptManager | TPB | Trưởng phòng ban |
| ProjectManager | PM | Giám đốc dự án |
| Procurement | PRO | Phòng Cung ứng |
| CostControl | CCM | Phòng Kiểm soát chi phí |
| Finance | FIN | Phòng Tài chính |
| Accounting | ACT | Phòng Kế toán |
| Equipment | EQU | Phòng Thiết bị |
| Director | BOD | Ban Giám đốc |
| AuthorizedSigner | NĐUQ | Người được Ủy quyền ký HĐ |
| HrAdmin | HRA | Phòng Nhân sự - Hành chính |
Identity Name = code English giữ nguyên (FK + [Authorize] attr). Chỉ thêm 2 cột display VN.
13 Demo users seed (password User@123456):
- bod.huynh + bod.le (BOD)
- pm.nguyen (PM)
- TPB cho CCM/PRO/FIN/ACT/EQU/HRA (6 user)
- qs.hoang + qs.ngo (QS Drafter)
- nv.cao + nv.dinh (PRO/FIN Drafter)
FE Admin updates:
types/users.ts: RoleShortName + RoleLabel + roleDisplayName helperUsersPage: column Phòng ban + Chức vụ, badge Vai trò = ShortName (tooltip full label), Edit dialog mới (dept/position/active), Create dialog 2-col grid + dropdown Phòng ban, Roles checkbox "ShortName — Full Label"PermissionsPagePanel 1: 2-line per role (ShortName semibold + Description small)
Stats cumulative
| Trước session | Sau session | Δ | |
|---|---|---|---|
| BE LOC | ~4800 | ~7800 | +3000 |
| DB tables | 24 | 36 | +12 (7 details + 1 changelog + 4 catalogs) |
| Migrations | 8 | 11 | +3 (Migration 9/10/11) |
| API endpoints | ~50 | ~80 | +30 (details CRUD + catalogs CRUD + changelogs) |
| FE pages | ~20 | ~22 | +2 (UserDashboardPage + CatalogsPage) |
| FE components | many | many+ | +ContractDetailContent/WorkflowHistoryPanel/ContractDetailsTab/ContractChangelogsTab/ContractDetailsPreview |
| Commits session này | — | 22 | b75448e → ae59cfe |
Architectural decisions
-
Option B per-type Details (vs single bảng + JSON): chuẩn schema, strict typing, TS strict mode FE bắt typo. Trade-off: 7 bảng riêng + nhiều handler lặp pattern. Worth.
-
ContractChangelogs unified — 1 bảng audit cho mọi entity HĐ (Contract/Detail/Workflow/Comment/Attachment), KHÁC ContractApprovals (workflow-only, dùng cho guard). View layer cho user đọc lịch sử.
-
Mã HĐ gen tại Create (vs DangDongDau) — trade-off: gap trong sequence khi reject, nhưng user có mã ngay từ đầu để reference.
-
Datalist HTML5 native autocomplete (vs library combobox) — đủ cho MVP, không add dependency, smart-fill qua handleFieldChange.
-
Identity Name English giữ nguyên + thêm ShortName/Description VN — không break FK, không cần data migration; FE/BE display layer convert qua dict mapping.
-
Per-type bảng Details không có User-level approver runtime guard yet — data model
WorkflowStepApprover.Kind=Userđã có, nhưng transition guard v1 chỉ check Role-kind. Iter sau enable.
Next session priority
- UAT 2-3 user thật — hard requirement
- Email outbox (chờ SMTP config)
- Rotate creds (SA/vrapp/JWT/admin)
- SQL backup Task Scheduler
- Roles CRUD admin (custom role ngoài 12 hardcoded)
- User-kind approver runtime guard
- PermissionsPage: grant Workflows.Read non-admin → Wf_* visible
- Update docs (sẽ làm trong commit chốt session này)
Cron audit fire 2026-05-01
Cron task solution-erp-skill-audit-monthly sẽ chạy tự động đầu tháng
sau — log vào docs/changelog/skill-audit-2026-05.md + commit auto.