[CLAUDE] Contract: tách HĐ Thầu phụ thành 01A/01B + thân document-view + pre-fill + khoá bản cứng (YC-032)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 2m41s

Owner YC-032/033/034/036 — 4 vế:

1. TÁCH LOẠI: +2 ContractType (HopDongThauPhuVatTu=8 / HopDongThauPhuThietBi=9),
   họ HD-TP-VT / HD-TP-TB, menu 01A./01B. (giữ 02.-07. nguyên, loại cũ =1 legacy).
   Bịt 5 nhánh câm nuốt loại mới: WorkflowPolicy (mất trạm CCM), ContractCodeGenerator
   (sai mã RG-001, không hồi tố được), ContractDetailsFeatures x2 (bundle rỗng HTTP 200),
   SeedWorkflowDefinitions (Designer V1 rỗng). ContractDetailsHelpers.ThauPhuFamily —
   3 loại chung bảng ThauPhuDetails ⇒ 0 migration cho vế này.

2. THÂN DOCUMENT-VIEW: ContractBodyView.tsx + lib/contractBody/ (002.02 = 36 ô/2 bảng/5 điều ·
   002.03 = 46 ô/6 bảng/6 điều · PHẦN 2 dùng chung 5 điều read-only gắn CUỐI theo YC-034).
   Lưu vào Contract.DraftData lược đồ {schemaVersion,kind,body,paymentTerms}.
   Gỡ draftData:null hardcode 4/4 site — trước đây mỗi lần Lưu là xoá trắng thân HĐ.

3. PRE-FILL: cầu KHKK đổ 17 ô (Bên B · chủ đầu tư · gói thầu · số HĐ · giá trị) — 17/17 khớp
   slot.key. Địa điểm lấy pe.DiaDiem (0% rỗng) thay Project.Location (93% rỗng). Vá regression
   cầu KHKK đánh rơi PaymentTerms + BypassProcurementAndCCM so với cầu PE cũ.

4. KHOÁ BẢN CỨNG MỘT CHIỀU (YC-033 "giấy trắng mực đen"): Mig AddContractSealedAt
   (+SealedAt +SealedByUserId), set ??= (upload lần 2 không đè mốc đầu), rào 2 cửa —
   xoá đính kèm bản cứng ⇒ 409, sửa HĐ ⇒ chặn. Test-before 2 ca.
   + print CSS in trình ký (ô điền in ra thành đường kẻ, không phải khung input).

Template: 002.02/002.03 convert .doc→.docx vào wwwroot + trỏ đúng 2 loại mới (trước cùng trỏ
loại cũ ⇒ dropdown Mẫu sẽ rỗng) + reconcile IsActive giới hạn 2 FormCode (bản đầu quét toàn bộ
sẽ hồi sinh mẫu admin đã xoá mỗi restart — database-reviewer-style bắt).

Đo: build 0 error · test 697→699 PASS (+2 seal) · has-pending-model-changes = No changes ·
tsc --noEmit exit 0 x2 app · mọi cặp file 2-app sha256 trùng · Menu keys 120→122 · Policies 480→488.

NỢ ĐÃ-BIẾT (owner cố ý hoãn, không phải bỏ sót): VAT (chưa VAT, để sau) · bảng tóm tắt PHẦN 1
trỏ "xem ĐIỀU 8/12" mà 002.04 chỉ có 5 điều ⇒ con-trỏ chết · phân quyền upload bản cứng ·
12 điều PHẦN 2 không có trong tài liệu. Chưa soi: 2 vai style FE/BE (lane không tạo được artifact).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-14 04:11:20 +07:00
parent 1e9df0c3f5
commit 88bdd05492
55 changed files with 13223 additions and 80 deletions

View File

@ -62,6 +62,11 @@ epo-archive` **16,49GB** (cache chính chủ Gitea, tự tái tạo) → free **
| `YC-030` | "Q1 ->như KHKK ⏎ Q2 -> Chỉ select theo loại HĐ ⏎ Q3 -> Port sang luôn ⏎ Q4 -> Người tao xóa người duyệt ko đc xóa, chỉ trả lại thôi. ⏎ Q5 -> Thay luôn và mỗi loại 1 quy trình tương tự KHKK và cấu trúc duyệt và history cũng tương tư KHKK ⏎ Xong thì push và deploy lên nhé. Để tao kiểm tra" | 2026-08-12 · S190 | **mở** | 1 | run `2026-08-12-S190-soltuon-dieu-chinh-hd/` *(thi-công → WAL)* | 5 phán quyết đóng Q1-Q5 của YC-029 + lệnh deploy: **Q1** layout my-contracts về **KHKK-THUẦN** (bác nhánh hoán-đổi đã chạy: BỎ cột danh-sách thường-trực bên phải; cây trái = trục, flat-list = fallback trong CÙNG panel khi search/lọc; panel-3 = workflow+history/dashed y KhkkListPage) · **Q2** panel cây giữ **Select theo LOẠI HĐ** (trục nhóm của KHKK ⇒ trục loại của HĐ) · **Q3** PORT 3 món KHKK vào màn duyệt HĐ (ô "Cấp này KẾT THÚC" + badge "Duyệt thay CEO" + banner kết-thúc-sớm — cần nở `ContractDetail` DTO + service đọc cờ) · **Q4** *"người TẠO xóa (typo 'tao'), người DUYỆT KHÔNG được xóa — chỉ Trả lại"* = XÁC NHẬN đúng W5 đã ship (approver-delete KHÔNG BAO GIỜ mở cho HĐ — khác PE; đóng `[carry:w8-delete-policy]` vế approver) · **Q5** THAY `QT-HD-V2-001` bằng đúng 7 bản `HD-*` per-loại (data-op cả Dev lẫn prod) + cấu trúc duyệt & history màn HĐ = y khuôn KHKK (gộp Q1/Q3) · rồi **PUSH + DEPLOY prod để anh kiểm tra** (⇒ mở CỬA NGOÀI-GIỜ: dọn workspace runner vá-gốc P0 TRƯỚC push) | |
| `YC-029` | "Thứ 1 (Ành 1): Bỏ phần này sang bên này nhé. ⏎ Thứ 2 (Ảnh 2): Điều chỉnh. ⏎ Thứ 3: Phần hợp đồng Menu đang bị lẫn lộn, click vào menu này thì nhảy sang Menu khác, điều chỉnh lại nhé. ⏎ Thứ 4: Phần thao tác, duyệt, xóa ... -> Cấu trúc tương tự như KHKK. ⏎ Thứ 5: Bên trong Admin -> Cấu hình Menu đúng chính xác cho từng loại HĐ nguyên tắc, thầu phụ -> Cấu trúc Menu tương tự giống với KHKK và Duyệt NCC (Ảnh 3) ⏎ Cho /fable-real invest và review các điều chỉnh spec, ra các wave và checklist cụ thể. ⏎ /fable-clone review lại 1 lần nữa. ⏎ /fable-real vào các vai style FE, BE -> Invest Ra cái spec list để style đồng nhất với các thiết kế đó. ⏎ /fable-clone Vai FE, BE review style -> Review lại ⏎ /fable-real tổng hợp cuối cùng ra từng wave cụ thể, sau đó ⏎ -> Sau đó Fan-out cho OPus 5 MAX xử lý toàn bộ plan, tên Plan \"SOLTUON-12-08-2026\"" *(kèm 3 ảnh prod eoffice `my-contracts?type=1` + admin Designer)* | 2026-08-12 · S190 | **mở** | 1 | run `2026-08-12-S190-soltuon-dieu-chinh-hd/` *(thi-công → WAL)* | Kết quả review GĐ3 của anh (vế 2 YC-025) = 5 điều chỉnh UAT: **(1)** ảnh-1 dời khối được khoanh (cột danh-sách HĐ trống) sang vị-trí mũi-tên chỉ — đọc-hình bậc-2, invest xác nhận từ khuôn KHKK trước khi khoá spec · **(2)** ảnh-2 mỗi LOẠI HĐ = 1 quy-trình duyệt RIÊNG, UI phải thể hiện đúng (7 menu loại đã khoanh) · **(3)** BUG menu HĐ lẫn lộn: click menu này nhảy sang menu khác — điều chỉnh routing/menu-key · **(4)** bộ thao-tác (duyệt/xóa/thao tác/đang duyệt/đã duyệt/đã xóa) cấu trúc y KHUÔN KHKK · **(5)** ảnh-3 Admin Designer: thêm mục cấu-hình quy-trình per-LOẠI-HĐ (nguyên tắc, thầu phụ, …) y khuôn "Duyệt NCC (Mới)" + "Duyệt KHKK — Nhóm 1..8". Pipeline anh chỉ định 6 bước: ① `/fable-real` invest+review điều chỉnh spec → wave+checklist *(em gán `investigator-codebase`)*`/fable-clone` review lại *(`reviewer`)*`/fable-real` ×2 vai style FE/BE invest spec-list style đồng nhất *(`front-end-reviewer-style` + `back-end-reviewer-style`)*`/fable-clone` FE/BE review style lại ⑤ `/fable-real` tổng hợp cuối ra wave cụ thể *(`reviewer`)* ⑥ fan-out **Opus 5 MAX** xử lý toàn bộ plan, tên plan **"SOLTUON-12-08-2026"** (giữ nguyên văn tên anh đặt) | |
| `YC-031` | "Admin -> tạm ôn. ⏎ eOffice -> vào trắng màn hình" *(kèm ảnh prod eoffice trắng trơn)* ⏎ → "fix luôn đi, lỗi này bị 2-3 lần rồi" ⏎ → "Fix lỡi này luôn rồi chạy /session-end" | 2026-08-13 · S191 | **mở** *(vá GỐC đã ship `305b573f`, CI đang verify; đóng khi anh xác nhận prod ổn qua 1 chu-kỳ deploy KHÔNG hotfix tay)* | 3 | `docs/gotchas.md` #92 + `.gitea/workflows/deploy.yml` + session-log S189-S191 *(thi-công → WAL)* | Anh kiểm prod GĐ3 sau deploy #600 → eOffice **trắng màn**, admin tạm ổn. 🔴 Vế **"bị 2-3 lần rồi"** là phần NẶNG NHẤT của yêu-cầu: anh KHÔNG xin hotfix, anh đòi **thôi tái phát** ⇒ cấm vá triệu chứng (scp bundle) rồi tuyên xong. Đội hiểu: **(1)** cứu prod ngay (build local lành scp đè ×2 app — đã làm, console 0 lỗi) · **(2)** truy ROOT-CAUSE thật: `deploy.yml` xoá `package-lock.json` rồi `npm install` ⇒ mỗi run resolve lại cây theo semver ⇒ cùng commit ra bundle khác nhau ⇒ CI xanh mà bundle crash `useState null`; lockfile cũ (23/04) thiếu `@microsoft/signalr` nên "xoá cho lành" từng có vẻ hợp lý · **(3)** vá gốc: lockfile tái sinh từ cây lành + `npm ci` + **GUARD-92** chặn React trùng bản (fault-inject 4 ca, bắt được dương-giả `lucide-react` trước khi push) · **(4)** khắc gotcha **#92** kèm luật "verify deploy FE phải có 1 phép đo RUNTIME" — vì 2 lần lọt đều do mọi phép đo chỉ đo FILE (byte-match + HTTP 200), không đo CHƯƠNG TRÌNH CHẠY. ✅ **ĐÓNG vế kỹ-thuật @S191:** CI run **#488 PASS 6/6**, hash CI == local **4/4** (`CR538vZx`/`C10ta-wB`), runtime-verify 2 app console 0 lỗi. 🔴 **ĐÍNH CHÍNH 2 điều lead ghi SAI ở dòng này (cặp H24 bắt @close):** **(a)** `.nvmrc` **CÓ tồn tại** (`fe-admin/.nvmrc` + `fe-user/.nvmrc` = `20`, tracked từ `25dad7f3`) — cái thiếu là **người ĐỌC nó** (`deploy.yml` 0 hit `setup-node`) = ghost-wire class-2, không phải file-missing; chẩn sai thì vá sai (đi tạo lại file = vô ích). **(b)** nghi vấn "chênh node/npm là nguồn bất-định còn lại" **BỊ BÁC bằng đo**: runner node v24.15.0/npm 11.12.1 vs local v22.13.0/npm 10.9.2 vẫn ra **đúng 4/4 hash** ⇒ nguồn bất-định duy nhất là việc xoá lockfile, đã vá. 🔸 **1 điểm chưa khớp CẦN ANH 1 CÂU:** anh nói **"2-3 lần"**, sổ + gotcha #92 truy được **2 ca có vết** (S189 #486 · S191 #600); grep `"trắng màn"` toàn sổ bền = 6 hit/5 file, **100% thuộc 2 ca đó, 0 vết cho ca thứ 3**. ⇒ hoặc có 1 ca chưa từng vào sổ (mẫu root-cause đang thiếu 1/3 dữ liệu), hoặc anh nói ước lượng. 🔸 CÒN TREO: node/npm runner **chưa pin** — chờ anh quyết pin `setup-node` đọc `.nvmrc` hay khai thẳng "cố ý không pin". | |
| `YC-032` | "Spec đổi 1 chút nhé chỗ hợp đồng: ⏎ Hợp đồng thầu phụ -> Tách làm 2 Menu Thầu phụ (Nhân công & Vật tư) và Thầu phụ (Nhân công & Thiết bị): ⏎ -> Sau đấy chỗ khung form nhập : Lấy từ form này đưa vào (Hình 3) -> Người nhập sẽ giống như đang view từ trên xuống toàn bộ cái hợp đồng. ⏎ Thông tin sẽ kế thừa từ Duyệt NCC và KHKK -> Fill vào các cô đó, từ các thống tin duyệt NCC đã fill đầy -> KHKK đã fill đầy -> Sau đó fill đầy vào cái nào còn thiếu sẽ fill cuối cùng. Trọn thành 1 cái hợp đồng -> Chỉ cần in ra trình ký thôi. Sau đó upload bảng cứng lên và khóa. ⏎ Làm trước cho tao xem 2 cái hợp đồng đó trước thử. ⏎ Cho /fable-clone invest và review cách làm ra từng wave cụ thể -> Sau đó cho Opus 5 MAX xử lý" *(kèm 3 ảnh: ×2 prod eoffice menu `DUYỆT HỢP ĐỒNG 01. HĐ Thầu phụ` khoanh đỏ + 1 ảnh thư mục `D:\Dropbox\CONG_VIEC\SOLUTION\FORM` khoanh đỏ 2 file `SOL-CCM-FO-002.02` và `002.03`)* | 2026-08-13 · S194 | **mở** | 1 | *(thi-công → WAL)* | Đổi spec GĐ3 Duyệt Hợp đồng, 4 vế: **(1) TÁCH menu** `01. HĐ Thầu phụ` (nay 1 mục, `ContractType.HopDongThauPhu`/`HD-TP`) thành **2 menu ruột riêng**: *Thầu phụ (Nhân công & Vật tư)* ↔ form `SOL-CCM-FO-002.02.v01` · *Thầu phụ (Nhân công & Thiết bị)* ↔ form `SOL-CCM-FO-002.03.v01` — 🔴 chưa rõ tách ở tầng nào (thêm `ContractType` mới ⇒ đụng enum + 7 quy trình `HD-*` + policy/menu-key, hay 1 type + cờ biến-thể) = **câu invest phải trả, không tự chọn**. **(2) ĐỔI KHUÔN FORM NHẬP** — bỏ dạng field rời rạc, dựng **document-view cuộn từ trên xuống đúng thân hợp đồng gốc**, nội dung lấy từ chính 2 file `.doc` anh khoanh (516.608 B + 591.360 B, `D:\Dropbox\CONG_VIEC\SOLUTION\FORM\`; định dạng `.doc` binary cũ **không phải** `.docx` — trích cần office-document, và bản `002.02` **đang mở trong Word** [file khoá `~$`] ⇒ chỉ đọc). **(3) PRE-FILL 3 TẦNG dồn về 1 văn bản trọn:** Duyệt NCC (đã fill đầy) → KHKK (đã fill đầy) → người nhập chỉ điền **phần còn thiếu ở bước cuối** ⇒ ra hợp đồng hoàn chỉnh **chỉ để IN ra trình ký**. **(4) CHỐT bằng bản cứng:** upload bản đã ký → **KHÓA** (khớp mốc-cứng 1-MỐC của KHKK W7). **Phạm vi lượt này = LÀM TRƯỚC 2 HĐ đó cho anh xem**, không làm cả 7 loại. **Pipeline anh chỉ định:** `/fable-clone` invest + review → ra **từng wave cụ thể** → rồi **Opus 5 MAX** xử lý. | |
| `YC-033` | "97 -> là sao ? ⏎ 99 -> đc upload có quy trình duyệt riêng -> Duyệt nhanh thôi nhưng đã chốt rồi ko sửa đc (bảng cứng đã ký - giấy trắng mực đen upload thì làm sao sửa). ⏎ 100 -> hiện là chưa VAT nhưng nói chung chỗ này để sau. ⏎ 101 -> Tùy mày. ⏎ 102 -> Cái này cho nhân viên -> Có quy trình riêng nhưng để sau." | 2026-08-14 · S194 | **mở** *(4/5 câu đã phán; `(97)` anh HỎI LẠI ⇒ lead phải giải thích lại, chưa tính là đã đáp)* | 1 | `runs/2026-08-13-S194-yc032-hd-thauphu-2form/spec-…§⑤.g` *(thi-công → WAL)* | Đáp 4/5 câu của `YC-032`: **(97) anh hỏi ngược "là sao?"** ⇒ 🔴 lỗi ở LEAD — câu hỏi viết bằng từ nội bộ ("12 điều thiếu của PHẦN 2"), anh không có nghĩa vụ đoán; phải trình lại bằng vật thể anh nhìn được (bảng mục lục trong chính file anh gửi vs ruột file `002.04`). **(99) BẢN CỨNG = MỘT CHIỀU TUYỆT ĐỐI** — upload đi qua **một quy trình duyệt RIÊNG, duyệt nhanh**; duyệt xong là **CHỐT, không sửa được**. Lý lẽ anh nêu (ghi lại vì nó là *nguyên tắc*, không phải tuỳ chọn cài đặt): *"bảng cứng đã ký — giấy trắng mực đen upload thì làm sao sửa"* ⇒ đội hiểu: khoá phải là **bất-khả-đảo** (không phải cờ 2 chiều xoá-file-là-mở như hiện tại), và **xoá/thay file sau khi chốt = CẤM**. **(100) giá hiện là CHƯA VAT** — nhưng anh chốt **"để sau"** ⇒ KHÔNG dựng xử-lý VAT lượt này; vẫn phải KHAI trong spec rằng thân HĐ ghi "bao gồm VAT" mà số đang chưa VAT = **nợ đã biết**, không phải bỏ quên. **(101) đánh số menu = UỶ QUYỀN cho lead**. **(102) người upload = NHÂN VIÊN**, có quy trình riêng nhưng **để sau** ⇒ lượt này KHÔNG dựng phân quyền upload, nhưng lỗ authz `B-4` (endpoint 0 policy/0 ownership) vẫn phải KHAI là nợ đang mở. | |
| `YC-034` | "à có nhé, file này" *(kèm ảnh thư mục FORM khoanh đỏ `SOL-CCM-FO-002.04.v01 Dieu kien chung hop dong tron goi.docx` 189 KB)* ⏎ → "nhưng vậy cho nó phần cuối là đc" | 2026-08-14 · S194 | **đóng** *(đáp nốt câu `(97)` — bộ 5 câu `YC-032` nay 5/5 CÓ ĐÁP)* | 1 | `spec-…§⑤.g` + `②.3` *(thi-công → WAL)* | Đáp `(97)`: PHẦN 2 "Điều kiện chung" **= chính file `002.04`** anh khoanh, và **đặt ở PHẦN CUỐI** của document-view. ⇒ **CHẶN GỠ**, nhưng gỡ bằng **thu hẹp phạm vi**, KHÔNG phải bằng tìm ra 12 điều: đo lại bằng thước ĐÃ VÁ (control-dương 3/3 CO sau khi sửa lỗi nối-mảnh-chữ bằng dấu cách) ⇒ `002.04` vẫn **5 điều / 40 đoạn / 6.929 chữ**; 12 tên điều (Đơn giá · Tiện ích · Phát sinh · Nghiệm thu · **Tạm ứng** · Nghĩa vụ · Phạt · Chấm dứt · **Bảo hành** · Bất khả kháng · Thông báo · Hối lộ) **0 hit**. ⇒ Đội hiểu: document-view = **PHẦN 1** (ruột riêng, lấy từ `002.02`/`002.03`) **+ PHẦN 2 gắn ở cuối** (dùng chung, lấy từ `002.04`, **5 điều**). 🔴 **Hệ quả phải khai, không được im:** bảng tóm tắt cuối PHẦN 1 có ô trỏ *"xem ĐIỀU 8 / ĐIỀU 12"* của PHẦN 2 — 2 điều đó **không tồn tại trong `002.04`** ⇒ con trỏ chết vẫn còn, chỉ là **owner chấp nhận đi tiếp**, không phải đã hết. Ghi thành nợ đã-biết cùng hạng với VAT `(100)`. | |
| `YC-035` | "OK làm tiếp đi nhé" | 2026-08-14 · S194 | **đóng** *(lệnh đi-tiếp, thi-hành ngay trong lượt)* | — | WAL chain G1 *(thi-công → WAL)* | Duyệt cho lead HOÀN NỐT 7 site backend còn lại của G1 bằng tay (sau khi lead khai wave land nửa chừng: BE 1/8 site, 2 nhánh câm đang nuốt 2 loại mới). KHÔNG phải yêu-cầu mới — là tái xác nhận `YC-032` vế "cho Opus 5 MAX xử lý", nên KHÔNG tính là mục nhắc-lại mới. | **`YC-032`** |
| `YC-036` | "OK xong hết hoàn toàn đi rồi tao sẽ test" | 2026-08-14 · S194 | **mở** | — | WAL chain G1-G5 *(thi-công → WAL)* | Lệnh làm TRỌN `YC-032` — hết 4 vế, không dừng giữa chừng để hỏi, rồi anh tự kiểm trên prod. Đội hiểu: chạy nốt G1 (office + verify FE) → G2 khung document-view → G3 pre-fill → G4 in + khoá bản cứng → G5 review + deploy, và **deploy lên prod** vì "tao sẽ test" hàm ý anh test trên máy thật. 🔴 Ràng buộc GIỮ NGUYÊN, không được lấy chữ "xong hết" để bỏ qua: 4 nợ đã-biết ở spec `§⑥.c` (VAT · con-trỏ chết ĐIỀU 8/12 · authz đính kèm · 12 điều PHẦN 2) là owner CỐ Ý hoãn — vẫn phải KHAI khi báo cáo, cấm im lặng cho tròn. | **`YC-032`** |
| `YC-018` | "2 phần bookend và bookstart -> trong đợt adapt này AI_INFRA cũng có hướng dẫn bọn mày chạy 1 mạch hết toàn bộ ko còn pause/tiep nữa, chú ý cấu hình cái đó kỹ nhé" | 2026-08-09 · S185 | **đóng** *(cấu hình land 4 site @S185 + chạy thật trọn 1 mạch bookend @close cùng đêm — nghiệm bằng vận hành; 🔴 nhắc lần 2 @S188 = PN-001: lead bỏ 3 vai @close với lý do "ngân sách" — owner bác, chạy nốt ngay trong lượt)* | **2** | WAL chain (TASK → WAL) | Nghi-thức 2 đầu phiên (`/session-start` bookstart + `/session-end` bookend) phải chạy **TRỌN TRONG MỘT LƯỢT** như hub kể ở thư 08-08 Phần 1b ("lượt mở phiên gần nhất chạy trọn trong một lượt duy nhất, không cần cửa tạm dừng nào chen giữa") — cấu hình luật ONE-SHOT vào 2 file lệnh, CẤM rải nghi-thức qua nhiều cửa pause/tiep, CẤM hẹn-cửa-sau. *(Đội hiểu: pause/tiep VẪN là recovery khi đứt bất-khả-kháng [limit/crash — H22 giữ nguyên]; thứ bị cấm là DÙNG chúng làm nhịp chia-chặng nghi-thức. Anh bác cách hiểu này thì em sửa.)* | |
> 🔴 **MỘT yêu-cầu, nhắc 4 lần.** Đây là dữ-liệu **TC-01** sinh ra để bắt, và nó tố-giác chính lead: hiểu sai ở `YC-002` nên anh phải nói lại 3 lần. **Ghi lại chứ không làm đẹp.**