This commit is contained in:
2026-08-11 18:43:50 +08:00
parent e1487162a5
commit bc5d9a6215
25 changed files with 1424 additions and 28 deletions
@@ -13,10 +13,12 @@ import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@@ -81,6 +83,15 @@ public class InternalPalletLocationController {
return ApiResponse.success(service.settle(request));
}
@GetMapping("/occupied-resources")
@Operation(summary = "查询业务当前占用资源", description = "PDA提交前使用的只读实时库存事实")
public ApiResponse<List<LocationDtos.OccupiedResource>> occupiedResources(
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
@RequestParam long tenantId, @RequestParam String sourceService, @RequestParam long businessId) {
verify(token);
return ApiResponse.success(service.occupiedResources(tenantId, sourceService, businessId));
}
@PostMapping("/rebind-temporary-location")
@Operation(summary = "A0临时库位换绑", description = "将一条具体A0托盘占用换绑到同仓空闲普通库位")
public ApiResponse<PalletAllocationDtos.RebindTemporaryLocationResult> rebindTemporaryLocation(
@@ -458,6 +458,19 @@ public class LocationResourceService {
.toList();
}
/** PDA 提交前读取当前占用事实;只读快照不持有数据库行锁。 */
@Transactional(readOnly = true)
public List<OccupiedResource> findOccupiedResources(long tenantId, String sourceService, long businessId) {
return repository.findOccupanciesByBusiness(tenantId, sourceService, businessId).stream()
.filter(item -> "OCCUPIED".equals(item.getOccupancyStatus()))
.sorted(Comparator.comparingLong(LocationOccupancyEntity::getReservationId)
.thenComparingLong(LocationOccupancyEntity::getId))
.map(item -> new OccupiedResource(item.getReservationId(), item.getId(), 0,
item.getWarehouseId(), item.getPalletId(), item.getLocationId(), item.getLocationCode(),
Boolean.TRUE.equals(item.getSharedOverflow()), requireAllocatedPackageCount(item)))
.toList();
}
/** 将 A0 的一条托盘占用换绑到同仓空闲普通库位。 */
@Transactional
public LocationDtos.RebindTemporaryLocationResult rebindTemporaryLocation(
@@ -153,9 +153,6 @@ public class OverseasStorageFeeService {
.thenComparingInt(OverseasStorageFeeDtos.TierRequest::startDay));
for (String feeType : List.of("STORAGE", "RETURN_STORAGE")) {
List<OverseasStorageFeeDtos.TierRequest> group = tiers.stream().filter(t -> feeType.equals(t.feeType())).toList();
if (source.size() == 9 && (("STORAGE".equals(feeType) && group.size() != 5)
|| ("RETURN_STORAGE".equals(feeType) && group.size() != 4)))
throw new BizException(ResultCode.VALIDATION_FAILED, "仓租必须5档,退货仓储费必须4档");
int expectedStart = 1;
for (int i = 0; i < group.size(); i++) {
OverseasStorageFeeDtos.TierRequest tier = group.get(i);
@@ -538,6 +538,11 @@ public class PalletLocationAllocationService {
return new ArrayList<>(locationResourceService.findActiveResources(tenantId, sourceService, businessId));
}
public List<LocationDtos.OccupiedResource> occupiedResources(long tenantId, String sourceService,
long businessId) {
return locationResourceService.findOccupiedResources(tenantId, sourceService, businessId);
}
private static PalletAllocationDtos.BatchResult fromActive(List<LocationDtos.ActiveResource> active,
PalletVolumeSplitter.SplitResult split) {
if (active.size() != split.palletCount()) {