Phân tích luồng sau chuyển — batch/batches — vòng 2
logic-reviewerviết dựa trên code đã implement, đối chiếu với code cũ. Chế độ thu hẹp. F-01 có file trong fix.diff (CurrentUserAdapter,JwtAuthorityClaimReader) nên viết lại. Các bước không có file trong fix.diff dùng lại kết luận vòng 1.
F-01 Lô có tồn của ĐVT trong kho cho kiểm kê
- Điểm vào: cũ
easyposbackend1:src/main/java/vn/softdreams/easypos/web/rest/InventoryCheckingManagementResource.java:81-92→ mớisrc/main/java/com/softdreams/easypos/warehouse/presentation/web/batch/InventoryCheckingBatchController.java:47-66 - 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 F as BaseAuthenticationFilter / DefaultAuthenticationExtractor (starter, jwt_verify)
participant IC as InventoryCheckingBatchController.batches
participant S as InventoryCheckBatchService.getBatches
participant U as CurrentUserAdapter.findAuthorityClaim → JwtAuthorityClaimReader.read
participant Q as BatchQueryService.findInventoryCheckBatches (@Transactional readOnly)
participant W as WarehouseQueryService.existsActive → WarehouseRelationalRepository.existsActive
participant R as BatchRelationalRepository → InventoryCheckBatchReader.read
C->>F: GET ?comId&warehouseId&ppuId[&keyword], header Authorization: Bearer <jwt>
F->>F: kiểm chữ ký token (không hợp lệ/thiếu → 401 của starter, chưa vào controller)
F->>IC: bind @RequestParam comId, warehouseId (thiếu → 400); record InventoryCheckingBatchFilter
IC->>IC: ppuId null → MissingServletRequestParameterException → 400
IC->>S: getBatches(InventoryCheckBatchQuery)
S->>U: findAuthorityClaim()
U->>U: RequestContextHolder → header Authorization → bỏ "Bearer " + trim → split(".") → Base64URL decode [1] → JSON "auth"
U-->>S: rỗng (không request/header/claim, token hỏng) → SystemException EXCEPTION_ERROR (500)
S->>S: BatchPermission.canAccessInventoryCheck (Set.of(split(","))) — IAE → 500; không 3401/3403 → AuthenticationException 401 UNAUTHORIZED_BY_CHECK
S->>Q: findInventoryCheckBatches
Q->>W: SELECT 1 FROM warehouse WHERE com_id=:comId AND id=:id AND status=1 (maxResults 1)
W-->>Q: false → BadRequestException INVENTORY_CHECK_WAREHOUSE_INVALID (400)
Q->>R: native SQL nguyên văn findBatchStocksByWarehouseAndPpu, ORDER BY b.id DESC
R-->>Q: List<InventoryCheckBatchItem> (ngày Instant)
Q-->>IC: danh sách
IC->>IC: BatchWebMapper.toInventoryCheckingBatchResponses (ngày → chuỗi UTC yyyy-MM-dd'T'HH:mm:ss.SSSxxx)
IC-->>C: 200 BaseResponseDTO.ok(items, SUCCESS_GET_LIST)
Đố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 gói dịch vụ HandleInterceptorCustom.preHandle (LF-21) |
— | KHÁC có chủ đích (D-08) — như vòng 1 |
| 2 | Bind 4 @RequestParam, thiếu/sai kiểu → 400 body rỗng (InventoryCheckingManagementResource.java:85-90, LF-03) |
InventoryCheckingBatchController.java:50-58 |
KHÁC có chủ đích (D-02, D-09) — như vòng 1 |
| 3 | CheckAuthorizeAspect.java:38-39 → UserService.java:1979-1995 giải payload của credentials (token từ JWTFilter.java:42-50, TokenProvider.java:129) → BaseJwtDTO.auth |
InventoryCheckBatchService.java:37-38 → CurrentUserAdapter.java:31-33 → JwtAuthorityClaimReader.java:39-63 giải payload token header Authorization (cùng token starter đã kiểm chữ ký) |
KHỚP (thiếu claim/payload hỏng: 417 → 500, D-03); F-logic-1 vòng 1 đã sửa |
| 4 | Set.of(authStr.split(",")), anyMatch 3401/3403 (CheckAuthorizeAspect.java:40-41) |
BatchPermission.java:25-28; IAE bọc SystemException (InventoryCheckBatchService.java:39-44) |
KHỚP (D-04; D-03 cho 417→500) |
| 5 | Không quyền → BaseAuthenticateException 401 UNAUTHORIZED_BY_CHECK (CheckAuthorizeAspect.java:43-45) |
InventoryCheckBatchService.java:45-46 |
KHỚP (text: D-10) — nay tới được |
| 6 | @Transactional(readOnly) + @ReadQuery (ICS:173-176) |
BatchQueryService.java:56 |
KHỚP (D-07, UNVERIFIED) — như vòng 1 |
| 7 | warehouseExists (ICS:178-180; BaseInventoryCheckingQueryRepositoryImpl.java:38-41) → 400 |
BatchQueryService.java:58-60; WarehouseRelationalRepository.java:32-56 |
KHỚP — như vòng 1 |
| 8 | normalize/appendLike (BaseInventoryCheckingQueryRepositoryImpl.java:142-151,176-178) |
InventoryCheckBatchReader.java:58-64 |
KHỚP — như vòng 1 |
| 9 | SQL native BaseBatchesRepository.java:29-60 |
InventoryCheckBatchReader.java:23-35 |
KHỚP — như vòng 1 |
| 10 | Projection ngày Object → Jackson StdDateFormat UTC |
InventoryCheckBatchReader.java:77-96 + BatchWebMapper |
KHỚP (D-06, UNVERIFIED) — như vòng 1 |
| 11 | BaseResultDTO(SUCCESS, SUCCESS_GET_LIST, true, list) (ICS:181-185) |
InventoryCheckingBatchController.java:61-65 |
KHÁC có chủ đích (D-02) — như vòng 1 |
| 12 | Lỗi SQL → 417 EXCEPTION_ERROR (LF-13) |
→ 500 EXCEPTION_ERROR |
KHÁC có chủ đích (D-03) — như vòng 1 |
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, com_id, id, status = true |
đọc, com_id, id, status = 1, setMaxResults(1) |
tương đương |
batches ⋈ batches_detail ⋈ inventory |
đọc, SQL R-04 | đọc, SQL nguyên văn | không lọc i.com_id ở cả hai |
JWT claim auth |
đọc từ payload token (credentials) |
đọc từ payload token header Authorization |
khớp |
| Redis gói dịch vụ | đọc (interceptor) | không | D-08 |
Transaction, khoá, idempotency, tenant
- Ranh giới transaction: kiểm quyền ngoài transaction (cũ AOP ở controller; mới
InventoryCheckBatchService), đọc trongBatchQueryService.findInventoryCheckBatchesreadOnly. Kết quả: khớp. - Khoá / cập nhật nguyên tử: không có (chỉ đọc).
- Idempotency, thời điểm phát event: không có event.
- Lọc
comId: theo tham số ở mọi truy vấn như cũ; không đối chiếu công ty token (D-01, GIỮ).
Lệch so với luồng mới đã duyệt (spec mục 6)
Không. Cấu trúc đúng sơ đồ mục 6. Riêng cách đọc claim khác mô tả spec mục 5 (đọc header thay vì BaseUserDTO.getClaim), không đổi luồng.
Dev cần chú ý khi review
| Vị trí | Vì sao |
|---|---|
infrastructure/security/JwtAuthorityClaimReader.java:47-63 |
Tự giải payload JWT, không kiểm chữ ký. Chỉ an toàn vì starter jwt_verify đã kiểm chữ ký chính header này và /api/client/page/** không public. Nếu đổi authentication-type sang header_forwarded hoặc thêm path public thì reader trả rỗng (500) hoặc tin token chưa kiểm |
infrastructure/security/JwtAuthorityClaimReader.java:39-45 |
Phụ thuộc RequestContextHolder: gọi ngoài thread request (async, Kafka) → rỗng → 500 |
application/batch/InventoryCheckBatchService.java:36-48 |
Thứ tự lỗi: thiếu claim → 500, trùng mã → 500, không quyền → 401, đều trước mọi truy cập DB |
infrastructure/relational/batch/adapter/InventoryCheckBatchReader.java:77-96 |
Đổi ngày sang Instant phụ thuộc kiểu driver trả (D-06, UNVERIFIED) — như vòng 1 |