Phân tích luồng sau chuyển — warehouse/import-excel-save-data — vòng 2
F-01 Lưu import — cập nhật (type=2)
- Điểm vào: cũ
easyposbackend1:src/main/java/vn/softdreams/easypos/web/rest/WarehouseResource.java:117-121→ mớiWarehouseController.java:155-182 - Quy tắc: R-01, R-02, R-03, R-04, R-05, R-08, R-09, R-10
Đối chiếu từng bước
| # | Luồng cũ | Luồng mới | Kết luận |
|---|---|---|---|
| 1 | Không validate — WarehouseResource.java:118-119 |
Không validate, map dòng sang command — WarehouseController.java:158-167 |
KHỚP; phần tử null → KHÁC (F-logic-2) |
| 2 | data.isEmpty() → FAIL — BaseWarehouseServiceImpl.java:1101-1103 |
rows == null || isEmpty → empty — WarehouseImportService.java:74-76; FAIL — WarehouseController.java:172-177 |
KHÁC có chủ đích (D-02, D-12) |
| 3 | Không kiểm công ty (LF-20) | requireCompanyOfCurrentUser — WarehouseImportService.java:77 |
KHÁC có chủ đích (D-01) |
| 4 | Gom SKU, map dòng sau thắng — …:1106-1111 |
WarehouseImportService.java:96-101 |
KHỚP |
| 5 | findBySkuIn(listSku, comId) |
findAllBySkuIn → native SKU in :skus and com_id = :comId |
KHỚP |
| 6 | copyProperties(mapData.get(sku), …); null → IllegalArgumentException |
null → SystemException(EXCEPTION_ERROR) |
KHÁC có chủ đích (D-02, D-08) |
| 7 | Chép mọi field kể cả comId dòng, status=getStatus(), không đổi normalizedName |
Warehouse.applyImport, comId = request |
KHỚP; comId KHÁC có chủ đích (D-03) |
| 8 | Dirty-check → @PreUpdate làm sạch + audit |
so businessValues thô → cleanText + audit |
KHỚP |
| 9 | saveAll (merge entity managed, không SQL) — …:1135 |
WarehouseRepository.saveAll: một findAllById (trả instance managed), so comId, mapper.apply — WarehouseRelationalRepository.java:174-199 |
KHỚP về dữ liệu ghi; thêm 1 SELECT (thay N SELECT vòng 1) — F-logic-1 ĐÃ HẾT |
| 10 | 200 SUCCESS, data = entity, count |
ok(toResponses, WAREHOUSE_IMPORT_SUCCESS) + count |
KHÁC có chủ đích (D-02) |
| 11 | Interceptor gói (LF-21) | không có | KHÁC có chủ đích (D-11) |
Transaction, khoá, idempotency, tenant
- Transaction: cũ cấp class (LF-33) → mới
@TransactionaltrênsaveImportData, qua proxy;SystemExceptionrollback toàn bộ. - Khoá: không ở cả hai (KHỚP R-09). Không event; gửi lại cùng request thì chép đè lại (audit chỉ đổi khi dirty).
comId: truy vấn lọccom_idđã kiểm;comIdghi vào kho lấy từ dòng do controller gán (F-logic-3).
Dev cần chú ý khi review
| Vị trí | Vì sao |
|---|---|
WarehouseImportService.java:102-110 |
Nhánh lỗi khi SKU khác hoa thường (D-08); ném trước mọi lệnh ghi |
Warehouse.java:115-132 |
Dirty-check thô quyết định có ghi updater/update_time (K-02) |
WarehouseRelationalRepository.java:177-180,190-192 |
findAllById không lọc com_id trong SQL, an toàn tenant dựa vào phép so comId; kho bị xoá đồng thời giữa hai SELECT → WAREHOUSE_NOT_FOUND (rất hiếm, rollback) |
WarehouseRelationalRepository.java:197-198 |
Kết quả lấy từ danh sách entity gốc — đúng vì persist giữ instance khi id null |
WarehouseJpaRepository.findAllBySkuInAndComId |
Native SQL, collation MSSQL chưa kiểm (K-13) |
F-02 Lưu import — tạo mới (type=1)
- Điểm vào: như F-01
- Quy tắc: R-01, R-02, R-03, R-04, R-06, R-08, R-09, R-10
Đối chiếu từng bước
| # | Luồng cũ | Luồng mới | Kết luận |
|---|---|---|---|
| 1 | Rỗng / không validate / không kiểm công ty | như F-01 | như F-01 |
| 2 | findBySku(sku) không lọc com_id, Optional — …:1121 |
countBySkuAllCompanies — WarehouseRelationalRepository.java:205-214 |
KHỚP (D-04 GIỮ) |
| 3 | ≥2 dòng → 417 | count > 1 → SystemException(EXCEPTION_ERROR) |
KHÁC có chủ đích (D-02, D-04) |
| 4 | 1 dòng → bỏ qua | count == 1 → bỏ qua |
KHỚP |
| 5 | copyProperties(dòng, kho) gồm id, comId dòng |
Warehouse.create/copyFrom, id null, comId request |
KHÁC có chủ đích (D-03) |
| 6 | genCode(request.comId, "WH") |
WarehouseCodeGenerator.generate(comId) (tách nguyên vòng cũ) |
KHỚP |
| 7 | isNullOrEmpty(SKU) → SKU = code |
copyFrom: null hoặc "" → code |
KHỚP |
| 8 | normalizedName([name, SKU dòng]) |
WarehouseText.normalizedName([name, sku dòng]) |
KHỚP |
| 9 | status = getStatus(), sellable thô |
createFromImport: status = activeStatus() |
KHỚP (D-09) |
| 10 | @PrePersist làm sạch + creator/updater |
cleanText + audit trong create |
KHỚP |
| 11 | saveAll → INSERT từng dòng |
save từng kho → INSERT |
KHỚP |
Dev cần chú ý khi review
| Vị trí | Vì sao |
|---|---|
WarehouseRelationalRepository.java:205-214 |
Truy vấn cố ý không lọc com_id (D-04); sku == null trả 0 bằng code |
WarehouseImportService.java:117-124 |
Kiểm SKU rồi mới sinh mã; lỗi ≥2 kho ném sau khi dòng trước đã tiêu mã Redis |
WarehouseCodeGenerator.java + WarehouseManagementService |
Refactor dùng chung với warehouse/create |
Warehouse.java:98-102 |
create ép status=TRUE rồi createFromImport ghi đè — phụ thuộc thứ tự |
F-03 Lưu import — type khác 1/2
- Điểm vào: như F-01. Quy tắc: R-01, R-02, R-03, R-07, R-08, R-10
| # | Luồng cũ | Luồng mới | Kết luận |
|---|---|---|---|
| 1 | Không duyệt data |
Controller map mọi dòng | KHÁC (F-logic-2) với phần tử null |
| 2 | Rỗng → FAIL | như F-01 | KHÁC có chủ đích (D-02, D-12) |
| 3 | Không kiểm công ty | requireCompanyOfCurrentUser |
KHÁC có chủ đích (D-01) |
| 4 | Không nhánh nào khớp → saveAll([]) |
warehouses = List.of() |
KHỚP (D-10) |
| 5 | 200 SUCCESS, data=[], count=0 |
ok([]) + count=0 |
KHÁC có chủ đích (D-02) |
Vòng 2 (thu hẹp): F-01 bước 9 và F-02 bước 11 viết lại theo
logic-reviewervòng 2 (lưu quasaveAll); F-03 không đổi so với vòng 1 (rỗng thì không gọisaveAll, kết quả nhưsaveAll([])cũ).