Luồng xếp kệ đến từ 2 nguồn của service No-diem:
| Job xếp kệ (Rescan) | API xếp kệ (Vận hành) | |
|---|---|---|
| Entry point | ReScanInsertPkgToPctMarginRouteService.rescanSaveRoute |
POST /api/v1/add-package-onto-shelf |
| Phạm vi | Toàn bộ BC — phá kệ + xếp lại hàng loạt | Một đơn tại thời điểm quét |
| Trigger | Kafka / Async thread từ Xteam | REST API đồng bộ được call từ các api xếp kệ từ Xteam-backend |
| Service xếp đơn lẻ | AddPackageOntoShelfService.ontoShelf(..., false) |
AddAndMovePackageOntoShelfService.ontoShelf → ontoShelf(..., true) |
| Strategy | IGNORE_MARGIN_CONDITION |
API_IGNORE_MARGIN_CONDITION |
| Response | Không trả về client (chạy nền) | PackageOntoShelfResponse (route + tên kệ) |
*** Logic xếp kệ cho từng đơn nằm trong logic xếp kệ của cả BC(Ở bước 8) ***
Method: getAggregateRouteService.getAllByStationIdAndStatusIdAndTypeIn(...)
| Thao tác | Bảng |
|---|---|
| Đọc | routes (status = WAITING_PULL, type SORT/CONNECTION) |
| Đọc | route_packages (đơn trong route) |
Method: filterRouteHasRescan(stationId, isChangeConfig)
| Thao tác | Bảng |
|---|---|
| Đọc | routes (route mix qua routeSearchAdapter) |
| Đọc | routes + config KBBC / khung giờ (getRouteIdsNeedRescanByKBBC hoặc getAllRouteIdNeedRescanByStationIdAndStatusId) |
Chỉ đọc, chưa ghi DB.
Method: removePkgIntoRouteService.removePkgIntoRoute(...)
Bỏ qua nếu route thuộc tụ (checkRouteBelongToFocusPoint → đọc focus_point_packages).
| Thao tác | Bảng | Chi tiết |
|---|---|---|
| Sửa | route_packages |
status: WAITING_PULL → ROUTE_PACKAGE_REMOVE_FOR_RESCAN |
| Sửa | temp_route_packages |
status tương tự (nếu là đơn tạm) |
| Thêm | no_shelf_packages |
INSERT đơn với status NOT_YET_SAVE_ROUTE |
| Thêm | tmp_shelf_packages |
INSERT (nếu là đơn tạm) |
| Sửa | scan_shelf_packages |
Gán kệ xấu (assignBadShelfForPackageNotOntoStandardShelf) |
| Sửa | routes |
status: WAITING_PULL → ROUTE_REMOVE_FOR_RESCAN (khi route rỗng, không còn route_bookings) |
| Xóa | demand_config_routes |
deleteByRouteIdIn khi route bị xóa hoàn toàn |
Đọc kiểm tra: route_bookings (nếu còn đơn booking thì không đổi status routes).
Method: demandStationConfigAdapter.removeNormalRouteInDemandTable(...)
| Thao tác | Bảng |
|---|---|
| Đọc | demand_config_routes, demand_station_configs |
| Xóa | demand_config_routes |
Method: getAggregateShelfPackageService.getAllByStationIdAndStatusId(stationId, NOT_YET_SAVE_ROUTE)
| Thao tác | Bảng |
|---|---|
| Đọc | no_shelf_packages |
| Đọc | tmp_shelf_packages (đơn tạm) |
Method: sortPkgOrderByDistanceToStation → calRelateInfoLogCR.sortPkgOrderByDistanceToStation
| Thao tác | Bảng |
|---|---|
| Đọc | packages (tọa độ đơn), stations (tọa độ BC) |
Method: packageCollectionAdapter.getPackageCollectionMap(...)
| Thao tác | Bảng |
|---|---|
| Đọc | Bảng collection/đối tác (partner_id) — chỉ đọc, không ghi |
addPackageOntoShelfService.ontoShelf(...)Luồng chính (BC dùng strategy IGNORE_MARGIN_CONDITION):
AddPackageOntoShelfService.ontoShelf
→ IgnoreMarginConditionService.addPkgOntoShelf
→ RoutePlanner.planRoute // tìm route phù hợp
→ PreCreateNewRouteObjService.addPkgToRoute // TH: ghép vào route có sẵn
→ PreCreateNewRouteObjService.addNewRoute // TH: không có route → tạo mới
| Layer | Method |
|---|---|
| Chọn route | RoutePlanner.allocateRoute → selectRouteByPriority |
| Ghi DB | PreCreateNewRouteObjService.addPkgToRoute |
| Validate SL đơn | RoutePackageService.addNewPkgIntoRoute |
| Transaction ghi | SaveAggregateRoutePackageService.saveAll |
Chuỗi ghi DB qua saveAll (theo thứ tự @Order):
| # | Service | Bảng | Thao tác |
|---|---|---|---|
| 0 | ValidationBeforeAddPkgIntoRouteService |
route_packages, routes, xteam_routes |
Đọc (validate) |
| 1 | AddPkgIntoRouteService |
route_packages |
INSERT đơn vào route |
| 1 | AddPkgIntoRouteService |
temp_route_packages |
INSERT (nếu đơn tạm) |
| 2 | UpdateRouteTypeConnectionPointService |
routes |
Sửa type → CONNECTION (đơn nối điểm) |
| 3 | UpdateStatusInShelfPackageService |
no_shelf_packages / tmp_shelf_packages |
Sửa status → SAVE_ROUTE_SUCCESS |
| 4 | AssignShelfForPackageService |
physical_shelf_packages |
INSERT gán kệ vật lý |
| 4 | AssignShelfForPackageService |
scan_shelf_packages |
INSERT/UPDATE system_shelf_id (tên kệ quét) |
| 5 | UpdateDemandConfigRouteService |
demand_config_routes |
Sửa total_delivery_time (route cung cầu) |
Kết quả trả về:
route_id(từroutes),shelf_id/system_shelf_id(tên kệ quét trênscan_shelf_packages).
| Layer | Method |
|---|---|
| Tạo route | PreCreateNewRouteObjService.addNewRoute → RouteAndRoutePackageService.createNewRouteAndRoutePackage |
| Ghi route | DefaultRouteShelfAdapter.createNewRouteAndRoutePackage |
| Bảng | Thao tác |
|---|---|
routes |
INSERT (status WAITING_PULL, gán shelf_id) |
route_packages |
INSERT đơn đầu tiên |
demand_config_routes |
INSERT (nếu route cung cầu) |
no_shelf_packages |
Sửa status |
physical_shelf_packages, scan_shelf_packages |
INSERT/UPDATE (qua saveAll như trên) |
multiXPackageIntoRouteService.intoRoute(...)MultiXPackageIntoRouteServiceImpl.intoRoute
→ CepMultiXPackageIntoRouteService.into // route có đơn nội tỉnh
→ CepMultiXPackageIntoDRouteService.into // route chỉ đơn D
→ multiPackageNewRouteService.createNewRoute // fallback: tạo mới
| Layer | Method |
|---|---|
| Lọc route | CepRouteInputFilter.filterMultiPackage |
| Tính margin | CepRouteDiffBuilder.build + RouteDistanceFilter |
| Chọn route tốt nhất | ChooseBestRouteCollector.choose |
| Ghi DB | MultiPackageRoutePackageService.addMultiPackageIntoRoute → SaveAggregateRoutePackageService.saveAll |
Bảng tác động: giống bảng ở mục 8A (route_packages INSERT, no_shelf_packages UPDATE, scan_shelf_packages UPDATE, demand_config_routes UPDATE...).
| Method | Bảng |
|---|---|
DefaultRouteShelfAdapter.createNewRouteMultiPackage |
INSERT routes + INSERT nhiều route_packages + chuỗi saveAll như trên |
Method: rescanConsecutivePackageService.saveRoute(stationId) (nếu config bật)
| Sub-step | Method | Bảng tác động |
|---|---|---|
| B3.1 Ghép đơn nối điểm vào route có sẵn | RescanAdditionalConsecutivePackageService → ConsecutivePackageIntoRouteAlreadyExistsService |
INSERT route_packages, Sửa routes.type, Sửa no_shelf_packages, scan_shelf_packages |
| B3.2 Tạo route nối điểm mới | RescanAdditionalConsecutiveRouteService → ConsecutivePackageIntoRouteService |
INSERT routes, route_packages |
Method: saveShelfAssignToPackageService.assignBadShelfForPackage(stationId, pkgOrders)
| Thao tác | Bảng |
|---|---|
| Đọc | route_packages (lọc đơn đã có route hợp lệ) |
| Sửa/Thêm | scan_shelf_packages |
| Bảng | Vai trò trong luồng |
|---|---|
routes |
Tập route/kệ logic; INSERT khi tạo mới, UPDATE status khi phá kệ |
route_packages |
Liên kết đơn ↔ route; INSERT khi ghép đơn, UPDATE status khi phá kệ |
no_shelf_packages |
Hàng đợi đơn chưa xếp kệ; INSERT khi phá kệ, UPDATE khi xếp thành công |
scan_shelf_packages |
Tên kệ quét đơn (system_shelf_id); INSERT/UPDATE khi gán kệ |
physical_shelf_packages |
Kệ vật lý thực tế |
demand_config_routes |
Route cung cầu; DELETE khi phá kệ, INSERT/UPDATE khi tạo/ghép |
temp_route_packages / tmp_shelf_packages |
Đơn tạm (nếu có) |
Nếu cần, tôi có thể vẽ tiếp sequence diagram chi tiết cho một case cụ thể (đơn lẻ ghép route cũ vs đơn gom tạo route mới).
Tất cả các luồng xếp kệ bên Xteam-backend đều đi qua một điểm gọi ND duy nhất:
ND endpoint: POST ${add-package-onto-shelf} → mặc định api/v1/add-package-onto-shelf
NoDiemRestClient.getAddPackageToShelf()
← DefaultNdService.addPkgOntoShelf()
← (2 nhánh chính bên dưới)
NewWrapCheckinUseCaseImplgetAddPackageToShelfResponse() → ndService.addPkgOntoShelf()
Gọi từ: handleForNewStationConfigs, handleForNotRunStation, addPkgOntoShelfHoldHUB
PackageCheckInToShelfAbstract.callNdToFindShelf()PackageCheckInToShelfUseCase.process() → strategy → updateShelf() → chỉ gọi ND khi không tìm được kệ hệ thống sẵn (findGoodsSystemShelf empty)
| Strategy | typeId |
|---|---|
DefaultDelayPackageCheckInToShelfStrategy |
IMPORT_PKG_CHECKIN, SCAN_PILLAR_TO_BAG, CONFIRM_DELAY_PACKAGE, CONFIRM_DELAY_CIC |
DefaultYcckCheckInPackageOntoShelfStrategy |
YCCK_CHECKIN, APPROVED_YCCK_CHECKIN, CRON_APPROVED_YCCK_CHECKIN |
Có thể một số luồng outdate không còn chạy, có thể nhờ BA verify kết hợp check log Kibana
NewWrapCheckinUseCase| Method | Endpoint | Use case | Ghi chú |
|---|---|---|---|
| POST | /api/v1/pk-bus/packages/checkin |
NewCheckInPkBusUseCaseImpl |
Đơn kệ xấu → addPkgOntoShelfSupportTempDataWhenNotRunConfig |
| POST | /api/v1/pk-bus/packages/rescan-checkin |
ProcessRescanPackageUseCaseImpl |
wrapCheckinUseCase.checkin() |
| POST | /api/v1/pk-bus/packages/scan-ycck |
ScanYCCKPackageUseCaseImpl.checkIn |
Luồng cũ (BC không trong config mới) |
| POST | /api/v1/pk-bus/packages/scan-ycck-v2 |
ScanYCCKPackageUseCaseImpl.checkInV2 |
Phần BC không trong STATIONS_RUN_NEW_RESCAN_PACKAGE_CHECKIN_SHELF + luồng HOLD_HUB |
| POST | /api/v1/pk-bus/packages/scan-pillar |
NewCheckInPkBusUseCaseImpl |
BC không trong config mới → processHandleOldScanPillar |
| POST | /api/v1/pk-bus/packages/scan-import-packages |
ScanImportPackageUseCaseImpl |
BC không trong config mới; luồng consecutive cũng gọi checkin() |
| POST | /api/v1/pk-bus/packages/scan-import-psc-point |
ScanImportPackageUseCaseImpl |
Tương tự scan-import |
| POST | /api/v1/distributor/checkin-package-shelf |
CheckinPackagesNotOnShelf |
handleForNewStationConfigs() khi đơn có trong no_shelf_packages |
| POST | /api/v1/service/distributor/packages/confirm-export-for-pk |
AddPkYcckOntoShelfRunNewScanShelfServiceImpl |
BC chạy luồng xếp kệ mới → handleForNewStationConfigs |
PackageCheckInToShelfUseCase| Method | Endpoint | Use case | typeId |
|---|---|---|---|
| POST | /api/v1/pk-bus/packages/scan-pillar |
NewCheckInPkBusUseCaseImpl |
SCAN_PILLAR_TO_BAG |
| POST | /api/v1/pk-bus/packages/scan-import-packages |
ScanImportPackageUseCaseImpl |
IMPORT_PKG_CHECKIN |
| POST | /api/v1/pk-bus/packages/scan-import-psc-point |
ScanImportPackageUseCaseImpl |
IMPORT_PKG_CHECKIN |
| POST | /api/v1/pk-bus/packages/scan-ycck-v2 |
ScanYCCKPackageUseCaseImpl.checkInV2 |
YCCK_CHECKIN |
| POST | /api/v1/service/packages/push-to-pool-package |
PushDelayPackageToPoolUseCaseImpl |
CONFIRM_DELAY_PACKAGE |
| Method | Endpoint | Luồng gọi ND |
|---|---|---|
| POST | /api/v1/distributor/confirm-export/confirm-export-packages-of-cod |
ApproveXteamReportCustomerService.processPutOrderOnToShelf → nhánh B (APPROVED_YCCK_CHECKIN) |
| POST | /api/v1/cod/pillar/confirm-export-package |
Tương tự qua approve() |
| POST | /api/v1/cod/pillar/confirm-export-package-v2 |
Tương tự |
| POST | /api/distributor/v1/nvbc/confirm-xteam-report-customer |
ConfirmKeepPkgUseCase → ConfirmCustomerReportService → approve() |
| POST | api/service/v1/xteam-nvbc/confirm-report-customer |
ConfirmXteamKeepPkgUseCase → tương tự |
Lưu ý: processPutOrderOnToShelf chỉ chạy khi BC thuộc luồng mới (STATIONS_RUN_NEW_RESCAN_PACKAGE_CHECKIN_SHELF rỗng hoặc BC nằm trong config). Các BC còn lại dùng luồng kệ xấu local, không gọi ND tại bước duyệt.
| Job | Schedule | Luồng | typeId |
|---|---|---|---|
CronOutboxEventConfirmYCCKEvent |
@Scheduled(fixedDelay=5000) |
Outbox CONFIRM_YCCK_EVENT (sau duyệt YCCK) → defaultPackageCheckInToShelfUseCase.process |
CRON_APPROVED_YCCK_CHECKIN |
CronOutboxConfirmDelayPackageCloseShiftEvent |
@Scheduled(fixedDelay=10000) |
Outbox delay chốt ca → pushDelayPackageToPool → nhánh B |
CONFIRM_DELAY_PACKAGE / CONFIRM_DELAY_CIC |
CronAddPackagesCloseShifts |
Handler chain | AutoOpenToBagAfterConfirmedDelayHandler → packageCheckInToShelfUseCase.process |
CONFIRM_DELAY_PACKAGE / CONFIRM_DELAY_CIC |
Hiện tại, logic tìm kệ cho đơn hàng(AddPackageOntoShelfService::ontoShelf) đang được xử lý đồng thời với logic định tuyến (routing) và chia thành 2 trường hợp:
getScannedShelfService.getEmptyShelfNearly(stationId).Tách biệt hoàn toàn logic xếp kệ và logic định tuyến thành 2 bài toán độc lập bên trong AddPackageOntoShelfService::ontoShelf. Quy trình mới được quy định như sau:
shelf_id)Hệ thống sẽ xác định kệ cho đơn hàng dựa trên địa chỉ giao hàng và phân loại thời gian giao, thay vì phụ thuộc vào trạng thái của Route:
Lưu ý: Tham khảo và tái sử dụng logic cũ đã triển khai trong hàm
ShelfServiceImpl::buildMapPkgOrderWithWardName.
Thiết kế và xây dựng một Service Routing mới độc lập. Yêu cầu kỹ thuật bao gồm:
Dữ liệu đầu vào (Inputs):
Thông tin Đơn hàng (Package/Order).
Danh sách Route tối ưu ("Route ngon").
Danh sách Route chưa tối ưu ("Route chưa ngon").
Thông tin Bưu cục (BC).
Các tham số cấu hình liên quan khác.
Dữ liệu đầu ra (Outputs):
Kết quả trả về của Service Routing mới phải đảm bảo cấu trúc dữ liệu đầy đủ và tường minh.
Cung cấp đủ thông tin cần thiết để phục vụ cho các thao tác INSERT và UPDATE vào các bảng dữ liệu tương ứng ở Bước 8 trong luồng xử lý.
Vị trí triển khai: Toàn bộ logic phân tách và điều hướng trên sẽ được quản lý và xử lý tập trung tại hàm
AddPackageOntoShelfService::ontoShelf. Sau có nhu cầu refactoring code hoặc logic chọn và phá kệ có thể sửa trong job xếp kệ