Files
solution-erp/docs/changelog/sessions/2026-06-19-S78-pe-attach-file-on-approve.md
pqhuy1987 f0e616fd5a [CLAUDE] Docs: S78 closeout — PE attach-file khi duyet (Run #330) + gotcha #71 + cicd flush
STATUS/HANDOFF tier +S78 (bundle CsJetgZH/BVS0ApIm, no migration, test 354 unchanged) + trim S75 row. gotcha #71 (them enum value vao entity dung-chung -> pollute UI/guard proxy-predicate supplierId===null). session log S78. cicd-monitor MEMORY self-flush Run #330. curate-debt carry: reviewer 45.2KB + cicd 38.8KB + inv 35.7KB keep-floor-hit (archive-gate A7 PASS 186/186). Docs-only -> CI skip.
2026-06-19 19:32:41 +07:00

35 lines
4.8 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 78 (2026-06-19) — PE: đính kèm file khi DUYỆT (UAT Tra Sol / 5 tester)
**Anh:** forward chat Zalo (Tra Sol + team — "5 tester đang testing kaka" 15:30) → *"CHỖ MÀN HÌNH duyệt — ĐỂ THÊM chỗ attach file… để khi họ duyệt mà muốn đính kèm cái file của mình lên vì có trường hợp thay đổi ko muốn trả lại"**"OK public và push luôn đi nhé"*`/session-end`.
## Yêu cầu
Ở modal Duyệt PE (popup "Duyệt → Đã gửi duyệt") thêm trường **ĐÍNH KÈM FILE** — người duyệt tải file của mình lên ngay lúc duyệt, thay vì phải Trả lại phiếu (tình huống có thay đổi nhỏ).
## Thiết kế (em-main solo — schema/UX decision)
- **Reuse hệ attachment có sẵn, MIGRATION-FREE:** thêm 1 enum `PurchaseEvaluationAttachmentPurpose.ApprovalAttachment = 5` (lưu int → 0 đổi schema). Endpoint `POST {id}/attachments` đã nhận sẵn `purpose`+`note`, validator `IsInEnum()`, controller `[Authorize]` + handler KHÔNG guard drafter-only → **approver upload được (no 403)**.
- **Upload-then-approve:** FE modal picker multi-file → bấm Xác nhận → upload từng file (purpose=5) TRƯỚC → rồi mới `/transitions` chuyển phase. File lỗi (định dạng/>20MB) → throw, KHÔNG duyệt.
- **Hiển thị:** mục "📎 File đính kèm khi duyệt" trong `PeWorkflowPanel` (download + preview qua `AttachmentPreviewDialog`), gắn CreatedBy + CreatedAt. KHÔNG lẫn vào "Bảng so sánh".
## Done (commit `7886fd0`, 7 file +313/14, Run #330 PASS)
- **BE (1 file):** enum `ApprovalAttachment=5``PurchaseEvaluationAttachment.cs`. No migration. Test **354 PASS** (unchanged). GET bundle project `e.Attachments` KHÔNG lọc purpose → file purpose=5 tới FE.
- **FE 2 app SHA-identical:** `PeWorkflowPanel.tsx` (picker + upload-before-transition + display section + close-reset) · `PeDetailTabs.tsx` (2 filter fix) · `types/purchaseEvaluation.ts` (enum + label "File khi duyệt").
- **Fix correctness (gotcha #71):** 2 filter dùng `supplierId===null` làm proxy "Bảng so sánh" → loại purpose=5 (tránh lẫn section + false-pass submit-guard "Chưa đính kèm Bảng so sánh").
## Cách chạy
em-main-led + self-gate (HMW-mode ON nhưng tight-coupling modal + go-live → `feedback_workflow_fanout_reliability`: em-main ≈ fan-out, tránh #53; reviewer over-cap 45KB → grep no-leak thay vai). **1 sub spawn = cicd-monitor** (verify Run #330). Verify chain: 3 build PASS + 354 test + SHA-parity identical (`diff` = 0) + grep no-leak (mọi `.purpose`/`supplierId===null` 2 app) + GET-bundle-projection check.
## 3 vấn đề em tự bắt khi build (review-trước-deploy)
1. **Authz** — đọc handler `UploadPurchaseEvaluationAttachmentCommandHandler` confirm KHÔNG guard drafter-only → approver upload được (no 403; verify TRƯỚC build per gotcha #44 silent-403 pattern).
2. **Filter pollution (#71)** — file-khi-duyệt (supplierId=null) lẫn "Bảng so sánh" + false-pass submit-guard → vá 2 filter ×2 app.
3. **Dialog mirror-truncate** — bản fe-admin em sót `</Dialog>` (new_string copy-truncate) → build fe-admin riêng BẮT → vá. **Bài học: build-verify TỪNG app, không tin "mirror identical".**
## Deploy (cicd-monitor PASS — Run #330 ~4m56s)
Test gate 354. Bundle ROTATE: admin **`BqKD3Y23 → CsJetgZH`** / user **`Cn-i349D → BVS0ApIm`** (+css). NO migration (Mig 57 latest, sys.tables 88). Smoke 4×200 + `POST .../attachments` 401-wired. Ship-proof byte-stable (admin 1,617,391b · user 1,521,772b, fetch#1==#2) + fake-hash control (gotcha #69 non-determ rotate).
## Lưu ý / NEXT
- **Minor (chấp nhận UAT):** upload-then-transition KHÔNG atomic — upload OK nhưng transition lỗi → file orphan gắn phiếu (hợp lệ, retry được).
- **NEXT UAT (anh/Tra Sol/5 tester, Ctrl+F5 lấy `CsJetgZH`/`BVS0ApIm`):** phiếu chờ duyệt → ✓ Duyệt → "+ Chọn file đính kèm" (multi) → Xác nhận → file ở mục "📎 File đính kèm khi duyệt" (download/preview). Chỉ hiện ở hành động Duyệt.
- **🔴 NEXT (em) — carry GẤP curate L1 over-cap (carry 6 session S72→S78):** reviewer **45.2KB** + cicd-monitor **38.8KB** + inv-codebase **35.7KB** = keep-floor-hit (manual SPLIT/condense, KHÔNG auto-drain; archive-gate `memory-archive-gate.ps1` A7 GATE PASS 186/186 — archive integrity OK, chỉ L1-hot truncate-on-inject) + FD 26.1KB / test-spec 27.7KB WATCH strike-1.
- **Ops giữ S58/S59:** tzutil VPS UTC+7 · anh Chương email typo · 5 real-staff pw `User@1234567` · gán CNTT. **Monthly audit 2026-07-01:** STATUS/HANDOFF re-tier · docs/CLAUDE deep-doc count-flush (Mig→57, test→354, gotcha→71) + schema-diagram §16+ Mig 32-57 ERD.
- **Pending product (carry):** "Ngưỡng giá CEO" Mig 54 Designer UAT · "C" chuyển phiếu→dự án chờ spec form.