This commit is contained in:
2026-09-15 20:52:02 +08:00
parent 4b671bb0ab
commit 8b19085bc4
24 changed files with 387 additions and 38 deletions
@@ -113,6 +113,16 @@ public class PlatformDropshipPalletizationController {
return ApiResponse.success(service.seal(taskId, palletId, request, user.userId(), user.username()));
}
@PostMapping("/tasks/{taskId}/pallets/{palletId}/unseal")
@PreAuthorize("hasAuthority('platform:firstleg:pda:work')")
public ApiResponse<Task> unseal(@AuthenticationPrincipal AuthenticatedUser user,
@PathVariable @Positive long taskId,
@PathVariable @Positive long palletId,
@Valid @RequestBody DropshipPalletizationDtos.UnsealPalletRequest request) {
FirstlegScopeGuard.platform(user);
return ApiResponse.success(service.unseal(taskId, palletId, request, user.userId(), user.username()));
}
@GetMapping("/tasks/{taskId}/pallets/{palletId}/print")
@PreAuthorize("hasAuthority('platform:firstleg:pda:view')")
public ResponseEntity<byte[]> printTaskPallet(@AuthenticationPrincipal AuthenticatedUser user,
@@ -44,6 +44,10 @@ public final class DropshipPalletizationDtos {
@NotBlank @Size(max = 128) String operationId,
@Positive int expectedVersion) {}
public record UnsealPalletRequest(@Positive long warehouseId,
@NotBlank @Size(max = 128) String operationId,
@Positive int expectedVersion) {}
public record PendingTask(Long taskId, Long inboundId, String inboundCode, Long tenantId,
String customerName, Long warehouseId, String warehouseName,
Integer totalCartons, Integer countedCartons, Integer boundCartons,
@@ -170,6 +170,15 @@ public interface DropshipPalletizationMapper {
AND EXISTS(SELECT 1 FROM fl_dropship_pallet_carton c WHERE c.pallet_id=#{palletId} AND c.task_id=#{taskId})""")
int seal(@Param("taskId") long taskId,@Param("palletId") long palletId,@Param("expectedVersion") int expectedVersion,
@Param("warehouseId") long warehouseId,@Param("operationId") String operationId,@Param("operatorId") long operatorId,@Param("operatorName") String operatorName);
@Select("SELECT COUNT(*) FROM fl_loading_plan_item WHERE pallet_id=#{palletId} AND deleted=0")
int activeLoadingAssignmentCount(@Param("palletId") long palletId);
@Update("""
UPDATE fl_dropship_pallet SET pallet_status='OPEN',seal_operation_id=#{operationId},completed_by=NULL,
completed_by_name=NULL,completed_at=NULL,version=version+1,updated_at=CURRENT_TIMESTAMP(3)
WHERE id=#{palletId} AND warehouse_id=#{warehouseId} AND pallet_status='SEALED' AND version=#{expectedVersion}
AND EXISTS(SELECT 1 FROM fl_dropship_pallet_carton c WHERE c.pallet_id=#{palletId} AND c.task_id=#{taskId})""")
int unseal(@Param("taskId") long taskId,@Param("palletId") long palletId,@Param("expectedVersion") int expectedVersion,
@Param("warehouseId") long warehouseId,@Param("operationId") String operationId);
@Select("""
SELECT COUNT(DISTINCT p.id) FROM fl_dropship_pallet_carton c
JOIN fl_dropship_pallet p ON p.id=c.pallet_id
@@ -189,6 +198,13 @@ public interface DropshipPalletizationMapper {
WHERE o.id=#{inboundId} AND o.tenant_id=#{tenantId} AND o.process_status='WAIT_PALLETIZE'
AND EXISTS(SELECT 1 FROM fl_dropship_pallet_task t WHERE t.id=#{taskId} AND t.task_status='COMPLETED')""")
int completeInbound(@Param("taskId") long taskId,@Param("tenantId") long tenantId,@Param("inboundId") long inboundId,@Param("operatorId") long operatorId);
@Update("""
UPDATE fl_dropship_pallet_task SET task_status='CLAIMED',completed_at=NULL,version=version+1,updated_at=CURRENT_TIMESTAMP(3)
WHERE id=#{taskId} AND task_status='COMPLETED'""") int reopenTask(@Param("taskId") long taskId);
@Update("""
UPDATE fl_inbound_order SET process_status='WAIT_PALLETIZE',updated_by=#{operatorId},version=version+1
WHERE id=#{inboundId} AND tenant_id=#{tenantId} AND process_status='WAIT_SPLIT'""")
int reopenInbound(@Param("tenantId") long tenantId,@Param("inboundId") long inboundId,@Param("operatorId") long operatorId);
@Select("""
SELECT c.*,p.pallet_no,o.inbound_code FROM fl_dropship_pallet_carton c
@@ -130,7 +130,7 @@ public class DropshipPalletizationService {
public Task seal(long taskId,long palletId,SealPalletRequest request,long operatorId,String operatorName){
TaskRow task=requireWorkingTask(taskId,request.warehouseId(),operatorId);
PalletRow replay=mapper.palletBySealOperation(operation(request.operationId()));
if(replay!=null){ if(!Objects.equals(replay.getId(),palletId)||!Objects.equals(replay.getWarehouseId(),request.warehouseId())) throw conflict("封托幂等号已用于其他托盘"); return view(requireTask(taskId,request.warehouseId())); }
if(replay!=null){ if(!Objects.equals(replay.getId(),palletId)||!Objects.equals(replay.getWarehouseId(),request.warehouseId())||!"SEALED".equals(replay.getPalletStatus())) throw conflict("封托幂等号已用于其他操作"); return view(requireTask(taskId,request.warehouseId())); }
requireOpenPallet(taskId,palletId,request.warehouseId());
if(mapper.seal(taskId,palletId,request.expectedVersion(),request.warehouseId(),operation(request.operationId()),operatorId,operatorName)!=1)
throw conflict("空托盘、托盘状态或版本已变化,请刷新后重试");
@@ -145,6 +145,38 @@ public class DropshipPalletizationService {
return view(requireTask(taskId,request.warehouseId()));
}
@Transactional
public Task unseal(long taskId,long palletId,UnsealPalletRequest request,long operatorId,String operatorName){
TaskRow task=requireTask(taskId,request.warehouseId());
if(task.getAssigneeId()==null || !Objects.equals(task.getAssigneeId(),operatorId)) throw conflict("任务不属于当前操作员");
if(!List.of("CLAIMED","COMPLETED").contains(task.getTaskStatus())) throw conflict("当前任务状态不能解除封托");
String operation=operation(request.operationId());
PalletRow replay=mapper.palletBySealOperation(operation);
if(replay!=null){
if(!Objects.equals(replay.getId(),palletId)||!Objects.equals(replay.getWarehouseId(),request.warehouseId())||!"OPEN".equals(replay.getPalletStatus())) throw conflict("解除封托幂等号已用于其他操作");
return view(requireTask(taskId,request.warehouseId()));
}
PalletRow pallet=mapper.pallet(taskId,palletId,request.warehouseId());
if(pallet==null) throw new BizException(ResultCode.NOT_FOUND,"托盘不存在");
if(!"SEALED".equals(pallet.getPalletStatus())) throw conflict("托盘尚未封托");
if(mapper.activeLoadingAssignmentCount(palletId)>0) throw conflict("托盘已进入装柜计划,请先从柜次移除后再解除封托");
List<TaskRow> participants=new ArrayList<>();
for(Long participatingTaskId:mapper.taskIdsByPallet(palletId)){
TaskRow participating=requireTask(participatingTaskId,request.warehouseId());
if(!List.of("WAIT_PALLETIZE","WAIT_SPLIT").contains(participating.getProcessStatus())) throw conflict("托盘已进入后续履约,不能解除封托");
participants.add(participating);
}
if(mapper.unseal(taskId,palletId,request.expectedVersion(),request.warehouseId(),operation)!=1)
throw conflict("托盘状态或版本已变化,请刷新后重试");
for(TaskRow participating:participants){
if("COMPLETED".equals(participating.getTaskStatus()) && mapper.reopenTask(participating.getId())!=1)
throw conflict("合托任务状态已变化,请刷新后重试");
if("WAIT_SPLIT".equals(participating.getProcessStatus()) && mapper.reopenInbound(participating.getTenantId(),participating.getInboundId(),operatorId)!=1)
throw conflict("入仓单状态已变化,请刷新后重试");
}
return view(requireTask(taskId,request.warehouseId()));
}
public List<Pallet> inboundPallets(long tenantId,long inboundId){
String code=mapper.inboundCode(tenantId,inboundId);
if(code==null) throw new BizException(ResultCode.NOT_FOUND,"入库单不存在");