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

Tồn kho · inventory/cogs-calculate · api

POST/api/client/page/warehouse/cogs/calculate

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

Báo cáo sai lệch — inventory/cogs-calculate — 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: A (tiền giá vốn, ghi cogs_history, task log làm đổi số tiền phiếu/hoá đơn) → người cần đọc: spec + báo cáo + toàn bộ diff
  • Số quy tắc: 18 · PASS 9 (R-04, R-06…R-11, R-13, R-14) · DEVIATION có chủ đích 7 (R-01, R-02, R-03, R-12, R-15, R-17, R-18) · DEVIATION KHÔNG chủ đích 0 · UNVERIFIED 2 (R-05 phía tiêu thụ, R-16)
  • Coverage thấp nhất: F-01 99.2% dòng / 88.9% nhánh
  • Finding logic: CRITICAL 0 · MAJOR 0 · MINOR 1 · UNSURE 0
  • Nghi vấn bug code cũ (mục 3c): 5 (CAO 2) · Quyết định tự chốt cần xác nhận (mục 3d): 9
  • Chạy bằng: /mig-auto lượt 20261105-1351 (spec qua 2 lần spec-reviewer, chưa có người duyệt) · Số vòng: 1 verify / lần sửa 0/3
  • Phạm vi API còn nghi vấn (❓) — warehouse-api-scope-final.md mục 1.2: "Cần quyết định có thuộc kho không".

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

Mã Mục tiêu Kết quả Bằng chứng
G1 mvnw verify ✅ verify/round-1/build.md (677 test, SpotBugs 0)
G2 Test khớp test-plan ✅ verify/round-1/oracle.md (48/48 TC)
G3 Coverage mỗi luồng ✅ verify/round-1/coverage.md
G4 Sonar CHỜ NGƯỜI sonar-ide.md
G5 0 CRITICAL/MAJOR ✅ 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; 38 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, GM-02 — tầng A, nên chạy trước khi commit)

Coverage theo luồng

Luồng Tên % dòng % nhánh
F-01 Nhận yêu cầu, chọn nhánh, gửi task log tính sau 99.2% (236/238) 88.9% (48/54)
F-02 Tính giá vốn đồng bộ, gửi cập nhật, ghi lịch sử 99.1% (333/336) 89.4% (93/104)

2. Ma trận truy vết

Quy tắc Tầng Code mới Test Golden Kết luận
R-01 A CogsController, CogsCalculationRequest TC-01, 02 — DEVIATION (D-02: body 400)
R-02 A CogsCalculationService.java:54 TC-03, 04 — DEVIATION (D-01)
R-03 A CogsCalculationService.java:55-58, CogsPeriod TC-05, 06 — DEVIATION (D-02: key reason null bị bỏ)
R-04 A CogsCalculationService.java:60-64; SQL ppu chính TC-07..11 GM-02 PASS
R-05 A CogsCalculationService.java:65-73 TC-08, 12, 13, 14 GM-02 PASS phía gửi; phía tiêu thụ UNVERIFIED (D-07)
R-06 A CogsComputationService.java:68-78 TC-15, 16 GM-01 PASS
R-07 A CogsRelationalRepository SQL TC-17, 18, 19 GM-01 PASS (H2; MSSQL UNVERIFIED)
R-08 A CogsItem.aggregate TC-20, 21 GM-01 PASS
R-09 A CogsItem.calculate TC-22 GM-01 PASS
R-10 A CogsComputationService.java:116-184 TC-23..28, 46, 47 GM-01 PASS (giữ D-04)
R-11 A CogsComputationService.java:80-82 TC-29 — PASS
R-12 A CogsComputationService.saveHistories, INSERT TC-30..33 GM-01 DEVIATION (D-09 giờ VN)
R-13 A CogsController.java:46-53 TC-34, 35 — PASS (định dạng D-02)
R-14 A thứ tự gửi trước, ghi sau TC-36 — PASS (giữ D-05)
R-15 A CogsTaskLogMongoRabbitAdapter TC-37..40 GM-01, 02 DEVIATION (D-07 adapter mới; tương thích easyposasync UNVERIFIED)
R-16 A — — — DEVIATION (D-08) — UNVERIFIED
R-17 A SystemException(EXCEPTION_ERROR) TC-41, 42 — DEVIATION (D-03: 417 → 500)
R-18 A SendQueueConfigRelationalAdapter TC-43, 44, 45 — DEVIATION (D-10: không Redis, không EasyInvoice)

3. Người cần xem

# Vị trí Vì sao cần người xem
1 Toàn bộ diff (tầng A) — 29 file main, 7 file test verify/round-1/changes.diff
2 infrastructure/messaging/CogsTaskLogMongoRabbitAdapter.java Định dạng document task_log_reference + message RabbitMQ phải khớp easyposasync; chưa chạy với Mongo/RabbitMQ thật. Repo đích chưa có cấu hình spring.rabbitmq.* — cần bổ sung trước khi chạy
3 Consumer easyposasync @RabbitListener của CogsCompletionListener/CogsUpdateAsyncListener đang bị comment trong source → xác nhận bản prod có bật không (nếu tắt: nhánh > 100 không bao giờ tính, phiếu/hoá đơn không được cập nhật — ở cả cũ và mới)
4 infrastructure/relational/config/adapter/SendQueueConfigRelationalAdapter.java:43-46 (F-logic-1, MINOR) config.business_type NULL → NullPointerException thay vì SystemException(EXCEPTION_ERROR)
5 CogsTaskLogMongoRabbitAdapter.java:105-112 (flow-analysis) Chỉ nuốt AmqpException; cũ nuốt mọi Exception khi gửi queue
6 CogsRelationalRepository.java SQL Native SQL chỉ chạy H2 — chạy GM-01 trên MSSQL (K-13)
7 Phạm vi API (❓) Chốt API này có thuộc warehouse-service không
8 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 KHỚP / KHÁC / CHỈ CŨ / CHỈ MỚI Lệch luồng đã duyệt Điểm dev cần chú ý
F-01 Nhận yêu cầu, chọn nhánh, gửi task log 7 / 4 (D-01, D-02, D-03, D-10) / 1 (D-08) / 0 Không Gửi Mongo/Rabbit trong transaction SQL; chỉ nuốt AmqpException; định dạng document; lỗi lô k không thu hồi
F-02 Tính đồng bộ, gửi cập nhật, ghi lịch sử 12 / 2 (D-09, D-07/D-10) / 0 / 0 Không Không đổi HashSet/HashMap (D-04); wardDeltas dùng chung; ghi giờ VN; SQL chỉ chạy H2

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

B-01 Giá vốn tính dở khi ppu cha và ppu con rơi vào hai lô khác nhau

  • Mức nghi ngờ: CAO — số tiền phiếu xuất/hoá đơn lệch với giá vốn đã lưu cùng lần tính; xảy ra khi tập cha + con > 100 ppu.
  • Ở đâu: code cũ easyposbase:src/main/java/sds/ep/baseservice/services/impl/BaseCogsHistoryServiceImpl.java:83-106,142-168 → mới (giữ nguyên) application/cogs/CogsComputationService.java:73-146
  • Code cũ đang làm gì: chia các ppu (cha và con) thành từng lô 100. Sau mỗi lô, tính giá vốn với số liệu đã có tới lô đó và gửi ngay lệnh cập nhật đơn giá phiếu xuất/hoá đơn. Dòng của ppu con ở lô sau làm đổi giá vốn của cha, nhưng các lệnh đã gửi ở lô trước không được tính lại.
  • Ví dụ cụ thể: ppu cha A đầu kỳ 10 cái × 100đ, xuất 5 cái trong kỳ; có 150 ppu con, con thứ 150 nhập 10 cái × 160đ (rơi lô 2). Lô 1: giá vốn A = 100 → phiếu xuất của A cập nhật 500đ. Lô 2: giá vốn A = 130 → lịch sử giá vốn lưu 130, API trả 130, nhưng phiếu xuất vẫn 500đ (lẽ ra 650đ). Thêm: dòng hoá đơn của con ở lô trước khi cha chưa có số liệu thì không bao giờ được cập nhật.
  • Vì sao nghi là sai: cùng một lần tính mà giá vốn ghi vào lịch sử khác giá vốn dùng cho phiếu; ppu nào rơi lô nào phụ thuộc thứ tự băm, không theo nghiệp vụ.
  • Ảnh hưởng nếu đúng là bug: sản phẩm có nhiều đơn vị quy đổi/biến thể (> 100 ppu trong họ) sẽ có giá trị xuất kho và giá vốn hoá đơn sai; chỉ xảy ra nếu consumer easyposasync đang bật.
  • Đã xử lý khi chuyển: GIỮ nguyên. Test khoá: TC-46 (CogsComputationServiceTest#partialCogsAcrossBatches), TC-47 (#billOfChildBeforeParentItemDropped).
  • Nếu muốn sửa: tính giá vốn cho mọi lô xong mới tạo lệnh cập nhật (CogsComputationService.calculate), đổi TC-46/47; monolith còn chạy song song sẽ cho số khác.
  • Liên quan: D-04, R-06, R-10

B-02 API lỗi nhưng lệnh cập nhật phiếu/hoá đơn đã gửi vẫn được thực hiện

  • Mức nghi ngờ: CAO — dữ liệu tiền lệch khi có lỗi giữa chừng.
  • Ở đâu: easyposbase:…/BaseTaskLogServiceImpl.java:121-130,373-388, BaseCogsHistoryServiceImpl.java:104-121 → mới CogsComputationService.java + CogsTaskLogMongoRabbitAdapter.java:91-113
  • Code cũ đang làm gì: ghi task log vào Mongo và gửi RabbitMQ ngay khi tạo (không chờ lưu DB xong), lịch sử giá vốn ghi cuối cùng.
  • Ví dụ cụ thể: 20 ppu, đã gửi lệnh cập nhật phiếu xuất, tới bước ghi cogs_history thì mất kết nối DB → API báo lỗi, lịch sử không có; nhưng easyposasync (nếu bật) vẫn đổi đơn giá phiếu xuất theo giá vốn mới.
  • Vì sao nghi là sai: người dùng thấy lỗi nhưng dữ liệu đã đổi một phần.
  • Ảnh hưởng nếu đúng là bug: hiếm (chỉ khi lỗi hạ tầng giữa chừng), nhưng khó phát hiện.
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-36 (#publishBeforeSave), TC-45 (#failureBeforeSave).
  • Nếu muốn sửa: gửi task log sau commit (@TransactionalEventListener(AFTER_COMMIT) như task log quyết toán của repo đích).
  • Liên quan: D-05, R-14

B-03 Phiếu đã xoá mềm vẫn được tính vào giá vốn

  • Mức nghi ngờ: TRUNG BÌNH — ý nghĩa status = 0 chỉ suy từ tên method delete…ForMedicine.
  • Ở đâu: easyposbase:…/repositories/BaseCogsHistoryRepository.java:22-66 → mới CogsRelationalRepository.java:59-85
  • Code cũ đang làm gì: đọc mọi dòng phiếu/hoá đơn, không lọc trạng thái.
  • Ví dụ cụ thể: nhập 10 × 100đ (phiếu đã xoá) + nhập 10 × 200đ → giá vốn 150 (lẽ ra 200).
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-17 (CogsRelationalRepositoryTest#detailRows, dòng G).
  • Nếu muốn sửa: thêm rio.status/trạng thái hoá đơn vào SQL, đổi TC-17/18.
  • Liên quan: D-11

B-04 Lịch sử giá vốn bị trùng khi ppu có nhiều lô trong một kho

  • Mức nghi ngờ: TRUNG BÌNH — chắc chắn sinh trùng; chưa biết báo cáo nào đọc cogs_history có cộng dồn không.
  • Ở đâu: easyposbase:…/repositories/BaseInventoryRepository.java:272-277 → mới CogsRelationalRepository.java:87-95
  • Ví dụ cụ thể: ppu 501 có 2 lô ở kho 1 → 2 dòng cogs_history(kho 1) giống nhau, data 2 phần tử giống nhau, count = 1.
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-30, TC-32.
  • Nếu muốn sửa: DISTINCT theo (ppu_id, warehouse_id).
  • Liên quan: D-12

B-05 Không kiểm dữ liệu vào; báo status: true cả khi thất bại

  • Mức nghi ngờ: THẤP — có thể client đọc message[0].code.
  • Ở đâu: easyposbase:…/BaseWarehouseServiceImpl.java:1891-1927 → mới CogsCalculationService.java:55-64
  • Ví dụ cụ thể: thiếu ngày → 200 {"message":[{"code":"FAIL"}],"status":true}; fromDate sau toDate vẫn chạy và lưu lịch sử from > to.
  • Đã xử lý khi chuyển: GIỮ. Test khoá: TC-05, TC-07, TC-48.
  • Liên quan: D-06

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ũ (input → cũ / mới) Người cần xác nhận gì
1 D-07 (PHỤ THUỘC NGOÀI) Port + adapter Mongo task_log_reference + RabbitMQ (Jackson2JsonMessageConverter), giữ định dạng cũ — (định dạng như cũ, chưa chạy thật) Bổ sung spring.rabbitmq.*; xác nhận consumer easyposasync prod có bật; chạy GM-02 với easyposasync
2 D-10 (PHỤ THUỘC NGOÀI) Kiểm config.business_type + company.service, không Redis, không EasyInvoice Redis không có key + công ty không cấu hình EasyInvoice → cũ 417 / mới 200 và ghi dữ liệu; Redis có nhưng DB thiếu → cũ chạy / mới 500 Redis CONFIG_COM_ID có luôn được nạp không; có cần kiểm EasyInvoice
3 D-01 (LỖI KỸ THUẬT) Kiểm công ty token comId khác → cũ tính hộ / mới 400 Đồng ý chặn
4 D-02 (ADR BẮT KHÁC) BaseResponseDTO, giữ status true, mã, reason, count key null (data, count, reason) bị bỏ; body hỏng 400 INVALID_REQUEST Client chịu được thiếu key
5 D-03 (ADR BẮT KHÁC) SystemException(EXCEPTION_ERROR) 417 → 500 —
6 D-08 (PHỤ THUỘC NGOÀI) Không kiểm gói hết gói → cũ 400 / mới tính Tầng nào kiểm gói
7 D-09 (MƠ HỒ) Ghi cogs_history và norm_date task log theo giờ VN JVM cũ ở UTC → khác ngày/giờ Múi giờ JVM prod cũ
8 spec-review Spec qua 2 lần review; các R-xx đã sửa theo CRITICAL/MAJOR: R-05, R-10, R-14, R-15, R-18 — Đọc kỹ các quy tắc này trong spec.md
9 Phạm vi ❓ Chuyển vì người yêu cầu đích danh — Chốt API có thuộc warehouse-service

4. Finding đã xác nhận

Không có CRITICAL/MAJOR. MINOR: F-logic-1 (mục 3 dòng 4) — 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ị
G4 chờ người kiểm Sonar G4
F-logic-1 (MINOR) — muốn sửa thì ghi SỬA —

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

38 file (verify/round-1/changed-files.md), đều trong src/main, src/test: context mới domain/cogs, application/cogs, port CogsTaskLogPort, SendQueueConfigPort, adapter infrastructure/relational/cogs, infrastructure/relational/config, infrastructure/messaging/CogsTaskLog*, presentation/web/inventory/CogsController + DTO; sửa InventoryWebMapper, i18n vi/en.

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

Đề xuất Đưa vào đâu
Task log Mongo task_log_reference của monolith luôn qua getConfigSendQueue (Redis → config + company + EasyInvoice) trước khi ghi — lỗi ở đó làm 417 legacy-facts.md
RabbitTemplate monolith dùng Jackson2JsonMessageConverter (body JSON "id", __TypeId__) — adapter mới phải tự dựng message legacy-facts.md
Listener easyposasync cho COGS đang tắt trong source — kiểm @RabbitListener bị comment trước khi mô tả "bên tiêu thụ" lessons.md 1a
H2 MODE=MSSQLServer không nhận AUTO_INCREMENT (dùng IDENTITY); cột value cần NON_KEYWORDS=VALUE target-cheatsheet.md mục 5
Constructor tối đa 7 tham số (Checkstyle); chuỗi cứng trong method bị chặn ngoài infrastructure/relational|nonrelational target-cheatsheet.md mục 4
Shell Bash của máy không nhận heredoc/chuỗi dài có ký tự đặc biệt — ghi script bằng công cụ Write lessons.md Phần 2

Nguồn của trang này

  • Báo cáo sai lệch migrations/inventory/cogs-calculate/report.md vòng 1 · sha256 c2b146f461b0

v1 dựng 2026-11-06 00:42 · base commit đích a06ccfa6d4