Commit Graph

153 Commits

Author SHA1 Message Date
50e6d8c382 [CLAUDE] Contract: K1 SP-002 danh muc loai HD - ContractCatalogEntries (Mig 70) + seed 86 + CQRS + FE kind-5 x2 app + 8 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m31s
Gate: reviewer PASS-WITH-FLAGS 9f (sub-reviewer-gate-k1.md). Xu ly: F4
IncludeInactive mac-dinh-loai (spec K1.c) + test T5b; F7 comment 5-kind;
F1 OG-6 doi nhan soat-SAU @PAUSE-2 (seeder skip-if-exists giu sua-tay CRUD
qua restart - update-branch co y KHONG co); F3 authz mirror khuon Catalogs,
gioi-han khai: 4 policy ContractCatalog.* sinh ra nhung chua endpoint nao
tieu thu (display-layer khac API-layer, #82); F6 ten index IX_ giu EF-default
(NIT). Suite 598/0 (45D+553I). Mig 70 ap SQL Server that OK. Drift DELTA:
MenuKeys.All 55->56, policies 220->224, bang 96->97.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 15:45:50 +07:00
761d8183f3 [CLAUDE] App+Infra+Tests: W6 KHKK — duong ong HD V2 (view per-HD 3-site + inbox V2+ADMIN + guard trinh +PMH)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m52s
- View: vế isV2Approver per-HĐ ở CẢ 3 call-site GetEligiblePhases (:301/:381/:486) — không role-blanket, nháp-riêng-tư S89 giữ, deleted-view cùng vị ngữ
- Inbox: ghép v2InboxIds precompute (mirror PE ResolveV2InboxIdsAsync) + nhánh ADMIN phase-list tường minh +ChoDuyet (DR-4/F-B13) — HĐ ChoDuyet vào inbox cả approver lẫn admin
- Guard trình CWS:73-78: Drafter|DeptManager|người-tạo|Procurement + chặn null==null lọt guard (actorUserId is Guid); Reject :49-66 + vùng W3 :217-394 0-diff (O-A giữ)
- tests +7 (587/0): 5 PIN + admin-inbox DR-4 + Submit 4-vế/null-trap
- Reviewer: Trục 1-3 vai PASS 0-critical + 4-7 lead — 2 ghi-nhận owner: workflow-blanket-by-design độ rộng + Reject pre-existing AMPLIFIED (bán kính nổ tăng khi view mở)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 23:27:19 +07:00
df52fa0cd0 [CLAUDE] App+Infra+Api+FE-User+FE-Admin+Tests: W3 KHKK — duyet 3 tram OR-of-N + finalize chot gia (test-before 6 RED->GREEN)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m54s
- ContractSigningPlanWorkflowService: copy khuon ApproveV2Async (con-tro doi StepIndex+LevelOrder, GroupBy Order, OR-of-N, LevelOpinions UPSERT "(duyet — khong y kien)") — CAM Proposal-flatten; KHONG port 2 duong ket-thuc-som (owner phan PHA VO S155)
- Choke-point finalize ApplyApprovedValuesOnFinalize (Line.ApprovedAmount ??= Proposed) 1-SITE-BY-DESIGN: hop-dong transitions khong co targetPhase => admin cung xuyen choke-point (triet lop #81 tu goc); RULE-comment khuon :356-360
- Transitions endpoint: submit/approve/return/reject (hop-dong LEAD-dinh-nghia literal — reviewer Truc-4 KHOP 5/5, truc W2 tung dut 6 diem); guard trinh CreatedBy|Drafter|DeptManager-cung-phong|Admin; changelog/approvals bang KHKK rieng (CAM IChangelogService — FK-547 rao bang vang-mat-dep); notify Cap-ke dich danh + exclusion actor/drafter (S86)
- Save-diem: 1 SaveChanges cuoi = 1 transition 1 unit-of-work (service la diem vao, khac nguon :537)
- FE KhkkWorkflowPanel x2 app SHA-pair: so-do Buoc/Cap + banner den-luot + Gui/Duyet/Tra/Tu-choi + y kien; panel GATE nut theo actor (khong de an 403)
- Test-before: 6 test san PIN RED-evidence 6/6 (5 NotImplemented + 1 assert) -> GREEN 6/6; sua-test dung 1 seed FAULT-INJECT sot (0 assert doi); suite 574 -> 580/0
- Reviewer 7/7 truc DAT 0 chan (4 truc vai + 3 truc lead on-behalf; Q1-Q6 duyet)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 22:33:11 +07:00
6cbc6ad937 [CLAUDE] App+Api+FE-User+FE-Admin+Tests: W2 KHKK — CRUD phieu nhap + can cu b.8-9 + FE 3 page x2 app + 12 fix reviewer
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m56s
- BE mega-file ContractSigningPlanFeatures (Create 4-rao + auto-Lines snapshot per-winner + MaKeHoach @CREATE + UpdateDraft null-safe + Get/List/inbox-precompute-V2/deleted + Dossier + Attachments + Delete allow-list M6 + picker) + Controller 15 action policy per-action 15/15 (KeHoachKyKet.*)
- FE pages/khkk 3 page + types x2 app SHA-pair + 4-place (6 leaf Khkk_* het coming-soon; WfView: user=matrix?type=10 [whitelist +10] / admin=Designer deep-link); root KeHoachKyKet -> /khkk/list
- Reviewer adversarial: 12 finding (3 CRITICAL dut-2-bo FE-BE: route picker + peId body + dossier planId; 2 MAJOR security: detail+download 0 rao -> EnsureCanViewAsync mirror PE S89 nhap-rieng-tu; PUT-vs-POST de-ban-sao; peTenGoiThau; winnerSupplierNames; Content-Disposition RFC6266; LEFT-join Projects) -> 11 FIXED + 1 GIU (F-10 ke thua khuon PE, bit dong bo sau)
- tests: +8 (574 total 0 fail) — authz reflection dong + Create/Delete/guard/khong-dot-ma-khi-409 + fixture-co-interceptor

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 21:19:41 +07:00
a8027c04fe [CLAUDE] Domain+App+Infra+Admin: W1 KHKK — Mig 69 ContractSigningPlans 7 bang + policy KeHoachKyKet + seeder UPGRADE-if-exists + CodeGen KHKK + Designer type-10
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m40s
- Domain/ContractSigningPlans: 7 entity + 3 enum (Phase 1/2/3/98/99; DossierItem Kind/Status start=1); ApplicableType += ContractSigningPlan=10 (slot 10, append-only)
- Mig 69 AddContractSigningPlans: 7 CreateTable / 20 CreateIndex / 0 ALTER; UNIQUE filtered (PlanId,SupplierId) WHERE IsDeleted=0 (#57); FK 6 con Cascade 1-hop + 2 Restrict, 0 multiple-cascade-path; database-agent review PASS 8/8 + DB11
- MenuKeys.All += KeHoachKyKet (policy KeHoachKyKet.* x4 sinh runtime; menu-row prod KHONG doi — 142 giu); STATUS canonical 54->55 / 216->220
- DbInitializer.SeedKeHoachKyKetAccessAsync: UPGRADE-if-exists (F-S1 — khong insert-NO-OP) + vế CanDelete (Drafter/Admin), 13/13 role CanCreate+CanUpdate, chay SAU revoke; revoker khong phu Khkk_* (reviewer Truc-1 PASS)
- ContractSigningPlanCodeGenerator: KHKK/{YYYY}/{Seq:D3} (owner OK @S161) qua WorkflowAppCodeSequences dung chung, SERIALIZABLE
- AWV2AdminFeatures: 3 site count/retained/orphan + nhanh ContractSigningPlanLevelOpinions (chong no FK 500 khi xoa Level); +label VN type-10 (F-7); +ep false 2 co early-finalize server-side cho type-10 (F-8 — containment tang BE, FE da ep o levelFlagsPayload)
- fe-admin Designer: deep-link type-10 + an 2 checkbox early-finalize (anh phan "PHA VO" S155) — containment 2 lop render+payload
- tests: +4 (566 total, 0 fail) — schema-invariant 7 bang + codegen format (fault-inject 2 chieu chung co rang)

Reviewer: PASS_WITH_FLAGS 10 issue -> 8 fixed cung commit, 2 giu trang thai (F-1 acceptance đo-CO cho prod; F-4 ke thua y PE prod)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 20:04:39 +07:00
ea962b1e59 [CLAUDE] Contract+FE-User: dot-5 menu 6-leaf y-chang-Duyet-NCC + GET /contracts/deleted + bo hero + "Tong quan quy trinh"
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m38s
- BE: ListDeletedContractsQuery (IgnoreQueryFilters + Where(IsDeleted) + IDOR mirror; LUAT thay so-dem theo reviewer FLAG-10) + GET /contracts/deleted [Contracts.Read]
- Seeder: Ct x7 +3 leaf (WfView/Approved/Deleted) + labelBackfill "Dang duyet" x7 + Khkk 6 leaf + Dashboard -> "Tong quan quy trinh" + reviewKeys +23 key
- FE user: matrix +type=3 (HD chung 1 bo V2) + route /contracts/workflow-matrix + Ct regex +3 action + MyContractsPage (phase/deleted + banner + an nut Tao + FLAG-2 guard selectContract khi deleted) + MenuLeaf depth-0 UPPERCASE + UserDashboardPage BO HERO (owner: "bo cai tren di, cai duoi OK") + title "Tong quan quy trinh"
- fe-admin: staticMap +2 Khkk (FLAG-1); leaf Ct_ moi van an theo isAdminHidden (da kiem CLEAN)
- reviewer PASS_WITH_FLAGS 10 FLAG (0H/4M/6L): fix 4M, park 6L co ghi (FLAG-4 dinh nghia "Da duyet" HD -> cho owner)
- build fe x2 + BE PASS; test 562 PASS

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 14:40:10 +07:00
a2bbcb91c3 [CLAUDE] FE-User: dot-4 danh sach toan trinh - 7 FLAG reviewer fix + nhan 'Bang cung' (owner ve)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m39s
- FLAG-1[M]: row HD mobile het ngo cut - mirror nhanh matchMedia cua MyContractsPage (desktop ?id= / mobile /contracts/:id)
- FLAG-2[M]: JourneyDots nhan per-dot states; DOT_TEXT.none trung tinh; +state 'linked' (PeListItem.contractId THAT); contractDots: DangDongDau/DaPhatHanh cham dung GD4 (suy dien tuyen tinh CUNG module - hop le); aria chi ke cham CO thong tin
- FLAG-3[L]: Pager dung page-state thay data.page (het race bam nhanh)
- FLAG-4[L]: vung role=status giu ton tai khi 0 ket qua (screen-reader duoc bao)
- FLAG-5[L]: 4-cham vao sub-line mobile (tang lien ket 2 khong bien mat tren dien thoai)
- FLAG-6[L]: (ghi nhan - count tab vs search: de nguyen co chu thich o code, xu ky hon khi co UAT)
- FLAG-7[L]: nut X goi clearSearch() - xoa NGAY khong cho debounce
- Seeder: Hdc_ leaf + ' - Bang cung' (tree.Add + labelBackfill 7 entry; prod SQL suffix=7 cung ngay)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 13:51:07 +07:00
2a7269581c [CLAUDE] Infra: go nhanh S92 khoi revoker (owner supersede: hien thi het) + skeleton menu GD2/GD4 + ComingSoonPage x2
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m56s
- RevokeTemporarilyHiddenModulesAsync: GO Contracts+Ct_*/Master-set khoi predicate (bai tra gia: grant SQL tay bi revoker lat o restart #423 - 447/494 row roi; regrant=447 da chay truoc commit nay). Hrm/Off/Personal GIU (y owner: vung dang-lam chi admin)
- reviewKeys += ContractMenuKeys + MasterMenuKeys + KhkkKeys + HdcKeys (CanRead-only all-role, fresh-env hoi tu)
- Seeder tree.Add: Khkk_G1 + 4 leaves (khuon Duyet NCC) + Hdc_x7 (tai dung nhan 01.-07.) - prod da INSERT truc tiep (perm=156)
- ComingSoonPage mirror x2 (md5-identical) + route /coming-soon x2 + staticMap 11 leaf x2 (gotcha #50)
- Test: AdminOnlyModulesRevokeTests tach StillHidden/Reopened + REGRESSION-GUARD S159 (re-add nhanh S92 => do); ProcurementMasterAccessSeedTests doc lai isolation bang CO CAO (spec-change S92->S159, update test + code chung commit)
- 562 test PASS - nghiem thu cuoi = restart THAT khi deploy run nay (khuon S91)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 12:34:15 +07:00
1a47a61c21 [CLAUDE] FE-User: tab strip 4 giai doan tren phieu PE + menu 4-GD + danh so 01-07 nhom HD (UAT anh Kiet)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m44s
- PePipelineStrip moi (mirror x2 app md5-identical): Duyet NCC | Ke hoach ky ket HD | Duyet hop dong | Hop dong cung — chen dau PeDetailTabs (GD1 active)
- Menu 4-GD: rename 2 root (PurchaseEvaluations->Duyet NCC, Contracts->Duyet hop dong) + 2 root placeholder KeHoachKyKet/HopDongCung (ngoai MenuKeys.All, staticMap -> /dashboard) — prod da SQL truc tiep cung ngay, seeder+labelBackfill giu hoi tu (gotcha #11)
- Danh so 01.-07. nhom HD: prod prepend-only 0-VN-over-wire (renamed=7), seeder typeLabels + labelBackfill 7 entry
- Dong bo nhan 4-GD tren dashboard (3 title + 3 group aria)
- reviewKeys += 2 placeholder CanRead-only; test 562 PASS; build fe x2 PASS

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 12:06:19 +07:00
4464a464c5 [CLAUDE] PurchaseEvaluation: nut XOA phieu o man duyet + menu 3 muc + man "Da xoa" (dot 2)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m47s
Dong ca UAT goc (Tra Sol): "lo bam sai cai goi thau, quay lai khong duoc, phai
xoa thi no moi ko co luy ke len". Dot 1 (b1bae77) da dung NEN (co F6 + lenh sua
quy trinh tai cho); dot 2 la phan nguoi dung cham vao.

- App: PeSoftDeleteFeatures.cs MOI
  - DELETE /api/purchase-evaluations/{id}/by-approver — 3 rao: phase ChoDuyet
    ^ dung luot actor ^ matchingLevel.AllowApproverDelete (PER-NGUOI, khong g.Any)
  - GET /api/purchase-evaluations/deleted — IgnoreQueryFilters() KEM .Where(IsDeleted)
    (IgnoreQueryFilters GO filter chu khong DAO — thieu Where la liet ke ca phieu song)
    + tai lap khoi IDOR cua list hien hanh
  - ghi vet ChangelogAction.Delete + ly do
- Api: 2 endpoint moi. 🔴 by-approver CO Y KHONG co [Authorize(Policy)] — do tren DB:
  moi vai dang lam nguoi duyet (Procurement/CostControl...) deu CanDelete=0 va khong
  seeder nao nang co do => gan policy la 403 voi dung nguoi can dung, ma FE gate cung
  quyen nen khong thay nut khong thay loi (gotcha #44). Quyen = 3 rao handler; co F6
  la admin tick dich danh tung nguoi => chat hon quyen theo vai.
- Dto: ApprovalWorkflowOptionsDto + AllowApproverDelete. Thieu field nay thi FE gate
  luon sai => nut KHONG BAO GIO hien, ma BE lan FE deu build sach (reviewer bat).
- Domain/Infra: 2 menu key Pe_{code}_Approved / _Deleted (KHONG vao MenuKeys.All =>
  giu 54/216) + seed tree + labelBackfill "Duyet" -> "Dang duyet" + 2 danh sach permission
- FE x2 app: nut Xoa trong PeWorkflowPanel (md5 mirror khop) + dialog ly do + Layout
  regex/route cho 2 muc moi + man "Da xoa" chi-xem
- Tests: +11 (562 tong, 0 fail). T27 khoa CA LOP loi entity-co-co-ma-DTO-khong-co
  (fault-inject xac nhan: go field ra => T27 do ngay)

Review: 12 FLAG, chot chan H1 (DTO thieu field) da va. Deploy KHONG co migration
nhung CO seed menu => phai restart API.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 14:06:14 +07:00
b1bae77c9c [CLAUDE] Workflow: sua quy trinh duyet TAI CHO + co F6 AllowApproverDelete (dot 1)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m31s
Nen cho tinh nang "xoa phieu PE o man duyet" (UAT: phieu bam sai goi thau dang
an luy ke). Dot 1 lam NEN, dot 2 moi lam nut xoa.

Vi sao phai lam nen truoc: phieu dang chay pin ApprovalWorkflowId va doc workflow
SONG theo Id do. Moi POST tao workflow moi = Id MOI, nen tick co tren ban moi
KHONG BAO GIO toi duoc phieu dang treo. Phai co lenh sua-tai-cho giu nguyen Id.

- Domain: ApprovalWorkflowLevel + AllowApproverDelete (F6, per-NGUOI) + Mig
  20260727033522_AddPeAllowApproverDelete (AddColumn bit default false, no new table)
- Application: UpdateAwDefinitionCommand + Validator + Handler
  - 2 phep thu: (T1) khung khong doi - Order tung row bat bien
                (T2) luat choi khong doi - cam CeoApprovalThreshold, AllowApproverFinalize,
                     Code, ApplicableType => 409 bao tao ban moi
  - diff theo Level.Id (CAM delete-then-insert: no FK Restrict + mo coi LevelOpinion)
  - guard 2 tang chu ky: tang 1 chu ky tren ho so CON SONG; tang 2 chu ky CON LUU
    (cha xoa mem hoac opinion xoa mem) - ca hai deu CHAN, khong xoa cung
  - purge chi khi ho so cha KHONG CON ROW; boc transaction (ExecuteDelete tu commit)
  - KHONG tang Version, KHONG dung IsActive, KHONG doi Id
- Api: PUT /api/approval-workflows-v2/{id} + [Authorize(Policy="Workflows.Create")]
- Infra: message 403 in TEN NGUOI thay GUID tran
- FE: Designer tach "Sua tai cho" (PUT) vs "Tao phien ban moi" (POST) + o tick F6
- Tests: +21 (551 tong, 0 fail) - gom F12 chung minh phieu dang chay nhan thay doi ngay

Review: 14 FLAG, 3 HIGH da va (ExecuteDelete ngoai transaction / purge xoa cung
chu ky phieu xoa mem / endpoint khong co day FE goi toi).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 12:36:59 +07:00
6664a6136a [CLAUDE] PurchaseEvaluation: luy ke TAM TINH vs CHINH XAC — ComputePendingAsync + 5-field DTO + FE 2-app sub-dong amber/banner man duyet + D4 audit-note (UAT anh Kiet 15-07, 0 mig, test 520→528)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m27s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 14:27:19 +07:00
d4fbced02f [CLAUDE] PurchaseEvaluation: freeze ngân sách phiếu DaDuyet — Mig 67 snapshot 11 cột + display-gate budgetFrozen + 2 terminal-guard (UAT anh Kiệt 07-16)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m29s
- Bug UAT: PeWorkItemBudgets (record NS dùng chung per Dự án × Hạng mục) sửa được sau duyệt → phiếu ĐÃ DUYỆT đổi số retroactive (detail-bundle load pair LIVE :911 + FE fallback ?? bs.*).
- Fix: Mig 67 AddPeApprovedBudgetSnapshot — 11 cột ApprovedBudget* trên PurchaseEvaluations; helper ApplyBudgetSnapshotOnFinalizeAsync gọi ở 5 site set DaDuyet (4 finalize + admin-override catch-all — reviewer catch #81-class, assignment qua biến lọt literal-grep); display-gate: DaDuyet+SnapshotAt → serve snapshot + BudgetFrozen=true + CanEdit=false, else LIVE (R2: NS live vẫn là "bản cập nhật gần nhất" cho phiếu chưa duyệt — UpdatePeBudgetPro/Ccm giữ nguyên không phase-guard).
- 2 terminal-guard block CẢ Admin: SetPeCcmBudgetPeriod + AdjustBudget → Conflict khi DaDuyet/TuChoi (đường chính thống: un-terminal → duyệt lại → re-snapshot overwrite).
- Backfill idempotent phiếu DaDuyet cũ = live hiện tại (số tại-thời-điểm-duyệt không khôi phục được — Changelogs attribution-gap); OUTER APPLY dịch đúng predicate PeBudgetAccumulator (3 bản khớp: SQL ↔ accumulator ↔ code gốc); demo-seeder DbInitializer cũng snapshot (fresh-DB gap — reviewer catch).
- PeBudgetAccumulator extract lũy kế behavior-preserving (dùng chung GetDetail live + helper snapshot); FE 2 app: types +budgetFrozen + PeDetailTabs badge khoá NS (SHA-mirror giữ, hash 2 app bằng nhau).
- Tests 509→520 (T0 reproduce RED→GREEN + T1-T9 + AdminOverride site-5); build slnx 0/0; npm build ×2 PASS; Mig applied 2 LocalDB (Dev catch-up cả Mig 66 lag).
- Pipeline S133: /fable-real invest (wf_348f6155) → spec → HMW Opus MAX (wf_d9639faa / wf_4bef08b8 / wf_75c6bfd3) → reviewer PASS_WITH_FIXES (wf_f9c0b939) → 2 SHOULD fixed. #53 return-fail ×3/5 lane — disk-truth recover 3/3, 0 mất việc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 11:14:25 +07:00
c2135bae2b [CLAUDE] Auth: PRO role giu quyen Master/NCC qua deploy (seeder chay-sau-revoke) + scope-isolation test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m33s
Van de (UAT anh Kiet FDC, S118): user tra.bui (Bui Le Thuy Tra, Procurement TP) dang nhap khong
thay menu quan ly NCC/Suppliers. Nguyen nhan: seeder S92 RevokeTemporarilyHiddenModulesAsync (chay
moi startup) set CanRead=false cho Master/Suppliers/Projects/Departments/Catalog* voi moi role
non-Admin ("chi Admin thay").

Fix (owner chot mo ngoai-le CHI role Procurement, ben qua deploy):
- Them SeedProcurementMasterAccessAsync chay NGAY SAU revoke de THANG (mirror pattern Hrm S65 /
  Office S69). Chi dung role Procurement -- S92 "chi Admin thay" GIU NGUYEN cho moi role khac.
- Grant 9 key: Suppliers (R+C+U -- quan ly + cong bo NCC, S113 publish can Suppliers.Update);
  Master/Projects/Departments/Catalogs + 4 Catalog leaf (Read-only). KHONG Delete.
- Dashboard/Reports CO Y KHONG cap (reviewer bat: Reports lo tong gia tri HD + top NCC/du an theo
  gia tri, nguoc S92; owner chot bo).
- Upgrade-only idempotent: nang co desired len true, khong ha co, khong dung role khac.

Test: +4 regression scope-isolation (ProcurementMasterAccessSeedTests) -- Procurement duoc nang
dung ma tran, role khac (DeptManager rieng) VAN bi revoke. 501 -> 505.

Reviewer PASS (scope cach-ly sach, no over-grant). Grant tam da ap prod (tra.bui verified 20 menu);
deploy nay = ban ben. Follow-up: gate ReportsController thieu policy (task rieng).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:29:44 +07:00
316a82f96d [CLAUDE] PurchaseEvaluation: endsBeforeCeo pointer-aware + duyệt theo khoảng Min–Max (Mig 66)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m26s
Hai chỉnh từ buổi UAT anh Kiệt FDC (S117):

1) Fix hiển thị lũy kế "duyệt rồi không bắt" — root cause là DISPLAY-LIE, không phải
   lũy kế bug. endsBeforeCeo cho phiếu CHƯA DaDuyet nay POINTER-AWARE: chỉ báo "kết
   thúc trước CEO" khi con-trỏ còn ở/trước cấp finalize. Phiếu đã đi QUA cấp finalize
   (approver bỏ tick "Cấp này KẾT THÚC" → trình tiếp CEO) → false: sơ đồ hết làm mờ
   Bước CEO + hết nói dối "Kết thúc tại Cấp X" khi phiếu đang chờ CEO. 3 site (detail
   in-memory + list/inbox EF-subquery). Filter lũy kế GIỮ nguyên (đúng nguyên tắc
   "duyệt rồi mới bắc"). BE-only — FE là consumer thuần nên tự render đúng.

2) Feature "duyệt theo KHOẢNG Min–Max": khi PRO có cả Min & Max, người duyệt cấp cuối
   chọn CẢ HAI (radio "PRO — cả Min và Max", source=ProMinMax) → Min ở ApprovedPriceAmount
   + Max ở ApprovedPriceMaxAmount (Mig 66 AddColumn nullable, no backfill, phiếu cũ
   nguyên vẹn). Bất-biến Max⟺ProMinMax, Min≤Max (guard ở service + validator). HĐ.GiaTri
   KHÔNG đọc giá chốt (= SUM báo giá NCC được chọn) → range thuần record-of-decision
   hiển thị, 0 tác động HĐ. FE 2-app SHA-mirror (Panel + DetailTabs).

Test 495 → 501 (+1 pointer-aware repro, +5 ProMinMax). Cả 2 điều tra qua /fable-real
engine-đắt (investigator-codebase deep-pass) theo yêu cầu anh Kiệt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 11:14:09 +07:00
88368fd87e [CLAUDE] PurchaseEvaluation: cho nhập giá ÂM ô báo giá hạng mục + submit-guard all-zero (S116)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m28s
Feature (anh Kiệt FDC ⇄ Duy Nguyen 2026-07-13): cho nhập SỐ ÂM ô "Số tiền báo giá
cho hạng mục" (Quote.ThanhTien) — âm = phát-sinh-giảm / hoàn-tiền của NCC = giá THẬT.
Nguyên-tắc "có giá là được": ≥1 giá thật (âm/dương) → gửi được; chỉ chưa-nhập-gì mới chặn.

FE (2 app byte-identical PeDetailTabs.tsx):
- Nút ± toggle 2 input quote (AddSupplierDialog + QuoteDialog), ghi giá-CÓ-DẤU thẳng vào
  form.thanhTien (2 dialog POST commit trực tiếp, không nút Lưu riêng → tránh mất-dấu thầm lặng).
- Submit gate + toast >0 → !==0. Ô ngân sách giữ ≥0 (không toggle).
- 2 FE submit-mirror (:201 missingForApproval + :235 submitChecklist) đổi từ SUM
  computeGiaChaoThau → helper hasRealSelectedQuote (iterate details[].quotes IsSelected≠0;
  SUM không phân-biệt all-zero vs net-zero).

BE (1 điều-kiện): PurchaseEvaluationWorkflowService.cs:206 selectedThanhTien.Sum()<=0
  → All(x=>x==0) — chặn chỉ khi TẤT CẢ selected=0. BE+DB nhận âm sẵn (0 validator,
  decimal(18,2), no CHECK, KHÔNG migration).

Owner-decisions: R1 cho Contract.GiaTri âm (no clamp) · R2 nới submit-guard · R-CEO
  giữ NET threshold (dòng âm có thể kéo dưới ngưỡng → CCM finalize, owner chấp nhận).

Tests +9 (486→495): ngân-sách-bất-biến · winnerQuoteTotal signed-sum · submit-guard
  all-zero/negative/net-zero · CCM-threshold net.

Pipeline S116: /fable-clone invest (4-lane) → owner-gate → /fable-clone review (3-lane)
  → /fable-real (Fable, #53 garble → em-main-solo gate GO-WITH-FIXES) → hmw implement (Opus MAX).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 17:08:34 +07:00
d436af2971 [CLAUDE] PurchaseEvaluation: multi-NCC per hạng mục — chọn ≥2 NCC-TP trúng thầu/1 hạng mục (mỗi nhà 1 giá riêng)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m17s
Đổi winner-truth từ whole-supplier Supplier.IsWinner (Mig 58 liên-danh) sang per-hạng-mục
Quote.IsSelected (Mig 12 dormant hook → nay nguồn-sự-thật); Supplier.IsWinner = DERIVED (== Any IsSelected).
Anh Kiệt LOCKED D1=SUM(IsSelected) · D2=THAY-THẾ · D3=giá-chào-gốc · D4=1HĐ/NCC. 0 bảng/cột mới.

BE:
- SelectWinnerCommand + POST /select-winner: body {supplierIds} → {detailId, supplierIds} (per hạng mục).
- Re-key 5 financial-SUM → WHERE IsSelected: winnerQuoteTotal, submit-guard, CCM-threshold, giaTri, budget-B.
- giaTri bỏ shortcut isSingle→detailsSum (single đổi budget→bid theo D4).
- Derive IsWinner invariant ở MỌI writer: SelectWinner + UpsertQuote + seed + DeleteQuote/DeleteDetail (helper PeWinnerInvariant, fix Bước 4).
- GIỮ IsWinner-derived cho winner-names/existence + CreateContract winners-list.
- Migration BackfillPeQuoteIsSelectedAndWinnerInvariant (data-only 2-chiều IsWinner↔IsSelected, Down no-op).

FE 2-app (PeDetailTabs SHA-identical): HangMucCard per-cell winner grid Detail×NCC + toggle per-detail; NccSelectorRow hạ-cấp read-only summary; giữ derived display.

Test: 7 file update + 8 test mới (per-hạng-mục total, giaTri single-partial, threshold-crossing, derive-invariant, delete-path). 486 PASS.

Flow: fable-clone invest ensemble → anh Kiệt 4-decision → fable-clone review ensemble (6 adjustment) → hmw implement (disk-recover #53) → fable-clone verify (bắt MUST bug delete-path → fix test-before).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 22:22:09 +07:00
5fa11b588a [CLAUDE] Supplier: import v2 — Mig 64 publish/draft + dedup-MST + template + file mẫu
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m14s
- Mig 64 AddSupplierPublishState: +IsPublic (draft/public); backfill 22 prod->public; filtered-unique doi [Code]<>'' (cho phep nhieu nhap Code=''); no new table (89).
- Import v2: dedup MST-primary + Code-backstop (chong 500 unique-violation); re-bake 30 token header THAT byte-exact (LayoutValid khop file that); nhap Ma NCC per-row (=Code); thieu Ma NCC->nhap (IsPublic=false); MST thieu->canh bao mem (MstMissing).
- PublishSupplierCommand rieng (ne #73 clobber); GET /suppliers/import/template (BE-gen xlsx 30-col).
- FE 2-app SHA-mirror: badge Public/Nhap; nut Cong bo; filter; nut Tai file mau; cot Ma editable; canh bao MST. Picker PE + tao HD loc published=true (an nhap -> ma HD khong dinh Code rong). CreateSupplier set IsPublic=true.
- authz D3: import/preview/confirm/template/publish = Policy Suppliers.Update (khop FE PermissionGuard, het 403).
- Tests +19 (477 PASS): dedup T1-T7, publish-guard, list-filter, all-or-nothing, LayoutValid. Fix null-Code NRE (path R4 loi).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 19:03:37 +07:00
e100ef065b [CLAUDE] Supplier: Excel-import Phase B (upload NCC preview/confirm) + Mig 63
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m25s
Import Excel 'Database NCC': upload→preview classify (New/Update/Skip/Error)→confirm all-or-nothing upsert-by-Code (OrdinalIgnoreCase dedup, fill-nulls-safe). Mig 63 +SourceUpdatedAt/By (2 nullable). Parser layout-locked header-fingerprint NFC-normalized + absolute-cell-index + #REF!-null + NAS-backslash-raw. Type-lạ→NhaCungCap. FE dialog fe-admin+fe-user byte-identical. 10 test SupplierExcelImportServiceTests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 16:13:46 +07:00
a829d0df99 [CLAUDE] PurchaseEvaluation: A1 người-tạo ký ô cấp mình + EDGE-5 khóa terminal + opinion-history
A1: ApplyDrafterBypassOnSubmitAsync bypass CHỈ NV cấp dưới creator (order<minOwn), creator ký tay ô mình qua ApproveV2Async (bỏ auto-ký-hộ), giữ skip-NV S60. EDGE-5: guard đầu TransitionAsync chặn non-admin transition từ DaDuyet/TuChoi (admin+system exempt). History: log ý-kiến cũ→PurchaseEvaluationChangelog trước ghi đè (no migration). Tests: 4 bypass→A1 + 8 mới (happy/non-contiguous/EDGE-5/history), 458 PASS. UAT: phiếu 1-bước creator-là-cấp-cuối nay cần bấm Duyệt (bỏ auto-terminal-on-submit, đúng bám-quy-trình).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 16:13:46 +07:00
778fc98b2f [CLAUDE] Supplier: Mig 62 expand 30-field + seed 4 NCC + FE form 2-app
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m7s
Phase A of the NCC/TP Excel-import backlog (anh Kiet FDC). Supplier
entity 9 -> 27 fields to hold the 30-column supplier database.

Backend:
- Supplier +18 nullable cols; SupplierType +CaHai=6 (append-only);
  new nullable SupplierStatus enum.
- Mig 62 ExpandSupplierFields (3-file): AddColumn x18 + guarded un-cram
  Sql (clear legacy crammed Note on the 4 seeded rows, exact-match).
  No new table (89), reversible Down.
- Seed fill-nulls-if-exists: populate 30 fields for TRUONGGIANG/TANPHU/
  TGN/DONGDUONG from Excel; idempotent, never clobbers existing cols.
- DTO + Create/Update commands + validators (MaximumLength-only, no
  NotEmpty so open-auth Create minimal payload stays valid) + 2 query
  projections.

Frontend (fe-admin + fe-user, byte-identical SHA-mirror):
- types/master.ts +18 fields +SupplierStatus; SuppliersPage form 4
  section groups + Status select + 3 NAS links via new shared PathLink
  (extracted from PE HoSoLink render+Copy). All new fields optional.

Excel upload auto-map = Phase B (deferred). Tests test-after (UAT mode).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 16:06:11 +07:00
fb2dfa9f7a [CLAUDE] PurchaseEvaluation: Mig 61 backfill EndedByLevelFinalize từ Changelogs (fix Mig 60 wrong-table) — phiếu finalize-CCM hết hiện sai "Đã được CEO duyệt" (anh Kiệt FDC UAT)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m12s
- Root-cause: Mig 60 backfill query PurchaseEvaluationApprovals cho marker "[Duyệt KẾT THÚC tại]", nhưng marker do LogTransitionAsync ghi vào PurchaseEvaluationChangelogs (approval-history là record riêng dòng :745) → match 0 dòng
- Phiếu finalize-sớm pre-Mig60 (PE/2026/A/005, A/008 — CCM Cấp 2 Phan Văn Chương duyệt-thay-CEO, KHÔNG qua CEO) giữ EndedByLevelFinalize=0 → endsBeforeCeo=False → badge SAI "Đã được CEO duyệt"
- Mig 61: backfill ĐÚNG bảng Changelogs (ContextNote LIKE N'%Duyệt KẾT THÚC tại%' + PhaseAtChange=7), idempotent, SQL-Server-only (tests SQLite no-replay)
- Verified prod: A/005/A/008 fin_marker=1 (finalize CCM) vs A/010 fin_marker=0 (CEO thật). gotcha #79

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:30:30 +07:00
8037fa01d1 [CLAUDE] PurchaseEvaluation: endsBeforeCeo theo RUNTIME (Mig 60 EndedByLevelFinalize) — phiếu lên CEO hết báo sai "không qua CEO" (anh Kiệt FDC UAT)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m21s
- Bug: phiếu có cấp AllowApproverFinalize nhưng approver opt-out → lên CEO thật + CEO duyệt, nhưng sơ đồ báo sai "kết thúc tại CCM, không qua CEO" + làm mờ Bước CEO (endsBeforeCeo tính theo CONFIG workflow)
- Fix: +field runtime EndedByLevelFinalize (set true CHỈ ở nhánh level-finalize service) → EndsBeforeCeo cho phiếu DaDuyet đọc runtime thay config; ChoDuyet giữ heads-up config
- BE: entity + EF config + service + 4 projection (detail/List/Inbox/ListApproved) runtime-aware
- Mig 60 AddPeEndedByLevelFinalize + backfill (dò marker "Duyệt KẾT THÚC tại" set phiếu finalize-sớm cũ; ccm-delegation không match → giữ false)
- FE: gate làm-mờ finalizeFlowStep theo endsBeforeCeo (2 app SHA-mirror b7abbc2f)
- Test 440 PASS (repro peFinButWentCeo: config-finalize + EndedByLevelFinalize=false → false) + reviewer PASS 0-issue

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 19:23:03 +07:00
36cbf8b1cc [CLAUDE] PurchaseEvaluation: mark-read noti "cần duyệt" cũ khi phiếu rời cấp (fix chuông stale — anh Kiệt FDC)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m3s
anh Kiệt "chuông không bỏ ra được" — noti "Phiếu cần bạn duyệt" của approver (kể cả CEO) KHÔNG tự xóa khi phiếu đã xong/chuyển bởi người khác (duyệt-thay tại Cấp CEO, co-approver OR-of-N, finalize) → chuông đầy phiếu thừa.

Fix: trong LogTransitionAsync (chạy MỌI transition), TRƯỚC block notify cấp mới → mark-read (ReadAt) tất cả noti Generic + RefId=phiếu còn unread. Phiếu rời cấp (finalize/advance/return/reject) → noti cũ tự sạch; approver cấp MỚI nhận noti fresh (tạo sau mark-read). Best-effort try/catch, V2-only, ExecuteUpdateAsync. KHÔNG đổi target (noti vẫn báo đúng lúc), chỉ thu-hồi khi stale.

Test: +test #7 (finalize → noti CEO cũ mark-read). 435→436 PASS. BE-only, no migration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:47:08 +07:00
e657faa74a [CLAUDE] PurchaseEvaluation: ô "Cấp này KẾT THÚC quy trình" → opt-out bỏ-tick-được (anh Kiệt FDC)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m12s
anh Kiệt UAT "cái này option thôi chứ e" — cấp cấu hình AllowApproverFinalize (Mig 58, S89 auto-finalize im lặng) NAY là ô-tích BỎ được:
- Default checked = giữ hành vi cũ (duyệt xong KẾT THÚC, không lên CEO) — backward-compat.
- BỎ tick (applyLevelFinalize=false) → KHÔNG finalize, trình tiếp CEO/cấp sau; giá chốt ẩn (CEO chọn sau).

BE: +param applyLevelFinalize (default true) xuyên interface → service (finalize guard `&& applyLevelFinalize`) → command → handler → controller body. FE: ô xanh static → checkbox 2 app (fe-admin+fe-user SHA-mirror) + hint động + sendPrice/shouldPickPrice gate theo cờ. Test: +test #6 opt-out→advance-to-CEO (spec change; #1-5 backward-compat giữ). Build slnx + 2 FE PASS 0-err; test 434→435.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:39:24 +07:00
ba4b8e0339 [CLAUDE] Infra: import NCC DONGDUONG (Excel anh Kiệt) + Supplier-field backlog
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m6s
- SeedRealMasterDataAsync +DONGDUONG (CP DV Công nghệ Đông Dương, NTP, gói Thang máy) = NCC thứ 4 từ Excel "Database NCC" anh Kiệt FDC 1/7; 3 NCC còn lại (TRUONGGIANG/TANPHU/TGN) đã seed sẵn S55/S59 → idempotent skip
- Scope option-3 (anh chốt): 9 field entity + gói extras (Loại/NĐD/TK/GUQ/Trạng thái) vào Note; KHÔNG migration (data-only ungated idempotent seed → prod)
- docs/STATUS: backlog "15-18 field note lại từ từ tính" (Supplier schema mở rộng khi anh chốt)
- Build slnx PASS 0 warn/err. Seed thẳng deploy (anh chốt).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 14:49:37 +07:00
1408d4eb03 [CLAUDE] Infra: ẩn 5 nhóm menu (Hợp đồng + Danh mục + HRM/Office/Cá nhân) chỉ Admin thấy trên eoffice (S92)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m24s
- RevokeTemporarilyHiddenModulesAsync mở rộng predicate: +Contracts/Ct_*
  +Master/Suppliers/Projects/Departments/Catalog* (cộng dồn S58 Hrm*/Off*/Personal).
- Tắt 2 re-grant public cũ: SeedAllRolesHrmProfileReadPermissions (S65) +
  SeedAllRolesOfficeModulePermissions (S69). Revoke là bước permission CUỐI trong
  SeedAdminPermissionsAsync (ungated) → durable, re-ẩn mỗi restart prod (gotcha #75).
- Thu hẹp InReviewScope → chỉ Pe_* (Duyệt NCC giữ nguyên cho user thường;
  master-data GET = any-auth nên form PE vẫn chọn được Dự án/NCC/Hạng mục dù menu ẩn).
- 2 method grant giữ private static (reversibility) → 2 seed test cũ vẫn invoke cô-lập, pass.
- +AdminOnlyModulesRevokeTests (3 test-before-merge, security): non-Admin revoked 4 cờ /
  Admin untouched / PE preserved. Test 431→434 PASS (45 Domain + 389 Infra).
- Reviewer PASS (5 attack vector: seed-order/under-revoke/over-revoke/test-genuine/prod-impact).
  FYI: role CatalogManager (0 user hiện tại) cũng bị thu Danh mục — intended-by-spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 14:58:59 +07:00
55494ad477 [CLAUDE] Infra: gate SeedDemoMasterData sau DemoSeed:Disabled (chống resurrect NCC demo go-live)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m10s
Sau wipe 18 NCC demo (scripts/s91-wipe-golive.sql, go-live anh Kiệt FDC 26/06), phát hiện
SeedDemoMasterDataAsync chạy UNGATED + per-code idempotent (skip-if-code-exists else Add) ->
mỗi restart / IIS recycle TỰ ADD lại 18 NCC demo (NCC-VLXD / CDT-VIN / Sun Group ...) ->
undo danh sách NCC sạch anh Kiệt vừa chốt.

Fix: gate SeedDemoMasterDataAsync (Supplier + Project DEMO) sau cờ DemoSeed:Disabled, mirror
cách Contracts/PE/Workflow demo đã gated. Prod hiệu lực Disabled=true (appsettings.json deployed;
appsettings.Production.json render từ .example KHÔNG có DemoSeed -> fallback appsettings.json=true,
đúng fallback đã giữ contracts/PE gated nhiều tháng). -> SKIP -> wipe BỀN qua restart. Dev
Disabled=false -> vẫn seed demo local. Master data THẬT (SeedRealMasterDataAsync: 62 dự án + 71
hạng mục + 3 NCC) ungated -> KHÔNG ảnh hưởng.

User test (38) đã an toàn từ S89 (gỡ khỏi mảng SeedDemoUsers). Build slnx OK 0 warn / 0 err.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 10:53:25 +07:00
681b1edc7e [CLAUDE] Infra · Scripts: xóa hết User test khỏi prod (38) + gỡ seed — chỉ giữ 17 User Solutions thật
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m51s
anh Kiệt FDC: "Xóa hết các User test ko liên quan, lấy User Solution thật vào".
Recon prod: 55 user → GIỮ 17 (admin + 16 real) → XÓA 38 (37 test rõ + 1 typo
chuong.phan@solution.com.vn — anh chốt xóa, anh Chương dùng bản @solutions).
An toàn FK: KHÔNG user test nào là ApproverUserId (NO_ACTION không bị chặn — recon verified);
5 bảng con CASCADE (EmployeeProfiles/UserRoles/Claims/Logins/Tokens); nv.test 1 PE loose-Guid xóa kèm.

- DbInitializer: gỡ 16 user mẫu khỏi SeedDemoUsersAsync + gỡ LockDemoSampleUsersAsync (call+method).
  Seed giờ chỉ tạo/reconcile 17 user thật. SeedItDepartmentStaff + sample-workflow seeds null-guard
  (skip user đã xóa) → deploy KHÔNG resurrect/crash. ⚠ PHẢI deploy để binary mới không tái tạo test.
- scripts/s89-delete-test-users.sql: whitelist-keep 17 + BACKUP + XACT_ABORT + count-guard[30,45].
  ĐÃ CHẠY prod (backup SolutionErp_S89_preuserdelete.bak): count=38, PE=1, còn đúng 17 user. Build slnx xanh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:25:00 +07:00
9b1ee0c3a5 [CLAUDE] PurchaseEvaluation: Section B (THỰC HIỆN) tách 3 cột per-cột kỳ-này (Mig 59, anh Kiệt FDC / CCM)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m8s
Section B "Tổng hợp ngân sách trình ký" tách 3 cột Dự án|PRO|CCM giống Section A —
mỗi cột nhập "NS kỳ này" RIÊNG + tính thực-hiện độc-lập (lũy-kế / còn-lại / % /
so-sánh) theo ngân-sách-full của cột đó:
- PRO: budgetPeriodAmount (có sẵn) đối chiếu proFull
- CCM: ccmBudgetPeriodAmount (MỚI, Mig 59) đối chiếu ccmFull — CCM nhập (canEditCcm)
- Dự án: — (chưa wire, như A)
Số thực-tế dùng chung mọi cột (NCC đề xuất, lũy kế lịch sử). Submit-guard giữ trên
budgetPeriodAmount (không đụng).

Mig 59 AddCcmBudgetPeriodToPurchaseEvaluation (1 cột nullable, no backfill). NEW
endpoint PATCH /budget/ccm-period role-gate Admin|CostControl (fail-closed). FE
Section B rewrite <BudgetRow> list -> <table> 3 cột (colCalc per-cột), 2 app SHA-mirror.
Test 395->402 (+7 authz setter). Build sạch BE + 2 FE. Workflow wf_aafb18fe-d9d
(BE->FE->test + 3-lane review: math PASS, authz PASS, mirror self-gated identical).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 16:06:59 +07:00
f1b10e9c33 [CLAUDE] PurchaseEvaluation: CCM 3-fix — multi-winner sum + budget=0 hợp lệ + cấp KẾT THÚC quy trình (Mig 58, anh Kiệt FDC)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m10s
CCM (Lưu Trần / anh Kiệt FDC) — làm 3/4 mục (mục 3 "CCM sửa ngân sách" để riêng):

1. Multi-winner: chọn NHIỀU NTP/NCC/ĐVDV cùng trúng → winnerQuoteTotal = SUM
   ThanhTien MỌI đơn vị isWinner (vd 3 ông 37.8+9+10 = 56.8tr). Cột mới
   PurchaseEvaluationSupplier.IsWinner (Mig 58, backfill từ SelectedSupplierId).
   SelectWinner → multi-toggle SupplierIds[]. FE: bảng so sánh tick nhiều ô +
   dòng "Tổng chi phí đã chọn"; mọi guard/checklist/computeGiaChaoThau/tạo-HĐ
   đổi sang isWinner (selectedSupplierId = null khi liên-danh ≥2).

2. Ngân sách = 0 hợp lệ: nới submit-guard + 3 validator (chỉ chặn khi NULL,
   số 0 cố ý đi qua; fallback ProInitial chỉ khi null). Mirror BE + FE.

3. Cấp KẾT THÚC quy trình: ApprovalWorkflowLevel.AllowApproverFinalize (Mig 58)
   — admin bật per-cấp trong Workflow Designer; duyệt tới cấp đó TỰ DaDuyet,
   bỏ qua CEO (AUTO theo cấu hình quy trình, không ô-tích runtime — anh Kiệt
   chốt). FE: banner cảnh báo + bắt chọn giá chốt.

Mig 58 AddPeMultiWinnerAndLevelFinalize (2 AddColumn bool + backfill IsWinner,
additive/reversible). Test 377→395 (+PeMultiWinnerTests +PeApproverFinalizeTests
+budget=0; auto-model gọn bớt 2 test bypass/opt-out). FE 2 app SHA-mirror.
Build sạch BE + 2 FE local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 15:22:35 +07:00
ae4f106fd7 [CLAUDE] PurchaseEvaluation: notify "cần duyệt" loại người tạo phiếu (anh Kiệt FDC UAT)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m57s
Người TẠO phiếu (drafter) không còn nhận chuông "Phiếu cần bạn duyệt" cho
phiếu mình tạo — kể cả khi được cấu hình làm approver ở một Cấp. Chỉ approver
KHÁC người tạo ở Cấp hiện tại mới nhận. Drafter vẫn nhận chuông KẾT-QUẢ
(đã duyệt / trả lại) như cũ (block :1060 giữ nguyên).

- PurchaseEvaluationWorkflowService.LogTransitionAsync: thêm filter
  `l.ApproverUserId != evaluation.DrafterUserId` (in-memory LINQ, nullable-safe).
- test-specialist: +3 regression PeApproverNotifyExcludesDrafterTests
  (drafter-excluded · co-approver-vẫn-nhận · result-notify-intact; RED-on-old
  đã chứng minh). Test 374 -> 377.
- docs/STATUS.md: re-ground canonical (S85-closeout sót: test 356->377,
  gotcha 71->73, bundle #341) + dòng S86 +3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:37:22 +07:00
a5e936fc0a [CLAUDE] PurchaseEvaluation: drafter tự gỡ cờ GẤP + ngân sách kỳ này tự nhảy từ ban-hành (anh Kiệt FDC UAT R2)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m46s
D2 — Người KHAI phiếu tự GỠ cờ GẤP của mình (nới luật S77 "GỠ=chỉ TP"). BE handler
restructure SET/UNSET: GẮN giữ role-only (PRO/CCM/Admin); GỠ +drafter (DrafterUserId==actor)
→ drafter/Admin clear CẢ 2 cờ, TP-vai clear cờ vai mình. FE canToggle +isDrafter.
D3 — "Ngân sách kỳ này" (row3) tự nhảy từ "Ngân sách Ban hành lần đầu"
(PeWorkItemBudget.ProInitialAmount) khi chưa nhập tay. Submit-guard BE + FE missingForApproval
dùng effective = budgetPeriodAmount ?? proInitialAmount (mirror 2 tầng, chống bypass gotcha #44).

BE 2 file (Urgent handler + Workflow submit-guard). FE PeDetailTabs ×2 app SHA-identical.
Test +5 PeUrgentToggleAuthzTests (drafter-self-unset authz matrix) → 371 PASS. BE slnx + 2 FE build PASS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:00:33 +07:00
fc1f19db8c [CLAUDE] PurchaseEvaluation: require quy trinh duyet V2 o create+submit (dong lo hong quy-trinh-cu)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m58s
Validator NotEmpty(ApprovalWorkflowId) + submit guard (sau Section-3, truoc mutate phase). Dong lo hong validate FE-only -> phieu null-workflow ket nhanh V1-legacy "quy trinh cu" (khong Buoc/Cap, khong route duyet). Test-before (RED confirmed): +2 validator test (PeWorkItemGuardTests) + rewrite test 7/13 PeSubmitGuardAndBypass (V1-submit deprecated, data V1 wipe S59). 356 pass (45D+311I).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 17:06:46 +07:00
424131d0b1 [CLAUDE] PurchaseEvaluation: chuong bao nguoi duyet khi phieu vao cap cua ho (submit + moi cap)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m48s
Tra Sol (Zalo): 'khong thay chuong bao - viec co ho so can duyet'. PE workflow truoc chi notify DRAFTER luc terminal; nguoi DUYET khong duoc bao khi phieu toi cap cua ho. Fix: block trong LogTransitionAsync (sau drafter-notify) - khi toPhase==ChoDuyet, resolve approver cap hien tai (workflow.Steps[CurrentWorkflowStepIndex].Levels Order==CurrentApprovalLevelOrder -> ApproverUserId OR-of-N, exclude actor) -> NotifyManyAsync Generic 'Phieu can ban duyet'. Fire moi luc phieu vao cap ChoDuyet: submit (cap 1) + moi approve-advance (cap ke) - 5 call-site advance deu log toPhase=ChoDuyet sau khi set pointer (verified). Best-effort try/catch (notify fail KHONG rollback transition). V2-only guard. Bell render Generic san (urgent->CEO da chung minh). BE-only, no-mig. Build slnx 0/0, test 354 PASS (khong vo transition cu). Notify = test-after (UAT).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:22:44 +07:00
94e0e12f77 [CLAUDE] PurchaseEvaluation: Mig 57 ghi chu gia de xuat PRO/CCM + so phan cach VND + sua chinh ta + guard #70
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m52s
Theo Tra Sol + anh Kiet FDC (Zalo): A) o nhap tien VndInlineEdit + BudgetCell nhay phan cach vi-VN (300.000.000) on-keystroke (o dialog da co san). B) them o ghi chu PRO + CCM canh nut Luu trong khoi Gia de xuat (giai thich vi sao chon Min/Max) — Mig 57 AddPeSuggestedPriceNotes (+ProSuggestedPriceNote +CcmSuggestedPriceNote nvarchar(1000) null, additive no-backfill no-table); 2 setter command +Note absolute-set rides role-gate PRO/CCM/Admin; DTO +2 field; controller body +note. C) sua chinh ta 'd. Ban so sanh' -> 'd. Bang so sanh gia' (2 app). GUARD gotcha #70: o gia + ghi chu echo nhau absolute-set -> them peFetching khoa nut Luu toi khi pe-detail refetch land, tranh stale-echo mat du lieu (mirror bang ngan sach S76; em-main review bat impl-frontend sot guard). BE slnx 0-warn 0-err; FE build PASS x2; test 344->351 (+7); PeDetailTabs/PeWorkspaceCreateView 2 app SHA256-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:08:45 +07:00
e33481efb6 [CLAUDE] PurchaseEvaluation: Mig 56 ngan sach MA TRAN 3 cot (Du an|PRO|CCM) + badge quyen NS theo role
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m57s
S76 (anh Kiet FDC + chi Tra Sol) — form ngan sach + hien thi quyen nhap NS trong flow:
- Part 1: form ngan sach -> MA TRAN 3 cot, moi phong nhap+dieu chinh cot minh
  (PRO canEditPro / CCM canEditCcm / Du an FE hien-thi-only). Mig 56
  +ProInitialAmount/ProAdjustmentAmount (additive-nullable + data-migrate
  ProEstimate->ProInitial). full moi cot = ban hanh + hieu chinh.
- Part 2: Workflow Designer (fe-admin) +badge "NS PRO/CCM" canh approver
  (suy tu role Admin|Procurement / Admin|CostControl, hien-thi-only no-authz).
- Part 3: flow quy trinh fe-user/fe-admin (Duyet NCC) +badge tuong tu.
- Fix race mat-du-lieu Part 1 (useIsFetching khoa Luu khi refetch — dong
  cua-so stale-echo, reviewer Part2/3 bat).
- Test 339->344 (+5). 2 workflow review (Part 1 PASS + Part 2/3 PASS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:02:47 +07:00
8655ebf1ba [CLAUDE] PurchaseEvaluation: Mig 55 ô "Ghi chú từ CCM" ngân sách gói thầu — CCM nhập số + ghi lý do giống PRO
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m54s
- Entity PeWorkItemBudget +CcmNote (mirror ProNote, nvarchar 1000) + Mig 55 additive-nullable
- UpdatePeBudgetCcmCommand +CcmNote absolute-set, role-gate CostControl/Admin fail-closed
- DTO PeBudgetSummaryDto +CcmNote + controller BudgetCcmBody + GET mapping
- FE 2 app SHA-mirror: dòng "Ghi chú từ CCM" gate canEditCcm (sau V0/hiệu chỉnh), absolute-set đủ 3 field
- Test +5 (set CCM/Admin, null-clear, non-priv Forbidden, all-3-persist) -> 339 pass

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:05:10 +07:00
1d86abcdc5 [CLAUDE] PurchaseEvaluation: Mig 54 giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m22s
Theo note anh Kiệt FDC (go-live so-sánh-giá thứ Hai):
- (1) Giá chào thầu thêm giá đề xuất NGOÀI giá NCC: PRO nhập dải Min/Max +
  CCM nhập 1 giá (2 lệnh role-gate Procurement/CostControl, fail-closed).
  Khi duyệt cấp cuối, người duyệt CHỌN 1 giá chốt (Ncc/ProMin/ProMax/Ccm)
  -> luu ApprovedPriceAmount/Source (bind tai moi nhanh DaDuyet, bat buoc
  chon; auto-approve he thong mien).
- (3) CCM duyet-done mien CEO: DOI tu AUTO-threshold (S69) sang O-TICH-TAY
  (finalizeByCcmDelegation) -- CCM chu dong tich, fail-closed theo nguong
  + role + gia goi. An toan hon (khong vo tinh bo CEO).
- Mig 54 additive-nullable (5 cot PE) - FE 2 app SHA-mirror - test 306->334
  (+28: opt-in 6->11, +10 gia chot, +13 setter authz).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:51:39 +07:00
ebd7e1c42f [CLAUDE] PurchaseEvaluation: cờ gấp PRO/CCM + CCM duyệt-final theo ngưỡng giá trị (Mig 53) + 14 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m41s
Yêu cầu anh Kiệt FDC (sau họp sếp). Mig 53 AddPeUrgentAndCeoApprovalThreshold — 3 AddColumn, no new table (Mig 52→53). Rollout an toàn: cột nullable, ngưỡng null = giữ luồng duyệt cũ 100% cho tới khi admin set.

B — CCM duyệt-final theo NGƯỠNG GIÁ TRỊ ("gói CEO phân quyền theo giá trị"):
- ApprovalWorkflow += CeoApprovalThreshold (decimal?, admin nhập trong Workflow Designer).
- ApproveV2Async: actor role CostControl (CCM) + winnerQuoteTotal (tổng giá NCC được chọn) < ngưỡng → DaDuyet luôn (bỏ CEO); ≥ ngưỡng → đẩy lên CEO như cũ. Ngưỡng null = luồng tuyến tính cũ. Q4 chốt nhận diện theo ROLE người duyệt.
- reviewer PASS 0 blocker: cascade-safe (Off/role không lan), tested load-bearing (CCM dưới ngưỡng → DaDuyet skip CEO).

A — cờ gấp per-vai (visibility-only, Q3 KHÔNG đổi luồng):
- PE += IsUrgentByPro (PRO đỏ) / IsUrgentByCcm (CCM xanh).
- Endpoint PUT /purchase-evaluations/{id}/urgent role-gated (Procurement→ByPro, CostControl→ByCcm, Admin→cả 2, khác→Forbidden) + notify CEO (Director) khi MỚI bật (best-effort).

FE ×2 app: Workflow Designer ô "Ngưỡng giá trị gói CEO" (fe-admin) + PE detail nút bật/tắt cờ gấp đỏ/xanh theo role + badge GẤP + hint "giá trị gói vs ngưỡng → CCM duyệt-final/cần CEO" + PE list badge gấp.
DTO: PE detail += isUrgentByPro/Ccm + winnerQuoteTotal + ceoApprovalThreshold; list += isUrgentByPro/Ccm; workflow V2 += ceoApprovalThreshold.

+14 test (292→306): PeCcmThresholdFinalizeTests 5 (B routing) + PeUrgentToggleAuthzTests 9 (A authz). Build slnx 0/0 · npm build ×2 0 err · dotnet test 306 PASS.

C (sau duyệt xong chuyển phiếu đến dự án) — chờ anh Kiệt làm chi tiết form, CHƯA làm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:27:50 +07:00
1f8947e763 [CLAUDE] Auth: golive Văn phòng số — public Read+Create module Office cho mọi role (allow-list 16 key) + 6 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
Anh chốt "public văn phòng số cho all user eoffice". Mở quyền Xem + Tạo (self-service) module Office cho mọi role trên cả 2 app.

- NEW SeedAllRolesOfficeModulePermissionsAsync (DbInitializer): grant CanRead+CanCreate=true cho allow-list 16 key Office, chạy SAU RevokeTemporarilyHiddenModulesAsync để THẮNG revoke (mirror đúng pattern S65 HRM public). Upgrade-only: nâng false→true trên row prod đã có, KHÔNG hạ, KHÔNG đụng CanUpdate/CanDelete. No migration (seed-logic, idempotent).
- ALLOW-LIST 16: Off + Off_Dashboard + Off_DanhBa + Off_PhongHop(View/Book) + Off_DeXuat(List/Create/Inbox) + Off_DonTu(Leave/Ot/Travel) + Off_DatXe + Off_ItTicket.
- GIỮ ẨN (ngoài allow-list → revoke vẫn che non-Admin): Off_PhongHop_Manage (admin CRUD phòng), Off_AttendanceReport (báo cáo chấm công — riêng tư), Off_ChamCong (Cá nhân — golive riêng). HRM (trừ Hồ sơ NS S65) + Personal VẪN ẩn (anh chỉ mở Office).
- reviewer PASS 0 blocker (security): cascade-safe (Off KHÔNG phải inherit-root trong GetMyMenuTree → excluded-3 giữ false, không lan); KHÔNG mở write-path thật (Office controller dùng [Authorize] self-service + [Authorize(Roles=Admin)] cho admin-write — CanCreate chỉ mở menu + nút tạo FE, API authz độc lập menu key; quản lý phòng double-protected).
- +6 test OfficeModulePermissionSeedTests (286→292) lock: allow-list read+create=true · excluded-3 stay hidden (load-bearing) · admin not demoted · no-leak HRM/Personal · upgrade-only preserves admin-raised Update/Delete.
- Build slnx 0/0 · dotnet test 292 PASS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:33:32 +07:00
a8bbdaeeea [CLAUDE] FE: Văn phòng số foundation — shared PageHeader/KpiCard/WidgetCard + Dashboard landing (PURO · CSS Hồ sơ NS) + sync fe-admin index.css + menu Off_Dashboard
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m41s
- 3 shared component PageHeader/KpiCard/WidgetCard ×2 app SHA256-identical; tái dùng token Hồ sơ NS (.app-gradient-brand/.card-accent/.icon-chip/.stat-value/.label-eyebrow + accent palette teal/violet/amberx/greenx); gotcha #66 text-white! trên gradient header.
- OfficeDashboardPage 2-cột widget kiểu PURO HomePage: Đề xuất/Đơn từ/Ticket/Phòng họp hôm nay + "Công việc của tôi" + Thao tác nhanh. Reuse query endpoint sẵn có (shared TanStack cache, KHÔNG BE/API mới), đếm client-side, loading/error/empty mỗi widget.
- Sync fe-admin/src/index.css ← fe-user (đóng drift S66-S68: heading 600→700, ink #0f172a→#0b1220, label-eyebrow slate→brand-600 + rule gotcha #66). Nay 2 app đồng bộ.
- Menu key Off_Dashboard (MenuKeys.cs const + All[] + DbInitializer seed Order 0 dưới Off) — no migration, idempotent. GIỮ ẨN non-Admin (RevokeTemporarilyHiddenModules StartsWith Off). Chưa golive.
- Wire 4-place ×2 app: App.tsx route /office/dashboard + menuKeys.ts + Layout staticMap.
- Fix KpiCard activeBorder -300 → -500 (accent palette chỉ 50/100/500/600/700 — chống "vỡ màu im lặng" Tailwind v4: border-teal-300 rơi default Tailwind, border-amberx-300 drop hẳn).
- Build PASS x2 (fe-user index-DrxDysO7 / fe-admin index-TbkadgKd) + dotnet slnx 0/0. reviewer PASS 0 blocker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 09:24:17 +07:00
5a0aaa4e83 [CLAUDE] PurchaseEvaluation: +mục E "Link hồ sơ" (hyperlink NAS) + rename "Dự trù PRO"->"Ngân sách PRO"
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m25s
Anh Kiệt (FDC UAT): (1) thêm mục "e. Link hồ sơ" dưới mục "d. Bản so sánh" — 1 ô dán
hyperlink tới thư mục hồ sơ trên NAS công ty, hiện dạng <a> bấm-mở (target _blank rel
noopener noreferrer), null-safe; (2) đổi nhãn "Dự trù PRO"->"Ngân sách PRO" (cả badge
+ row label; GIỮ "Ghi chú từ PRO" + field-code/biến).
- BE: PurchaseEvaluation +HoSoLink string? (Mig AddHoSoLinkToPurchaseEvaluation —
  nvarchar(1000) nullable, no new table, Down reversible) + Create/Update command
  (+trailing optional =null -> backward-compat, 0 call-site break) + Detail DTO + projection.
  Build slnx PASS.
- FE x2 app SHA256 mirror (PeDetailTabs + PeWorkspaceCreateView): mục E input/hyperlink +
  rename. types +hoSoLink.
Workflow fan-out (BE song song FE -> review); FE+reviewer return-rỗng -> em main recover
disk + build-verify x3 + self-gate (bắt badge sót rename).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:13:39 +07:00
0f44d9754d [CLAUDE] Infra: phân cấp phòng ban (Department.ParentId) + /tree + gán phòng cha
Nền cây tổ chức cho trang Hồ sơ Nhân sự (anh: bố trí giống NamGroup; chốt phân
cấp thật + tự gán phòng cha trong quản lý phòng ban).
- Mig AddDepartmentParentId: +ParentId Guid? loose-Guid (no FK vật lý, convention
  PE) + IX_Departments_ParentId. AddColumn+CreateIndex, no new table, Down reversible
  (DropIndex->DropColumn). Chưa apply (CI/prod seed apply).
- GET /api/departments/tree: ráp cây in-memory + đếm NV active theo User.DepartmentId
  (EmployeeProfile KHÔNG có DepartmentId — link qua User, field phòng ban ở User Mig 11)
  + rollup TotalEmployeeCount + cycle-guard HashSet. Authz = class [Authorize] (= GET list).
- Create/Update +ParentId (write vẫn khóa Admin,CatalogManager). Update có cycle-guard:
  chặn tự-làm-cha + đi ngược chuỗi cha gặp lại Id (chống vòng A->B->A).
Build PASS (0 warn/err full solution). Test-after (test-specialist).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:34:52 +07:00
4004481989 [CLAUDE] Auth: public module Nhân sự (Hồ sơ NS) read-only cho mọi role
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m40s
Anh user yêu cầu public module Nhân sự cho user thường tra cứu hồ sơ.
Thêm SeedAllRolesHrmProfileReadPermissionsAsync (DbInitializer) grant
CanRead cho Hrm + Hrm_HoSo cho 13 role, chạy SAU RevokeTemporarilyHiddenModulesAsync
(S58) để thắng revoke. Upgrade-only (nâng false→true trên row prod đã tồn
tại, mirror Pe S57bis :2107) — không NO-OP im lặng. Read-only: chỉ CanRead;
Create/Update/Delete vẫn khóa qua policy controller. Giữ ẩn Dashboard NS +
Hrm_Config*. Migration-free, idempotent. Reviewer PASS 7/7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 09:51:49 +07:00
79ef8da9f4 [CLAUDE] PurchaseEvaluation: ngan sach goi thau theo Excel anh Kiet - bang tong hop 2 block + nhap theo role PRO/CCM + xoa module Budget cu (Mig 50)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m31s
- Mig 50 ReplaceBudgetModuleWithPeWorkItemBudgets: bang moi PeWorkItemBudgets (1 record/cap Du an x Hang muc, UNIQUE filtered [IsDeleted]=0) + drop 5 bang Budget cu + PE/Contracts drop BudgetId + backfill BudgetManualAmount->BudgetPeriodAmount TRUOC DropColumn (phieu UAT giu so) + DELETE menu/permission Bg_* IN-list children-first
- BE: PUT {id}/budget/pro (role Procurement) + {id}/budget/ccm (role CostControl, Adjustment cho phep AM) fail-closed Forbidden-truoc-side-effect + EnsureTrackedAsync race-safe (catch unique -> re-fetch winner, loi khac rethrow) + auto-create record khi tao phieu + budgetSummary DTO (luy ke trinh-truoc/chon-thau-truoc/de-xuat-ky-nay + full fallback du-tru-PRO + canEdit flags) + submit-guard (3) doi predicate BudgetPeriodAmount -> "chua nhap Ngan sach ky nay" + PATCH budget-adjust absolute-set 2 field moi + Contract GIU BudgetManual* (HD nhap tay khong doi) + ke thua HD map BudgetPeriodAmount
- FE x2 app SHA256 identical: bang "TONG HOP NGAN SACH TRINH KY" block A (full dam + ban hanh + V0 hieu chinh + du tru PRO + ghi chu, editable theo canEditPro/canEditCcm) + block B 9 dong cong thuc Excel (5=1+3, 6=2+4, 7=full-5, 8 tu nhap default 7, 9=4+8) + to mau vuot ngan sach #C00000 / am do / red-soft row8>row7 + "Chua chon" khi count=0 + banner phieu chua gan Hang muc + o "Ngan sach ky nay" o create/header + XOA pages/components/types budgets + routes + menuKeys + Layout staticMap 4-place
- Tests: +22 PeWorkItemBudgetTests (auto-create x3, ensure/race x2, authz matrix PRO x5 + CCM x3, budgetSummary aggregates x5, adjust x4) - 14 BudgetPolicyTests xoa theo module - 1 test via-BudgetId -> 263 PASS (45 Domain + 218 Infra, 0 fail)
- database-agent advise adopted: khong FK vat ly PE/Contracts->Budgets (DropColumn khong can DropForeignKey) + DropIndex truoc DropColumn (SQL 5074) + IN-list thay LIKE Bg_% (underscore wildcard + miss root) + khong Serializable wrap (nested-tx conflict codegen)
- Reviewer PASS-with-minor 0 blocker (verdict-first survived); 2 minor da sua truoc commit (comment adjustMut absolute-set + dead key budgetId); note: F4 approver-edit-budget UI entry tam drafter-only, BE van cho approver scope - cho UAT anh Kiet
- Scaffold-bug caught: EF tu sinh RenameColumn BudgetManualAmount->ExpectedRemainingAmount (SAI semantics) -> thay bang Add+UPDATE+Drop

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 01:07:27 +07:00
6db195dd42 [CLAUDE] PurchaseEvaluation: go han hanh dong "Tu choi" - chi con Duyet hoac Tra lai (UAT anh Kiet S60 14:14)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m30s
- Domain policy: xoa MOI transition -> TuChoi o ca 4 policy (NccOnly + NccWithPlan + ForV2Schema + FromDefinition) -> NextPhases het tra TuChoi, nut FE tu bien mat
- Service guard S60: chan targetPhase=TuChoi moi caller ke ca Admin (dung truoc moi branch — spec bo han, khong escape hatch); message huong dan dung Tra lai / Xoa nhap
- FE x2 app: filter phong thu next.filter(p != TuChoi) PeWorkflowPanel (SHA256 identical); dialog/isCancel giu dead-safe de flip lai de
- Enum TuChoi + phieu TuChoi cu + tab filter "Tu choi" GIU display (data cu render binh thuong)
- SlaExpiryJob chi dung Contract — PE khong auto-TuChoi, khong anh huong
- Tests spec-change cung commit: Domain flip BothPolicies_TuChoi_RemovedFromAllTransitions_S60 + NEW V2SchemaPolicy fact; Infra NEW TargetTuChoi_WithRejectDecision_Throws_TuChoiRemoved_S60 (guard #45 test cu giu nguyen PASS — van dung truoc)
- Test 254 -> 256 PASS (59 Domain + 197 Infra)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:30:38 +07:00
37122f0f64 [CLAUDE] PurchaseEvaluation: rang buoc du 4 thong tin muc 3 moi gui duyet + bypass nguoi soan trong chuoi duyet (UAT anh Kiet S60)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m38s
- Rename muc 3: "Chon NCC / TP thang thau" -> "Don vi NCC/TP duoc chon" (anh Kiet chot chu) x2 app + wording phu nhat quan
- Guard gui duyet du CA 4 (anh chot): don vi duoc chon + gia chao thau >0 + ngan sach (Budget link HOAC nhap tay) + bang so sanh dinh kem
  + BE ConflictException gop moi muc thieu 1 lan, ap ca Admin (TransitionAsync submit branch)
  + FE pre-check missingForApproval cung predicate -> disable nut + tooltip liet ke du (computeGiaChaoThau extract single-source)
- Bypass drafter-in-chain (luat GENERIC theo cap, anh chot): V2-only, BUOC DAU only - nguoi soan la approver cap k -> auto qua Cap 1..k khi gui
  + Audit 3 tang: Approval row AutoApprove per cap + LevelOpinion CHI slot chinh chu (khong gan chu ky NV bi skip) + Changelog
  + Pointer: k<max -> Cap k+1; het buoc -> Buoc 2 Cap 1; workflow 1 buoc -> terminal DaDuyet
  + TraLai resubmit ap lai idempotent (opinion UPSERT)
- Tests: +14 PeSubmitGuardAndBypassTests (240 -> 254 PASS)
- Reviewer die mid-run (gotcha #53 class) -> em main self-gate evidence-checklist PASS 0 blocker

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 11:53:50 +07:00
c869d2617d [CLAUDE] PurchaseEvaluation: rename 71 WorkItems theo format PMH anh Kiet FDC chot (MAT-n/SUB-n/MEP-SUB-n/MEP-EQU-n + ten "STT nhom ten") + FE sort numeric
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
- anh Kiet 16:59: "MA CV gom chu MEP-SUB-1 roi ten 1 MEP Sub MEP (Full) - dung kieu vay".
- DbInitializer seed tuples 71 ma moi (VT->MAT, TP->SUB, MEP-0n->MEP-SUB-n, TB->MEP-EQU-n).
- scripts/s59-rename-workitems-pmh.sql DA CHAY prod + LocalDB Dev TRUOC push (UPDATE giu Id,
  71/71, OLD-CODES=0, verify JSON qua API prod tieng Viet nguyen ven).
- FE x2 app (SHA256 mirror): PeWorkspaceCreateView + PeHeaderForm sort numeric-aware
  (ma khong pad -> string-sort loan "10"<"2") + tree Panel 1 workItemName numeric:true.
- scripts/master-import-data.generated.md sync 71 dong W| + note mapping.
2026-06-11 17:14:06 +07:00
bbd1554f74 [CLAUDE] Infra: WorkItems chi giu dung 71 ma PMH cong ty gui (chi Tra Sol chot) - go seed 15 demo + wipe prod 86->71
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m31s
- DbInitializer: XOA block seed 15 WorkItems demo (Phan tho/Hoan thien/Co dien/Khac
  - DAO-MONG, SON-NUOC, TRAT-TUONG... "ma anh tu de ra") -> nguon duy nhat =
  SeedRealMasterDataAsync 71 ma PMH (VT-01..16 + TP-01..30 + MEP-01..09 + TB-01..16).
- scripts/s59-wipe-demo-workitems.sql DA CHAY prod + LocalDB Dev: 86 -> 71,
  demo categories bien mat, doi chieu 71/71 khop bang PMH cong ty gui tung dong.
- An toan: PE=0 (Run #273 wipe) -> khong phieu nao tro WorkItemId demo.
2026-06-11 16:56:46 +07:00