优化
This commit is contained in:
+2
-1
@@ -41,7 +41,8 @@ public class InternalPalletLocationController {
|
||||
}
|
||||
|
||||
@PostMapping("/reservations")
|
||||
@Operation(summary = "按托盘主数据拆分并预占库位")
|
||||
@Operation(summary = "按已确认称重图片逐条预占库位",
|
||||
description = "一张图片对应一条库位预占;托盘仅作为可重复引用的主数据,不按容量拆分或限制")
|
||||
public ApiResponse<PalletAllocationDtos.BatchResult> reserve(@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
|
||||
@Valid @RequestBody PalletAllocationDtos.ReserveRequest request) {
|
||||
verify(token);
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.warehouse.dto.LocationDtos;
|
||||
import com.baiyue.warehouse.dto.PalletAllocationDtos;
|
||||
import com.baiyue.warehouse.dto.LocationDtos.ActiveResource;
|
||||
import com.baiyue.warehouse.dto.LocationDtos.ConfirmCommand;
|
||||
import com.baiyue.warehouse.dto.LocationDtos.ExactSelectiveReleaseCommand;
|
||||
@@ -284,7 +285,7 @@ public class LocationResourceService {
|
||||
continue;
|
||||
}
|
||||
Integer allocatedPackageCount = occupancy.getAllocatedPackageCount();
|
||||
if (allocatedPackageCount == null || allocatedPackageCount < 1) {
|
||||
if (allocatedPackageCount == null || allocatedPackageCount < 0) {
|
||||
throw new BizException(ResultCode.CONFLICT,
|
||||
"Occupied location has no valid allocated package count and cannot be released exactly");
|
||||
}
|
||||
@@ -322,7 +323,7 @@ public class LocationResourceService {
|
||||
if (!requested.contains(occupancy.getReservationId())) continue;
|
||||
Integer allocated = occupancy.getAllocatedPackageCount();
|
||||
LocationEntity location = repository.findOwned(command.tenantId(), occupancy.getWarehouseId(), occupancy.getLocationId());
|
||||
if (allocated == null || allocated < 1 || location == null || repository.releaseOccupancy(occupancy, command.reason()) != 1
|
||||
if (allocated == null || allocated < 0 || location == null || repository.releaseOccupancy(occupancy, command.reason()) != 1
|
||||
|| (!Boolean.TRUE.equals(occupancy.getSharedOverflow()) && repository.changeStatus(command.tenantId(),
|
||||
occupancy.getWarehouseId(), occupancy.getLocationId(), "OCCUPIED", "AVAILABLE", location.getVersion(),
|
||||
command.operatorId()) != 1)) {
|
||||
@@ -567,7 +568,7 @@ public class LocationResourceService {
|
||||
|
||||
private static int requireAllocatedPackageCount(LocationOccupancyEntity occupancy) {
|
||||
Integer allocated = occupancy.getAllocatedPackageCount();
|
||||
if (allocated == null || allocated < 1) {
|
||||
if (allocated == null || allocated < 0) {
|
||||
throw new BizException(ResultCode.CONFLICT, "已占用资源缺少有效分配箱数");
|
||||
}
|
||||
return allocated;
|
||||
@@ -593,6 +594,33 @@ public class LocationResourceService {
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
/** 活动分配重放必须与原始称重图片幂等键及托盘引用完全一致。 */
|
||||
@Transactional(readOnly = true)
|
||||
public void requireSameActiveReservations(long tenantId, long warehouseId, String sourceService,
|
||||
long businessId, String requestIdempotencyKey,
|
||||
List<PalletAllocationDtos.PalletReference> references) {
|
||||
Map<String, Long> expected = references.stream().collect(Collectors.toMap(
|
||||
item -> requestIdempotencyKey + ":" + item.weightResultId(),
|
||||
PalletAllocationDtos.PalletReference::palletId,
|
||||
(first, duplicate) -> {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "同一张称重图片不能重复预占库位");
|
||||
}));
|
||||
List<LocationReservationEntity> active = repository.findReservationsByBusiness(
|
||||
tenantId, sourceService, businessId).stream()
|
||||
.filter(item -> "RESERVED".equals(item.getReservationStatus())
|
||||
|| "CONFIRMED".equals(item.getReservationStatus()))
|
||||
.toList();
|
||||
Map<String, Long> actual = active.stream().collect(Collectors.toMap(
|
||||
LocationReservationEntity::getIdempotencyKey, LocationReservationEntity::getPalletId,
|
||||
(first, duplicate) -> {
|
||||
throw new BizException(ResultCode.CONFLICT, "活动库位分配存在重复幂等键");
|
||||
}));
|
||||
boolean sameWarehouse = active.stream().allMatch(item -> item.getWarehouseId() == warehouseId);
|
||||
if (!sameWarehouse || !actual.equals(expected)) {
|
||||
throw new BizException(ResultCode.CONFLICT, "活动库位分配与本次称重图片引用不一致");
|
||||
}
|
||||
}
|
||||
|
||||
private LocationReservationEntity reservation(ReserveCommand command, ReservationTarget target,
|
||||
LocationEntity location) {
|
||||
long id = IdWorker.getId();
|
||||
|
||||
+15
-7
@@ -53,10 +53,12 @@ public class PalletLocationAllocationService {
|
||||
@BusinessAudit(event = "PALLET_LOCATION_RESERVE", resourceType = "INBOUND", resourceId = "#request.businessId", description = "复用托盘主数据并预占库位", captureBefore = false)
|
||||
public PalletAllocationDtos.BatchResult reserve(PalletAllocationDtos.ReserveRequest request) {
|
||||
if (!Boolean.TRUE.equals(request.measurementCompleted())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "只能使用已完成测量的总体积拆分托盘并占用库位");
|
||||
throw new BizException(ResultCode.CONFLICT, "只能为已确认的称重图片预占库位");
|
||||
}
|
||||
List<LocationDtos.ActiveResource> existing = active(request.tenantId(), request.sourceService(), request.businessId());
|
||||
if (!existing.isEmpty()) {
|
||||
locationResourceService.requireSameActiveReservations(request.tenantId(), request.warehouseId(),
|
||||
request.sourceService(), request.businessId(), request.idempotencyKey(), request.pallets());
|
||||
return fromActive(request.tenantId(), request.warehouseId(), existing, request.totalVolumeCbm());
|
||||
}
|
||||
|
||||
@@ -69,12 +71,7 @@ public class PalletLocationAllocationService {
|
||||
pallets.add(pallet);
|
||||
}
|
||||
|
||||
List<LocationDtos.ReservationTarget> targets = new ArrayList<>(pallets.size());
|
||||
for (int index = 0; index < pallets.size(); index++) {
|
||||
PalletEntity pallet = pallets.get(index);
|
||||
targets.add(new LocationDtos.ReservationTarget(pallet.getId(), pallet.getPalletCode(),
|
||||
request.idempotencyKey() + ":" + request.pallets().get(index).weightResultId()));
|
||||
}
|
||||
List<LocationDtos.ReservationTarget> targets = reservationTargets(request, pallets);
|
||||
|
||||
List<LocationDtos.ReservationResult> reservations = locationResourceService.reserveAvailable(
|
||||
new LocationDtos.ReserveCommand(request.tenantId(), request.warehouseId(), request.sourceService(),
|
||||
@@ -523,6 +520,17 @@ public class PalletLocationAllocationService {
|
||||
return new ArrayList<>(locationResourceService.findActiveResources(tenantId, sourceService, businessId));
|
||||
}
|
||||
|
||||
private static List<LocationDtos.ReservationTarget> reservationTargets(
|
||||
PalletAllocationDtos.ReserveRequest request, List<PalletEntity> pallets) {
|
||||
List<LocationDtos.ReservationTarget> targets = new ArrayList<>(pallets.size());
|
||||
for (int index = 0; index < pallets.size(); index++) {
|
||||
PalletEntity pallet = pallets.get(index);
|
||||
targets.add(new LocationDtos.ReservationTarget(pallet.getId(), pallet.getPalletCode(),
|
||||
request.idempotencyKey() + ":" + request.pallets().get(index).weightResultId()));
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
public List<LocationDtos.OccupiedResource> occupiedResources(long tenantId, String sourceService,
|
||||
long businessId) {
|
||||
return locationResourceService.findOccupiedResources(tenantId, sourceService, businessId);
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
SET NAMES utf8mb4;
|
||||
USE baiyue_warehouse;
|
||||
|
||||
-- 编码由平台维护接口自动生成;两个国内作业仓各初始化一条可复用托盘主数据。
|
||||
-- 两个国内作业仓各初始化木托盘、塑料托盘各一条,共四条可复用托盘主数据。
|
||||
INSERT INTO wh_pallet(id,tenant_id,warehouse_id,pallet_code,pallet_type,capacity_cbm,weight_kg,color,remark,created_by,updated_by)
|
||||
VALUES
|
||||
(190000000000000101,0,190000000000000001,'TP-001','木托盘',1.200000,8.000,'黄色',NULL,0,0),
|
||||
(190000000000000102,0,190000000000000002,'TP-002','胶托盘',2.400000,12.000,'黑色',NULL,0,0)
|
||||
(190000000000000102,0,190000000000000002,'TP-002','塑料托盘',2.400000,12.000,'黑色',NULL,0,0),
|
||||
(190000000000000103,0,190000000000000001,'YW-TP-002','塑料托盘',2.400000,12.000,'黑色',NULL,0,0),
|
||||
(190000000000000104,0,190000000000000002,'DG-TP-002','木托盘',1.200000,8.000,'黄色',NULL,0,0)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
tenant_id=0,
|
||||
warehouse_id=VALUES(warehouse_id),
|
||||
@@ -16,6 +18,31 @@ ON DUPLICATE KEY UPDATE
|
||||
color=VALUES(color),
|
||||
remark=VALUES(remark);
|
||||
|
||||
DROP PROCEDURE IF EXISTS assert_domestic_pallet_seed;
|
||||
DELIMITER //
|
||||
CREATE PROCEDURE assert_domestic_pallet_seed()
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT expected.warehouse_id
|
||||
FROM (
|
||||
SELECT 190000000000000001 AS warehouse_id
|
||||
UNION ALL SELECT 190000000000000002
|
||||
) expected
|
||||
LEFT JOIN wh_pallet pallet
|
||||
ON pallet.tenant_id=0
|
||||
AND pallet.warehouse_id=expected.warehouse_id
|
||||
AND pallet.pallet_type IN ('木托盘','塑料托盘')
|
||||
AND pallet.deleted=0
|
||||
GROUP BY expected.warehouse_id
|
||||
HAVING COUNT(DISTINCT pallet.pallet_type)<>2
|
||||
) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='国内作业仓木托盘、塑料托盘初始化不完整';
|
||||
END IF;
|
||||
END//
|
||||
DELIMITER ;
|
||||
CALL assert_domestic_pallet_seed();
|
||||
DROP PROCEDURE IF EXISTS assert_domestic_pallet_seed;
|
||||
|
||||
-- 义乌仓初始化 A-F 六个库区,每区 A1-A15 共 90 个普通库位。
|
||||
-- A0 仍是系统共享溢出位;东莞仓继续保留最小 A1 + A0 基线。
|
||||
-- 这里只创建公共资源,不初始化预占、占用或业务单据。
|
||||
|
||||
Reference in New Issue
Block a user