Báo cáo sai lệch — inventory/batch-on-hands — vòng 1
0. Kết luận nhanh
- Điều kiện đạt:
G1 ✅ G2 ✅ G3 ✅ G4 — G5 ✅ G6 ✅→ CHỜ KIỂM SONAR (máy đạt hết, chờ người kiểm G4) - Trạng thái: SẴN SÀNG CHO NGƯỜI XEM
- Tầng rủi ro: C (chỉ đọc) → người cần đọc: spec + báo cáo
- Số quy tắc: 11 · PASS 3 (R-03, R-06*, R-08 mã lỗi) · DEVIATION có chủ đích 6 (R-01, R-02, R-04 kho lớn, R-07, R-10, R-11) · DEVIATION KHÔNG chủ đích 0 · UNVERIFIED 2 (R-05 thứ tự lô, R-09 DB đọc) — *R-06 xem F-logic-2
- Coverage thấp nhất: F-01 100% dòng (41/41) / 100% nhánh (8/8)
- Finding logic: CRITICAL 0 · MAJOR 0 · MINOR 2 · UNSURE 0
- Nghi vấn bug code cũ (mục 3c): 0 · Quyết định tự chốt cần xác nhận (mục 3d): 9
- Chạy bằng:
/mig-autolượt20261105-1351(spec dospec-reviewerkiểm, chưa có người duyệt) · Số vòng: 1 verify / lần sửa 0/3
1. Điều kiện đạt
| Mã | Mục tiêu | Kết quả | Bằng chứng |
|---|---|---|---|
| G1 | Kiến trúc ADR (mvnw verify) |
✅ | verify/round-1/build.md (623 test, exit 0) |
| G2 | Test khớp test-plan, mọi R-xx có test | ✅ | verify/round-1/oracle.md (23/23 TC) |
| G3 | Coverage mỗi luồng | ✅ | verify/round-1/coverage.md |
| G4 | 0 issue Sonar | CHỜ NGƯỜI | sonar-ide.md |
| G5 | 0 finding CRITICAL/MAJOR đã xác nhận | ✅ | verify/round-1/review-logic.md (không cần xác minh) |
| G6 | Không lách cổng | ✅ | verify/round-1/gates.md; 17 file đều có trong impl-notes.md |
Không chặn nhưng cần người: Integration test CHƯA CHẠY · Golden master CHƯA CHẠY (GM-01)
Coverage theo luồng
| Luồng | Tên | % dòng | % nhánh |
|---|---|---|---|
| F-01 | Tồn theo lô của danh sách ppu trong một kho | 100.0% (41/41) | 100.0% (8/8) |
2. Ma trận truy vết
| Quy tắc | Tầng | Code mới | Test | Golden | Kết luận |
|---|---|---|---|---|---|
| R-01 | C | BatchOnHandController.java, BatchOnHandsRequest.java |
TC-01, 02, 11 | — | DEVIATION (có chủ đích, D-02) |
| R-02 | C | InventoryQueryService.java:96-97 |
TC-03, 04 | — | DEVIATION (có chủ đích, D-03) |
| R-03 | C | BatchOnHandJdbcRepository.java:27-41, InventoryQueryService.java:98-104 |
TC-05..09 | GM-01 | PASS (H2; MSSQL UNVERIFIED — K-13) |
| R-04 | C | BatchOnHandJdbcRepository.java:37-38 |
TC-10, 11, 12 | GM-01 | DEVIATION (có chủ đích, D-09: kho > 2048 lô cũ lỗi, mới không) |
| R-05 | C | BatchOnHandJdbcRepository.java:41, InventoryQueryService.java:99-104 |
TC-13, 14, 18 | GM-01 | UNVERIFIED (thứ tự lô cũ không xác định — D-04) |
| R-06 | C | BatchOnHandItemResponse.java, BatchOnHandJdbcRepository.java:72-74 |
TC-15, 16, 17 | GM-01 | PASS khi JVM ở UTC+7; xem F-logic-2 |
| R-07 | C | BatchOnHandController.java:46-47 |
TC-19, 20 | — | DEVIATION (có chủ đích, D-02, D-07) |
| R-08 | C | InventoryQueryService.java:93-95 |
TC-21 | — | DEVIATION (có chủ đích, D-06: 417 → 500); thứ tự kiểm khác (F-logic-1) |
| R-09 | C | InventoryQueryService.java:91 |
TC-22 | — | UNVERIFIED (D-08) |
| R-10 | C | — | — | — | DEVIATION (có chủ đích, D-05) |
| R-11 | C | InventoryRelationalRepository.java:68-74 |
TC-23 | — | DEVIATION (có chủ đích, D-06) |
3. Người cần xem
| # | Vị trí | Vì sao cần người xem |
|---|---|---|
| 1 | BatchOnHandJdbcRepository.java:72-74 + BatchOnHandItemResponse.java (F-logic-2, MINOR) |
Ngày mfgDate/expDate: nếu JVM prod mới chạy UTC mà mapper HTTP có time-zone: Asia/Ho_Chi_Minh (application-dev.yml:64) thì giờ 17:00–23:59 bị đẩy sang ngày hôm sau (đã chạy thử: 2026-06-30T23:59:59Z → "2026-07-01"). Chốt múi giờ JVM prod (cũ và mới) hoặc đổi adapter sang atZone(Asia/Ho_Chi_Minh). Spec R-06 ghi "luôn = ngày trong DB" là chưa đủ điều kiện. BatchRelationalRepository có sẵn cùng cách đọc |
| 2 | InventoryQueryService.java:93-97 (F-logic-1, MINOR) |
Thiếu ppuIds và token không có companyId cùng lúc → mới 500 EXCEPTION_ERROR, cũ báo lỗi công ty/token trước. Đổi thứ tự 2 kiểm nếu muốn khớp |
| 3 | BatchOnHandJdbcRepository.java:27-41 |
SQL native chỉ chạy H2; chạy GM-01 trên MSSQL để chốt R-03..R-06 (K-13) |
| 4 | R-05 (D-04) | Thứ tự lô cũ không có ORDER BY — mới sắp theo id lô; UNVERIFIED |
| 5 | InventoryQueryService, InventoryRelationalRepository |
Constructor thêm phụ thuộc (CurrentUserPort, BatchOnHandJdbcRepository); sửa dòng dựng ở WarehouseTransferServiceTest |
| 6 | G4 | Sonar chưa kiểm |
3b. Phân tích luồng sau chuyển
Chi tiết: verify/round-1/flow-analysis.md
| Luồng | Tên | Số bước KHỚP / KHÁC / CHỈ CÓ Ở CŨ / CHỈ CÓ Ở MỚI | Lệch luồng đã duyệt (spec mục 6) | Điểm dev cần chú ý |
|---|---|---|---|---|
| F-01 | Tồn theo lô của danh sách ppu trong một kho | 4 / 8 (đều có chủ đích hoặc MINOR) / 1 (kiểm gói, D-05) / 0 | không | Thứ tự tham số comId, comId, warehouseId; ngày phụ thuộc múi giờ; HashSet nhận null; @JsonInclude(ALWAYS) bắt buộc |
3c. Nghi vấn bug / sai ở code cũ (đã GIỮ nguyên khi chuyển)
Không có.
3d. Quyết định AI tự chốt và thay đổi tự động (cần người xác nhận)
| # | Nguồn | AI đã làm gì | Khác code cũ ở điểm nào (input → cũ / mới) | Người cần xác nhận gì |
|---|---|---|---|---|
| 1 | D-07 (ADR BẮT KHÁC) | Theo BaseResponseDTO + mapper starter |
không lô nào khớp → cũ "data":{} / mới không có key data |
Chốt chung với inventory/get-detail-product D-07, warehouse/get-with-paging |
| 2 | D-09 (LỖI KỸ THUẬT) | Một câu JOIN, không đưa id lô vào IN |
kho > 2048 lô khác nhau → cũ 417 EXCEPTION_ERROR / mới 200 có dữ liệu |
Đồng ý kho lớn không còn lỗi |
| 3 | D-03 (PHỤ THUỘC NGOÀI) | Công ty = claim companyId của token |
token không có companyId → cũ quản trị {} / user thường 500 COMPANY_NOT_EXISTS, mới TOKEN_INVALID_OR_EXPIRED; công ty không tồn tại → cũ 400, mới data rỗng; token đổi mật khẩu → cũ 500 TOKEN_EXPIRED, mới đọc được |
Filter starter đã đủ kiểm token; không cần kiểm user/password version ở service |
| 4 | D-08 (MƠ HỒ, lệch ADR-0201:180) | @Transactional không readOnly |
không khác (nếu suy luận đúng) | Chốt đọc DB chính hay replica |
| 5 | D-04 (MƠ HỒ) | ORDER BY b.id, i.id, bd.id |
thứ tự lô: cũ do DB, mới theo id lô | Chấp nhận thứ tự theo id |
| 6 | D-02 (ADR BẮT KHÁC) | Body response/lỗi theo starter | body hỏng → cũ 400 rỗng / mới 400 INVALID_REQUEST |
Client không đọc body 400 rỗng |
| 7 | D-05 (PHỤ THUỘC NGOÀI) | Không kiểm gói | công ty hết gói → cũ 400 ACCOUNT_EXPIRED / mới trả tồn |
Tầng nào kiểm gói |
| 8 | D-06 (ADR BẮT KHÁC) | SystemException(EXCEPTION_ERROR) |
ppuIds null, lỗi DB → cũ 417 / mới 500, cùng mã |
Client không phụ thuộc 417 |
| 9 | spec-review | Spec qua 1 lần review, các R-xx đã sửa theo MAJOR: R-04, R-06 (F-spec-1, F-spec-2) | — | Đọc kỹ R-04, R-06 trong spec.md (R-06 xem thêm mục 3 dòng 1) |
4. Finding đã xác nhận
Không có finding CRITICAL/MAJOR. Finding MINOR (chuyển cho người, mục 3 dòng 1–2): F-logic-1 (thứ tự kiểm ppuIds null với token), F-logic-2 (múi giờ ngày) — chi tiết ở verify/round-1/review-logic.md.
5. Finding bị loại
| Finding | Lý do loại |
|---|---|
| (không có) |
6. Xử lý của người
| Vấn đề | Cổng | Chỉ thị |
|---|---|---|
| (không có vấn đề làm trượt cổng máy; G4 chờ người kiểm Sonar) | G4 | |
F-logic-1 (MINOR) — muốn sửa thứ tự kiểm thì ghi SỬA |
— | |
F-logic-2 (MINOR) — muốn cố định múi giờ VN ở adapter thì ghi CÁCH KHÁC: atZone(Asia/Ho_Chi_Minh) |
— |
7. So với vòng trước
| Vấn đề | Vòng trước | Vòng này |
|---|---|---|
| (vòng đầu) | — | — |
8. Thay đổi trong repo đích
17 file (verify/round-1/changed-files.md), đều trong src/main, src/test:
- Mới (main):
BatchOnHandController,dto/request/BatchOnHandsRequest,dto/response/BatchOnHandItemResponse,domain/inventory/result/BatchOnHandResult,infrastructure/relational/inventory/jpa/BatchOnHandJdbcRepository. - Sửa (main, file đã tạo/sửa ở unit
inventory/get-detail-productcùng lượt):InventoryWebMapper,InventoryQueryService,InventoryRepository,InventoryErrorCode,InventoryRelationalRepository,i18n/messages_vi|en.properties. - Test mới:
BatchOnHandControllerTest,BatchOnHandJdbcRepositoryTest; test sửa:InventoryQueryServiceTest(@Nested),InventoryRelationalRepositoryTest(@Nested),WarehouseTransferServiceTest(1 dòng).
9. Đề xuất bổ sung kinh nghiệm
| Đề xuất | Đưa vào đâu |
|---|---|
@JsonFormat(pattern) không timezone: Jackson đổi giá trị sang múi giờ của mapper nếu mapper có múi giờ tường minh (đã chạy thử). Repo đích đặt spring.jackson.time-zone: Asia/Ho_Chi_Minh còn code cũ thì không → ngày phụ thuộc múi giờ JVM. Ghi vào spec khi API trả ngày |
legacy-facts.md + lessons.md 1a |
Hibernate 5.6 + SQL Server: danh sách IN rỗng → in (null) (không lỗi); in_clause_parameter_padding: true làm tròn tham số lên luỹ thừa 2 → > 2048 phần tử vượt 2100 tham số |
legacy-facts.md |
getUserWithAuthorities (backend): công ty lấy từ claim JWT, các kiểm user/công ty chỉ chạy khi cache miss; lỗi phần lớn 500 BaseInternalServerException, riêng công ty không tồn tại 400 |
legacy-facts.md mục 3 |