diff --git a/docs/gotchas.md b/docs/gotchas.md index 26bb6ebb..f6bc1763 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -1515,3 +1515,30 @@ for h in resp.points: # ← .points không phải iterable trực tiếp 34. Nếu Gitea Actions run CANCELLED ngay sau khi push 2 commit sát nhau → auto-cancel cùng-branch: đọc run CUỐI của range + verify artifact-level (bundle/marker/seeder-log), KHÔNG đọc CANCELLED thành deploy-fail; side-effect @startup chỉ chạy 1 lần cho cả cụm (#86) 35. Nếu probe endpoint để hỏi **authz** mà nhận **415/411** → đó là mã **PRE-AUTH**, vô nghĩa cho câu hỏi authz: request bị loại ở tầng **action-selection / IIS** TRƯỚC authorization filter. Re-probe đúng dạng body (multipart cho endpoint upload; có body cho SignalR negotiate) rồi mới đọc 401/403 (#87) 36. Nếu login prod 500 "transient failure UseSqlServer" + DB RECOVERY_PENDING sau sự cố disk đầy → check **cờ nén NTFS** trên .mdf/.ldf (`compact `, Msg 5118): SET OFFLINE → backup copy → restart service nhả handle → `compact /U` → SET ONLINE. CẤM nén cây SQL DATA (#88) + +### 93. Dấu PHẨY trong tên file asset ⇒ `MSB4186` — CI đỏ mà LOCAL không tài nào tái hiện (Session 194) + +**Triệu chứng:** commit thêm 2 file `.docx` vào `wwwroot/templates/`. Local: build 0 error, **699 test PASS**, `tsc` sạch. Push → CI run **#489 ĐỎ sau 2m42s**, chết giữa test-gate Infrastructure, **chưa tới build FE, chưa tới deploy**. + +``` +Microsoft.NET.Publish.targets(851,9): error MSB4186: Invalid static method invocation syntax: +"[MSBuild]::MakeRelative($(MSBuildProjectDirectory), …\SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx)". +Method '[MSBuild]::MakeRelative' not found. +``` + +**Cơ chế:** MSBuild property-function **tách tham số bằng dấu phẩy**. Tên file chứa `, ` biến lời gọi 2-tham-số thành **3 tham số** ⇒ không có overload ⇒ `MSB4186`. Lỗi ở **BUILD**, nên test không kịp khởi động — đọc log thấy "test fail" là đọc nhầm tầng. + +🔴 **Vì sao LOCAL KHÔNG BAO GIỜ BẮT ĐƯỢC — đây mới là phần đắt:** +`global.json` = `{"sdk":{"version":"10.0.104","rollForward":"latestFeature"}}`. `latestFeature` **cho phép nhảy feature-band** ⇒ local `10.0.104`, CI `10.0.202`. Đo quyết định: +``` +grep -c "MakeRelative" /Microsoft.NET.Publish.targets = 0 ← dòng gây lỗi KHÔNG TỒN TẠI ở local +grep -c "ContentWithTargetPath" cùng file = 8 ← CONTROL DƯƠNG (thước sống) +ls "C:\Program Files\dotnet\sdk\" = 10.0.104, 9.0.311 (không có 10.0.2xx) +``` +⇒ *"Local 699 PASS"* là **đúng-với-local**, không phải đo ẩu. Chạy lại bao nhiêu lần cũng không đỏ. + +**Control có sẵn ngay trong thư mục, không cần dựng thêm:** 4 template CŨ cùng chỗ **không có phẩy** → CI xanh nhiều tháng (control dương). 2 file mới **có phẩy** → đỏ ngay run đầu (control âm). Biến duy nhất đổi = dấu phẩy. + +**LUẬT:** 🔴 **tên file dưới `wwwroot/` CẤM chứa dấu phẩy.** Khoảng trắng thì OK (4 file cũ đều có). Đổi tên phải sửa kèm chuỗi seed trong `DbInitializer.cs` (2 điểm tham chiếu). + +**Họ hàng với #92:** cùng lớp *build-env CI trôi khỏi local*, nhưng #92 ở tầng **npm** (đã khoá bằng lockfile + `npm ci`), còn đây ở tầng **.NET SDK** — vẫn **thả trôi** qua `rollForward: latestFeature`. Siết thành `latestPatch`/`disable` sẽ đóng cả lớp, **nhưng rủi ro thật**: runner đang có `10.0.202`; pin về feature-band `10.0.1xx` mà runner không cài bản đó thì **CI chết hẳn** thay vì chỉ đỏ một run. Cần đo SDK có trên runner TRƯỚC khi siết — quyết định của chủ dự án. diff --git a/fe-admin/src/lib/contractBody/body002_02.ts b/fe-admin/src/lib/contractBody/body002_02.ts index 058d83d2..cc8a698f 100644 --- a/fe-admin/src/lib/contractBody/body002_02.ts +++ b/fe-admin/src/lib/contractBody/body002_02.ts @@ -1,5 +1,5 @@ // ═══ HĐ TRỌN GÓI NHÂN CÔNG & VẬT TƯ — `SOL-CCM-FO-002.02` (`HD-TP-VT`, ContractType = 8) ═══ -// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx` +// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong va vat tu.docx` // (đọc `word/document.xml`, gộp mọi `` trong cùng `` bằng chuỗi RỖNG). Đối chiếu // `runs/2026-08-13-S194-yc032-hd-thauphu-2form/form-002-02-structure.md` (122 đoạn + 4 bảng · // 91 ô = 36 ô đơn + 55 ô bảng). diff --git a/fe-admin/src/lib/contractBody/body002_03.ts b/fe-admin/src/lib/contractBody/body002_03.ts index d661e4f7..68278505 100644 --- a/fe-admin/src/lib/contractBody/body002_03.ts +++ b/fe-admin/src/lib/contractBody/body002_03.ts @@ -1,5 +1,5 @@ // ═══ HĐ TRỌN GÓI NHÂN CÔNG & THIẾT BỊ — `SOL-CCM-FO-002.03` (`HD-TP-TB`, ContractType = 9) ══ -// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong, thiet bi.docx` +// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong va thiet bi.docx` // (đọc `word/document.xml`, gộp mọi `` trong cùng `` bằng chuỗi RỖNG — 201 đoạn + // 11 bảng). ⚠️ `form-002-03-structure.md` §1 bị LỖI TRÍCH ở ~40 block (in ra XML thô thay vì // chữ) và cắt câu ở ~150 ký tự ⇒ chữ ở đây đọc THẲNG từ .docx, không chép từ file structure đó. diff --git a/fe-user/src/lib/contractBody/body002_02.ts b/fe-user/src/lib/contractBody/body002_02.ts index 058d83d2..cc8a698f 100644 --- a/fe-user/src/lib/contractBody/body002_02.ts +++ b/fe-user/src/lib/contractBody/body002_02.ts @@ -1,5 +1,5 @@ // ═══ HĐ TRỌN GÓI NHÂN CÔNG & VẬT TƯ — `SOL-CCM-FO-002.02` (`HD-TP-VT`, ContractType = 8) ═══ -// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx` +// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong va vat tu.docx` // (đọc `word/document.xml`, gộp mọi `` trong cùng `` bằng chuỗi RỖNG). Đối chiếu // `runs/2026-08-13-S194-yc032-hd-thauphu-2form/form-002-02-structure.md` (122 đoạn + 4 bảng · // 91 ô = 36 ô đơn + 55 ô bảng). diff --git a/fe-user/src/lib/contractBody/body002_03.ts b/fe-user/src/lib/contractBody/body002_03.ts index d661e4f7..68278505 100644 --- a/fe-user/src/lib/contractBody/body002_03.ts +++ b/fe-user/src/lib/contractBody/body002_03.ts @@ -1,5 +1,5 @@ // ═══ HĐ TRỌN GÓI NHÂN CÔNG & THIẾT BỊ — `SOL-CCM-FO-002.03` (`HD-TP-TB`, ContractType = 9) ══ -// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong, thiet bi.docx` +// Nguồn chữ: `wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong va thiet bi.docx` // (đọc `word/document.xml`, gộp mọi `` trong cùng `` bằng chuỗi RỖNG — 201 đoạn + // 11 bảng). ⚠️ `form-002-03-structure.md` §1 bị LỖI TRÍCH ở ~40 block (in ra XML thô thay vì // chữ) và cắt câu ở ~150 ký tự ⇒ chữ ở đây đọc THẲNG từ .docx, không chép từ file structure đó. diff --git a/src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx b/src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong va vat tu.docx similarity index 100% rename from src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx rename to src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong va vat tu.docx diff --git a/src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong, thiet bi.docx b/src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong va thiet bi.docx similarity index 100% rename from src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong, thiet bi.docx rename to src/Backend/SolutionErp.Api/wwwroot/templates/SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong va thiet bi.docx diff --git a/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs b/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs index 22b2ecfd..80146dc0 100644 --- a/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs +++ b/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs @@ -3843,6 +3843,14 @@ public static class DbInitializer private static async Task SeedContractTemplatesAsync(ApplicationDbContext db, ILogger logger) { + // 🔴 LUẬT (S194 — CI run #489 ĐỎ thật): TÊN FILE dưới `wwwroot/` CẤM CHỨA DẤU PHẨY. + // MSBuild property-function tách tham số bằng dấu phẩy ⇒ `[MSBuild]::MakeRelative(a, b)` + // với đường dẫn có "," biến thành lời gọi 3 tham số ⇒ `MSB4186: Method not found`, + // CHẶN NGAY Ở BUILD (test chưa kịp khởi động). + // 🔴 Bẫy đắt nhất: LOCAL KHÔNG TÁI HIỆN ĐƯỢC. `global.json` để `rollForward: latestFeature` + // ⇒ CI nhảy SDK 10.0.202 còn local 10.0.104; `grep -c MakeRelative` trong + // `Microsoft.NET.Publish.targets` = **0 ở SDK local**, tức dòng mã gây lỗi KHÔNG TỒN TẠI + // trên máy dev. Cùng họ gotcha #92 (build-env CI trôi khỏi local) nhưng ở tầng .NET SDK. // Chỉ IsActive=true nếu file thực tế tồn tại trong wwwroot/templates/. // 3 file .doc (FO-002.02/03/06) chưa convert sẽ IsActive=false. var templates = new (string FormCode, string Name, ContractType? Type, string FileName, string Format, string? Description)[] @@ -3854,10 +3862,10 @@ public static class DbInitializer // tách loại, `FormFeatures.cs:33` lọc template THEO `ContractType` ⇒ giữ nguyên thì // dropdown "Mẫu" của 2 loại mới RỖNG (reviewer B-5). Mỗi biến-thể nay trỏ đúng loại nó. ("SOL-CCM-FO-002.02", "Hợp đồng trọn gói — Nhân công + Vật tư", ContractType.HopDongThauPhuVatTu, - "SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx", "docx", + "SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong va vat tu.docx", "docx", "Template HĐ thầu phụ trọn gói — Nhân công & Vật tư (01A)"), ("SOL-CCM-FO-002.03", "Hợp đồng trọn gói — Nhân công + Thiết bị", ContractType.HopDongThauPhuThietBi, - "SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong, thiet bi.docx", "docx", + "SOL-CCM-FO-002.03.v01 Hop dong trong goi nhan cong va thiet bi.docx", "docx", "Template HĐ thầu phụ trọn gói — Nhân công & Thiết bị (01B)"), ("SOL-CCM-FO-002.04", "Điều kiện chung hợp đồng trọn gói", null, "SOL-CCM-FO-002.04.v01 Dieu kien chung hop dong tron goi.docx", "docx",