fix(discard): recover completed PDA confirmation without duplicate writes

This commit is contained in:
2026-10-05 08:10:43 +08:00
parent 5864e62443
commit 113d2b1fec
2 changed files with 148 additions and 4 deletions
@@ -50,7 +50,10 @@ public class PdaCargoDiscardService {
CargoDiscardApplication application = applications.findNoByWarehouse(discardNo,
String.valueOf(identity.overseasWarehouseId()));
if (application == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "废弃任务不存在或不属于当前仓库");
if (!CargoDiscardService.APPROVED.equals(application.getStatus())) throw conflict("废弃任务当前不可进行 PDA 作业");
boolean terminal = CargoDiscardService.PDA_COMPLETED.equals(application.getStatus())
|| CargoDiscardService.COMPLETED.equals(application.getStatus());
if (!CargoDiscardService.APPROVED.equals(application.getStatus()) && !terminal)
throw conflict("废弃任务当前不可进行 PDA 作业");
PdaCargoDiscardDtos.PalletTask task = palletTasks(application).stream().filter(t -> t.palletNo().equals(palletNo.trim()))
.findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "托盘不属于该废弃单"));
Map<Long,Integer> actuals = request.lines().stream().collect(Collectors.toMap(PdaCargoDiscardDtos.ActualLine::itemId,
@@ -58,11 +61,29 @@ public class PdaCargoDiscardService {
if (!actuals.keySet().equals(task.skus().stream().map(PdaCargoDiscardDtos.Sku::itemId).collect(Collectors.toSet()))) {
throw conflict("必须提交该托盘全部 SKU 的实际废弃数量");
}
LocalDateTime now = LocalDateTime.now();
List<CargoDiscardItem> palletItems = new ArrayList<>();
for (PdaCargoDiscardDtos.Sku line : task.skus()) {
CargoDiscardItem item = items.selectById(line.itemId());
if (item == null || !application.getCustomerId().equals(item.getCustomerId())
|| !Objects.equals(application.getId(), item.getApplicationId())
|| !Objects.equals(task.profileId(), isReturnItem(item) ? item.getReturnCartonId() : item.getProfileId()))
throw conflict("废弃明细不属于当前申请或托盘");
if ("COMPLETED".equals(item.getPdaStatus())
&& !Objects.equals(item.getActualDiscardPackages(), actuals.get(item.getId())))
throw conflict("已完成托盘的实际数量不能修改");
palletItems.add(item);
}
if (terminal && items.listApplication(application.getCustomerId(), application.getId()).stream()
.anyMatch(item -> !"COMPLETED".equals(item.getPdaStatus())
|| !application.getCustomerId().equals(item.getCustomerId())
|| !Objects.equals(application.getId(), item.getApplicationId())))
throw conflict("废弃申请终态存在未完成明细,不能恢复作业结果");
// A completed pallet is an immutable result, including the final pallet after application completion.
if (palletItems.stream().allMatch(item -> "COMPLETED".equals(item.getPdaStatus()))) return task;
if (terminal) throw conflict("废弃终态不能执行未完成托盘");
LocalDateTime now = LocalDateTime.now();
for (CargoDiscardItem item : palletItems) {
if ("COMPLETED".equals(item.getPdaStatus())) {
if (!Objects.equals(item.getActualDiscardPackages(), actuals.get(item.getId()))) throw conflict("已完成托盘的实际数量不能修改");
continue;
}
List<CargoDiscardCarton> links = cartons.listApplication(application.getCustomerId(), application.getId()).stream()
@@ -84,7 +105,8 @@ public class PdaCargoDiscardService {
discardService.updateLinkedStatus(application.getCustomerId(), application, CargoDiscardService.APPROVED,
CargoDiscardService.PDA_COMPLETED, identity.operatorKey(), "全部托盘 PDA 废弃作业完成,待仓库确认");
}
return task;
return palletTasks(application).stream().filter(value -> value.palletNo().equals(palletNo.trim()))
.findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "托盘不属于该废弃单"));
}
private List<PdaCargoDiscardDtos.PalletTask> palletTasks(CargoDiscardApplication application) {