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

batch · batch/delete-multiple · api

POST/api/client/page/batches/delete-multiple

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

Phân tích luồng sau chuyển — batch/delete-multiple — vòng 1

logic-reviewer viết dựa trên code đã implement (repo C:/Projects/warehouse-service-wt/ws1), đối chiếu với code cũ. Viết tắt: backend: = easyposbackend1:src/main/java/vn/softdreams/easypos/; đường dẫn mới tính từ src/main/java/com/softdreams/easypos/warehouse/.

F-01 Xoá nhiều lô theo danh sách

  • Điểm vào: cũ backend:web/rest/BatchesManagementResource.java:60-64 → mới presentation/web/batch/BatchController.java:96-104
  • Quy tắc: R-01, R-03, R-04, R-05, R-06, R-07

Sơ đồ luồng mới (theo code thực tế)

sequenceDiagram
    participant C as Client
    participant BC as BatchController.deleteMultiple
    participant M as BatchWebMapper.toDeleteMultipleCommand
    participant S as BatchManagementService.deleteMultiple (@Transactional)
    participant R as BatchRelationalRepository.deleteAllWithoutDetails (translate)
    participant W as BatchWriter.deleteAllWithoutDetails
    C->>BC: POST BatchDeleteMultipleRequest (không validate)
    BC->>M: request
    M-->>BC: Command(ids, paramCheckAll, BatchFilter)
    BC->>S: command
    S->>S: paramCheckAll khác TRUE → ids = command.ids()
    S->>S: ids null/rỗng → return 0
    S->>R: deleteAllWithoutDetails(ids)
    R->>W: DELETE b FROM batches b WHERE b.id IN (:ids) AND NOT EXISTS(batches_detail)
    W-->>S: n (PersistenceException → SystemException EXCEPTION_ERROR)
    S->>S: n != ids.size() → BadRequestException LOT_HAS_TRANSACTIONS_CANNOT_DELETE (rollback)
    BC-->>C: 200 ok(n, DELETE_BATCHES_SUCCESS)

Đối chiếu từng bước

# Luồng cũ (repo:path:dòng) Luồng mới (path:dòng) Kết luận
1 Body DeleteBatchRequest, không validate — backend:web/rest/BatchesManagementResource.java:60-62 BatchController.java:96-98, BatchDeleteMultipleRequest (9 field) KHỚP
2 Body hỏng → 400 body rỗng (LF-03) 400 starter KHÁC có chủ đích (D-02)
3 ids = request.getIds(); Objects.equals(paramCheckAll, true) sai → giữ ids — backend:service/impl/BatchesManagementServiceImpl.java:360-361 BatchManagementService.java:107-109 (Boolean.TRUE.equals) KHỚP
4 Không kiểm token/công ty Không gọi CurrentUserPort KHÁC có chủ đích? — không: giữ như cũ (D-01 GIỮ) → KHỚP
5 ids null/rỗng → 200 data 0 — …ServiceImpl.java:377-379 BatchManagementService.java:110-112 KHỚP
6 Một câu DELETE IN (?1) + NOT EXISTS trên writeEntityManager — backend:repository/impl/BatchRepositoryImpl.java:355-363 BatchWriter.java:42-49,78-80 (IN (:ids)) KHỚP
7 numberRowsDeleted != ids.size() → BaseBadRequestAlertException → 400, rollback — …ServiceImpl.java:381-384 BatchManagementService.java:113-116 KHỚP
8 Lỗi SQL → 417 EXCEPTION_ERROR (LF-13) BatchRelationalRepository.java:151-154,172-178 → 500 EXCEPTION_ERROR KHÁC có chủ đích (D-03)
9 Kiểm gói dịch vụ (LF-21) không có KHÁC có chủ đích (D-04)
10 200 DELETE_BATCHES_SUCCESS, data = số dòng — …ServiceImpl.java:386 BatchController.java:99-103 KHÁC có chủ đích về khung response (D-02); mã và data KHỚP

Dữ liệu và side effect

Bảng / topic / cache Cũ (đọc/ghi, điều kiện) Mới (đọc/ghi, điều kiện) Ghi chú
batches DELETE id IN (:ids), không lọc com_id như cũ D-01
batches_detail đọc trong NOT EXISTS như cũ
event/cache không không

Transaction, khoá, idempotency, tenant

  • Ranh giới transaction: cũ @Transactional cấp class BatchesManagementServiceImpl (:55-57) → mới @Transactional trên BatchManagementService.deleteMultiple (:105), gọi từ controller qua proxy; ngoại lệ unchecked → rollback cả câu xoá.
  • Khoá / cập nhật nguyên tử: một câu DELETE duy nhất ở cả hai bên; không đọc-sửa-ghi.
  • Idempotency, event: không áp dụng (API, không phát event). Gọi lại cùng ids sau khi đã xoá → 0 ≠ size → 400 như cũ.
  • Lọc comId: không có ở câu xoá ở cả hai bên (D-01).

Lệch so với luồng mới đã duyệt (spec mục 6)

Không (port tên deleteAllWithoutDetails thay cho deleteWithoutDetails(List) — chỉ đổi tên).

Dev cần chú ý khi review

Vị trí Vì sao
application/batch/BatchManagementService.java:113-116 Rollback cả lượt dựa vào việc ném BadRequestException (unchecked) trong method @Transactional; đừng bắt/nuốt ngoại lệ này ở tầng trên trong cùng transaction.
infrastructure/relational/batch/adapter/BatchWriter.java:78-80 Một câu IN cho mọi id; > ~2100 tham số (padding bật) → lỗi 500 (D-06). ids chứa null (đặc biệt [null]) chưa chạy thật trên MSSQL/Hibernate 6 — đưa vào GM-01.
infrastructure/relational/batch/adapter/BatchRelationalRepository.java:151-154 Câu xoá không lọc com_id — cố ý theo D-01 (NGHI BUG mức CAO, người cần chốt).

F-02 Xoá mọi lô khớp bộ lọc

  • Điểm vào: cũ backend:web/rest/BatchesManagementResource.java:60-64 → mới presentation/web/batch/BatchController.java:96-104
  • Quy tắc: R-01, R-02, R-03, R-04, R-05, R-06, R-07

Sơ đồ luồng mới (theo code thực tế)

sequenceDiagram
    participant C as Client
    participant BC as BatchController.deleteMultiple
    participant S as BatchManagementService.deleteMultiple (@Transactional)
    participant R as BatchRelationalRepository
    participant F as BatchFilterReader.findIds
    participant K as BatchKeyword.likePattern
    participant W as BatchWriter.deleteAllWithoutDetails
    C->>BC: POST {comId, paramCheckAll:true, keyword, status, inventoryQuantityStatus, ...}
    BC->>S: Command(ids bị bỏ qua, TRUE, BatchFilter(comId, keyword, status, invQtyStatus))
    S->>R: findIdsByFilter(filter)
    R->>F: findIds(filter)
    F->>K: likePattern(keyword) (null/"" → không lọc)
    F->>F: SELECT b.id FROM batches b ⟕ batches_detail ⟕ ppu WHERE com_id=:comId(null→"") [+LIKE][+status] GROUP BY [+HAVING]
    F-->>S: ids (PersistenceException → SystemException EXCEPTION_ERROR)
    S->>S: rỗng → return 0
    S->>R: deleteAllWithoutDetails(ids)
    R->>W: DELETE ... IN (:ids) AND NOT EXISTS(...)
    S->>S: n != ids.size() → 400 LOT_HAS_TRANSACTIONS_CANNOT_DELETE (rollback)
    BC-->>C: 200 ok(n, DELETE_BATCHES_SUCCESS)

Đối chiếu từng bước

# Luồng cũ (repo:path:dòng) Luồng mới (path:dòng) Kết luận
1 Body, không validate, không kiểm token — BatchesManagementResource.java:60-62 BatchController.java:96-104; BatchWebMapper.java:58 dựng BatchFilter từ body KHỚP (D-01 GIỮ)
2 Dựng SearchBatchRequest từ comId/keyword/status/invQtyStatus/ppuId — …ServiceImpl.java:362-367 BatchWebMapper.java:58-63 (bỏ ppuId) KHỚP — ppuId chỉ đổi ORDER BY/cột SELECT (BatchRepositoryImpl.java:125-179), không đổi tập id
3 comId null → Common.setParams bind "" — backend:util/Common.java:227-236 BatchFilterReader.java:90 KHỚP
4 FROM/JOIN/WHERE b.com_id = :comId — BatchRepositoryImpl.java:39-42 BatchFilterReader.java:22-27 KHỚP
5 Keyword khác null/"" → LIKE '%'+normalizedName+'%' — BatchRepositoryImpl.java:43-46, Common.java:1315-1329 BatchFilterReader.java:92-96, domain/batch/model/BatchKeyword.java:17-21 → BatchNormalizedName.of KHỚP (" " → %%)
6 status 0/2/1 với CASE kẹp, khác/null không lọc — BatchRepositoryImpl.java:48-107 BatchFilterReader.java:29-54,108-119 KHỚP
7 GROUP BY 8 cột; HAVING tồn 1/2 — BatchRepositoryImpl.java:108-117 BatchFilterReader.java:55-63,121-129 KHỚP
8 Câu COUNT + SELECT đầy đủ + ORDER BY, map BatchItem, lấy id — BatchRepositoryImpl.java:118-189, …ServiceImpl.java:368-374 Chỉ SELECT b.id — BatchFilterReader.java:99-102 KHÁC có chủ đích (D-07)
9 Đọc bằng field entityManager (@Autowired + @PersistenceContext(readOnly)) — BatchRepositoryImpl.java:27-29 EM chung trong transaction ghi (primary) KHÁC có chủ đích / UNVERIFIED (D-08 GIỮ DB chính)
10 Rỗng → 200 data 0 — …ServiceImpl.java:377-379 BatchManagementService.java:110-112 KHỚP
11 DELETE IN + so size → 400 rollback — …ServiceImpl.java:381-384, BatchRepositoryImpl.java:355-363 BatchManagementService.java:113-116, BatchWriter.java:78-80 KHỚP
12 Lỗi SQL ở lọc/xoá → 417 EXCEPTION_ERROR BatchFilterReader.java:103-105, BatchRelationalRepository.java:172-178 → 500 EXCEPTION_ERROR KHÁC có chủ đích (D-03)
13 Response 200 DELETE_BATCHES_SUCCESS BatchController.java:99-103 KHỚP (khung response D-02)

Dữ liệu và side effect

Bảng / topic / cache Cũ (đọc/ghi, điều kiện) Mới (đọc/ghi, điều kiện) Ghi chú
batches ⟕ batches_detail ⟕ product_product_unit đọc 2 câu (COUNT, SELECT), com_id = :comId body đọc 1 câu SELECT b.id, cùng điều kiện D-07, D-08
batches DELETE id IN (:ids) như cũ D-01
event/cache không không

Transaction, khoá, idempotency, tenant

  • Ranh giới transaction: cũ cả lọc + xoá trong transaction cấp class (nguồn đọc lọc chưa chắc — D-08) → mới cả hai trong BatchManagementService.deleteMultiple @Transactional (readOnly=false).
  • Khoá / cập nhật nguyên tử: SELECT id rồi DELETE; lô được thêm chi tiết giữa hai câu → NOT EXISTS loại ra → 400 rollback, như cũ.
  • Idempotency, event: không áp dụng.
  • Lọc comId: theo comId body, không đối chiếu token (D-01); câu xoá không lọc com_id.

Lệch so với luồng mới đã duyệt (spec mục 6)

Không.

Dev cần chú ý khi review

Vị trí Vì sao
infrastructure/relational/batch/adapter/BatchFilterReader.java:22-63 SQL nguyên văn ghép từ text block với \ cuối dòng — sửa xoá dấu cách trước \ sẽ làm dính từ khoá SQL; chỉ khoá bằng mock (K-13), cần GM-01.
infrastructure/relational/batch/adapter/BatchFilterReader.java:90 comId null bind "" → so cột int với '' (SQL Server đổi thành 0) — UNVERIFIED.
application/batch/BatchManagementService.java:107-109 Chọn tất cả lấy comId từ body, xoá được lô công ty khác (D-01, mức CAO, người cần chốt).
infrastructure/relational/batch/adapter/BatchRelationalRepository.java:157-159 Đọc lọc trên DB chính trong transaction ghi (D-08), khác cũ nếu cũ thực sự đọc replica.

Nguồn của trang này

  • Phân tích luồng migrations/batch/delete-multiple/verify/round-1/flow-analysis.md vòng 1 · sha256 b1156514a568

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