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

Kho · warehouse/update · api

PUT/api/client/page/warehouse/update

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

Phân tích luồng sau chuyển — warehouse/update — vòng 1

F-01 Sửa kho

  • Điểm vào: cũ easyposbackend1:src/main/java/vn/softdreams/easypos/web/rest/WarehouseResource.java:59-67 → mới src/main/java/com/softdreams/easypos/warehouse/presentation/web/warehouse/WarehouseController.java:69-80
  • Quy tắc: R-01, R-02, R-03, R-04, R-05, R-06, R-07, R-08, R-09, R-10, R-11, R-12, R-13, R-14

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

sequenceDiagram
    participant C as Client
    participant WC as WarehouseController.updateWarehouse
    participant G as Guard.validateInput
    participant WS as WarehouseManagementService.saveWarehouse (@Transactional)
    participant CC as CurrentCompanyService.requireCompanyOfCurrentUser
    participant WR as WarehouseRelationalRepository
    participant W as Warehouse
    participant DP as WarehouseDuplicatePolicy.validate
    participant BP as BillRelationalAdapter.countProcessingBills
    C->>WC: PUT /update (WarehouseSaveRequest)
    WC->>WC: request.id()==null → BadRequestException(ID_NOT_NULL)
    WC->>G: validateInput(validator, request) → INVALID_REQUEST (mọi vi phạm)
    WC->>WS: saveWarehouse(mapper.toSaveCommand(request))
    WS->>CC: requireCompanyOfCurrentUser(comId) → INVALID_COMPANY / COMPANY_NOT_OF_CURRENT_USER / 401
    WS->>WR: lockCompanyWarehouses(comId) (SELECT TOP 1 + sp_getapplock)
    WS->>WS: WarehouseAudit(findUserId() or 0, now(clock))
    WS->>WR: findById(comId,id) → không có: SystemException(WAREHOUSE_NOT_FOUND)
    WS->>W: update(command, audit): copyFrom, status=activeStatus, so businessValues; đổi → cleanText + updater/updateTime
    WS->>WR: findNameSkus(comId) (native, không ORDER BY)
    WS->>WS: duplicateRows: thay dòng id==warehouse.id bằng warehouse.nameSku()
    WS->>DP: validate(rows, command) (SKU trước tên, chạm 2 → lỗi)
    WS->>W: validateDefaultWarehouse() (code null/sellable null → SystemException EXCEPTION_ERROR)
    opt !warehouse.isActive()
        WS->>BP: countProcessingBills(comId, command.id) > 0 → BadRequestException(WAREHOUSE_STATUS_FALSE_CHECK_BILL, name)
    end
    WS->>WR: save(warehouse): findByComIdAndId → mapper.apply(entity, warehouse) → UPDATE lúc commit (@DynamicUpdate, chỉ khi dirty)
    WR-->>WS: WarehouseResult (toResult(entity))
    WS-->>WC: WarehouseResult
    WC-->>C: 200 BaseResponseDTO.ok(WarehouseResponse, SUCCESS_UPDATE)

Đố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 Interceptor kiểm gói easyposbackend1:…/config/HandleInterceptorCustom.java:86-105 (không có) CHỈ CÓ Ở CŨ, có chủ đích (D-12)
2 id == null → BaseBadRequestAlertException(ID_NOT_NULL) trước validate, easyposbackend1:…/web/rest/WarehouseResource.java:61-63 WarehouseController.java:72-74 KHỚP (body lỗi theo starter: D-02)
3 baseCommon.validateInput WarehouseResource.java:64 Guard.validateInput WarehouseController.java:75 KHỚP (định dạng INVALID_REQUEST: D-02)
4 Không kiểm comId theo token (LF-20) WarehouseManagementService.java:77, CurrentCompanyService.java:30-39 KHÁC có chủ đích (D-01)
5 Không khoá WarehouseManagementService.java:78, WarehouseRelationalRepository.java:113-122 KHÁC có chủ đích (D-05)
6 findByComIdAndId → BaseInternalServerException(WAREHOUSE_NOT_FOUND) easyposbase:…/BaseWarehouseServiceImpl.java:174-178 WarehouseManagementService.java:88-89 KHỚP (500, D-04 GIỮ)
7 BeanUtils.copyProperties (kể cả null, getStatus() null→false) BaseWarehouseServiceImpl.java:182; SKU rỗng → code :183-185; normalizedName(request.name, request.SKU) :189 Warehouse.java:97-101,154-164 KHỚP (D-06, D-07 GIỮ)
8 Hibernate flush entity dirty trước native checkDuplicateByComId → @PreUpdate làm sạch + audit, UPDATE ghi ngay BaseWarehouseServiceImpl.java:190 (LF-34) Làm sạch + audit trong bộ nhớ khi businessValues khác Warehouse.java:101-106; UPDATE để tới commit WarehouseRelationalRepository.java:129-133 Giá trị sau làm sạch và audit KHỚP; thời điểm ghi DB KHÁC (F-logic-1)
9 Dòng của chính kho trong kết quả kiểm trùng mang giá trị đã flush BaseWarehouseServiceImpl.java:190 WarehouseManagementService.java:113-121 (thay bằng nameSku() hiện tại) KHỚP (D-09, D-14 GIỮ)
10 Vòng đếm SKU trước tên, có id thì chạm 2 mới lỗi BaseWarehouseServiceImpl.java:195-205,230-245 WarehouseDuplicatePolicy.java:32-59 KHỚP (D-08 GIỮ)
11 checkDataWarehouseDefault: code.equals("WH1"), !status || !sellable (NPE khi null) BaseWarehouseServiceImpl.java:207,219-227 Warehouse.java:118-134 KHỚP (NPE → SystemException(EXCEPTION_ERROR) 500: D-03, D-10)
12 !status → checkExistsBillProcessing(comId, request.id), >0 → lỗi kèm warehouse.getName() BaseWarehouseServiceImpl.java:208-213; SQL easyposbase:…/BaseWarehouseRepository.java:84-85 WarehouseManagementService.java:95-97,123-130; SQL BillRelationalAdapter.java:27-35,53-59 KHỚP (SQL giống từng chữ; tên = tên sau làm sạch nếu có đổi)
13 warehouseRepository.save(warehouse) (merge, entity managed) BaseWarehouseServiceImpl.java:215 WarehouseRelationalRepository.java:125-134 KHỚP (UPDATE @DynamicUpdate chỉ khi dirty)
14 BaseResultDTO(SUCCESS, SUCCESS_UPDATE, true, warehouse) BaseWarehouseServiceImpl.java:216 WarehouseController.java:76-79 KHỚP (body theo starter: 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ú
warehouse Đọc findByComIdAndId; đọc select name, SKU … where com_id=?; UPDATE khi dirty, ghi ở lần flush trước câu kiểm trùng Đọc SELECT TOP 1 (mở transaction cho khoá); đọc findByComIdAndId (2 lần: tải và trong save); đọc SELECT id,name,SKU … where com_id; UPDATE khi dirty, ghi lúc commit Lọc com_id ở mọi câu. Thời điểm ghi khác: F-logic-1
bill, bill_product COUNT khi status=false COUNT khi !isActive(), cùng SQL Đọc chung DB, qua BillPort
Khoá ứng dụng MSSQL — sp_getapplock warehouse:save:<comId>, phạm vi transaction D-05
Redis / sequence — — (TC-08 khẳng định không gọi sequenceService) KHỚP
Gói dịch vụ Interceptor đọc PackageCacheService — D-12

Transaction, khoá, idempotency, tenant

  • Ranh giới transaction: cũ dùng @Transactional cấp class trên BaseWarehouseServiceImpl (easyposbase:…/BaseWarehouseServiceImpl.java:66), kiểm id và validate nằm ngoài, ở controller. Mới dùng @Transactional trên WarehouseManagementService.saveWarehouse (WarehouseManagementService.java:75), gọi từ controller qua proxy, không có self-invocation. Kiểm id và validate cũng ở controller, ngoài transaction. Khớp.
  • Khoá / cập nhật nguyên tử: cũ không khoá; khi entity dirty thì khoá X dòng của chính kho từ lúc flush (trước câu kiểm trùng). Mới khoá applock theo công ty trước khi tải kho; khoá X dòng chỉ có lúc commit. Request của service chạy lần lượt; giữa monolith và service không có bảo vệ (D-05). Đã xét thứ tự khoá monolith ↔ service, không thấy vòng chờ mới.
  • Idempotency, thời điểm phát event: không có event. PUT lặp lại cùng body thì businessValues không đổi → không làm sạch, không gán audit, Hibernate không UPDATE.
  • Lọc comId: có ở findByComIdAndId, findNameSkusByComId, câu COUNT đơn, câu SELECT trong khoá và tên tài nguyên khoá. comId dùng là giá trị đã kiểm theo token.

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

Không. Code chỉ có thêm WarehouseAudit dựng sau khoá và save tải lại entity trước mapper.apply, cả hai là chi tiết hiện thực của phần tái sử dụng, không đổi thứ tự nghiệp vụ.

Dev cần chú ý khi review

Vị trí Vì sao
WarehouseController.java:72-75 Kiểm id phải đứng trước Guard.validateInput (D-13); đảo thứ tự là đổi body lỗi
Warehouse.java:97-108 Thay cho dirty check của Hibernate: tập businessValues phải đúng các cột request có thể đổi (thiếu một cột là audit/làm sạch sai)
WarehouseManagementService.java:113-121 Mô phỏng flush trước câu kiểm trùng (K-01): dòng của chính kho mang giá trị hiện tại; sai ở đây làm lệch D-09/D-14
WarehouseManagementService.java:95-97 Tham số lỗi là warehouse.getName() sau làm sạch, không phải tên đang lưu
WarehouseRelationalRepository.java:125-134 UPDATE chỉ xảy ra lúc commit, sau mọi kiểm nghiệp vụ (khác thứ tự lỗi DB: F-logic-1); tải lại entity bằng comId của domain
WarehouseRelationalRepository.java:37-48,113-122 sp_getapplock chỉ kiểm bằng mock (K-12, K-13), cần chạy trên MSSQL thật

Nguồn của trang này

  • Phân tích luồng migrations/warehouse/update/verify/round-1/flow-analysis.md vòng 1 · sha256 5b7e978c35d0

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