Files
solution-erp/docs/changelog/sessions/2026-04-23-1500-toolkit-data-roles.md
pqhuy1987 ff5e35f279
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m47s
[CLAUDE] Docs: chốt session 2026-04-23 chiều — toolkit + 4-bảng + master + roles VN
11 commit feature work (b75448eae59cfe) → 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>
2026-04-23 14:39:48 +07:00

257 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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ệt
- `ContractsListPage` (fe-admin): same pattern + Pagination compact
- `InboxPage` (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=X` qua 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) ✓
- `UserDashboardPage` mới: 5-card "Của tôi" (DraftsInProgress / Pending /
DueSoon / Overdue / TotalValue) + section 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 .
**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 (vd MuaBan ThueVAT, NguyenTac
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 ( Mới)
### F. "Thao tác" — 2-panel + Edit/Xóa hover + Mở fullpage ✓
`ContractCreatePage` rewrite:
- 2-panel: Panel 1 List 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: phải ngay khi tạo, không đợi DangDongDau.
- `CreateContractCommandHandler`: gen trước khi `db.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) gen` cho legacy
- `BackfillContractCodesAsync` trong 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, IsActive
- `ServiceItem` (ServiceItems) vận chuyển, bảo trì, vấn, ...
- `WorkItem` (WorkItems) đào móng, đổ 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ì, vấn, kiểm định, ...)
- 15 WorkItems demo (đào móng, đổ 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 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
Commits: e27c547, 16e24ed
### I. Roles VN labels + Users dept/position + 13 demo users (migration 11) ✓
**Entity changes:**
- `Role` + `ShortName` (max 50) viết tắt VN
- `User` + `DepartmentId` Guid? 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 ) |
| 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 |
| 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 helper
- `UsersPage`: 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"
- `PermissionsPage` Panel 1: 2-line per role (ShortName semibold +
Description small)
Commits: 330d529, ae59cfe
## 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
1. **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.
2. **ContractChangelogs unified** 1 bảng audit cho mọi entity
(Contract/Detail/Workflow/Comment/Attachment), KHÁC ContractApprovals
(workflow-only, dùng cho guard). View layer cho user đọc lịch sử.
3. **Mã HĐ gen tại Create** (vs DangDongDau) trade-off: gap trong
sequence khi reject, nhưng user ngay từ đầu để reference.
4. **Datalist HTML5 native autocomplete** (vs library combobox) đủ
cho MVP, không add dependency, smart-fill qua handleFieldChange.
5. **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.
6. **Per-type bảng Details không User-level approver runtime guard
yet** data model `WorkflowStepApprover.Kind=User` đã , nhưng
transition guard v1 chỉ check Role-kind. Iter sau enable.
## Next session priority
1. **UAT 2-3 user thật** hard requirement
2. Email outbox (chờ SMTP config)
3. Rotate creds (SA/vrapp/JWT/admin)
4. SQL backup Task Scheduler
5. Roles CRUD admin (custom role ngoài 12 hardcoded)
6. User-kind approver runtime guard
7. PermissionsPage: grant Workflows.Read non-admin Wf_* visible
8. 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.