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

4.8 KiB
Raw Blame History

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=5PurchaseEvaluationAttachment.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.