优化
This commit is contained in:
-19
@@ -37,25 +37,6 @@ public class DeliveryTransferController {
|
||||
return ApiResponse.success(dispatchDelivery.preview(actor(user),dispatchNo).groups());
|
||||
}
|
||||
|
||||
/** 一次快照提供全部客户目的地、费用证据及既有安排的完整数组。 */
|
||||
@GetMapping("/dispatches/{dispatchNo}/delivery-arrangement")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.DISPATCH_LIST + "')")
|
||||
public ApiResponse<ArrangementPreview> arrangement(@AuthenticationPrincipal AuthenticatedUser user,@PathVariable String dispatchNo) {
|
||||
requirePlatform(user);
|
||||
return ApiResponse.success(dispatchDelivery.preview(actor(user),dispatchNo));
|
||||
}
|
||||
|
||||
/** 平台一次安排本车全部客户,身份只从认证上下文获取。 */
|
||||
@PostMapping("/dispatches/{dispatchNo}/transfer-delivery")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.DISPATCH_TRANSFER_DELIVERY + "')")
|
||||
@Operation(summary = "按真实客户生成出库单并按客户目的地生成派送单")
|
||||
public ApiResponse<CommandResult> transfer(
|
||||
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String dispatchNo,
|
||||
@Valid @RequestBody ArrangeDelivery request) {
|
||||
requirePlatform(user);
|
||||
return ApiResponse.success(dispatchDelivery.arrange(actor(user),dispatchNo,request));
|
||||
}
|
||||
|
||||
@PostMapping("/outbound-orders/one-click-dropship")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.OUTBOUND_CREATE + "')")
|
||||
@Operation(summary = "Create one-click dropship outbound and push a PDA picking task")
|
||||
|
||||
+48
-3
@@ -126,6 +126,51 @@ public class DispatchDeliveryService implements DispatchDeliveryPort {
|
||||
var input=inputs.get(group.key());var coverage=fees.coverage(group,input,actor.operatorId(),external.get(group.customerId()));
|
||||
fees.validate(group,input,coverage,external.get(group.customerId()));coverages.put(group.key(),coverage);
|
||||
}
|
||||
var fact=createDocuments(context,actor,request.idempotencyKey(),businessHash,groups,inputs,external,coverages);
|
||||
return execution.recordArrangement(context,actor,identity,fact,false);
|
||||
}
|
||||
|
||||
/** 装车父事务内自动生成全车单据;未知派送资料和未确认费用保持未登记。 */
|
||||
@Override
|
||||
@Transactional(propagation=Propagation.MANDATORY)
|
||||
public ArrangementFact prepareForDeparture(Context context,Actor actor,String commandKey) {
|
||||
if(actor==null || blank(actor.operatorId()) || blank(commandKey) || commandKey.length()>255)
|
||||
throw conflict("缺少装车操作身份或原请求标识");
|
||||
if(context==null || context.status()!=Status.ACTIVE || context.stage()!=Stage.AFTER_LOADING
|
||||
|| !context.pickingReconciled() || context.loadingCompletedAt()==null || blank(context.loadingCompletionHash())
|
||||
|| blank(context.cargoHash()) || context.cargo()==null || context.cargo().isEmpty())
|
||||
throw conflict("请先完成真实拣货核平及装车确认");
|
||||
if(actor.mode()==ActorMode.PDA && !Objects.equals(actor.boundWarehouseId(),context.warehouseId()))
|
||||
throw conflict("排车不属于当前绑定仓");
|
||||
var saved=repository.arrangement(context.dispatchId(),true);
|
||||
if(saved!=null) {
|
||||
if(!Objects.equals(saved.getOriginalCommandKey(),commandKey)
|
||||
|| !Objects.equals(saved.getCargoHash(),context.cargoHash())
|
||||
|| !Objects.equals(saved.getLoadingCompletionHash(),context.loadingCompletionHash()))
|
||||
throw conflict("本车已有不同装车命令生成的派送事实");
|
||||
var facts=departureFacts(context,true);
|
||||
if(!facts.depart().allowed())throw conflict(facts.depart().blockReason());
|
||||
return fact(saved);
|
||||
}
|
||||
// 不能把缺少安排事实的孤立单据补建成另一套;全部客户在同一事务中创建。
|
||||
if(!repository.outbounds(context.dispatchId(),true).isEmpty() || !repository.deliveries(context.dispatchId(),true).isEmpty())
|
||||
throw conflict("已存在关联单据但缺少完整安排事实,请核对");
|
||||
var groups=grouping.groups(context);var external=fees.external(context);
|
||||
var inputs=new HashMap<String,ArrangeGroup>();
|
||||
for(var group:groups) {
|
||||
String carrier=context.resources()==null || context.resources().vehicle()==null?null:context.resources().vehicle().carrierName();
|
||||
inputs.put(group.key(),new ArrangeGroup(group.key(),group.cargoHash(),null,null,null,carrier,null,null,
|
||||
null,null,null,null,null,external.get(group.customerId()).snapshotHash(),null,List.of(),List.of()));
|
||||
}
|
||||
String businessHash=grouping.hash(Arrays.asList(context.dispatchNo(),context.cargoHash(),context.loadingCompletionHash(),
|
||||
groups.stream().map(g->inputs.get(g.key())).toList()));
|
||||
return createDocuments(context,actor,commandKey,businessHash,groups,inputs,external,Map.of());
|
||||
}
|
||||
|
||||
/** 自动装车与内部安排复用同一建单、来源锁及真实外接报价发布路径,不推定原费覆盖。 */
|
||||
private ArrangementFact createDocuments(Context context,Actor actor,String commandKey,String businessHash,List<Group> groups,
|
||||
Map<String,ArrangeGroup> inputs,Map<String,com.baiyue.lastleg.fleet.trip.FleetBookingFreight.Preview> external,
|
||||
Map<String,DeliveryFeeCoverageModels.Evidence> coverages) {
|
||||
var now=Instant.now();String key="DLA"+IdWorker.getId();var outbounds=new LinkedHashMap<String,OutboundOrder>();
|
||||
for (var customer:groups.stream().map(Group::customerId).distinct().sorted().toList()) {
|
||||
var cargo=context.cargo().stream().filter(c->customer.equals(c.customerId())).toList();
|
||||
@@ -169,9 +214,9 @@ public class DispatchDeliveryService implements DispatchDeliveryPort {
|
||||
var arrangement=new DispatchDeliveryArrangement();arrangement.setId(IdWorker.getId());arrangement.setDispatchOrderId(context.dispatchId());
|
||||
arrangement.setDispatchNo(context.dispatchNo());arrangement.setArrangementKey(key);arrangement.setBusinessHash(businessHash);
|
||||
arrangement.setCargoHash(context.cargoHash());arrangement.setLoadingCompletionHash(context.loadingCompletionHash());
|
||||
arrangement.setOriginalCommandKey(request.idempotencyKey());arrangement.setOriginalOperatorId(actor.operatorId());
|
||||
arrangement.setOriginalCommandKey(commandKey);arrangement.setOriginalOperatorId(actor.operatorId());
|
||||
arrangement.setResultJson(write(result));arrangement.setCargoJson(write(context.cargo()));arrangement.setCreatedAt(local(now));repository.create(arrangement);
|
||||
return execution.recordArrangement(context,actor,identity,fact(arrangement),false);
|
||||
return fact(arrangement);
|
||||
}
|
||||
|
||||
/** 发车先取得全部出库锁,再取得全部派送锁,当前读取不申请来源锁。 */
|
||||
@@ -281,7 +326,7 @@ public class DispatchDeliveryService implements DispatchDeliveryPort {
|
||||
var destination=group.destination();d.setDeliveryGroupKey(grouping.documentGroupKey(destination));d.setDestinationType(destination.type());
|
||||
d.setDestinationWarehouseId(destination.warehouseId());d.setDestinationWarehouseCode(destination.warehouseCode());d.setDestinationWarehouseName(destination.warehouseName());
|
||||
d.setDeliveryAddress(destination.address());d.setPostalCode(destination.postalCode());d.setContactName(destination.contactName());d.setContactPhone(destination.contactPhone());
|
||||
d.setStatus("WAIT_DELIVERY");d.setVersion(0L);d.setDeliveryMethod(input.deliveryMethod());d.setPlannedDeliveryAt(local(input.plannedDeliveryAt()));
|
||||
d.setStatus("WAIT_DELIVERY");d.setVersion(0L);d.setDeliveryMethod(input.deliveryMethod());d.setPlannedDeliveryAt(input.plannedDeliveryAt()==null?null:local(input.plannedDeliveryAt()));
|
||||
d.setWaybillNo(input.waybillNo());d.setCarrierName(input.carrierName());d.setPickupMethod(input.pickupMethod());d.setLoadingType(input.loadingType());
|
||||
d.setVehicleType(input.vehicleType());d.setVehicleSize(input.vehicleSize());d.setAppointmentAccount(input.appointmentAccount());d.setSellerName(input.sellerName());d.setRemark(input.remark());
|
||||
if(context.resources()!=null){if(context.resources().vehicle()!=null)d.setVehiclePlate(context.resources().vehicle().plate());
|
||||
|
||||
Reference in New Issue
Block a user