[CLAUDE] Docs: chốt session 5 — Budget FE + PE feature complete + Tests Phase 1-2 + CI gate
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 22s
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 22s
Session 5 (29/04) — 6 commit feature + 1 chốt MD này. ==== Stats sau session 5 ==== - 52 DB tables (+1 PEDeptOpinions) - 15 migrations (+`AddPurchaseEvaluationDepartmentOpinions`) - ~128 API endpoints (+4) - ~31 FE pages (+5 Budget + 1 PeWorkflowsPage) - 71 unit test pass (54 Domain + 17 Infra) — CI gate live, fail → no deploy - ~13050 BE LOC (+1300) - 30 demo user, 38 gotchas, 6 skill (no change) ==== MD touched ==== - STATUS.md: header Phase 8 + 6 row Recently Done session 5 + cumulative cột S5 + In Progress S6 (Hard blockers + Optional polish + Tests Phase 3-5 + Ops) - HANDOFF.md: TL;DR 6 milestone S5 + Cảnh báo S6 (CI test gate workflow mới) + Priority 0 S6 (UAT + Ops focus) + Phase status table cập nhật - migration-todos.md: Phase 8 done với A/B/C/D/E (FE Budget / PE-HD integration / PE WF Designer / Ý kiến 4 PB / Tests Phase 1-2) + Phase 9 active (UAT + Ops + carry over) - architecture.md: §11 Testing strategy mới (test pyramid bottom-heavy + stack + CI gate + phased priority + quy tắc bổ sung mỗi feature) - database/schema-diagram.md: Migration 15 row + total 52 tables + §13 PE Department Opinion (1 bảng UNIQUE PEId+Kind + Upsert behavior + SQL DDL) - ef-core-migration SKILL: migration 15 entry + 52 tables total + Phase 8 update note - CLAUDE.md (root): modules table + Tests row + scope `Tests` + Tests section mới + count update 15/52 - docs/CLAUDE.md: 7 module bullet + ERD 52 bảng + Roadmap Phase 8 done + Phase 9 active S6 - memory project_solution_erp.md: Phase 8 summary + Session 6 priority + workflow user mới (dotnet test → commit → push) - session log 2026-04-29-chot-session-5-budget-fe-pe-tests.md (NEW — 10+ section detail) ==== Verify ==== - dotnet test SolutionErp.slnx → 71 pass / 2s - git status clean sau commit này Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
# Migration To-dos — Atomic Roadmap
|
||||
|
||||
> Tick `[x]` khi xong. Phase 0-5 + Tier 3 + Phase 6 đã DONE — collapsed. Detail xem session
|
||||
> logs trong `docs/changelog/sessions/`. Active work: Phase 7 partial (Budget BE done, FE WIP) + Phase 8 (Budget refinement).
|
||||
> Tick `[x]` khi xong. Phase 0-8 đã DONE — collapsed. Detail xem session
|
||||
> logs trong `docs/changelog/sessions/`. Active work: Phase 9 (UAT + Ops + carry over PE PDF export + Tests Phase 3-5).
|
||||
|
||||
## ✅ Phase 0-5 + Tier 3 — Done (2026-04-21..22)
|
||||
|
||||
@ -102,34 +102,87 @@ Session log: `2026-04-28-chot-session-4-budget.md`.
|
||||
|
||||
### E. Pending migrations
|
||||
|
||||
- [ ] `AddPePaymentTermFields` (nếu chốt UX tách field)
|
||||
- [ ] `AddPeDepartmentOpinions` (nếu chọn Option A header columns)
|
||||
- [ ] `AddPePaymentTermFields` (nếu chốt UX tách field — JSON blob → 6 column)
|
||||
- [x] **`AddPurchaseEvaluationDepartmentOpinions`** ✅ migration 15 (S5)
|
||||
- [ ] `AddBudgetCodeSequences` (nếu chốt format MaNganSach atomic — hiện Random.Shared)
|
||||
- [ ] `AddBudgetVersionedWorkflow` (nếu user cần admin config UI thay vì hardcoded `BudgetPolicy.Default`)
|
||||
|
||||
## 📝 Phase 8 — Budget FE + integration (Session 5 active)
|
||||
## ✅ Phase 8 — Budget FE + PE/HD integration (Session 5 done)
|
||||
|
||||
### A. FE Budget pages — copy pattern PE
|
||||
### A. FE Budget pages — done ✅
|
||||
|
||||
- [ ] `fe-admin/src/types/budget.ts` (types + enum BudgetPhase + ApprovalDecision reuse)
|
||||
- [ ] `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel `[320px_1fr_360px]`)
|
||||
- [ ] `fe-admin/src/pages/budgets/BudgetCreatePage.tsx` (form Header)
|
||||
- [ ] `fe-admin/src/components/budgets/BudgetDetailTabs.tsx` (Thông tin / Hạng mục)
|
||||
- [ ] `fe-admin/src/components/budgets/BudgetWorkflowPanel.tsx` (Panel 3 timeline + transition + comment)
|
||||
- [ ] Mirror tất cả sang `fe-user/`
|
||||
- [ ] App.tsx routes `/budgets`, `/budgets/new`, `/budgets/:id` cả 2 app
|
||||
- [ ] Menu resolver `Bg_*` (Bg_List → `/budgets`, Bg_Pending → `/budgets?phase=Pending`, Bg_Create → `/budgets/new`)
|
||||
- [x] `fe-admin/src/types/budget.ts` (BudgetPhase 5-state enum + DTO types)
|
||||
- [x] `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel `[340px_1fr_360px]` + filter Phase/Năm + ?phase=Pending alias + readOnly mode + BudgetDetailPage fullpage mobile)
|
||||
- [x] `fe-admin/src/pages/budgets/BudgetCreatePage.tsx` (form Header — Tên/Năm/Dự án/Phòng ban/Mô tả)
|
||||
- [x] `fe-admin/src/components/budgets/BudgetDetailTabs.tsx` (Section Thông tin Header + Section Hạng mục table CRUD inline auto-compute ThanhTien=KL×ĐG)
|
||||
- [x] `fe-admin/src/components/budgets/BudgetWorkflowPanel.tsx` (Panel 3 timeline activePhases + nextPhases buttons + Dialog comment + Approvals/Changelog)
|
||||
- [x] Mirror tất cả sang `fe-user/`
|
||||
- [x] App.tsx routes `/budgets`, `/budgets/new`, `/budgets/:id` cả 2 app
|
||||
- [x] Menu resolver `Bg_*` (Bg_List → `/budgets`, Bg_Pending → `/budgets?phase=Pending`, Bg_Create → `/budgets/new`)
|
||||
|
||||
### B. PE/Contract → Budget integration
|
||||
### B. PE/Contract → Budget integration — done ✅
|
||||
|
||||
- [ ] **PE form** thêm field `Ngân sách` select Budget (filter Phase=DaDuyet, NamNganSach=current, ProjectId match)
|
||||
- [ ] **Contract form** tương tự — link sang Budget cho đối chiếu chi phí
|
||||
- [ ] PE Detail tab thêm cột "So với ngân sách" — compute từ BudgetDetail tương ứng (match GroupCode + ItemCode)
|
||||
- [x] **PE form** + Select "Ngân sách" filter Phase=DaDuyet, ProjectId match, BE validate
|
||||
- [x] **Contract form** (Header + Edit) tương tự, EditForm read-only link card khi !isDraft
|
||||
- [x] PE Detail Hạng mục thêm cột "NS link · Δ" — match per-row qua `groupCode|itemCode` + footer aggregate (xanh dưới / đỏ vượt / xám khớp)
|
||||
- [x] PE Detail UI restructure 4 section đánh số match form spec PHIẾU TRÌNH KÝ
|
||||
- [x] BE: BudgetSummaryDto shared + Create/Update PE+Contract commands + BudgetId? + GetQueries load Budget
|
||||
- [x] CreateContractFromEvaluation carry forward pe.BudgetId → contract.BudgetId
|
||||
|
||||
### C. Budget refinement (when needed)
|
||||
### C. PE Workflow Designer admin UI — done ✅
|
||||
|
||||
- [ ] Budget MaNganSach atomic sequence — chốt format chính thức rồi thêm `AddBudgetCodeSequences` migration + `IBudgetCodeGenerator` SERIALIZABLE pattern (mirror Contract/PE)
|
||||
- [ ] Budget versioned workflow — admin config UI nếu Solutions cần custom step approver beyond default 3-step
|
||||
- [x] BE `PeWorkflowAdminFeatures.cs` ~250 LOC mirror Contract pattern
|
||||
- [x] BE `PeWorkflowsController` 2 endpoint reuse policy `Workflows.*`
|
||||
- [x] FE `PeWorkflowsPage.tsx` ~500 LOC + designer dialog (clone/edit/+Role/+User)
|
||||
- [x] App.tsx route `/system/pe-workflows/:typeCode`
|
||||
|
||||
### D. Ý kiến 4 phòng ban — done ✅
|
||||
|
||||
- [x] Migration 15 `AddPurchaseEvaluationDepartmentOpinions` (UNIQUE PEId+Kind)
|
||||
- [x] Domain entity + enum `PeDepartmentKind` (PheDuyet/Ccm/MuaHang/SmPm)
|
||||
- [x] BE Upsert (sign=true → set SignedAt+UserId, sign=false giữ chữ ký cũ) + Delete + 2 endpoint
|
||||
- [x] FE Section "5. Ý kiến 4 phòng ban (sign-off)" 2x2 grid OpinionBox
|
||||
|
||||
### E. Tests Phase 1-2 + CI gate — done ✅
|
||||
|
||||
- [x] **Phase 1** — `tests/SolutionErp.Domain.Tests/` (xUnit + FluentAssertions 7.2): 54 test policy state machine (Contract WF + PE WF + Budget) + Registry + FromDefinition versioned + UserKindApprover
|
||||
- [x] **Phase 2** — `tests/SolutionErp.Infrastructure.Tests/` (EF SQLite + TestApplicationDbContext override `nvarchar(max) → TEXT`): 17 test code generator format + sequence + year boundary + persistence verify
|
||||
- [x] CI gate `.gitea/workflows/deploy.yml` — 2 step `dotnet test` trước build, fail → no deploy
|
||||
- [x] Total 71 test pass / ~2s
|
||||
- [x] Session log + commit + push
|
||||
|
||||
## 📝 Phase 9 — UAT + Ops + carry over (Session 6+ active)
|
||||
|
||||
### A. Hard blockers (chờ user / ops)
|
||||
|
||||
- [ ] UAT thật 1 tuần với 2-3 user (30 demo: 16 sample + 14 Solutions thật)
|
||||
- [ ] SMTP config → Email outbox (BLOCKED chờ user cấp host/user/pass)
|
||||
- [ ] Rotate credentials (admin + 30 demo + SA + vrapp + JWT secret + Gitea runner token)
|
||||
- [ ] Schedule SQL backup daily Task Scheduler
|
||||
|
||||
### B. PE feature gap còn lại
|
||||
|
||||
- [ ] Export phiếu PDF/Excel — `IDocumentConverter` + template `PE-TrinhDuyet.docx` (user pending — không quan trọng lắm)
|
||||
|
||||
### C. Optional polish (làm khi UAT phát sinh)
|
||||
|
||||
- [ ] Budget MaNganSach atomic sequence + migration `AddBudgetCodeSequences`
|
||||
- [ ] Budget versioned workflow + migration `AddBudgetVersionedWorkflow`
|
||||
- [ ] Payment terms PE tách field (JSON → 6 column)
|
||||
- [ ] Auto-map PE Details → Contract Details khi gen HĐ
|
||||
- [ ] Matrix Quotes bulk paste từ Excel
|
||||
- [ ] fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi"
|
||||
|
||||
### D. Tests Phase 3-5 (làm khi gặp bug recurring để justify ROI)
|
||||
|
||||
- [ ] **Phase 3** — Application handler tests (CQRS + EF InMemory) ~15 test
|
||||
- [ ] **Phase 4** — API smoke tests (WebApplicationFactory) ~7 test
|
||||
- [ ] **Phase 5** — FE Vitest cho lib utility (queryMatches, fmtMoney) ~10 test
|
||||
|
||||
### E. Ops chưa xong
|
||||
|
||||
- [ ] Remove binding cũ `.huypham.vn` sau verify stable
|
||||
- [ ] win-acme scheduled task fix unhealthy (cert expire 2026-06-18)
|
||||
|
||||
## 🔁 Skill governance (recurring)
|
||||
|
||||
@ -142,7 +195,7 @@ Quy tắc: `docs/rules.md §9`. Audit định kỳ mỗi đầu tháng — workf
|
||||
|
||||
Cron task `solution-erp-skill-audit-monthly` fire 9:00 AM ngày 1 mỗi tháng.
|
||||
|
||||
## 📦 Post-launch (Phase 9+ — future)
|
||||
## 📦 Post-launch (Phase 10+ — future)
|
||||
|
||||
- [ ] **Email outbox** (MailKit + SMTP) — blocked chờ SMTP config
|
||||
- [ ] E-signature integration (VNPT CA hoặc FPT CA)
|
||||
|
||||
@ -0,0 +1,266 @@
|
||||
# Session log — 2026-04-29 (Phase 8 — Budget FE complete + PE feature gap đóng + Tests Phase 1-2)
|
||||
|
||||
**Topic:** FE Budget pages 3-panel + PE/HD-Budget integration + PE Detail UI restructure + PE Workflow Designer + Ý kiến 4 phòng ban + Tests Phase 1-2 (Domain + Infra) + CI gate.
|
||||
|
||||
**Commits (6 total session 5):**
|
||||
- `df12fb1` — FE Budget pages 3-panel cả 2 app
|
||||
- `61e5d4d` — PE/Contract → Budget integration + cột "So với ngân sách" PE matrix
|
||||
- `7e36241` — PE Detail UI restructure theo spec PHIẾU TRÌNH KÝ (4 section đánh số)
|
||||
- `5d94bb4` — PE Workflow Designer admin UI + Ý kiến 4 phòng ban (Migration 15)
|
||||
- `d3f9346` — Tests Phase 1: Domain unit tests + CI gate
|
||||
- `df5988b` — Tests Phase 2: Code generator format + sequence (SQLite in-memory)
|
||||
- (Session log này — commit chốt MD session 5)
|
||||
|
||||
**Migration:** 15 `AddPurchaseEvaluationDepartmentOpinions` — 1 bảng UNIQUE PEId+Kind cho 4 phòng ban sign-off.
|
||||
|
||||
## A. FE Budget pages 3-panel (commit `df12fb1`)
|
||||
|
||||
Mirror pattern PE 3-panel cho cả `fe-admin` + `fe-user`:
|
||||
|
||||
| File | Mô tả |
|
||||
|---|---|
|
||||
| `types/budget.ts` | BudgetPhase 5-state enum + DTO types (BudgetListItem/DetailRow/Approval/Bundle/DetailBody) |
|
||||
| `pages/budgets/BudgetsListPage.tsx` | 3-panel `[340px_1fr_360px]` + filter Phase + Năm + `?phase=Pending` alias filter ChoCCM/ChoCEO + readOnly mode (menu Duyệt) + BudgetDetailPage fullpage mobile |
|
||||
| `pages/budgets/BudgetCreatePage.tsx` | Form Header (Tên/Năm/Dự án/Phòng ban/Mô tả). Edit mode khóa Project+Department |
|
||||
| `components/budgets/BudgetDetailTabs.tsx` | Section Thông tin Header + Section Hạng mục table CRUD inline (Add/Edit/Delete dialog auto-compute ThanhTien=KL×ĐG). Export `BudgetApprovalsSection` + `BudgetHistorySection` cho Panel 3 reuse |
|
||||
| `components/budgets/BudgetWorkflowPanel.tsx` | Panel 3 timeline activePhases visual + nextPhases buttons (Approve xanh / Reject đỏ / Trả về vàng) + Dialog xác nhận có comment + Approvals + Changelog |
|
||||
|
||||
App.tsx 3 route mới `/budgets`, `/budgets/new`, `/budgets/:id` cả 2 app. Layout resolver `Bg_List`/`Bg_Create`/`Bg_Pending` + root `Budgets` icon Wallet.
|
||||
|
||||
## B. PE/Contract → Budget integration (commit `61e5d4d`)
|
||||
|
||||
### BE (6 file)
|
||||
|
||||
- `Budgets/Dtos/BudgetDtos.cs`: + `BudgetSummaryDto` (compact header snapshot reuse cho PE & Contract)
|
||||
- `PE Dtos + Features`: + `BudgetId?` + `Budget?` vào DetailBundle. Create/Update PE commands + validate cùng Project + Phase=DaDuyet
|
||||
- `Contract Dtos + Features`: same pattern
|
||||
- `CreateContractFromEvaluation`: carry forward `pe.BudgetId → contract.BudgetId`
|
||||
|
||||
### FE (10 file)
|
||||
|
||||
- PE & Contract Create form: Select **"Ngân sách"** filter Phase=DaDuyet & Project match (BE-side filter qua `/budgets?projectId=&phase=4`)
|
||||
- PE InfoTab + Contract Edit: hiển thị Budget link clickable `→ /budgets?id=`
|
||||
- PE ItemsTab matrix: cột **"NS link · Δ"** chỉ hiện khi `ev.budgetId`, match per-row qua key `groupCode|itemCode` (fetch `/budgets/{id}` riêng), footer aggregate (xanh dưới / đỏ vượt / xám khớp)
|
||||
|
||||
## C. PE Detail UI restructure (commit `7e36241`)
|
||||
|
||||
Match form chính thức **PHIẾU TRÌNH KÝ CHỌN TP/NCC** với 4 section đánh số:
|
||||
|
||||
```
|
||||
1. Thông tin gói thầu (a Tên + b Dự án + Địa điểm/Mô tả compact)
|
||||
2. Chọn NCC / TP (a NCC chọn / b Ngân sách / c Giá chào thầu auto-compute / d Bản so sánh)
|
||||
3. NCC / TP tham gia ({n}) (table 5 cột UX web)
|
||||
4. Hạng mục + Báo giá ({n}) (matrix + cột "NS link · Δ")
|
||||
5. Ý kiến 4 phòng ban (sign-off) (2x2 grid OpinionBox — Section thêm trong commit kế)
|
||||
```
|
||||
|
||||
**Section 2.c "Giá chào thầu"** auto-compute: lookup `winnerSupplierRowId` qua `selectedSupplierId`, sum quotes có `purchaseEvaluationSupplierId === winnerRowId`. Hiện "—" khi chưa chọn NCC hoặc chưa nhập báo giá.
|
||||
|
||||
**Section 2.d "Bản so sánh"** dùng filter `purchaseEvaluationSupplierId === null` (file tổng, không gắn NCC cụ thể).
|
||||
|
||||
`FormRow` helper mới (label 176px + value flex) thay cho dl grid 2-col cũ. Drop helper `Field` cũ.
|
||||
|
||||
## D. PE Workflow Designer admin UI + Ý kiến 4 phòng ban (commit `5d94bb4`)
|
||||
|
||||
### PE Workflow Designer
|
||||
|
||||
- BE `Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs` ~250 LOC mirror Contract WorkflowAdminFeatures (GetOverview + CreateNewVersion deactivate cũ atomic)
|
||||
- BE `Api/Controllers/PeWorkflowsController.cs` 2 endpoint reuse policy `Workflows.Read` + `Workflows.Create`
|
||||
- FE `pages/system/PeWorkflowsPage.tsx` ~500 LOC: Landing 2-card grid → TypePanel khi pick code → DefinitionCard active+history + PeWorkflowDesigner dialog (clone từ existing + edit Code/Name/Description + add/remove steps + +Role / +User approvers)
|
||||
- App.tsx route `/system/pe-workflows` + `/system/pe-workflows/:typeCode`. Resolver `PeWf_<Code>` từ session 3 đã trỏ.
|
||||
|
||||
### Ý kiến 4 phòng ban PE
|
||||
|
||||
**Migration 15** `AddPurchaseEvaluationDepartmentOpinions`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE PurchaseEvaluationDepartmentOpinions (
|
||||
Id, PurchaseEvaluationId FK Cascade,
|
||||
Kind INT NOT NULL, -- 1=PheDuyet, 2=Ccm, 3=MuaHang, 4=SmPm
|
||||
Opinion NVARCHAR(2000) NULL,
|
||||
SignedAt DATETIME2 NULL,
|
||||
UserId UNIQUEIDENTIFIER NULL,
|
||||
UserName NVARCHAR(200) NULL,
|
||||
-- AuditableEntity columns
|
||||
);
|
||||
CREATE UNIQUE INDEX ON (PurchaseEvaluationId, Kind); -- max 1 row mỗi loại phòng ban per phiếu
|
||||
```
|
||||
|
||||
- Domain entity `PurchaseEvaluationDepartmentOpinion` + enum `PeDepartmentKind`
|
||||
- Application `PeDepartmentOpinionFeatures.cs`: Upsert pattern (sign=true → set SignedAt+UserId+UserName denorm, sign=false → giữ chữ ký cũ chỉ update text), Delete admin override
|
||||
- API `POST /api/purchase-evaluations/{id}/opinions` + `DELETE .../opinions/{kind}`
|
||||
- FE Section "5. Ý kiến 4 phòng ban (sign-off)" 2x2 grid `OpinionBox`:
|
||||
- Read mode (menu Duyệt readOnly): hiển thị text + chữ ký
|
||||
- Edit mode: textarea + 2 button "Lưu text" / "Lưu & Ký"
|
||||
- Badge "Đã ký" emerald + tên người ký + ngày
|
||||
|
||||
## E. Tests Phase 1 — Domain unit tests + CI gate (commit `d3f9346`)
|
||||
|
||||
```
|
||||
tests/SolutionErp.Domain.Tests/
|
||||
├── Contracts/WorkflowPolicyTests.cs (~17 test)
|
||||
├── PurchaseEvaluations/PurchaseEvaluationPolicyTests.cs (~17 test)
|
||||
├── Budgets/BudgetPolicyTests.cs (~13 test)
|
||||
└── SolutionErp.Domain.Tests.csproj (xUnit 2.9.3 + FluentAssertions 7.2)
|
||||
```
|
||||
|
||||
**Coverage:**
|
||||
- Standard 9-phase + SkipCcm 7-phase (HĐ): role transitions, CCM check, BOD signing, terminal phase, reject paths
|
||||
- Registry: DefaultPolicyName per ContractType (7 type) + bypass flag override Standard→SkipCcm
|
||||
- FromDefinition versioned: build từ ordered steps + reject path back to draft + TuChoi auto-add + UserKindApprover populate UserTransitions
|
||||
- NccOnly (PE-A) 3-step + NccWithPlan (PE-B) 5-step: skip ChoDuAn/ChoCEODuyetPA chỉ ở B
|
||||
- BudgetPolicy Default 3-step + DaDuyet/TuChoi terminal + SLA spec verify (5d/3d/2d)
|
||||
|
||||
**CI gate** `.gitea/workflows/deploy.yml`:
|
||||
|
||||
```yaml
|
||||
- name: Run unit tests (Domain)
|
||||
run: dotnet test tests/SolutionErp.Domain.Tests/...
|
||||
# Fail → exit $LASTEXITCODE → no deploy
|
||||
```
|
||||
|
||||
54 test pass / 6.4s. Verify local: `dotnet test SolutionErp.slnx`.
|
||||
|
||||
## F. Tests Phase 2 — Code generator format + sequence (commit `df5988b`)
|
||||
|
||||
```
|
||||
tests/SolutionErp.Infrastructure.Tests/
|
||||
├── Common/SqliteDbFixture.cs (Test fixture + TestApplicationDbContext)
|
||||
├── Services/ContractCodeGeneratorTests.cs (~10 test)
|
||||
├── Services/PurchaseEvaluationCodeGeneratorTests.cs (~7 test)
|
||||
└── SolutionErp.Infrastructure.Tests.csproj (+ EF Sqlite 10)
|
||||
```
|
||||
|
||||
### Setup SQLite in-memory
|
||||
|
||||
- `TestApplicationDbContext` subclass override `OnModelCreating` — iterate model, replace bất kỳ column type chứa "max" → "TEXT" (SQLite không support `nvarchar(max)`)
|
||||
- `FixedDateTime` stub `IDateTime` (control year boundary deterministic)
|
||||
- Shared `SqliteConnection` open trong fixture, EnsureCreated() từ DbContext model
|
||||
|
||||
### Coverage
|
||||
|
||||
- Format RG-001 cho 5 ContractType (HĐTP/HĐGK/NCC/HĐDV/MB) — `{Project}/{TypeCode}/SOL&{Supplier}/{Seq}`
|
||||
- Framework HĐ (NguyenTacNCC + NguyenTacDV) đặc biệt — `{Year}/{TypeCode}/SOL&{Supplier}/{Seq}` (year scope thay vì project)
|
||||
- Sequence increment per prefix (`/01` → `/02` → `/03`)
|
||||
- Different prefixes (project / supplier khác) có sequence độc lập
|
||||
- Year boundary cho framework — sang 2027 prefix mới reset seq
|
||||
- PE format `PE/{YYYY}/{A|B}/{Seq:D3}` — 3-digit padding test với 12 phiếu
|
||||
- PE Type A và B sequence độc lập trong cùng năm
|
||||
- PersistsSequenceRow LastSeq + UpdatedAt verification
|
||||
|
||||
**CI gate** thêm step thứ 2 — fail-fast tương tự Domain.
|
||||
|
||||
17 test pass / 2s. Total session 5 test count = **71** (54 Domain + 17 Infra).
|
||||
|
||||
## G. Stats sau session 5
|
||||
|
||||
| | Trước S5 | Sau S5 |
|
||||
|---|---:|---:|
|
||||
| BE LOC | ~11750 | **~13050** (+1300 PE WF Designer + Opinion + Budget integration) |
|
||||
| DB tables | 51 | **52** (+1 PEDeptOpinions) |
|
||||
| API endpoints | ~124 | **~128** (+2 PE WF + 2 Opinion) |
|
||||
| Migrations | 14 | **15** |
|
||||
| FE pages | ~26 | **~31** (+5 Budget + 1 PeWorkflowsPage) |
|
||||
| **Tests** | 0 | **71** (54 Domain + 17 Infra) |
|
||||
| CI gate | 1 (build) | **2 step test gate + build** |
|
||||
| Commits | ~75 | **~82** (+6 session 5 + chốt MD) |
|
||||
|
||||
## H. Cảnh báo session 6
|
||||
|
||||
1. **CI test gate active** — mỗi commit push trigger 2 step `dotnet test`. Test fail → NO deploy. Workflow mới: code → `dotnet test SolutionErp.slnx` local → commit → push.
|
||||
2. **Chưa xóa binding cũ `.huypham.vn`** — fallback active. Sau verify stable: `.\migrate-domains.ps1 -RemoveOld -SkipCert`.
|
||||
3. **win-acme scheduled task "unhealthy"** — fix trước cert expire 2026-06-18.
|
||||
4. **Login email default** vẫn `admin@solutionerp.local` (chỉ rebrand demo user).
|
||||
5. **Atomic sequence Budget chưa chốt** — Random.Shared race risk thấp nhưng không zero.
|
||||
6. **Versioned workflow Budget chưa có** — hardcoded `BudgetPolicy.Default` 3-step.
|
||||
7. **Export phiếu PDF/Excel PE** pending vô thời hạn (user nói không quan trọng lắm).
|
||||
|
||||
## I. Lessons learned session 5
|
||||
|
||||
1. **Test pyramid bottom-heavy hợp solo dev** — 71 test (54 Domain pure + 17 Infra SQLite) chạy < 3s. Bỏ E2E, tránh maintenance overhead.
|
||||
|
||||
2. **SQLite in-memory cho code generator test** đủ test format + sequence + year boundary, KHÔNG đủ test race condition thực (cần SQL Server thật cho `IsolationLevel.Serializable` strict). Workaround tốt cho CI runner không có LocalDB.
|
||||
|
||||
3. **TestApplicationDbContext subclass override** — pattern sạch nhất để adapt SQL Server-specific model (`nvarchar(max)`) cho SQLite mà không touch production DbContext.
|
||||
|
||||
4. **CI gate ROI cao cho solo dev** — bug Domain logic recurring (workflow phase, role transition) sẽ block deploy ngay. ~3.5 ngày upfront cho 5 phase, có thể stop ở Phase 2 (1.5 ngày) nếu Phase 3-5 ROI chưa rõ.
|
||||
|
||||
5. **PE Detail UI restructure theo spec form giấy** — match 4 section đánh số PHIẾU TRÌNH KÝ giúp UX consistent giữa fill web và print PDF (tương lai).
|
||||
|
||||
6. **Sign-off 4 phòng ban dùng table riêng thay vì 12 column header** — UNIQUE(PEId, Kind) bảo vệ max 1 row mỗi phòng, dễ query "phòng nào chưa ký", dễ extend nếu thêm kind.
|
||||
|
||||
7. **Workflow user mới end-of-task** = `dotnet test SolutionErp.slnx` → commit → push. CI tự run test gate trước build/deploy.
|
||||
|
||||
## J. Files touched session 5
|
||||
|
||||
```
|
||||
src/Backend/SolutionErp.Domain/PurchaseEvaluations/
|
||||
├── PurchaseEvaluation.cs (mod: + DepartmentOpinions navigation)
|
||||
└── PurchaseEvaluationDepartmentOpinion.cs (NEW — entity + enum PeDepartmentKind)
|
||||
|
||||
src/Backend/SolutionErp.Application/Contracts/
|
||||
├── ContractFeatures.cs (mod: + BudgetId in commands + GetQuery load Budget)
|
||||
└── Dtos/ContractDtos.cs (mod: + BudgetId + Budget? trong ContractDetailDto)
|
||||
|
||||
src/Backend/SolutionErp.Application/PurchaseEvaluations/
|
||||
├── PurchaseEvaluationFeatures.cs (mod: + BudgetId + DepartmentOpinions trong bundle)
|
||||
├── PeWorkflowAdminFeatures.cs (NEW — ~250 LOC mirror Contract pattern)
|
||||
├── PeDepartmentOpinionFeatures.cs (NEW — Upsert + Delete)
|
||||
├── CreateContractFromEvaluationFeatures.cs (mod: carry forward BudgetId)
|
||||
└── Dtos/PurchaseEvaluationDtos.cs (mod: + BudgetId + DepartmentOpinions list)
|
||||
|
||||
src/Backend/SolutionErp.Application/Budgets/
|
||||
└── Dtos/BudgetDtos.cs (mod: + BudgetSummaryDto)
|
||||
|
||||
src/Backend/SolutionErp.Application/Common/Interfaces/
|
||||
└── IApplicationDbContext.cs (mod: + DbSet PEDepartmentOpinions)
|
||||
|
||||
src/Backend/SolutionErp.Infrastructure/Persistence/
|
||||
├── ApplicationDbContext.cs (mod: + DbSet)
|
||||
├── Configurations/PurchaseEvaluationConfiguration.cs (mod: + DepartmentOpinions cascade + UNIQUE)
|
||||
└── Migrations/20260429041117_AddPurchaseEvaluationDepartmentOpinions.{cs,Designer.cs} (NEW)
|
||||
|
||||
src/Backend/SolutionErp.Api/Controllers/
|
||||
├── PurchaseEvaluationsController.cs (mod: + 2 opinion endpoints)
|
||||
└── PeWorkflowsController.cs (NEW)
|
||||
|
||||
fe-admin/src/ (FE mod files mirror lên fe-user)
|
||||
├── types/budget.ts (NEW)
|
||||
├── types/contracts.ts (mod: + BudgetSummary)
|
||||
├── types/purchaseEvaluation.ts (mod: + Budget + DepartmentOpinion + Kind enum)
|
||||
├── pages/budgets/BudgetsListPage.tsx (NEW)
|
||||
├── pages/budgets/BudgetCreatePage.tsx (NEW)
|
||||
├── pages/contracts/ContractCreatePage.tsx (mod: + Budget select)
|
||||
├── pages/pe/PurchaseEvaluationCreatePage.tsx (mod: + Budget select)
|
||||
├── pages/system/PeWorkflowsPage.tsx (NEW)
|
||||
├── components/budgets/BudgetDetailTabs.tsx (NEW)
|
||||
├── components/budgets/BudgetWorkflowPanel.tsx (NEW)
|
||||
├── components/pe/PeDetailTabs.tsx (mod: 4 section restructure + Budget col + Opinion section)
|
||||
├── App.tsx (mod: + 5 route Budget + 2 PE WF)
|
||||
└── components/Layout.tsx (mod: + Bg_* resolver)
|
||||
|
||||
tests/SolutionErp.Domain.Tests/ (NEW Phase 1)
|
||||
├── SolutionErp.Domain.Tests.csproj
|
||||
├── Contracts/WorkflowPolicyTests.cs (~17 test)
|
||||
├── PurchaseEvaluations/PurchaseEvaluationPolicyTests.cs (~17 test)
|
||||
└── Budgets/BudgetPolicyTests.cs (~13 test)
|
||||
|
||||
tests/SolutionErp.Infrastructure.Tests/ (NEW Phase 2)
|
||||
├── SolutionErp.Infrastructure.Tests.csproj (+ EF Sqlite 10)
|
||||
├── Common/SqliteDbFixture.cs (TestApplicationDbContext + FixedDateTime)
|
||||
├── Services/ContractCodeGeneratorTests.cs (~10 test)
|
||||
└── Services/PurchaseEvaluationCodeGeneratorTests.cs (~7 test)
|
||||
|
||||
SolutionErp.slnx (mod: + folder /tests/ với 2 project)
|
||||
.gitea/workflows/deploy.yml (mod: + 2 step dotnet test gate)
|
||||
|
||||
docs/STATUS.md (mod: header + 6 row Recently Done + cumulative cột S5)
|
||||
docs/HANDOFF.md (mod: TL;DR + Cảnh báo S6 + Priority 0 S6 + Phase status)
|
||||
docs/changelog/migration-todos.md (mod: Phase 8 done + Phase 9 active S6)
|
||||
docs/architecture.md (mod: + §11 Testing strategy + renumber §12 Liên quan)
|
||||
docs/database/schema-diagram.md (mod: Migration 15 row + 52 tables + §13 PEDeptOpinions)
|
||||
docs/CLAUDE.md (root + docs/) (mod: modules table + Tests row + Roadmap S5/S6 + Tests section)
|
||||
.claude/skills/ef-core-migration/SKILL.md (mod: 15 migrations + 52 tables + Phase 8 update)
|
||||
docs/changelog/sessions/2026-04-29-chot-session-5-budget-fe-pe-tests.md (NEW — file này)
|
||||
~/.claude/projects/.../memory/project_solution_erp.md (mod: Phase 8 summary + Session 6 priority)
|
||||
```
|
||||
Reference in New Issue
Block a user