wal: flush 20260727T1250

This commit is contained in:
pqhuy1987
2026-07-27 12:50:05 +07:00
parent dfbaeb1e76
commit 3ec2f116a2
4 changed files with 180 additions and 6 deletions

View File

@ -18,6 +18,172 @@
---
## Migration nội dung (đọc từ đĩa, file có trong commit)
`20260727033522_AddPeAllowApproverDelete.cs` Up():
```csharp
migrationBuilder.AddColumn<bool>(
name: "AllowApproverDelete", table: "ApprovalWorkflowLevels",
type: "bit", nullable: false, defaultValue: false);
```
→ AddColumn-only, **no new table** (kỳ vọng `sys.tables` giữ 89). Down = DropColumn (reversible).
## Pre-deploy bundle snapshot (chụp LÚC run đang chạy, 12:38)
| App | JS | CSS |
|---|---|---|
| admin | `index-hHISK1Ig.js` | `index-CBzUlgOA.css` |
| eoffice | `index-CJeXZso2.js` | `index-BHsBUA8e.css` |
## Stage 2 — Gitea Actions run (IN PROGRESS)
_(pending)_
- Run **id=529 · run_number=#416 · head_sha `b1bae77c`** — MATCH commit ✅
- created_at `2026-07-27T12:37:18+07:00` · status lúc đo đầu = `running`
- Run URL: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/416
- **TERMINAL: `status=success`** · updated `2026-07-27T12:42:49+07:00` · **duration 5m31s** (12:37:18→12:42:49) — trong dải bình thường (~5m30 các run gần đây)
- ⚠️ `conclusion=None` là bình-thường ở Gitea `tasks` API (đã tái-xác-nhận nhiều lần) → tin `status`.
### Test gate — CÓ CHẠY và PASS
Log web-UI `runs/416/jobs/0/logs` (17.856 B tải về), trích nguyên văn:
```
Passed! - Failed: 0, Passed: 45, Skipped: 0
Passed! - Failed: 0, Passed: 506, Skipped: 0
```
**45 Domain + 506 Infra = 551 PASS / 0 FAIL / 0 SKIP**. **KHỚP CHÍNH XÁC số local lead đo (551 = 45+506)**
Baseline dịch: 532 (run #407) → **551** (+19 Infra).
Test gate chạy TRƯỚC build/deploy ⟹ `status=success` ⟹ gate đã qua.
---
## 🔴 Stage 3 — MIGRATION TRÊN DB PROD (kiểm quan trọng nhất) — **PASS**
`sqlcmd` qua `ssh vietreport-vps`, DB `SolutionErp`, user `vrapp`. Output NGUYÊN VĂN:
```
=== TOP3 HISTORY ===
20260727033522_AddPeAllowApproverDelete
20260717032812_AddPeApprovedBudgetSnapshot
20260714035636_AddPeApprovedPriceRange
=== TARGET MIG ROW ===
20260727033522_AddPeAllowApproverDelete
=== COLUMN ===
ApprovalWorkflowLevels|AllowApproverDelete|bit|nullable=NO
=== SYSTABLES ===
89
=== DEFAULT ===
(CONVERT([bit],(0)))
```
**Đối chiếu (đây là điểm F8):**
| Kiểm | Kỳ vọng | Thực tế | KQ |
|---|---|---|---|
| Row `20260727033522_...` trong `__EFMigrationsHistory` | có + ở TOP | **có, ở TOP** | ✅ |
| Cột `AllowApproverDelete` trên `ApprovalWorkflowLevels` | tồn tại, `bit`, NOT NULL | **tồn tại, `bit`, nullable=NO** | ✅ |
| Default constraint | `0` | `(CONVERT([bit],(0)))` | ✅ |
| `sys.tables` (is_ms_shipped=0) | 89 (AddColumn no-new-table) | **89** | ✅ |
| **Nhất quán history ⟷ cột** | cả 2 cùng có | **cả 2 cùng có** | ✅ **KHÔNG lệch** |
🟢 **Kịch bản F8 (model có cột / DB không có ⟹ `Invalid column name` hạ 7 module) KHÔNG xảy ra.**
Baseline TRƯỚC deploy (đo lúc 12:38, run còn chạy): history top = `20260717032812_AddPeApprovedBudgetSnapshot`, chưa có mig mới
→ chứng minh mig được áp **trong** cửa-sổ deploy này, không phải sẵn có từ trước.
Mig repo mới nhất giờ = **Mig 68 `AddPeAllowApproverDelete`** (trước là Mig 67).
---
## Stage 4 — Smoke 7 module V2 — **PASS 8/8**
Bearer admin (`POST /api/auth/login` → HTTP 200, token 468 ký tự). Output thật:
```
PE /api/purchase-evaluations?page=1&pageSize=5 HTTP 200 bytes=5103 InvalidCol=False
HopDong /api/contracts?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
DeXuat /api/proposals?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
NghiPhep /api/leave-requests?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
TangCa /api/ot-requests?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
CongTac /api/travel-requests?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
DatXe /api/vehicle-bookings?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
AwV2-list /api/approval-workflows-v2 HTTP 200 bytes=41234 InvalidCol=False
```
**0/8 có chuỗi `Invalid column name`**, 8/8 HTTP 200. Kịch bản F8 không tái hiện được.
⚠️ Trung thực về độ mạnh: 6 module Văn-phòng-số trả 91 B (envelope rỗng, chưa có dữ-liệu) nên chỉ chứng minh **query chạy không ném**, chưa chứng minh join sâu vào Levels. Hai phép mạnh thật nằm ở PE (5.103 B có dữ-liệu) và AwV2 (41.234 B) dưới đây.
### 🔑 Phép thử TRỰC TIẾP nhất cho F8 — cột round-trip qua EF
`GET /api/approval-workflows-v2` (endpoint đọc THẲNG bảng `ApprovalWorkflowLevels`):
```
bytes 41234
count allowApproverDelete = 54
count allowApproverFinalize = 54
LEVEL sample: allowApproverDelete= False | order= 1 | keys# 17
```
→ Cột MỚI được EF materialize **54 lần** từ DB thật ra JSON, giá-trị `False` đúng default `0`.
Nếu DB thiếu cột thì chính truy-vấn này đã ném `Invalid column name`**đây là bằng-chứng khép kín model ⟷ DB đồng bộ.**
## Stage 5 — Endpoint MỚI `PUT /api/approval-workflows-v2/{id}` — **PASS (401, không phải 404)**
```
PUT /api/approval-workflows-v2/1111...1111 (KHÔNG token, có body) -> 401
GET /api/approval-workflows-v2/1111...1111 (KHÔNG token, có body) -> 405
--- control: route chắc chắn KHÔNG tồn tại ---
PUT /api/approval-workflows-v2-nonexistent/{id} -> 404
```
→ Route **401** = đã lên + `[Authorize]` chặn đúng. Control route bịa trả **404** ⟹ 404 đúng là tín-hiệu "route chưa lên", nên 401 ở route thật là có nghĩa (discriminator sạch, không phải may).
(405 ở GET chỉ nói `GET {id}` không được map — không liên quan.)
## Stage 6 — Bundle FE — **PASS (deploy thay file thật, không phải cache)**
```
== admin ==
JS pre=index-hHISK1Ig.js post=index-CiUBEEJr.js ROTATED
CSS pre=index-CBzUlgOA.css post=index-DX5ew0wg.css ROTATED
real-js index-CiUBEEJr.js HTTP 200 size=1670035 ct=application/javascript LM=Mon, 27 Jul 2026 05:41:28 GMT
FAKE-ctl index-ZZfakehash0.js HTTP 200 size=900 ct=text/html
== eoffice ==
JS pre=index-CJeXZso2.js post=index-DFh7GK0t.js ROTATED
CSS pre=index-BHsBUA8e.css post=index-BHsBUA8e.css FROZEN
real-js index-DFh7GK0t.js HTTP 200 size=1570257 ct=application/javascript LM=Mon, 27 Jul 2026 05:42:22 GMT
FAKE-ctl index-ZZfakehash0.js HTTP 200 size=876 ct=text/html
```
- **JS ROTATE cả 2 app** ✅ — khớp commit có sửa src cả `fe-admin` (1 file) lẫn `fe-user` (2 file).
- `Last-Modified` **05:41:28 / 05:42:22 GMT = 12:41:28 / 12:42:22 +07****NẰM TRONG cửa-sổ deploy** 12:37:1812:42:49 ✅ (đây mới là ship-proof chính, không phải hash-delta).
- real-size 1.670.035 / 1.570.257 B; bẫy SPA-fallback: hash bịa cũng trả 200 nhưng **`ct=text/html` + 900/876 B** ⟹ discriminator sạch, file thật là JS thật.
- eoffice **CSS FROZEN** = lành tính (#69-REFINE): 2 file fe-user sửa là logic/type, không thêm utility-class Tailwind mới ⟹ CSS byte-identical ⟹ cùng content-hash. Admin CSS rotate vì thêm ô chọn F6 (class mới).
### Byte-verify #77 — mã tính-năng CÓ THẬT trong bundle prod
```
admin size=1670035 allowApproverDelete=7 allowApproverFinalize=11
eoffice size=1570257 allowApproverDelete=1 allowApproverFinalize=5
```
→ chuỗi `allowApproverDelete` hiện diện trong CẢ HAI bundle đã ship ⟹ không chỉ "file mới" mà **đúng mã F6 đã lên**.
## Health
```
/health/live -> 200 b'Healthy'
/health/ready -> 200 b'Healthy'
```
---
## KẾT LUẬN
**CICD: PASS** — 6/6 hạng mục bắt buộc đạt, rủi ro F8 đã loại trừ bằng bằng-chứng trực tiếp trên DB prod.
| # | Hạng mục | KQ |
|---|---|---|
| 1 | Gitea run `b1bae77` + test gate | ✅ #416 success 5m31s · 551 PASS (45+506) 0 fail |
| 2 | 🔴 Mig áp trên DB prod | ✅ `20260727033522_AddPeAllowApproverDelete` ở TOP history |
| 3 | 🔴 Cột có thật | ✅ `bit` NOT NULL default 0 — **khớp history, không lệch** |
| 4 | Smoke 7 module | ✅ 8/8 HTTP 200, 0 `Invalid column name` |
| 5 | Endpoint mới PUT | ✅ 401 (control route bịa = 404) |
| 6 | Bundle FE 2 app | ✅ JS rotate ×2, LM trong cửa-sổ, marker F6 có trong bundle |
Không có mục nào "không truy được". Không có cảnh-báo cần leo thang.
Baseline cập nhật: test **532 → 551**; mig mới nhất **Mig 67 → Mig 68**; `sys.tables` giữ **89**.
<!-- END cicd-verify-dot1 -->