Báo cáo chuyển đổi warehouse-service

rsinoutward · rsinoutward/get-all-transactions · api

GET/api/page/rs-inoutward/get-all-transactions

Vòng
2
Cổng G1–G6
PENDING_SONAR
Bước
sonar-check
Nhánh đích
feat/thongpd/migrate-get-rs

Báo cáo sai lệch — rsinoutward/get-all-transactions — vòng 2

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: B (chỉ đọc DB/Mongo, ghi cache Redis mốc tồn đầu kỳ) → người đọc spec + báo cáo + đoạn gắn cờ ở mục 3
  • Số quy tắc: 17 · PASS 9 · DEVIATION có chủ đích 4 (R-01, R-02, R-15, R-16) · DEVIATION KHÔNG chủ đích 0 · UNVERIFIED 4 (R-06/R-07/R-11 SQL thật, R-17 replica; một phần R-04/R-09/R-12/R-13)
  • Coverage thấp nhất: F-02 99,6% dòng / 97,7% nhánh
  • Finding logic: CRITICAL 0 · MAJOR 0 · MINOR 1 (F-logic-1, vòng 1) · UNSURE 0 — không cần xác minh
  • Nghi vấn bug code cũ (mục 3c): 5 (CAO 0) · Quyết định tự chốt cần xác nhận (mục 3d): 13
  • Chạy bằng: /mig-auto (spec do spec-reviewer kiểm 2 lần, chưa có người duyệt) · Số vòng: 2 / lần sửa 1/3

1. Điều kiện đạt

Mã Mục tiêu Kết quả Bằng chứng
G1 mvnw verify ✅ verify/round-2/build.md (581 test)
G2 Test khớp test-plan, mọi R-xx có test ✅ verify/round-2/tc-map.md (61/61), verify/round-2/oracle.md
G3 Coverage mỗi luồng ✅ verify/round-2/coverage.md
G4 0 issue Sonar CHỜ NGƯỜI sonar-ide.md
G5 0 CRITICAL/MAJOR ✅ verify/round-2/review-logic.md (thu hẹp, 0 finding); vòng 1: 1 MINOR
G6 Không lách cổng ✅ verify/round-2/gates.md; 49/49 file 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 Kiểm đầu vào, dựng điều kiện, đếm + đọc trang 99,7% 98,4%
F-02 Bổ sung dòng và tổng 99,6% 97,7%
F-03 Liên thông dược (Mongo + Redis) 100% 100%

2. Ma trận truy vết

Quy tắc Tầng Code mới Test Golden Kết luận
R-01 C RsInoutwardQueryController TC-01..03 — DEVIATION (có chủ đích, D-02 — body 400)
R-02 C RsInoutwardTransactionQueryService TC-04..06 — DEVIATION (có chủ đích, D-01)
R-03 C service + TransactionDateRange TC-07..11 — PASS
R-04 C service, RsInoutwardErrorCode, i18n TC-12..14 — PASS mã; text theo locale UNVERIFIED (D-14)
R-05 C service + ProductUnitLookupRelationalAdapter TC-15..21 — PASS
R-06 C RsInoutwardTransactionSqlBuilder TC-22..27 GM-01 UNVERIFIED (SQL chưa chạy MSSQL)
R-07 C TransactionDateRange, builder TC-28..32 GM-01 UNVERIFIED (WHERE AND, IN () thật)
R-08 C RsInoutwardTransactionRelationalRepository TC-33..36 — PASS
R-09 C repository + response DTO TC-37..40, TC-58 — PASS; giờ date UNVERIFIED (D-07)
R-10 C service, adapter business type/customer TC-41..43 — PASS
R-11 C builder TC-44, TC-45 GM-01 UNVERIFIED (SQL thật)
R-12 C RsInoutwardPharmaEnricher, PharmaHistoryMongoAdapter TC-46..48 — PASS (mock Mongo)
R-13 B enricher, OpeningBalanceTimeRedisAdapter TC-49..53 — PASS (mock Redis)
R-14 C service, response DTO TC-54..56 — PASS
R-15 C adapter bọc lỗi TC-57, TC-58 — DEVIATION (có chủ đích, D-03: 417→500)
R-16 C — TC-59 — DEVIATION (có chủ đích, D-10 — không kiểm gói)
R-17 C @Transactional(readOnly = true) TC-60 — UNVERIFIED (replica, D-08)

3. Người cần xem

# Vị trí Vì sao cần người xem
1 …/infrastructure/relational/rsinoutward/adapter/RsInoutwardTransactionSqlBuilder.java SQL native giữ nguyên lỗi cũ (WHERE AND khi không có ngày, IN () khi quý rỗng); chỉ kiểm bằng mock — cần chạy MSSQL thật (GM-01)
2 …/infrastructure/mongo/pharma/PharmaHistoryMongoAdapter.java Dựng MongoTemplate riêng trên DB ${app.dbname.pharma:EasyPharma}; ws1 chưa khai thuộc tính → dev cũ là EasyPosPharma — người khai app.dbname.pharma theo môi trường (D-09). F-logic-1 MINOR: lỗi map document (vd pharmacy_push_status: "abc") không ra EXCEPTION_ERROR
3 …/infrastructure/cache/OpeningBalanceTimeRedisAdapter.java SET không TTL — ngoại lệ ADR-0401 (D-12)
4 src/main/resources/i18n/messages_vi.properties, messages_en.properties Thêm 7 key, sửa text PRODUCT_NOT_FOUND (đổi text dùng chung của key đã có), TOKEN_EXPIRED giữ text dính dòng (D-13); trùng key với ws2 khi gộp nhánh
5 BusinessTypePort/CustomerPort + adapter Thêm method vào port dùng chung (không đổi method cũ)
6 Toàn bộ SQL/Mongo/Redis UNVERIFIED trên hạ tầng thật (K-13)

3b. Phân tích luồng sau chuyển

Chi tiết: verify/round-1/flow-analysis.md, verify/round-2/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 Kiểm đầu vào, dựng điều kiện, đếm + đọc trang bước 9-12 đối chiếu lại: 4 KHỚP; các bước khác giữ như vòng 1 (KHÁC có chủ đích D-01/D-02, CHỈ CÓ Ở CŨ D-10) không RsInoutwardTransactionRelationalRepository.java:85-94 ép (int) offset và PageImpl dựng lại tổng (K-09)
F-02 Bổ sung dòng và tổng (trang có dòng) bước 6-8 đối chiếu lại: 3 KHỚP / 0 KHÁC / 0 CHỈ CÓ Ở CŨ / 0 CHỈ CÓ Ở MỚI; bước 1-5 giữ như vòng 1 không RsInoutwardTransactionSqlBuilder.java:134-155 câu tổng JOIN không DISTINCT (D-06), lô viết chữ thường
F-03 Liên thông dược (Mongo + Redis) 8 KHỚP / 1 KHÁC (F-logic-1) / 0 CHỈ CÓ Ở CŨ / 0 CHỈ CÓ Ở MỚI không Redis SET không TTL bằng serializer cũ (ngoại lệ ADR-0401, D-12). app.dbname.pharma chưa khai trong yml nào của ws1 nên mọi môi trường dùng EasyPharma, còn dev cũ dùng EasyPosPharma (D-09). DB pharma phải cùng cluster với MongoClient của ws1.

3c. Nghi vấn bug / sai ở code cũ (đã GIỮ nguyên khi chuyển)

B-01 Không chọn ngày, hoặc "từ ngày" sau "đến ngày" khác tháng → báo "Lỗi hệ thống"

  • Mức nghi ngờ: TRUNG BÌNH — câu SQL rõ ràng bị ghép thiếu, nhưng màn hình có thể luôn gửi ngày.
  • Ở đâu: code cũ easyposbackend1:…/repository/impl/RsInoutWardRepositoryImpl.java:195-199, easyposmodel:…/util/BaseCommon.java:2321-2352 → code mới (giữ nguyên) RsInoutwardTransactionSqlBuilder
  • Code cũ đang làm gì: luôn viết chữ WHERE rồi mới thêm điều kiện ngày; không có ngày thì câu SQL thành WHERE AND … — sai cú pháp. Khoảng ngày ngược tháng thì danh sách quý rỗng → IN () — cũng sai cú pháp.
  • Ví dụ cụ thể: ?comId=10 không có ngày → cũ 417 "Lỗi hệ thống", mới 500 "Lỗi hệ thống". Từ 10/05/2024 đến 30/04/2024 → lỗi tương tự. Lẽ ra: trả danh sách toàn bộ hoặc báo "ngày không hợp lệ".
  • Vì sao nghi là sai: lỗi cú pháp SQL không thể là ý định nghiệp vụ.
  • Ảnh hưởng nếu đúng là bug: client gọi không kèm ngày nhận lỗi hệ thống.
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-30, TC-31 (RsInoutwardTransactionRelationalRepositoryTest).
  • Nếu muốn sửa: đổi builder chỉ thêm AND khi đã có điều kiện trước, hoặc bắt buộc ngày bằng 400 DATE_TIME_INVALID; đổi TC-30/31.
  • Liên quan: D-04, R-07

B-02 Tổng tiền/số lượng bị nhân lên khi lọc theo sản phẩm/kho/lô

  • Mức nghi ngờ: TRUNG BÌNH — danh sách dùng DISTINCT còn câu tổng thì không, hai số trên cùng màn hình không khớp.
  • Ở đâu: code cũ RsInoutWardRepositoryImpl.java:326-338 (tổng), :351-385 (đếm SP) → mới RsInoutwardTransactionSqlBuilder.java:134-155
  • Code cũ đang làm gì: câu tổng nối với bảng chi tiết, mỗi dòng chi tiết khớp lại cộng thêm tiền và số lượng của cả phiếu. "Số sản phẩm" của phiếu lọc theo sản phẩm/lô nhưng không theo kho.
  • Ví dụ cụ thể: phiếu NK001 1.000.000đ, 10 cái, có 2 dòng cùng SP A (2 lô). Lọc SP A → danh sách 1 phiếu nhưng tổng nhập 2.000.000đ, tổng SL 20. Lẽ ra 1.000.000đ / 10.
  • Vì sao nghi là sai: tổng không khớp danh sách.
  • Ảnh hưởng nếu đúng là bug: người xem tổng tiền khi lọc theo SP/kho/lô thấy số lớn hơn thực tế.
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-42, TC-45.
  • Nếu muốn sửa: dùng EXISTS/DISTINCT trong câu tổng, đổi TC-45; monolith còn chạy song song sẽ ra số khác.
  • Liên quan: D-06, R-10, R-11

B-03 Từ khoá toàn dấu cách loại phiếu không có tên KH/NCC; %, _ không được hiểu nguyên văn

  • Mức nghi ngờ: THẤP
  • Ở đâu: RsInoutWardRepositoryImpl.java:207-210, backend:util/Common.java:1315-1329 → mới TransactionKeyword
  • Code cũ đang làm gì: từ khoá chỉ bị bỏ khi rỗng; chuẩn hoá xoá dấu cách nên " " thành "%%"; ký tự đại diện của LIKE không được escape.
  • Ví dụ cụ thể: keyword=" " → phiếu không có tên KH/NCC biến mất; keyword="a_b" khớp "acb".
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-25, TC-26.
  • Nếu muốn sửa: bỏ keyword toàn trắng, escape %_[.
  • Liên quan: D-05, R-06

B-04 Lọc theo kho không thấy phiếu chuyển vào kho đó

  • Mức nghi ngờ: THẤP
  • Ở đâu: RsInoutWardRepositoryImpl.java:251-256,333-335 → mới builder
  • Code cũ đang làm gì: điều kiện kho chỉ xét kho xuất (from_warehouse_id).
  • Ví dụ cụ thể: chuyển K1 → K2, lọc K2 → không thấy phiếu.
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-24.
  • Liên quan: D-11, R-06

B-05 Text lỗi "phiên hết hạn" bị dính dòng trong file ngôn ngữ cũ

  • Mức nghi ngờ: THẤP — rõ là lỗi file i18n.
  • Ở đâu: easyposmodel:src/main/resources/i18n_custom/messages_vi.properties:442 → mới messages_vi.properties (key TOKEN_EXPIRED)
  • Ví dụ cụ thể: token không có công ty → text "Phiên đăng nhập đã hết hạnOTP_NOT_NULL=Mã xác minh không được bỏ trống".
  • Đã xử lý khi chuyển: GIỮ text cũ. Chưa có TC khoá text (TC-04 khoá mã). Ws2 (batch/get-with-paging) đã dùng text sửa → khi gộp nhánh người chọn một.
  • Liên quan: D-13, R-02

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 F-spec-1 lần 2 (CHƯA QUYẾT) + D-14 Text thông báo theo locale của starter Accept-Language: en → cũ tiếng Việt / mới có thể tiếng Anh Chốt chung cho mọi unit: ép vi (đổi cấu hình locale toàn service) hay theo starter
2 auto-changes #1 Sửa test-plan TC-36 count 3 → 707 Không khác — test-plan tính sai số học (4294968003 − 2³² = 707) Xác nhận sửa test-plan dù không phải trường hợp "spec sai" của §10
3 auto-changes #2 Sửa spec R-11, TC-45 AND → and chữ thường Không khác hành vi (giữ đúng chữ code cũ) Xác nhận
4 D-01 Chỉ giữ 2 kiểm token/công ty token sau đổi mật khẩu → cũ 500 TOKEN_EXPIRED / mới trả danh sách Đồng ý bỏ kiểm user đầy đủ
5 D-02 Body lỗi/response theo starter thiếu comId → cũ 400 body rỗng / mới 400 body starter Đồng ý
6 D-03 417 → 500, giữ mã EXCEPTION_ERROR productIds=1,abc → 417 / 500 Đồng ý
7 D-07 Giờ date = giờ tường DB (coi JVM cũ GMT+7) Nếu JVM prod cũ không phải GMT+7 → giờ hiển thị và cờ liên thông khác Xác nhận múi giờ JVM prod cũ
8 D-08 readOnly = true → replica Không khác (cũ cũng replica — suy luận) Xác nhận
9 D-09 Mongo pharma qua adapter, thuộc tính app.dbname.pharma (mặc định EasyPharma) Dev cũ EasyPosPharma Khai app.dbname.pharma trong yml từng môi trường
10 D-10 Không kiểm gói dịch vụ công ty hết hạn dùng thử → cũ 400 TRIAL_EXPIRED / mới trả danh sách Đồng ý (gateway kiểm?)
11 D-12 Redis SET không TTL, serializer cũ Không khác cũ; trái ADR-0401 Duyệt ngoại lệ ADR-0401
12 spec-review mục 5 (F-spec-2 lần 2) Sửa text key PRODUCT_NOT_FOUND có sẵn ở ws1 theo text cũ Text cũ của ws1 "Không tìm thấy sản phẩm có id={0}" bị thay Xác nhận không API nào khác dựa vào text cũ của key này
13 F-logic-1 (MINOR) Chưa sửa Document Mongo sai kiểu → cũ 417 EXCEPTION_ERROR / mới lỗi handler chung Có cần bọc thêm MappingException/ConversionFailedException

4. Finding đã xác nhận

Không có finding CRITICAL/MAJOR ở cả hai vòng. MINOR (không qua xác minh, để người xem):

  • F-logic-1 (vòng 1) — PharmaHistoryMongoAdapter chỉ bọc DataAccessException; lỗi map/convert document đi ra handler chung — chi tiết verify/round-1/review-logic.md.

5. Finding bị loại

Finding Lý do loại
— —

6. Xử lý của người

Vấn đề Cổng Chỉ thị
Kiểm Sonar (SonarQube for IDE, Analyze VCS Changed Files trong ws1) G4

7. So với vòng trước

Vấn đề Vòng trước Vòng này
TC-45 (G2) MỚI ĐÃ HẾT
F-logic-1 (MINOR) MỚI CÒN (không sửa trong vòng lặp)

8. Thay đổi trong repo đích

49 file (verify/round-2/changed-files.md): 33 file src/main/java (mới: controller/web mapper/DTO, RsInoutwardTransactionQueryService, RsInoutwardPharmaEnricher, command/model/result/repository/port mới, adapter relational/Mongo/Redis; sửa: RsInoutwardErrorCode, BusinessTypePort, CustomerPort + 2 adapter), 2 file i18n, 13 file test + fixture. Không có file ngoài src/main, src/test; không sửa pom.xml.

9. Đề xuất bổ sung kinh nghiệm

Đề xuất Đưa vào đâu
Repo đích dùng auto-config Mongo/Redis: không khai thêm bean MongoTemplate/MongoOperations/RedisTemplate (tắt bean mặc định hoặc gây mơ hồ inject) — dựng template trong adapter lessons.md (1b)
Monolith có hibernate.jdbc.time_zone: Asia/Ho_Chi_Minh (easyposbackend1:…/application.yml:139-140) và getMessageI18n cố định vi (BaseCommon.java:1926-1929); starter dịch theo Accept-Language legacy-facts.md
Kiểm số học expected khi test-plan có phép ép kiểu tràn (TC-36 ghi 3 thay vì 707) lessons.md (1c)
@ReadQuery cấp service (aspect @Order(1) bọc ngoài transaction) → đọc replica, ngược với K-24 lessons.md (bổ sung K-24)

Nguồn của trang này

  • Báo cáo sai lệch migrations/rsinoutward/get-all-transactions/report.md vòng 2 · sha256 6d8ee9975b3d

v1 dựng 2026-11-09 14:46 · base commit đích 661efe9b8c