[CLAUDE] PurchaseEvaluation: demo seed 4 phieu + MaPhieu atomic sequence + Pe_* perm defaults

Polish session tiep cua PE module skeleton (commit 2c6f0ca..3990066):
3 task A (MISSING in MVP) khac STATUS.md In Progress:

1. Demo PE data seed (SeedDemoPurchaseEvaluationsAsync)
   - 4 phieu varied A/B x phase: A-001 DangSoanThao (mo), A-002
     ChoCEODuyetNCC (winner+9 quotes), A-003 DaDuyet (chua tao HD,
     PaymentTerms JSON), B-001 ChoDuAn (5-step giua chung).
   - Idempotent: skip-if-[DEMO]-exists.
   - Approval history dung policy A (3-step) hoac B (5-step).

2. MaPhieu atomic sequence — Migration 13
   - Format PE/{YYYY}/{TypeLetter}/{Seq:D3} (vd PE/2026/A/001).
   - PurchaseEvaluationCodeSequence entity (Prefix PK).
   - IPurchaseEvaluationCodeGenerator + impl SERIALIZABLE
     transaction (mirror ContractCodeGenerator 1:1).
   - Replace Random.Shared trong CreatePurchaseEvaluationCommandHandler.
   - Migration AddPurchaseEvaluationCodeSequences (1 bang).

3. Pe_* permission defaults
   - SeedPurchaseEvaluationPermissionDefaultsAsync — 7 role business x 9 menu key.
   - Drafter/DeptManager/Procurement: R+C+U; CostControl/PM/Director/AuthorizedSigner: R+U.
   - DeptManager them Delete (xoa nhap).
   - Idempotent per-(roleId x menuKey).

Build: 0 error, 2 warning (pre-existing DocxRenderer).

Files: 4 new + 8 modified (1 migration + entity + generator + DI + 2 ctx + 2 features).

Resolves: STATUS.md In Progress §A — 3 item PE MISSING.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-04-24 10:41:17 +07:00
parent 0048a2e83a
commit c48ac2116d
16 changed files with 3621 additions and 24 deletions

View File

@ -1,19 +1,22 @@
# HANDOFF — Brief 5 phút cho session tiếp theo
**Last updated:** 2026-04-23 tối (Phase 6 — PE skeleton + G-084 hardening, **PE còn chỉnh nhiều**)
**Last updated:** 2026-04-24 sáng (Phase 6 — PE polish: demo seed + MaPhieu atomic + Pe_* perm defaults)
## TL;DR
**PE module skeleton E2E** — 2 quy trình A/B config được admin, 10 bảng, 17
endpoint, 3 page × 2 app + kế thừa HĐ 1-click. BE + FE + migration đã push
lên Gitea main (`2c6f0ca..3990066`, 6 commit). **CHƯA XONG — nhiều polish
+ feature thiếu cho session tiếp** (xem STATUS.md §🔥 In Progress đầy đủ).
lên Gitea main (`2c6f0ca..3990066`, 6+ commit). **Polish session 2026-04-24:**
demo seed 4 phiếu (`[DEMO] PE/.../A-001..A-003 + B-001`) + MaPhieu atomic
sequence (mirror ContractCodeSequences) + Pe_* permission defaults cho 7
role business → admin login thấy data ngay. Còn polish nhỏ (designer UI,
attachments, details mapping, export PDF) — xem STATUS.md §🔥 In Progress.
**G-084 hardening:** localhost → 127.0.0.1 trong scripts + skill, doc gotcha
#33 từ bài học VietReport (IPv4/IPv6 port hijack trên VPS shared).
**Tổng:** 46 DB tables, ~110 endpoints, 12 migrations, 33 gotchas. Blocker
user/ops cũ vẫn còn: UAT thật + SMTP + rotate creds + runner apply.
**Tổng:** 47 DB tables (+1 `PurchaseEvaluationCodeSequences`), ~110 endpoints,
13 migrations (+13 `AddPurchaseEvaluationCodeSequences`), 33 gotchas.
## ⚠️ CẢNH BÁO session tiếp
@ -110,9 +113,9 @@ Xem **STATUS.md §🔥 In Progress** đầy đủ (nhóm A/B/C/D). Tóm tắt nh
2. **PE Attachments upload** — copy pattern `ContractAttachmentFeatures.cs` + `ContractAttachmentsSection.tsx`. Entity + enum có sẵn.
3. **Ý kiến 4 phòng ban** (Phê duyệt / P.CCM / P.MuaHàng / SM-PM) — Excel form có, entity chưa map. Cần design: 4 text field + signoff date, hoặc dùng Approvals với role-kind.
4. **Payment terms tách field** từ JSON blob → 6 field riêng (Tạm ứng / TT tạm / Quyết toán / Bảo hành / Hạn mức / Đánh giá) theo Excel section D.
5. **Seed demo PE data** — 2-3 phiếu cho UAT + screenshot.
6. **Permission grant Pe_* cho non-admin role**`/system/permissions` tick `PurchaseEvaluations.Read` + CRUD cho role Drafter/PRO/CCM/BOD.
7. **MaPhieu format chính thức** — user confirm.
5. ~~Seed demo PE data~~ ✅ DONE (2026-04-24, 4 phiếu varied A/B × phase).
6. ~~Permission grant Pe_* defaults~~ ✅ DONE (2026-04-24, 7 role × 9 menu key).
7. ~~MaPhieu format chính thức~~ ✅ DONE (2026-04-24, atomic `PE/{YYYY}/{A\|B}/{Seq:D3}`).
8. **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template.
9. **Auto-map PE Details → Contract Details** khi gen HĐ (optional — nâng cấp).

View File

@ -2,9 +2,9 @@
> **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`.
**Last updated:** 2026-04-23 tối (Phase 6 — PE module **skeleton E2E + G-084 hardening, CÒN CHỈNH NHIỀU**)
**Last updated:** 2026-04-24 sáng (Phase 6 — PE module **demo seed + MaPhieu atomic + Pe_* perm defaults**)
## 📍 Phase hiện tại: **Module Duyệt NCC (tiền-HĐ) — skeleton deployed, refinement WIP** — 46 DB tables (+10 PE), ~110 endpoints (+17 PE), 12 migrations, 6 commits PE push Gitea (`2c6f0ca..3990066`). Skeleton BE + FE + kế thừa HĐ hoạt động; còn nhiều polish + feature thiếu (designer UI, attachments, details mapping, export PDF).
## 📍 Phase hiện tại: **Module Duyệt NCC (tiền-HĐ) — skeleton deployed, refinement WIP** — 47 DB tables (+10 PE +1 MaPhieu seq), ~110 endpoints (+17 PE), 13 migrations (+13 `AddPurchaseEvaluationCodeSequences`), 6+ commits PE push Gitea. Skeleton BE + FE + kế thừa HĐ + 4 [DEMO] PE seed + Pe_* perm defaults hoạt động; còn polish: designer UI, attachments, details mapping, export PDF.
### 🌐 Production URLs
@ -27,8 +27,8 @@
- Menu leaf `PeWf_*` đã seed rồi, resolver Layout.tsx đã map `/system/pe-workflows/:code`
- [ ] **PE Attachments upload** — pattern copy từ `ContractAttachmentFeatures.cs` + FE `ContractAttachmentsSection.tsx`. Entity + `PurchaseEvaluationAttachmentPurpose` enum đã sẵn (QuoteDocument/RequirementSpec/DecisionExport).
- [ ] **Auto-map PE Details → Contract 7 per-type Details khi gen HĐ** — hiện `CreateContractFromEvaluationCommand` chỉ copy header + GiaTri, KHÔNG copy Details. Cần mapping per ContractType (PE Detail schema flat ≠ 7 Contract Details schemas).
- [ ] **Demo PE data seed** — chưa có `[DEMO]` PE nào. Cần 2-3 phiếu seed (1 NccOnly đã DaDuyet chưa tạo HĐ, 1 NccWithPlan ở phase ChoCCM giữa chừng, 1 TuChoi) cho UAT + screenshot.
- [ ] **MaPhieu format chính thức** — hiện `PE-YYYYMM-XXXX` random 4-digit. User said "tính sau". Cần confirm format: `{ProjectCode}/PE/{seq:D3}` hoặc atomic sequence bảng như `ContractCodeSequences`.
- [x] **Demo PE data seed** (2026-04-24) — 4 phiếu `[DEMO]` cover full state-space: A-001 DangSoanThao (Drafter mới mở), A-002 ChoCEODuyetNCC (winner đề xuất + 9 quotes), A-003 DaDuyet (chưa tạo HĐ — kế thừa demo), B-001 ChoDuAn (5-step giữa chừng). Idempotent skip-if-exists. PaymentTerms JSON cho A-003.
- [x] **MaPhieu atomic sequence** (2026-04-24) — Migration 13 `AddPurchaseEvaluationCodeSequences` (1 bảng, Prefix PK). `IPurchaseEvaluationCodeGenerator` + `PurchaseEvaluationCodeGenerator` (SERIALIZABLE transaction, mirror ContractCodeGenerator). Format `PE/{YYYY}/{TypeLetter}/{Seq:D3}` — VD `PE/2026/A/001`. Wired vào CreatePurchaseEvaluationCommandHandler thay Random.Shared. DI registered.
- [ ] **Section "Ý kiến các phòng ban" (Phê duyệt/P.CCM/P.MuaHàng/SM-PM) ở tab Thông tin** — Excel form mẫu có, entity hiện chưa map. Cần thêm 4-8 text field + signoff date (hoặc dùng Approvals row như ContractApprovals).
### B. UX / Polish cần chỉnh
@ -36,7 +36,7 @@
- [ ] **Payment terms chi tiết** — hiện JSON blob. UX tách field riêng (Tạm ứng / TT tạm / Quyết toán / Bảo hành / Hạn mức / Đánh giá) theo Excel section D.
- [ ] **Matrix Quotes bulk paste** — click cell → popup: OK. Nhưng bulk paste column giá từ Excel chưa có (power user feature).
- [ ] **Export phiếu PDF/Excel** — user cần bản in ký. Tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`.
- [ ] **Permission grant Pe_* cho non-admin role** — admin thấy menu Pe_*, non-admin chưa. Cần vào `/system/permissions` tick `PurchaseEvaluations.Read` cho role Drafter/Procurement/CostControl/Director.
- [x] **Permission grant Pe_* cho non-admin role** (2026-04-24) — `SeedPurchaseEvaluationPermissionDefaultsAsync` grant CRUD per role: Drafter/DeptManager/Procurement (R+C+U) · CostControl/PM/Director/AuthorizedSigner (R+U). DeptManager thêm Delete. Idempotent per-(roleId × menuKey). 9 menu key (PurchaseEvaluations + 2× group + 6× leaf) × 7 role = ~63 row defaults. Sau seed admin bật/tắt finer-grain qua `/system/permissions`.
- [ ] **fe-user Inbox** — hiện chỉ HĐ. Cần thêm section "Phiếu Duyệt NCC chờ tôi" (hoặc route `/pe-inbox` riêng).
- [ ] **Sidebar accordion fe-user** — test `Pe_DuyetNcc` group với `Ct_*` accordion context (Layout.tsx fe-user accordion hiện chỉ track `Ct_<code>`, có thể cần extend cover `Pe_<code>`).
@ -58,6 +58,7 @@
| Ngày | Ai | Task | Commit |
|---|---|---|---|
| 2026-04-24 | Claude | **PE polish — Demo seed + MaPhieu atomic + Pe_* perm defaults** — Migration 13 `AddPurchaseEvaluationCodeSequences` (Prefix PK, mirror ContractCodeSequences). `IPurchaseEvaluationCodeGenerator` + impl SERIALIZABLE — format `PE/{YYYY}/{A\|B}/{Seq:D3}`. Replace Random.Shared trong CreatePEHandler. `SeedDemoPurchaseEvaluationsAsync` 4 phiếu varied (A-001 DangSoanThao, A-002 ChoCEODuyetNCC + 9 quotes, A-003 DaDuyet PaymentTerms JSON, B-001 ChoDuAn 5-step). `SeedPurchaseEvaluationPermissionDefaultsAsync` 7 role × 9 menu key — Drafter/DeptManager/Procurement Create+Update, các role duyệt R+U, DeptManager thêm Delete. | (pending) |
| 2026-04-24 | Claude | **Rebrand 3 domain huypham.vn → solutions.com.vn E2E** — 18 file repo (FE env + scripts + CI/CD + docs + skill + code comments). Viết `scripts/migrate-domains.ps1` (ASCII-only gotcha #30) chạy trên VPS: 3 HTTP binding mới + 3 cert Let's Encrypt (HTTP-01 via SelfHosting) + auto HTTPS 443 + redirect. CI/CD auto-deploy commit `66c1a5c+b93dacf`: appsettings.Production.json CORS mới + FE bundle `VITE_API_BASE_URL=api.solutions.com.vn`. E2E verified: `/api/purchase-evaluations` 401, CORS preflight OK, FE dist có domain mới. URL cũ fallback. Claude SSH tự chạy (không cần user RDP). | `66c1a5c` · `b93dacf` |
| 2026-04-23 | Claude | **SeedDemoUsersAsync robust reconcile + 16 demo users** — Reconcile pattern (per-user try-catch, fix drift dept/position/role nếu user existing). 13 → 16 demo (+bod.tran NĐUQ thứ 2, +pm.le PM thứ 2, +nv.truong NV CCM). Detailed log created/fixed/failed counts. Resolves prod issue: chỉ thấy admin user vì old skip-if-exists fail silent. | `a667665` |
| 2026-04-23 | Claude | **G-084 hardening** — localhost → 127.0.0.1 trong `deploy-iis.ps1` + skill `iis-deploy-runbook`. Thêm gotcha #33 (IPv4/IPv6 port hijack) ref VietReport incident + 3 rules (reverse-proxy IP literal / backend loopback IPv4 explicit / service dependency). SOLUTION_ERP risk thấp (API in-process IIS, no ARR proxy) nhưng chuẩn hóa cho tương lai. | `3990066` |

View File

@ -336,19 +336,29 @@
- [ ] **Auto-map PE Details → Contract Details khi gen HĐ** (optional — nâng cấp)
- 7 mapping function per ContractType (khó vì schema khác biệt)
- MVP: skip, user nhập manual
- [ ] **Demo PE data seed**`SeedDemoPurchaseEvaluationsAsync`
- 1 NccOnly DaDuyet chưa tạo HĐ (showcase kế thừa button)
- 1 NccWithPlan phase ChoCCM (showcase workflow middle)
- 1 TuChoi (showcase reject path)
- [ ] **MaPhieu format chính thức** — hiện `PE-YYYYMM-XXXX` random. User confirm format + atomic sequence:
- Option A: `{ProjectCode}/PE/{yyyy}/{seq:D3}` — atomic via `PurchaseEvaluationCodeSequences` bảng mới
- Option B: Tái dùng `ContractCodeSequences` với Prefix = `PE-{yyyy}-{ProjectCode}`
- [x] **Demo PE data seed**`SeedDemoPurchaseEvaluationsAsync` (2026-04-24)
- A-001 DangSoanThao (Drafter mới mở, chưa có quotes)
- A-002 ChoCEODuyetNCC (winner đề xuất + 9 quotes 3×3 grid)
- A-003 DaDuyet (chưa tạo HĐ — showcase kế thừa button) + PaymentTerms JSON
- B-001 ChoDuAn (5-step giữa chừng)
- Idempotent: skip-if-`[DEMO]` exists
- [x]**MaPhieu format chính thức + atomic sequence** (2026-04-24)
- Format: `PE/{YYYY}/{TypeLetter}/{Seq:D3}` (TypeLetter = A | B)
- `PurchaseEvaluationCodeSequences` bảng mới (Prefix PK, mirror ContractCodeSequences)
- `IPurchaseEvaluationCodeGenerator` + impl SERIALIZABLE transaction
- Migration 13 `AddPurchaseEvaluationCodeSequences` (1 bảng)
- Wired vào CreatePurchaseEvaluationCommandHandler thay Random.Shared
### B. UX / Polish
- [ ] Matrix Quotes **bulk paste** từ Excel column giá → paste matrix row
- [ ] **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx` upload qua FormsPage
- [ ] **Permission grant Pe_* cho non-admin role** — 1 click trong PermissionsPage matrix (Pe_* inherit từ `PurchaseEvaluations.Read` tương tự Contracts inheritance)
- [x] **Permission grant Pe_* cho non-admin role** (2026-04-24)
- `SeedPurchaseEvaluationPermissionDefaultsAsync` — 7 role × 9 menu key
- Drafter/DeptManager/Procurement: R+C+U
- CostControl/PM/Director/AuthorizedSigner: R+U
- DeptManager thêm Delete (xóa nháp)
- Idempotent per-(roleId × menuKey), admin tinh chỉnh tiếp qua /system/permissions
- [ ] **fe-user Inbox** thêm section "Phiếu Duyệt NCC chờ tôi" (hoặc route `/pe-inbox`)
- [ ] **Sidebar accordion fe-user** extend cover `Pe_<code>` (hiện chỉ track `Ct_<code>`)
- [ ] **Dashboard** — thêm KPI "PE phiếu chờ tôi", "PE đã duyệt tháng này", "PE cần tạo HĐ"

View File

@ -0,0 +1,127 @@
# Session 2026-04-24 sáng — PE polish: Demo seed + MaPhieu atomic + Pe_* perm defaults
**Context:** Tiếp nối session "[Roles+Demo+Pending cleanup]" (commit a667665) — user yêu cầu
"Chốt lại toàn bộ MD: 'rules, architech, gotcha, skill, daily, hand-off, DB,
luồng DB ...' và làm tiếp đi nhé." → continue PE polish theo STATUS.md §🔥 In
Progress nhóm A (chức năng MISSING trong MVP).
## Tasks completed (4)
### 1. Demo PE data seed — 4 phiếu varied
**File:** `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs`
`SeedDemoPurchaseEvaluationsAsync` — pattern mirror `SeedDemoContractsAsync`:
| Phiếu | Type | Phase | Đặc điểm | Quotes |
|---|---|---|---|---|
| `[DEMO]-A-001` | DuyetNcc | DangSoanThao | Drafter mới mở, chưa nhập giá | 0 |
| `[DEMO]-A-002` | DuyetNcc | ChoCEODuyetNCC | Winner đề xuất + 9 quotes 3×3 grid | 9 |
| `[DEMO]-A-003` | DuyetNcc | DaDuyet | Chưa tạo HĐ — showcase kế thừa + PaymentTerms JSON | 4 |
| `[DEMO]-B-001` | DuyetNccPhuongAn | ChoDuAn | 5-step giữa chừng (Procurement đã chuyển) | 9 |
**Idempotent:** skip nếu MaPhieu prefix `[DEMO]` exists. Approval history seed
đúng theo policy A (3-step Procurement→CCM→CEO) hoặc B (5-step
Procurement→PM→CCM→CEO PA→CEO NCC). ApproverUserId mapping đúng role.
**Resolves:** STATUS.md §🔥 A — "Demo PE data seed".
### 2. MaPhieu atomic sequence — Migration 13
**Files mới:**
- `src/Backend/SolutionErp.Domain/PurchaseEvaluations/PurchaseEvaluationCodeSequence.cs` — Prefix PK + LastSeq + UpdatedAt
- `src/Backend/SolutionErp.Application/PurchaseEvaluations/Services/IPurchaseEvaluationWorkflowService.cs` — thêm `IPurchaseEvaluationCodeGenerator` interface
- `src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationCodeGenerator.cs` — impl SERIALIZABLE transaction
- `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/20260424033449_AddPurchaseEvaluationCodeSequences.cs` — 1 bảng (Prefix nvarchar(100) PK)
**Files modified:**
- `IApplicationDbContext` + `ApplicationDbContext` thêm `PurchaseEvaluationCodeSequences` DbSet
- `PurchaseEvaluationConfiguration` thêm `PurchaseEvaluationCodeSequenceConfiguration` (Prefix max 100)
- `DependencyInjection` register Scoped `IPurchaseEvaluationCodeGenerator → PurchaseEvaluationCodeGenerator`
- `PurchaseEvaluationFeatures` `CreatePurchaseEvaluationCommandHandler` constructor inject codeGen, replace `Random.Shared` với `await codeGen.GenerateAsync(entity, ct)`
**Format:** `PE/{YYYY}/{TypeLetter}/{Seq:D3}` — VD `PE/2026/A/001`, `PE/2026/B/001`.
TypeLetter = `A` (DuyetNcc) | `B` (DuyetNccPhuongAn).
**Pattern mirror:** `ContractCodeGenerator` 1:1 — SERIALIZABLE transaction +
UPDATE-or-INSERT seq row + commit. Race-safe trên multi-instance.
**Resolves:** STATUS.md §🔥 A — "MaPhieu format chính thức".
### 3. Pe_* permission defaults — 7 role × 9 menu key
**File:** `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs`
`SeedPurchaseEvaluationPermissionDefaultsAsync` — call cuối
`SeedAdminPermissionsAsync`. Strategy:
| Role | Read | Create | Update | Delete |
|---|---|---|---|---|
| Drafter, DeptManager, Procurement | ✓ | ✓ | ✓ | (chỉ DeptManager) |
| CostControl, ProjectManager, Director, AuthorizedSigner | ✓ | — | ✓ | — |
9 menu key per role: `PurchaseEvaluations` (root) + 2 group (`Pe_DuyetNcc`,
`Pe_DuyetNccPhuongAn`) + 6 leaf (List/Create/Pending × 2). Total ~63 row insert.
**Idempotent:** skip per-(roleId × menuKey) đã có row. Admin tinh chỉnh thêm
qua `/system/permissions`.
**Resolves:** STATUS.md §🔥 B — "Permission grant Pe_*".
### 4. Docs updates
- `docs/STATUS.md` — Phase line 7 "47 DB tables", "13 migrations". Tick `Demo PE data seed`, `MaPhieu format chính thức`, `Permission grant Pe_*`. Add Recently Done row.
- `docs/HANDOFF.md` — TL;DR update, gạch các item ✅ DONE, "47 DB tables" "13 migrations".
- `docs/changelog/migration-todos.md` — Tick 3 task PE.A.
## Build status
```
dotnet build SolutionErp.slnx --nologo -v minimal
→ Build succeeded. 2 Warning(s) (pre-existing DocxRenderer), 0 Error(s).
```
## Files touched (12)
**New (4):**
- `src/Backend/SolutionErp.Domain/PurchaseEvaluations/PurchaseEvaluationCodeSequence.cs`
- `src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationCodeGenerator.cs`
- `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/20260424033449_AddPurchaseEvaluationCodeSequences.cs` + `.Designer.cs`
**Modified (8):**
- `src/Backend/SolutionErp.Application/Common/Interfaces/IApplicationDbContext.cs`
- `src/Backend/SolutionErp.Application/PurchaseEvaluations/Services/IPurchaseEvaluationWorkflowService.cs`
- `src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs`
- `src/Backend/SolutionErp.Infrastructure/DependencyInjection.cs`
- `src/Backend/SolutionErp.Infrastructure/Persistence/ApplicationDbContext.cs`
- `src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/PurchaseEvaluationConfiguration.cs`
- `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs`
- `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs`
## Pending after this session (xem STATUS.md §🔥 In Progress)
### A. Còn MISSING
- PE Workflow admin designer UI (`/system/pe-workflows/:typeCode`)
- PE Attachments upload (entity + enum sẵn)
- Auto-map PE Details → Contract 7 per-type Details khi gen HĐ
- Section "Ý kiến phòng ban" trong PE form
### B. UX
- Payment terms tách field (JSON → 6 field)
- Matrix Quotes bulk paste từ Excel
- Export PDF/Excel
- fe-user Inbox PE section
- Sidebar accordion fe-user PE
### C. Edge case
- Reject path E2E
- Delete với linked contract
- Workflow v02 invariant pin v01
### D. Deploy
- win-acme task fix
- Remove huypham.vn old binding sau verify stable
## Commit
`[CLAUDE] PurchaseEvaluation: demo seed 4 phiếu + MaPhieu atomic sequence + Pe_* perm defaults`