Commit Graph

114 Commits

Author SHA1 Message Date
530af22910 [CLAUDE] Contract: KHKK man duyet — bo "(N dong)" + cot STT + ma hang muc (Mig 72)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 7m2s
Anh giao qua anh prod man duyet KHKK, 2 diem khoanh do:
 (1) "Bo 1 dong di nhe" -> go hau to "(N dong)" khoi title Section 2.
 (2) "Hien thi stt va ma hang muc (Du an) - ma hang muc chi tiet"
     -> bang 3->4 cot (+STT cot rieng, anh chot), cot HANG MUC them dong
        ma "<ma du an> - <ma chi tiet>" nam TREN ten.

Mig 72 AddMaHangMucToContractSigningPlanLines (anh chot DENORM co migration):
 - +cot MaHangMuc nvarchar(20) = BANG nguon ContractCatalogEntry.Code.
 - backfill Sql() idempotent (WHERE MaHangMuc IS NULL), COY KHONG loc IsDeleted:
   hang muc xoa mem SAU ngay lap phieu thi dong phieu van phai giu duoc ma —
   do chinh la ly do cot nay la denorm. Loc di la bo trong dung dong can cuu nhat.
 - ten bang doi chieu voi ToTable() cua CA HAI configuration truoc khi viet
   (Mig 60 tung backfill soi NHAM BANG, chay sach, phai de Mig 61 va — gotcha #78/#79).

PeWorkItemCode KHONG denorm — noi join WorkItems san co o Features.cs:929, 0 cot moi.
Chup lai vao KHKK la chup mot thu von da la con tro loose-Guid qua PE (Mig 49).

3 write-site denorm sua DU: :527 moi null · :695 gan lai · :805 tao moi.
Sot 1 cho = de dong co ten ma khong co ma, chi lo ra o luong it ai bam.

FE 2 app SHA IDENTICAL (verify identical @HEAD TRUOC khi copy de).
Build BE 0 warning 0 error · 2 app build sach · 644/644 test pass.
Lint 42 van de = NO CO SAN, 0 cai o 2 file luot nay dung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 14:47:08 +07:00
aaed699228 [CLAUDE] Contract: K7 SP-002 bridge KHKK->HD hoi-2-khoa + Line.ContractId + grant seeder (gate PASS-WITH-FLAGS 10, F-8 fixed)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
BE: POST {id}/create-contract (Contracts.Create AND KeHoachKyKet.Read) + guard 4-ve IsActive/IsUserSelectable
+ Line.ContractId write-site DAU TIEN + list-DTO ContractIds + SeedContractCreateAccessAsync (Drafter/
Procurement/Admin upgrade-only, cau III default cho ratify). FE x2 app SHA-pair 3/3: nut bridge gate 2-khoa
+ dialog khuon-san + cay GD3/GD4 doc TAP contractIds (union pe.contractId legacy). Test +17 (12 bridge T1-T12
+ 5 authz) suite 639/0; ngoai-le CreateContract trong AuthorizePolicyRegressionTests (#85).
Gate F-8 fixed truoc commit: neo so-dong :2516 chet-luc-land -> neo ten ham (3 cho) + 13/13->12/13 theo do
prod + khai chu-dich CanRead + sua tro-nham-ham. No mang theo (0-blocker): MAJOR-race-2-request-dong-thoi
(chong-trung in-memory, phuong an unique/RowVersion = nhip sau) + DraftData-khong-carry + a11y/O(n.m) FE.
UAT-NOI-TRUOC: nut sang sau restart + user RE-LOGIN (menu cache); acceptance seeder log = 0 added + 2 upgraded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 13:04:49 +07:00
88e7ecf263 [CLAUDE] Contract: K4a+K4b SP-002 sidebar 8 nhom x 6 leaf + noi ?group= end-to-end (0-mig)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m23s
K4a (gate PASS-WITH-FLAGS 4, sub-reviewer-gate-k4a.md): 49 key Khkk_G{2-8} bo-sinh
by-construction 3-phia (All/seed/grant) MenuKeys.cs + DbInitializer 49 row + labelBackfill
G1 nhan A1 + site-2 Concat + va 7/10/11/13/15 (nhan N2 co "pha do"; comment 1893 -> mo-neo
grep). All 64->113, Policies 256->452 (test T2 khoa runtime). Test +7 KhkkGroupMenuSeedTests
(T7 revoker-khong-dung-Khkk: probe vi-phan 112->0, gotcha #84).

K4b (gate PASS-WITH-FLAGS 4M/5m 0-chan, sub-reviewer-gate-k4b.md): KhkkListPage x2 derive
phase+group tu searchParams (leaf->leaf khong F5, navKey reset) + queryKey {group,phase,
search,page,deletedView} + KhkkCreatePage preset ?group= + staticMap G1 6-leaf group=1 +
regex Khkk_G([1-8])_* fe-user (fe-admin GHI RANG BUOC isAdminHidden) + FLAG-1 lead-fix:
GET /deleted +group mirror List (Controller+Query+handler SAU-IDOR) + FE noi 2-nhanh.

2 wave 1 commit CO KHAI: Layout.tsx dinh ca 2 wave khong tach hunk phi-tuong-tac; moi dong
deu qua gate rieng. STATUS canonical 5-row dong bo (71/97/452/113/620->621) + bundle :479.
No K4c: MAJOR-A test /deleted+group filter + MAJOR-C WfView doc group. Suite 621/0
(45D+576I) + filter 41/41 + npm x2 + dotnet 0E.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 10:10:11 +07:00
15349e8ee0 [CLAUDE] Contract: K3 SP-002 8 workflow nhom KHKK-N1-8 + port level-finalize + designer (0-mig) + 5 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m10s
Seed 8 workflow type-10 theo ROSTER LIVE prod (QT-DN-V2-001, lead verify tay
@SQLEXPRESS: 3 tram PRO->CCM->CEO, 11 nguoi, resolve EMAIL, idempotent per-Code;
co Finalize CHI cap chuong.phan). Port nhanh level-finalize mirror PE :866-876
(EndedByLevelFinalize K2-de-K3-tieu + ApplyApprovedValuesOnFinalize truoc Phase;
opt-out applyLevelFinalize 3-tang interface/service/controller, default true).
Sweep ep-false va-3: GO CREATE ep-false Finalize type-10 (OG-9 supersede PHA-VO
S155); GIU PUT-Conflict (luat versioning CHUNG - spec liet nham, khai lech);
GIU ep-false SkipToFinal type-10 (K3-test O-1 chong config-lie mới) + FE disable
o SkipToFinal cho KHKK (gate-K3 F-2). Rao (v) pin-dung-nhom regex KHKK-N[1-8].
+8 MenuKeys AwV2_KhkkN* (All 56->64, policies 224->256 may-dem) + 8 menu-row +
resolvePath fe-admin phep-am Khkk_ 0-hit. 5 test K3 (T-a..T-e, anti-tautology).
Gate K3 PASS-WITH-FLAGS 8f/0-blocker (sub-reviewer-gate-k3.md): F-1 checkbox
opt-out man duyet = KHAI HANDOFF dau-viec-#1 lan sau (tram CEO tam thoi qua
Designer bo co); F-2 va; F-3 dong truoc do. Suite 614/0 (45D+569I). K3-BE 2 luot
engine-exit -> che nho + lead-solo (bai: task-hep-Write-som song).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 18:21:39 +07:00
0779f2d45a [CLAUDE] Contract: K2 SP-002 phieu KHKK mang hang-muc + nhom duyet N1-8 (Mig 71) + FE x2 app + 11 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m12s
Mig 71 AddKhkkApprovalGroupCatalogAndFinalizeRuntime: +ApprovalGroup (backfill=1)
+EndedByLevelFinalize (K2 de, K3 tieu - ghost-window khai) + Line +CatalogEntryId/
TenHangMuc + unique (Plan,Supplier,CatalogEntry) filtered IsDeleted=0. Rao
1-PE-1-phieu doi (PeId,ApprovalGroup) 2 site + picker OG-7 ExistingGroups + nut
'Tao them cho nhom khac'. Submit-guard va-5 (CHAN null, thang nen cho-qua-legacy;
ghost-window K2->K4b khai) + dem-so-khop (gate F-1: bit duong hang-muc xoa-mem).
List ?group= end-to-end + Tong-Approved list (va-8). FE: select nhom default 1 +
badge N{g} + cot Hang-muc + cot Tong-duyet, SHA-pair 5/5. Gate K2 PASS-WITH-FLAGS
10f: F-1 guard fix + 2 test bit (xoa-mem chan + reflection ?group=); F-2/F-5/F-7/
F-8/F-9 comment-honest; F-3/F-4 docs-delta. Suite 609/0 (45D+564I). Wave co #53 x5,
artifact + relaunch-cat-got cuu 100% (0 mat cong).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 17:05:27 +07:00
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
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
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
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
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
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
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
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
6c5fd26428 [CLAUDE] Infra: tạm ẩn HRM/Văn phòng số/Cá nhân khỏi user thường + Danh mục xuống cuối sidebar (S58)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
Anh yêu cầu (screenshot eoffice): ẩn các tính năng chưa golive + thu hồi
phân quyền user thường; nhóm Danh mục đưa xuống cuối.

- NEW RevokeTemporarilyHiddenModulesAsync (chạy cuối seed pipeline): set 4 cờ
  CRUD=false cho MỌI role TRỪ Admin trên keys Hrm* (gồm Hrm_Config*) + Off*
  (gồm Off_ChamCong thuộc Cá nhân) + Personal. Giữ row (không xóa) — flip lại
  nhanh khi golive. Menu tự ẩn cả 2 app (GetMyMenuTree lọc CanRead).
- SeedAllRolesReviewReadPermissionsAsync: thu hẹp grant scope còn
  Master/Catalogs/Pe_* (bỏ Hrm/Off/Personal — không re-grant cái vừa revoke).
- Menu "Danh mục" (Master) Order 20→80 — cuối vùng nghiệp vụ, trước System 90.
  Main upsert tự re-set Order trên DB cũ (idempotent sẵn).
- KHÔNG đụng: Pe_* (sếp cần all-role) + Master/Catalogs CanRead (flow PE cần
  xem master data) + Admin (quản trị) + IsVisible layer (Menu eOffice toggle).

Runtime-proof Dev: MasterOrder=80 · NonAdminHrmOffPersonalCanRead=0 ·
AdminHrmOffCanRead=28 · NonAdminPeCanCreate=120 · NonAdminMasterCanRead=48.
Build 0/0, test 240 PASS. Lưu ý mức che: menu + permission matrix; URL gõ
trực tiếp chưa chặn (FE không PermissionGuard per-route — chấp nhận "tạm ẩn").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 13:36:08 +07:00
5998163642 [CLAUDE] Infra: fix lock-demo-user prod NO-OP — union 20 UAT-matrix email + DemoUserPassword 12 ký tự (S58)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m43s
Run #381 cicd phát hiện LockDemoSampleUsersAsync NO-OP trên prod: 14 email
named-person là population Dev-only. Root cause sâu: DemoUserPassword 11 ký tự
< prod RequiredLength=12 → CreateAsync silent-fail mọi startup từ trước tới giờ
(luôn cả nv.cao/nv.truong IT pool — root cause helpdesk inert S56 — và 5 real
staff thiếu account).

Fix (anh chốt 3 quyết định qua AskUserQuestion):
- Union 20 email UAT-matrix prod thật (act/equ/fin/hra/pm/qs × nv/pp/tp + bod.1/2,
  tạo tay 05-13) vào lock list — exact-email only, KHÔNG pattern (binh.le@ là
  người thật sát scheme demo).
- DemoUserPassword User@123456 → User@1234567 (12 ký tự, thỏa policy prod) →
  startup tới trên prod sẽ TẠO named-person (rồi lock ngay cùng startup) +
  nv.cao/nv.truong ACTIVE (helpdesk sống lại) + 5 real staff.
- GIỮ ACTIVE: nv.test (creds cicd smoke-verify) + chuong.phan@solution.com.vn
  (typo domain nhưng có thể login thật anh Chương — xác nhận rồi dọn sau).

Trade-off deadline 15:00: ship trước, test-specialist viết guard test sau
(test-after justify — list-data fix, logic lock không đổi).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 12:56:45 +07:00
dd117b749c [CLAUDE] PurchaseEvaluation: PE gắn Hạng mục công việc (Mig 49) + mở quyền Pe all-role + menu Cá nhân + khóa 14 demo user
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
Sếp chốt deadline 15:00 (Zalo 11:02-11:17): flow tạo phiếu chọn quy trình → dự án → HẠNG MỤC → NCC/TP; phiếu dạng «Dự án – Hạng mục»; all-user thấy Duyệt NCC + master config; clear data cũ.

- Mig 49 AddWorkItemToPurchaseEvaluation: PE.WorkItemId Guid? loose-Guid + index (KHÔNG FK vật lý — convention PE, database-agent design). Validator NotEmpty (create) + FK-guard AnyAsync(IsActive) → Conflict + UpdateDraft NULL-SAFE (client không gửi → giữ, chống null-hóa bug-class S42). 3 projection ListItemDto LEFT-join WorkItems.
- FE ×2 app: PeWorkspaceCreateView select «c. Hạng mục *» + PeHeaderForm (load existing + PUT gửi lại, SHA256 IDENTICAL) + PeDetailTabs (header «Dự án – Hạng mục» + FormRow + inline khóa) + types. Route reuse /catalogs/work-items.
- Perm: SeedAllRolesReviewReadPermissionsAsync extend Pe_* 11 key (factory — Pe leaf không nằm All) CanRead+CanCreate upgrade-only mọi role; PeWf_*/AwV2 GIỮ Admin. HRM/Office/Master/Catalogs CanRead (S57). Master write-lock Admin,CatalogManager ×3 controller.
- Menu «Cá nhân» (Personal root 30, mirror Puro) + Chấm công re-parent + HrmConfig→Master + parentBackfill idempotent + admin bỏ ẩn Master (đảo S29).
- LockDemoSampleUsersAsync: khóa 14/16 sample (GIỮ nv.cao+nv.truong IT-pool + catalog.manager) — ungated idempotent, IsActive=0+Lockout+SecurityStamp rotate.
- Tests +12 PeWorkItemGuardTests (validator/FK-guard/null-safe) → 240 PASS. npm ×2 + BE 0W/0E.
- Excel (3) đối chiếu: 62/71/3 identical S55 — no data change.
- Gate: em main evidence-checklist (2 reviewer-spawn die-0-byte — resume-kill; backstop 12 guard-test + authz-key/role-string/Mig-49 evidence-lệnh).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 12:13:26 +07:00
69cb3937bb [CLAUDE] Master: nạp master data thật từ Excel (62 dự án + 71 hạng mục + 3 NCC) + Project +4 cột (Mig 48)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
Nạp master data công ty từ file Excel 'HẠNG MỤC CÔNG VIỆC DỰ ÁN':
- 62 Projects (Mã + Năm; tên/CĐT/địa điểm/gói thầu cho ~6 dự án có chi tiết)
- 71 WorkItems: Vật tư 16 · Thầu phụ 30 · MEP 9 · Thiết bị 16
- 3 Suppliers (TRUONGGIANG/TANPHU/TGN)

Mig 48 AddProjectMasterFields: Project +4 cột nullable (Year/Investor/Location/Package) + ProjectFeatures DTO/Create/Update + ProjectsPage form ×2 app (SHA256 mirror).
SeedRealMasterDataAsync per-code idempotent, UNGATED → reaches prod (coexist demo). FLOCK01 collision → skip (demo wins).

Verify: build 0-err · test 216 PASS · runtime Dev proof (data landed, Investor col populates). Provenance: scripts/master-import-data.generated.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 09:27:04 +07:00
dbf66489a9 [CLAUDE] Office: P11-D ItTicket admin reassign-UI + P11-E AttendanceReport menu-key
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m21s
Task C - ItTicket admin reassign-UI (fe-admin only):
- Per-card reassign dialog on ItTicketsPage kanban (admin override of round-robin auto-assign).
- Reuses existing PUT /it-tickets/{id}/assign (Admin-only) + GET /users picker. No new BE endpoint.
- fe-admin intentionally diverges from fe-user (read-only) — admin-management action.

Task D - AttendanceReport menu-key (P11-E promote, no migration):
- MenuKeys.OffAttendanceReport 'Báo cáo chấm công' leaf under Văn phòng số (order 8), Admin-perm auto via All[].
- DbInitializer idempotent seed + fe-admin menuKeys.ts/Layout staticMap -> existing /attendance/report route.

Pipeline: implementer-backend -> implementer-frontend -> reviewer (PASS, 0 issues). dotnet+npm builds clean. Tests 203 (unchanged - no new BE logic/schema).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 15:00:30 +07:00
44b9e542fb [CLAUDE] Infra: gotcha #57 EXT Master filtered-unique Department/Supplier/Project (Mig 47)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m15s
Extend gotcha #57 filtered-unique fix to 3 Master catalogs (4th/5th/6th cumulative after Holiday Mig 43 S45 + HRM x3 Mig 45 S51).

Root cause: app-level dup-check db.X.AnyAsync(Code==req) runs through HasQueryFilter(!IsDeleted) so it ignores soft-deleted rows, but the bare .IsUnique() DB index counted them -> admin delete+re-add same Code = reachable 500. Fix aligns index with query filter via .HasFilter("[IsDeleted] = 0").

- Department/Project/Supplier Configuration: unique Code index + .HasFilter (Supplier Type index untouched)
- Mig 47 FilterMasterCatalogUniqueIndexesByIsDeleted (Up: 3x DropIndex+CreateIndex filtered; Down reversible)
- test-before MasterCatalogFilteredUniqueTests (3 RED->GREEN, delete+re-add same Code)
- Tests 200 -> 203 (58 Domain + 145 Infra)

Pipeline: test-specialist -> implementer-backend -> reviewer (PASS, 0 issues).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 14:28:04 +07:00
dcf76f8a9f [CLAUDE] Office: P11-D ItTicket auto-assign round-robin + SLA timer (Wave 2, Mig 46)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
Mig 46 AddSlaFieldsToItTicket (SlaDueAt/SlaWarnedSent/SlaBreached). CreateItTicketHandler: round-robin least-loaded assign cho IT staff (dept Code=IT, tie-break Id) + SlaDueAt theo Priority (Urgent 4h/High 8h/Medium 24h/Low 72h). ItTicketSlaJob background (breach+warning notify, KHONG auto-transition). PUT /{id}/assign admin override. DbInitializer seed dept IT + 2 sample staff (nv.cao/nv.truong). FE ItTicketsPage +MaTicket+assignee+SLA badge (2 app SHA256 mirror). +9 test (191->200). Self-review PASS (seed<->query dept-code verified; em main solo review do session-limit kill reviewer-spawn).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 13:23:45 +07:00
30a99aa03f [CLAUDE] Hrm: P11-C Vehicle+Driver catalogs (Mig 44) + gotcha #57 filtered-unique 3 HRM catalog (Mig 45)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m18s
P11-C: extend HrmConfigs +2 kind (Vehicle/Driver) declarative. Mig 44 AddVehicleAndDriverCatalogs (2 table filtered-unique Code, tables 91->93). Domain entity + EF config (filtered day-1) + 2 DbSet + HrmConfigFeatures Region5/6 CRUD + Controller +2 route-group (GET public / write Roles=Admin) + MenuKeys +2 +All (auto Admin perm) + DbInitializer 2 menu leaf + idempotent seed 2 veh/2 drv. FE declarative KIND_CONFIG +2 kind x2 app (SHA256 mirror) + 4-place (types/page/menuKeys/Layout staticMap), :kind-driven no new route.

gotcha #57 (bundled; OtPolicy missed in backlog, caught via grep) - Mig 45 FilterHrmCatalogUniqueIndexesByIsDeleted: LeaveType+ShiftPattern+OtPolicy bare .IsUnique() -> .HasFilter([IsDeleted]=0) (recreate-on-soft-deleted-slot 500 fix, mirror Holiday Mig 43). Tests +5 HrmConfigFilteredUniqueTests (181->186 PASS) test-before RED->GREEN. Reviewer caught FE<->BE Driver required-field mismatch -> fixed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:32:28 +07:00