Báo cáo sai lệch — batch/get-with-paging — vòng 1
…/ = src/main/java/com/softdreams/easypos/warehouse/. Repo đích ban đầu C:/Projects/warehouse-service-wt/ws2; từ 2026-11-06 08:03 code đã chuyển sang C:/Projects/warehouse-service-wt/ws1 (branch feat/thongpd/migrate-batch2) — xem chuyen-ws1.md.
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 → người cần đọc: spec + báo cáo
- Số quy tắc: 13 · PASS 8 · DEVIATION có chủ đích 3 (R-01, R-02, R-10 — D-01, D-02) · DEVIATION KHÔNG chủ đích 0 · UNVERIFIED 2 (R-11 nguồn đọc, R-13 kiểm gói) — SQL native của R-03…R-09 mới chỉ test bằng mock (K-13)
- Coverage thấp nhất: F-01 99.2% / 95.3%
- Finding logic: CRITICAL 0 · MAJOR 0 (đã xác nhận) · MINOR 4 · UNSURE 0
- Nghi vấn bug code cũ (mục 3c): 9 (CAO 1) · Quyết định tự chốt cần xác nhận (mục 3d): 11
- Chạy bằng:
/mig-auto(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: build, test, ArchUnit, Checkstyle/PMD/SpotBugs) |
✅ (526 test, 0 lỗi) | verify/round-1/build.md |
| G2 | Test khớp test-plan, mọi R-xx có test | ✅ (47/47 TC khớp) | verify/round-1/tc-map.md, oracle.md |
| G3 | Coverage mỗi luồng (dòng ≥ 80%, nhánh ≥ 70%) | ✅ | verify/round-1/coverage.md |
| G4 | 0 issue Sonar (người kiểm bằng SonarQube for IDE) | CHỜ NGƯỜI | sonar-ide.md |
| G5 | 0 finding logic CRITICAL/MAJOR đã xác nhận | ✅ (không có finding nặng — không cần xác minh) | verify/round-1/review-logic.md |
| G6 | Không lách cổng, không ghi ngoài phạm vi | ✅ | verify/round-1/gates.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 trong test-plan.md)
Coverage theo luồng
| Luồng | Tên | % dòng | % nhánh |
|---|---|---|---|
| F-01 | Danh sách lô theo trang | 99.2% (120/121) | 95.3% (61/64) |
2. Ma trận truy vết
| Quy tắc | Tầng | Code mới | Test | Golden | Kết luận |
|---|---|---|---|---|---|
| R-01 | C | …/presentation/web/batch/BatchController.java, dto/request/BatchPageRequest.java |
TC-01..04 | — | DEVIATION (có chủ đích, D-02: body lỗi theo starter) |
| R-02 | C | …/application/batch/BatchPageQueryService.java |
TC-05..09 | — | DEVIATION (có chủ đích, D-01: bỏ các kiểm user khác) |
| R-03 | C | BatchPageQueryService, …/infrastructure/relational/batch/adapter/BatchPageReader.java:158-170 |
TC-08, TC-10..16 | — | PASS (417→500 theo D-03) |
| R-04 | C | …/domain/batch/model/BatchKeyword.java, BatchPageReader.java:41 |
TC-17..21 | GM-01 | PASS |
| R-05 | C | BatchPageReader.java:42-67 |
TC-22..25 | GM-01 | PASS (SQL nguyên văn; chạy MSSQL UNVERIFIED) |
| R-06 | C | BatchPageReader.java (HAVING) |
TC-26..28 | GM-01 | PASS |
| R-07 | C | BatchPageReader.java (read, pageTotal) |
TC-13, TC-29..31 | GM-01 | PASS |
| R-08 | C | BatchPageReader.java:78-90 |
TC-32, TC-33 | GM-01 | PASS (thứ tự trùng khoá không xác định — D-09) |
| R-09 | C | BatchPageReader.java:230-262, dto/response/BatchListItemResponse.java |
TC-34..38 | GM-01 | PASS (ngày theo múi giờ — D-12 UNVERIFIED) |
| R-10 | C | BatchController.java |
TC-39, TC-40, TC-47 | — | DEVIATION (có chủ đích, D-02: mất key data khi rỗng) |
| R-11 | C | BatchPageQueryService.getBatchPage @Transactional |
TC-41 | — | UNVERIFIED (nguồn đọc của code cũ — D-10) |
| R-12 | C | BatchPageReader.read |
TC-15, TC-42..44 | — | PASS (500 thay 417, giữ mã — D-03) |
| R-13 | C | — | TC-45 | — | UNVERIFIED (không kiểm gói — D-11) |
3. Người cần xem
| # | Vị trí | Vì sao cần người xem |
|---|---|---|
| 1 | …/infrastructure/relational/batch/adapter/BatchPageReader.java:35-99 |
SQL native (điều kiện hạn dùng, HAVING, ORDER BY) chỉ test bằng mock — cần chạy thử trên MSSQL thật / GM-01 (K-13) |
| 2 | BatchPageReader.java toZonedDateTime (dùng chung BatchRelationalRepository.java:93) |
Nếu mfg_date/exp_date là kiểu SQL date (Hibernate 6 trả java.sql.Date/LocalDate) thì ép kiểu lỗi → 500 — cần xác nhận kiểu cột trên DB thật |
| 3 | F-logic-1..4 (MINOR) | xem mục 4; không chặn |
| 4 | G4 | Chưa kiểm Sonar |
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 | Danh sách lô theo trang | 17 bước: KHỚP 11 / KHÁC 4 (có chủ đích D-02 ×2, D-03 ×2) / CHỈ CÓ Ở CŨ 2 (D-01, D-11) / CHỈ CÓ Ở MỚI 0 | lệch spec mục 6: class BatchPageQueryService thay BatchQueryService (F-logic-1) |
(1) Hằng SQL ghép text block trong BatchPageReader.java:35-99 chỉ được test bằng mock, cần chạy thử MSSQL. (2) Phạm vi catch ở read (dòng 125-140). (3) Phép ép (int) offset và cách tính count (dòng 158-165, 219-228). (4) Nếu mfg_date/exp_date là kiểu SQL date thì toZonedDateTime ném ClassCastException và trả 500. |
3c. Nghi vấn bug / sai ở code cũ (đã GIỮ nguyên khi chuyển)
B-01 Tổng tồn của lô bị bỏ phần lẻ
- Mức nghi ngờ: CAO — cột tồn là số thập phân (21,6) nhưng code cũ đọc tổng thành số nguyên; màn danh sách hiển thị sai với hàng bán theo cân/lít.
- Ở đâu: code cũ
backend:domain/Batches.java:34,backend:repository/impl/BatchRepositoryImpl.java:158,175→ code mới (giữ nguyên)…/infrastructure/relational/batch/adapter/BatchPageReader.java:247-249 - Code cũ đang làm gì: cộng tồn các dòng của lô (đúng, có phần lẻ), nhưng khi đọc kết quả thì ép về số nguyên nên phần lẻ bị cắt.
- Ví dụ cụ thể: lô có 2 dòng tồn 5.5 kg và 7.2 kg → hệ thống cũ (và mới) hiển thị
totalOnHand = 12. Lẽ ra là 12.7. Lô tồn 0.5 kg → lọc "Còn hàng" vẫn ra lô này nhưng tồn hiển thị 0. - Vì sao nghi là sai: bộ lọc "Còn hàng/Hết hàng" dùng tổng thật (có phần lẻ) còn số hiển thị lại cắt — hai chỗ mâu thuẫn; field
totalOnHandOfPpucùng màn lại trả số thập phân. - Ảnh hưởng nếu đúng là bug: mọi công ty bán hàng theo đơn vị lẻ thấy tồn lô sai; tồn âm -3.5 hiển thị -3.
- Đã xử lý khi chuyển: GIỮ nguyên. Test khoá:
TC-34(BatchPageReaderTest#mapsTenColumnRowAndTruncatesOnHand),TC-35. - Nếu muốn sửa: đổi
totalOnHandsangBigDecimalởBatchListItem/BatchListItemResponse, đọc thẳngBigDecimalởBatchPageReader.toItem; sửa TC-34/35. Đổi kiểu JSON (số nguyên → thập phân) — frontend cần kiểm. - Liên quan: D-04, R-09
B-02 "Số sản phẩm" của lô đếm số dòng theo kho, không đếm sản phẩm
- Mức nghi ngờ: TRUNG BÌNH — tên field gợi ý số sản phẩm, nhưng có thể màn hình dùng theo nghĩa "số dòng".
- Ở đâu:
backend:repository/impl/BatchRepositoryImpl.java:157,174→BatchPageReader.java:96 - Code cũ đang làm gì: đếm mọi dòng chi tiết lô (mỗi kho một dòng) có đơn vị chính.
- Ví dụ cụ thể: lô L01 có sản phẩm A ở kho 1 và kho 2 →
totalProductProductUnits = 2dù chỉ 1 sản phẩm. Lẽ ra 1. - Vì sao nghi là sai: không có
DISTINCT. - Ảnh hưởng nếu đúng là bug: công ty nhiều kho thấy số sản phẩm của lô bị nhân lên.
- Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-34(giá trị 2 từ cột đếm), câu SQL ởTC-04,TC-32. - Nếu muốn sửa:
COUNT(DISTINCT ppu.id)trongSELECT_SQL; sửa mảnhSELtrong test-plan vàBatchPageReaderTest. - Liên quan: D-05, R-09
B-03 Lô không có hạn dùng hoặc không có cấu hình cảnh báo không thuộc "Còn hạn"/"Sắp hết hạn"
- Mức nghi ngờ: TRUNG BÌNH — create/update bắt buộc có đơn vị/giá trị cảnh báo (F-logic-3) nên chỉ lô ghi qua đường khác (import, ETL) hoặc lô không nhập ngày hết hạn mới gặp.
- Ở đâu:
backend:repository/impl/BatchRepositoryImpl.java:52-105→BatchPageReader.java:43-67 - Code cũ đang làm gì: mốc cảnh báo tính bằng
CASEkhông có nhánh mặc định → NULL → lô bị loại khỏi lọc 1 và 2. - Ví dụ cụ thể: lô hết hạn 2028-01-01, đơn vị cảnh báo NULL → chọn "Còn hạn" không thấy, "Sắp hết hạn" không thấy, chỉ thấy ở "Tất cả". Lô không có ngày hết hạn → chỉ thấy ở "Tất cả".
- Vì sao nghi là sai: người dùng nghĩ lô bị mất khi lọc.
- Ảnh hưởng nếu đúng là bug: lô nhập từ nguồn ngoài hoặc lô không hạn dùng.
- Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-23,TC-24(SQL nguyên văn). - Nếu muốn sửa: thêm
ELSEchoCASEtrongWARNING_DATE_SQL; sửa mảnhWARNtrong test-plan. - Liên quan: D-06, R-05
B-04 Lọc theo hạn dùng và cột trạng thái hiển thị lệch nhau
- Mức nghi ngờ: TRUNG BÌNH — lệch có hệ thống, nhất là trong ngày hết hạn.
- Ở đâu: lọc
backend:repository/impl/BatchRepositoryImpl.java:49-105, sắp xếp:129,138, jobbackend:service/impl/BatchesManagementServiceImpl.java:409-430→BatchPageReader.java:42-90 - Code cũ đang làm gì: bộ lọc so ngày hết hạn với giờ hiện tại của DB; cột
status(hiển thị, sắp xếp) do job 4 giờ/lần tính theo 00:00 hôm nay. - Ví dụ cụ thể: 06/11 10:00, lô hết hạn 06/11 00:00, cảnh báo 30 ngày, job đã chạy → cột
status=2(sắp hết hạn). Lọc "Hết hạn" ra lô này nhưng hiển thị "sắp hết hạn"; lọc "Sắp hết hạn" không ra. - Vì sao nghi là sai: hai nguồn trạng thái mâu thuẫn trên cùng màn.
- Ảnh hưởng nếu đúng là bug: người dùng thấy trạng thái không khớp bộ lọc trong ngày hết hạn và tới 4 giờ sau khi lô đổi trạng thái.
- Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-22,TC-32(ORDER theo cộtstatus),TC-34(trả cộtstatus). - Nếu muốn sửa: tính
statustrả về theo cùng công thức với bộ lọc, hoặc lọc theo cột; ảnh hưởng jobdailyUpdateStatuscủa monolith còn chạy song song. - Liên quan: D-07, R-05, R-08
B-05 ppuId chỉ đẩy lô lên đầu, không lọc; hai chỗ so ppuId khác nhau
- Mức nghi ngờ: TRUNG BÌNH
- Ở đâu:
backend:repository/impl/BatchRepositoryImpl.java:128,159→BatchPageReader.java:84-99 - Code cũ đang làm gì: sắp xếp so
ppuIdvới mọi đơn vị của dòng chi tiết; cột tồn củappuIdchỉ tính đơn vị chính. - Ví dụ cụ thể: chọn lô cho đơn vị phụ "hộp" (id 77) có tồn ở lô L01 → L01 lên đầu nhưng
totalOnHandOfPpu = 0; lô không có sản phẩm 77 vẫn hiện (xếp sau). - Vì sao nghi là sai: hai điều kiện cho cùng tham số không nhất quán.
- Ảnh hưởng nếu đúng là bug: màn chọn lô khi bán theo đơn vị phụ.
- Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-29,TC-33. - Nếu muốn sửa: thống nhất
bd.ppu_id/ppu.idtrongORDER_PPU_SQL/SELECT_PPU_SQL. - Liên quan: D-14, R-08, R-09
B-06 Thiếu page hoặc size trả toàn bộ lô; page/size sai báo lỗi hệ thống
- Mức nghi ngờ: THẤP — có thể là thiết kế cố ý (dùng cho "chọn tất cả").
- Ở đâu:
backend:dto/CommonPageable.java:11-16,backend:util/Common.java:279→…/application/batch/BatchPageQueryService.java:55-59,BatchPageReader.java:158-170 - Ví dụ cụ thể:
{"comId":10,"size":20}(quênpage) → trả cả 5.000 lô.page=-1→ 500EXCEPTION_ERROR(cũ 417) thay vì 400. Trái quy tắc đíchdocs/rules/performance.md:355(tối đa 200 dòng/trang). - Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-10..TC-16. - Nếu muốn sửa: validate 400 + giới hạn
sizeởBatchPageQueryService.validatePage. - Liên quan: D-13, R-03
B-07 Từ khoá chỉ có dấu cách loại lô chưa có tên chuẩn hoá; %, _ là ký tự đại diện
- Mức nghi ngờ: THẤP
- Ở đâu:
backend:repository/impl/BatchRepositoryImpl.java:43-46→…/domain/batch/model/BatchKeyword.java:42-46 - Ví dụ cụ thể: 5 lô, 1 lô
normalized_nameNULL:keyword=""→ 5 lô;keyword=" "→ 4 lô.keyword="_"→ mọi lô. - Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-19,TC-21. - Nếu muốn sửa:
trimtrước khi kiểm rỗng, escape%/_/[trongBatchKeyword.likePattern. - Liên quan: D-08, R-04
B-08 Số cảnh báo âm làm lô đã hết hạn vẫn thuộc "Còn hạn"
- Mức nghi ngờ: THẤP — API create/update chặn số âm (
SaveBatchRequest.java:21-23, F-logic-3); chỉ dữ liệu ghi qua đường khác gặp. - Ở đâu:
backend:repository/impl/BatchRepositoryImpl.java:79-105→BatchPageReader.java:67 - Ví dụ cụ thể: lô hết hạn 05/11, cảnh báo -10 ngày → lọc "Còn hạn" và "Hết hạn" đều ra lô này.
- Đã xử lý khi chuyển: GIỮ. Test khoá:
TC-24. - Nếu muốn sửa: thêm
AND b.exp_date > GETDATE()vàoVALID_SQL. - Liên quan: D-15, R-05
B-09 Số cảnh báo âm lớn làm lỗi cả danh sách khi lọc hạn dùng
- Mức nghi ngờ: THẤP — theo phạm vi
datetimecủa MSSQL, chưa chạy thử; cần dữ liệu âm ghi qua đường khác API. - Ở đâu:
backend:repository/impl/BatchRepositoryImpl.java:55-77,82-104→BatchPageReader.java:43-64 - Code cũ đang làm gì: chặn biên của số cảnh báo theo năm 9999 nhưng chiều âm
GETDATE()lùi quá 1753-01-01 đã tràn trước khi chạm biên chặn. - Ví dụ cụ thể: một lô cảnh báo -300 năm, chọn "Còn hạn" → lỗi SQL tràn
datetime→ cũ 417, mới 500EXCEPTION_ERROR, không ra danh sách. - Đã xử lý khi chuyển: GIỮ (SQL nguyên văn). Test khoá:
TC-23,TC-24(câu SQL). - Nếu muốn sửa: sửa biên chặn chiều âm; ghi D-xx mới.
- Liên quan: F-logic-4, R-05
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 | spec-review | spec qua 1 lần review (tầng C), 6 MINOR đã CHẤP NHẬN (R-01, R-05, R-09, D-07, D-12, D-13, D-15 mới, mục 5); các R-xx/D-xx đã sửa theo CRITICAL/MAJOR: không có | — | Đọc nhanh các mục trên trong spec.md/decisions.md |
| 2 | D-01 (PHỤ THUỘC NGOÀI) | chỉ giữ 2 kiểm token/công ty, đúng mã/HTTP cũ | token cũ sau đổi mật khẩu → cũ 500 TOKEN_EXPIRED / mới trả danh sách; user bị khoá → cũ 500 USER_NOT_FOUND / mới trả danh sách |
Chấp nhận bỏ kiểm user/password version? |
| 3 | D-02 (ADR BẮT KHÁC) | body theo starter | không có lô → cũ "data":[] / mới không có key data; thiếu comId → cũ 400 mã COMPANY_ID_NOT_NULL / mới 400 INVALID_REQUEST kèm danh sách vi phạm có COMPANY_ID_NOT_NULL |
Frontend chịu được? |
| 4 | D-03 (ADR BẮT KHÁC) | 417 → 500, giữ EXCEPTION_ERROR |
page=-1 → cũ 417 / mới 500 |
Xác nhận |
| 5 | D-09 (MƠ HỒ) | giữ ORDER BY nguyên văn | thứ tự lô trùng khoá do DB quyết ở cả hai | Có cần thêm b.id làm khoá cuối? |
| 6 | D-10 (MƠ HỒ) — nhiều khả năng sai | @Transactional không readOnly → DB chính |
Sau khi viết report, lesson-reviewer (migrations/_learn/20261106-0210/review.md P-03) chỉ ra: InjectionMetadata.checkConfigMembers để @PersistenceContext(readOnlyPersistenceUnit) thắng @Autowired → code cũ đọc replica. Vừa tạo lô → cũ có thể chưa thấy (replica trễ) / mới thấy ngay |
Ưu tiên: xác nhận (mở InjectionMetadata.checkConfigMembers của spring-beans 5.3 hoặc chạy thử monolith); nếu đúng, đổi D-10 thành đọc replica (@Transactional(readOnly = true), K-24), sửa TC-41, chạy /mig-run batch/get-with-paging |
| 7 | D-11 (PHỤ THUỘC NGOÀI) | không kiểm gói | công ty hết hạn dùng thử → cũ 400 TRIAL_EXPIRED / mới 200 |
Kiểm gói ở gateway? |
| 8 | D-12 (MƠ HỒ) | đọc ngày như BatchRelationalRepository |
exp_date 2026-12-31 00:00 JVM cũ UTC → cũ "2026-12-30" / mới "2026-12-31" (khi Jackson +7) |
Múi giờ JVM prod cũ/mới |
| 9 | F-logic-1 (lệch thiết kế mục 5) | use case ở class mới BatchPageQueryService thay vì method trong BatchQueryService (để không đổi constructor dùng trong WarehouseTransferServiceTest:136) |
không khác hành vi | Chấp nhận, hoặc gộp vào BatchQueryService + sửa test chuyển kho |
| 10 | F-logic-3 (spec lập luận sai) | không sửa (sau bước C không sửa decisions) | — | Sửa câu "lúc lưu chỉ chặn vượt max" ở R-05, D-06, D-15: create/update có @PositiveOrZero/@NotNull/@Min(1)/@Max(3) (SaveBatchRequest.java:21-27); giá trị âm/NULL chỉ từ đường ghi khác |
| 11 | F-logic-2 | giữ toLowerCase(Locale.ROOT) |
JVM locale tr: "LOI" → cũ %loı% / mới %loi% |
Xác nhận locale prod không phải tr/az |
4. Finding đã xác nhận
Không có finding CRITICAL/MAJOR. Finding MINOR (không qua xác minh, chép nguyên từ verify/round-1/review-logic.md):
F-logic-1
- Mức độ: MINOR · Loại: architecture · Quy tắc: R-02, R-03, R-11
- Code mới:
…/application/batch/BatchPageQueryService.java:18-60 - Mô tả: Spec mục 5 và 6 quy định thêm
getBatchPage(BatchPageQuery)vàoBatchQueryService; code tạo class mớiBatchPageQueryService. Hành vi không đổi.
F-logic-2
- Mức độ: MINOR · Loại: parity · Quy tắc: R-04
- Code mới:
…/domain/batch/model/BatchKeyword.java:31; code cũbackend:util/Common.java:1328 - Mô tả: cũ
toLowerCase()theo locale JVM, mớiLocale.ROOT; chỉ khác ở locale tr/az. Độ tin cậy thấp.
F-logic-3
- Mức độ: MINOR · Loại: parity (spec sai) · Quy tắc: R-05
- Code cũ:
backend:dto/batches/SaveBatchRequest.java:21-27;backend:web/rest/BatchesManagementResource.java:42,49 - Mô tả: spec ghi "lúc lưu chỉ chặn vượt max"; thực tế create/update chặn âm/NULL. Code đúng, chỉ lập luận spec sai. Đã tự kiểm: đúng.
F-logic-4
- Mức độ: MINOR · Loại: nghi-bug-cu · Quy tắc: R-05
- Code mới:
BatchPageReader.java:43-64; code cũbackend:repository/impl/BatchRepositoryImpl.java:55-77,82-104 - Mô tả: clamp chiều âm không chặn được tràn
datetime; lọc 1/2 lỗi cả danh sách khi có lô cảnh báo âm lớn. Xem B-09.
5. Finding bị loại
| Finding | Lý do loại |
|---|---|
| — | — |
6. Xử lý của người
| Vấn đề | Cổng | Chỉ thị |
|---|---|---|
Chưa kiểm Sonar (IntelliJ → SonarQube → Analyze VCS Changed Files trên C:/Projects/warehouse-service-wt/ws1) |
G4 |
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
22 file (verify/round-1/changed-files.md), đều trong src/main, src/test:
- Mới (main):
BatchController,BatchWebMapper,BatchPageRequest,BatchListItemResponse,BatchPageQueryService,BatchPageQuery,BatchKeyword,BatchListItem,BatchPage,BatchErrorCode,BatchPageReader. - Sửa (main):
BatchRepository(+findPage),BatchRelationalRepository(+findPage,toZonedDateTimethành package-private),i18n/messages_vi.properties,messages_en.properties(+5 khoá;TOKEN_EXPIRED,COMPANY_NOT_EXISTS_CODE,EXCEPTION_ERROR,SUCCESS_GET_LISTcó thể trùng khoá với branch ws1/repo chính khi gộp — bỏ bản trùng lúc merge). - Test: 6 lớp mới +
BatchRelationalRepositoryTestthêm@Nested [get-with-paging].
9. Đề xuất bổ sung kinh nghiệm
| Đề xuất | Đưa vào đâu |
|---|---|
Common.normalizedName của backend (util/Common.java:1315-1329) khác BaseCommon.normalizedName (LF-32): không xoá \r\n, trim sau khi nối — thêm mục LF riêng |
legacy-facts.md |
UserService.getUserWithAuthorities(comId) của backend: thiếu companyId → 400 TOKEN_EXPIRED, khác công ty → 500 COMPANY_NOT_EXISTS_CODE — đã gặp ở 2 unit, nên thành LF |
legacy-facts.md |
Starter Guard.validateInput một vi phạm vẫn ném INVALID_REQUEST kèm danh sách trong originalMessage (không đẩy mã vi phạm lên errorCode) — test khoá danh sách |
lessons.md (K-10) |
Khi nói "dữ liệu lạ không vào được qua API", mở cả DTO lưu (@PositiveOrZero, @Min…) chứ không chỉ service (F-logic-3) |
lessons.md (1a) |
Field @Autowired + @PersistenceContext(unitName=readOnly…) cùng lúc: nguồn đọc phụ thuộc thứ tự BeanPostProcessor — bổ sung K-24 |
lessons.md (K-24) |
| Thêm tham số vào constructor service đã có bị test luồng khác dựng tay → cân nhắc service mới ngay ở spec mục 5 | lessons.md (1b) |
| Text block thay chuỗi nối cho hằng SQL dài ngay từ đầu (spotless gộp chuỗi nối) — đã có ở K-15, gặp lại | lessons.md (K-15, cột "Gặp ở") |