优化
This commit is contained in:
+16
-12
@@ -16,11 +16,12 @@ public interface LoadingInboundMapper {
|
||||
batch.loaded_child_inbound_id AS loadedChildInboundId,
|
||||
batch.parent_inbound_id AS rootInboundId,
|
||||
source.process_status AS sourceStatus, source.version AS sourceVersion,
|
||||
child.process_status AS loadedChildStatus, child.version AS loadedChildVersion
|
||||
CASE WHEN batch.loaded_child_inbound_id IS NULL THEN source.process_status ELSE child.process_status END AS loadedChildStatus,
|
||||
CASE WHEN batch.loaded_child_inbound_id IS NULL THEN source.version ELSE child.version END AS loadedChildVersion
|
||||
FROM fl_inbound_split_batch batch
|
||||
JOIN fl_inbound_order source ON source.id=batch.source_inbound_id
|
||||
AND source.tenant_id=batch.tenant_id AND source.deleted=0
|
||||
JOIN fl_inbound_order child ON child.id=batch.loaded_child_inbound_id
|
||||
LEFT JOIN fl_inbound_order child ON child.id=batch.loaded_child_inbound_id
|
||||
AND child.tenant_id=batch.tenant_id AND child.deleted=0
|
||||
WHERE batch.tenant_id=#{tenantId} AND batch.status='APPLIED'
|
||||
AND (batch.source_inbound_id=#{inboundId} OR batch.loaded_child_inbound_id=#{inboundId})
|
||||
@@ -35,15 +36,14 @@ public interface LoadingInboundMapper {
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_inbound_order child
|
||||
JOIN fl_inbound_split_batch batch ON batch.loaded_child_inbound_id=child.id
|
||||
AND batch.tenant_id=child.tenant_id AND batch.status='APPLIED'
|
||||
JOIN fl_inbound_order source ON source.id=batch.source_inbound_id
|
||||
AND source.tenant_id=batch.tenant_id AND source.deleted=0
|
||||
SET child.process_status='LOADED', child.updated_by=#{operatorId}, child.version=child.version+1
|
||||
WHERE child.tenant_id=#{tenantId} AND batch.source_inbound_id=#{sourceInboundId}
|
||||
AND child.deleted=0 AND child.process_status='LOADING'
|
||||
AND source.version=#{expectedSourceVersion}
|
||||
UPDATE fl_inbound_split_batch batch
|
||||
JOIN fl_inbound_order target
|
||||
ON target.id=COALESCE(batch.loaded_child_inbound_id,batch.source_inbound_id)
|
||||
AND target.tenant_id=batch.tenant_id AND target.deleted=0
|
||||
SET target.process_status='LOADED', target.updated_by=#{operatorId}, target.version=target.version+1
|
||||
WHERE batch.tenant_id=#{tenantId} AND batch.source_inbound_id=#{sourceInboundId}
|
||||
AND batch.status='APPLIED' AND target.process_status='LOADING'
|
||||
AND target.version=#{expectedSourceVersion}
|
||||
""")
|
||||
int completeLoadedChild(@Param("tenantId") long tenantId,
|
||||
@Param("sourceInboundId") long sourceInboundId,
|
||||
@@ -73,5 +73,9 @@ public interface LoadingInboundMapper {
|
||||
record Snapshot(Long id, Long tenantId, String processStatus, Integer version) {}
|
||||
record CompletionTarget(Long sourceInboundId, Long loadedChildInboundId, Long rootInboundId,
|
||||
String sourceStatus, Integer sourceVersion,
|
||||
String loadedChildStatus, Integer loadedChildVersion) {}
|
||||
String loadedChildStatus, Integer loadedChildVersion) {
|
||||
public Long completionInboundId() {
|
||||
return loadedChildInboundId == null ? sourceInboundId : loadedChildInboundId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ public class LoadingDeliveryService {
|
||||
if (repository.completeLoadedChild(tenantId, target.sourceInboundId(), operatorId,
|
||||
request.expectedVersion()) != 1) throw concurrent();
|
||||
repository.aggregateRootLoaded(tenantId, target.rootInboundId(), operatorId);
|
||||
addHistory(tenantId, target.loadedChildInboundId(), "LOADING", "LOADED", COMPLETE_LOADING,
|
||||
addHistory(tenantId, target.completionInboundId(), "LOADING", "LOADED", COMPLETE_LOADING,
|
||||
request.remark(), operatorId, operatorName);
|
||||
return complete(tenantId, evidenceInboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse("LOADED", evidenceResponse(tenantId, evidenceInboundId)));
|
||||
|
||||
+37
-13
@@ -54,7 +54,7 @@ public interface InboundSplitSettlementMapper {
|
||||
#{packageCount},#{packageCount},actual_gross_weight_kg,chargeable_weight_kg,actual_volume_cbm,chargeable_volume_cbm,
|
||||
pallet_count,volume_weight_kg,actual_net_weight_kg,measure_completed_at,inbounded_at,express_company_code,
|
||||
express_company_name,express_tracking_no,public_remark,#{operatorId},#{operatorName},CURRENT_TIMESTAMP(3),
|
||||
#{operatorId},CURRENT_TIMESTAMP(3),0,0,'CHILD',#{parentInboundId},#{rootInboundId},#{splitSequence},'NOT_SPLIT',#{splitPurpose}
|
||||
#{operatorId},CURRENT_TIMESTAMP(3),0,0,'CHILD',#{rootInboundId},#{rootInboundId},#{splitSequence},'NOT_SPLIT',#{splitPurpose}
|
||||
FROM fl_inbound_order WHERE id=#{parentInboundId} AND tenant_id=#{accountId} AND deleted=0
|
||||
""")
|
||||
int cloneChildWithPurpose(@Param("accountId") long accountId, @Param("parentInboundId") long parentInboundId,
|
||||
@@ -70,7 +70,7 @@ public interface InboundSplitSettlementMapper {
|
||||
loaded_package_count,remaining_package_count,loading_plan_id,container_booking_id,status,remark,
|
||||
created_by,created_by_name,created_at,version)
|
||||
VALUES (#{batchId},#{accountId},#{parentInboundId},#{sourceInboundId},#{operationId},#{idempotencyKey},#{expectedParentVersion},
|
||||
#{packageCount},#{loadedChildId},#{remainderChildId},#{loadedPackageCount},#{remainingPackageCount},
|
||||
#{packageCount},NULL,#{remainderChildId},#{loadedPackageCount},#{remainingPackageCount},
|
||||
#{loadingPlanId},#{containerBookingId},'PREPARED',#{remark},#{operatorId},#{operatorName},CURRENT_TIMESTAMP(3),0)
|
||||
""")
|
||||
int insertBatchWithChildren(@Param("batchId") long batchId, @Param("accountId") long accountId,
|
||||
@@ -157,17 +157,41 @@ public interface InboundSplitSettlementMapper {
|
||||
@Param("packageCount") int packageCount, @Param("operatorId") long operatorId,
|
||||
@Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@Update("UPDATE fl_inbound_order SET package_count=0,split_status='FULLY_SPLIT',updated_by=#{operatorId},version=version+1 "
|
||||
+ "WHERE id=#{parentInboundId} AND tenant_id=#{accountId} AND inbound_role='MASTER' AND deleted=0 "
|
||||
+ "AND process_status IN ('INBOUNDED','LOADING') AND version=#{expectedVersion}")
|
||||
int markRootSplit(@Param("accountId") long accountId, @Param("parentInboundId") long parentInboundId,
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
@Update("UPDATE fl_inbound_order SET package_count=#{loadedPackageCount},process_status='LOADING',"
|
||||
+ "split_status='FULLY_SPLIT',updated_by=#{operatorId},version=version+1 "
|
||||
+ "WHERE id=#{sourceInboundId} AND tenant_id=#{accountId} AND deleted=0 "
|
||||
+ "AND process_status IN ('INBOUNDED','LOADING') AND split_status='NOT_SPLIT' "
|
||||
+ "AND COALESCE(package_count,total_package_count)>=#{loadedPackageCount} AND version=#{expectedVersion}")
|
||||
int markSourceLoaded(@Param("accountId") long accountId, @Param("sourceInboundId") long sourceInboundId,
|
||||
@Param("loadedPackageCount") int loadedPackageCount,
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@Update("UPDATE fl_inbound_order SET split_status='FULLY_SPLIT',updated_by=#{operatorId},version=version+1 "
|
||||
+ "WHERE id=#{sourceInboundId} AND tenant_id=#{accountId} AND inbound_role='CHILD' "
|
||||
+ "AND split_purpose='REMAINDER' AND split_status='NOT_SPLIT' AND deleted=0 AND version=#{expectedVersion}")
|
||||
int markRemainderConsumed(@Param("accountId") long accountId, @Param("sourceInboundId") long sourceInboundId,
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
@Update("UPDATE fl_inbound_order SET updated_by=#{operatorId},version=version+1 "
|
||||
+ "WHERE id=#{rootInboundId} AND tenant_id=#{accountId} AND inbound_role='MASTER' AND deleted=0 "
|
||||
+ "AND version=#{expectedVersion}")
|
||||
int touchRootSplit(@Param("accountId") long accountId, @Param("rootInboundId") long rootInboundId,
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_inbound_measurement_item
|
||||
SET package_count=#{packageCount},
|
||||
total_weight_kg=CASE WHEN unit_weight_kg IS NULL THEN NULL ELSE unit_weight_kg*#{packageCount} END,
|
||||
total_volume_cbm=unit_volume_cbm*#{packageCount},
|
||||
volume_weight_kg=volume_weight_kg/NULLIF(package_count,0)*#{packageCount},
|
||||
updated_at=CURRENT_TIMESTAMP(3)
|
||||
WHERE id=#{measurementItemId} AND tenant_id=#{accountId}
|
||||
""")
|
||||
int updateMeasurementItemForLoaded(@Param("accountId") long accountId,
|
||||
@Param("measurementItemId") long measurementItemId,
|
||||
@Param("packageCount") int packageCount);
|
||||
|
||||
@Update("UPDATE fl_inbound_measurement SET total_package_count=#{packageCount},updated_at=CURRENT_TIMESTAMP(3),"
|
||||
+ "version=version+1 WHERE id=#{measurementId} AND tenant_id=#{accountId} AND inbound_id=#{inboundId} "
|
||||
+ "AND status='APPROVED'")
|
||||
int updateMeasurementForLoaded(@Param("accountId") long accountId,
|
||||
@Param("inboundId") long inboundId,
|
||||
@Param("measurementId") long measurementId,
|
||||
@Param("packageCount") int packageCount);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_inbound_split_batch
|
||||
@@ -262,7 +286,7 @@ public interface InboundSplitSettlementMapper {
|
||||
child.volume_weight_kg=(SELECT COALESCE(SUM(item.volume_weight_kg),0)
|
||||
FROM fl_inbound_measurement_item item WHERE item.measurement_id=measurement.id),
|
||||
child.actual_net_weight_kg=NULL,child.pallet_count=0,child.version=child.version+1
|
||||
WHERE child.id=#{childInboundId} AND child.tenant_id=#{accountId} AND child.inbound_role='CHILD'
|
||||
WHERE child.id=#{childInboundId} AND child.tenant_id=#{accountId} AND child.deleted=0
|
||||
""")
|
||||
int normalizeChildMetrics(@Param("accountId") long accountId, @Param("childInboundId") long childInboundId,
|
||||
@Param("measurementId") long measurementId);
|
||||
|
||||
@@ -161,30 +161,23 @@ public class PdaPickSettlementService {
|
||||
OrderFulfillmentSplitClient.Response orderSplit = createOrderSplit(parent, root, measurementLines,
|
||||
pickedPackageCount, childPackageCount, loadingPlanId, containerBookingId, operationId,
|
||||
"pda-task-" + taskId, operatorId, operatorName);
|
||||
long loadedChildId = IdWorker.getId();
|
||||
long remainderChildId = childPackageCount > 0 ? IdWorker.getId() : 0L;
|
||||
long batchId = IdWorker.getId();
|
||||
String idempotencyKey = "pda-task-" + taskId;
|
||||
int parentVersion = root.version() == null ? 0 : root.version();
|
||||
int rootVersion = root.version() == null ? 0 : root.version();
|
||||
int sourceVersion = parent.version() == null ? 0 : parent.version();
|
||||
int sequence = splits.nextSplitSequence(parent.tenantId(), rootInboundId);
|
||||
String loadedChildCode = childInboundCode(root.inboundCode(), sequence);
|
||||
String remainderChildCode = childPackageCount > 0
|
||||
? childInboundCode(root.inboundCode(), sequence + 1) : null;
|
||||
requireAffected(splits.cloneChildWithPurpose(parent.tenantId(), rootInboundId, rootInboundId, loadedChildId,
|
||||
orderSplit.loadedChild().orderId(), orderSplit.loadedChild().orderNo(),
|
||||
loadedChildCode, pickedPackageCount, sequence, "LOADED", operatorId, operatorName), "实装子入库单");
|
||||
? childInboundCode(root.inboundCode(), sequence) : null;
|
||||
if (remainderChildId != 0L) {
|
||||
requireAffected(splits.cloneChildWithPurpose(parent.tenantId(), rootInboundId, rootInboundId, remainderChildId,
|
||||
requireAffected(splits.cloneChildWithPurpose(parent.tenantId(), parentInboundId, rootInboundId, remainderChildId,
|
||||
orderSplit.remainderChild().orderId(), orderSplit.remainderChild().orderNo(),
|
||||
remainderChildCode, childPackageCount, sequence + 1, "REMAINDER", operatorId, operatorName), "余量子入库单");
|
||||
remainderChildCode, childPackageCount, sequence, "REMAINDER", operatorId, operatorName), "余量子入库单");
|
||||
}
|
||||
requireAffected(splits.insertBatchWithChildren(batchId, parent.tenantId(), rootInboundId, operationId, parentInboundId,
|
||||
idempotencyKey, parentVersion, parentAvailable, loadedChildId, remainderChildId == 0L ? null : remainderChildId,
|
||||
idempotencyKey, rootVersion, parentAvailable, null, remainderChildId == 0L ? null : remainderChildId,
|
||||
pickedPackageCount, childPackageCount, loadingPlanId, containerBookingId,
|
||||
"PDA拣货后生成实装/余量子单", operatorId, operatorName), "拆分批次");
|
||||
long loadedMeasurementId = IdWorker.getId();
|
||||
requireAffected(splits.cloneMeasurement(parent.tenantId(), parentInboundId, sourceMeasurementId,
|
||||
loadedChildId, loadedMeasurementId, batchId, pickedPackageCount, operatorId), "实装子入库测量批次");
|
||||
long childMeasurementId = childPackageCount > 0 ? IdWorker.getId() : 0L;
|
||||
if (childPackageCount > 0) {
|
||||
requireAffected(splits.cloneMeasurement(parent.tenantId(), parentInboundId, sourceMeasurementId,
|
||||
@@ -192,51 +185,46 @@ public class PdaPickSettlementService {
|
||||
}
|
||||
|
||||
int lineNo = 1;
|
||||
for (MeasurementSplitLine line : measurementLines) {
|
||||
if (line.pickedPackageCount() <= 0) continue;
|
||||
long splitItemId = IdWorker.getId();
|
||||
requireAffected(splits.insertSplitItem(splitItemId, parent.tenantId(), batchId, rootInboundId,
|
||||
loadedChildId, lineNo, line.item().inboundDetailId(), sourceMeasurementId,
|
||||
line.item().measurementItemId(), line.pickedPackageCount()), "实装拆分明细");
|
||||
requireAffected(splits.cloneMeasurementItem(parent.tenantId(), sourceMeasurementId,
|
||||
line.item().measurementItemId(), loadedMeasurementId, splitItemId, IdWorker.getId(), lineNo,
|
||||
line.pickedPackageCount()), "实装子入库测量明细");
|
||||
lineNo++;
|
||||
}
|
||||
for (MeasurementSplitLine line : measurementLines) {
|
||||
if (line.remainingPackageCount() <= 0) {
|
||||
continue;
|
||||
}
|
||||
long splitItemId = IdWorker.getId();
|
||||
requireAffected(splits.insertSplitItem(splitItemId, parent.tenantId(), batchId, rootInboundId,
|
||||
remainderChildId == 0L ? loadedChildId : remainderChildId, lineNo, line.item().inboundDetailId(), sourceMeasurementId,
|
||||
remainderChildId, lineNo, line.item().inboundDetailId(), sourceMeasurementId,
|
||||
line.item().measurementItemId(), line.remainingPackageCount()), "拆分明细");
|
||||
requireAffected(splits.cloneMeasurementItem(parent.tenantId(), sourceMeasurementId,
|
||||
line.item().measurementItemId(), childMeasurementId, splitItemId, IdWorker.getId(), lineNo,
|
||||
line.remainingPackageCount()), "子入库测量明细");
|
||||
lineNo++;
|
||||
}
|
||||
requireAffected(splits.normalizeChildMetrics(parent.tenantId(), loadedChildId, loadedMeasurementId),
|
||||
"实装子单重量体积归一化");
|
||||
requireAffected(splits.markSourceLoaded(parent.tenantId(), parentInboundId, pickedPackageCount,
|
||||
operatorId, sourceVersion), "来源分片状态");
|
||||
if (parentInboundId != rootInboundId) {
|
||||
requireAffected(splits.touchRootSplit(parent.tenantId(), rootInboundId, operatorId, rootVersion), "根单拆分状态");
|
||||
}
|
||||
requireAffected(splits.applyBatch(parent.tenantId(), batchId), "拆分批次生效");
|
||||
for (MeasurementSplitLine line : measurementLines) {
|
||||
requireAffected(splits.updateMeasurementItemForLoaded(parent.tenantId(),
|
||||
line.item().measurementItemId(), line.pickedPackageCount()), "来源测量明细");
|
||||
}
|
||||
requireAffected(splits.updateMeasurementForLoaded(parent.tenantId(), parentInboundId, sourceMeasurementId,
|
||||
pickedPackageCount), "来源测量批次");
|
||||
requireAffected(splits.normalizeChildMetrics(parent.tenantId(), parentInboundId, sourceMeasurementId),
|
||||
"来源单重量体积归一化");
|
||||
if (remainderChildId != 0L) {
|
||||
requireAffected(splits.normalizeChildMetrics(parent.tenantId(), remainderChildId, childMeasurementId),
|
||||
"余量子单重量体积归一化");
|
||||
}
|
||||
requireAffected(splits.markRootSplit(parent.tenantId(), rootInboundId, operatorId, parentVersion), "主入库单拆分状态");
|
||||
if ("CHILD".equals(parent.inboundRole())) {
|
||||
requireAffected(splits.markRemainderConsumed(parent.tenantId(), parentInboundId, operatorId,
|
||||
parent.version() == null ? 0 : parent.version()), "余量子单消费状态");
|
||||
}
|
||||
requireAffected(splits.applyBatch(parent.tenantId(), batchId), "拆分批次生效");
|
||||
requireAffected(splits.insertHistory(IdWorker.getId(), parent.tenantId(), batchId,
|
||||
operationId + "-APPLY", "{\"sourceInboundId\":" + parentInboundId
|
||||
+ ",\"loadedChildInboundId\":" + loadedChildId
|
||||
+ ",\"loadedChildInboundId\":null"
|
||||
+ ",\"remainderChildInboundId\":" + (remainderChildId == 0L ? "null" : remainderChildId)
|
||||
+ ",\"loadedPackageCount\":" + pickedPackageCount
|
||||
+ ",\"remainingPackageCount\":" + childPackageCount
|
||||
+ ",\"loadingPlanId\":" + loadingPlanId
|
||||
+ ",\"containerBookingId\":" + containerBookingId + "}", operatorId, operatorName,
|
||||
"PDA拣货自动生成实装/余量子入库单"), "拆分审计");
|
||||
"PDA拣货后来源单承接实装并生成余量子入库单"), "拆分审计");
|
||||
|
||||
if (remainderChildId != 0L) {
|
||||
allocations.copyRemainingToChild(parent.tenantId(), remainderChildId, confirmedAllocations);
|
||||
@@ -245,7 +233,7 @@ public class PdaPickSettlementService {
|
||||
releasedReservationIds);
|
||||
allocations.markReleased(parent.tenantId(), parentInboundId, releasedReservationIds);
|
||||
settleWarehouseResources(parentInboundId, remainderChildId,
|
||||
remainderChildCode == null ? loadedChildCode : remainderChildCode,
|
||||
remainderChildCode == null ? root.inboundCode() : remainderChildCode,
|
||||
taskId, operatorId, operatorName,
|
||||
warehouseId, parentAvailable, childPackageCount, releasedReservationIds, transferItems);
|
||||
return true;
|
||||
@@ -282,14 +270,17 @@ public class PdaPickSettlementService {
|
||||
boolean remainderMatches = remainingPackageCount == 0 ? split.remainderChild() == null
|
||||
: validOrderChild(split.remainderChild(), "REMAINDER", source.orderId(), loadingPlanId,
|
||||
containerBookingId, remainingPackageCount);
|
||||
boolean sourceLoadedMatches = split.loadedChild() == null
|
||||
|| (Objects.equals(split.loadedChild().orderId(), source.orderId())
|
||||
&& validOrderChild(split.loadedChild(), "LOADED", source.orderId(), loadingPlanId,
|
||||
containerBookingId, loadedPackageCount));
|
||||
if (!Objects.equals(split.parentOrderId(), root.orderId())
|
||||
|| !Objects.equals(split.sourcePackageCount(), loadedPackageCount + remainingPackageCount)
|
||||
|| !Objects.equals(split.loadedPackageCount(), loadedPackageCount)
|
||||
|| !Objects.equals(split.remainingPackageCount(), remainingPackageCount)
|
||||
|| !Objects.equals(split.loadingPlanId(), loadingPlanId)
|
||||
|| !Objects.equals(split.containerBookingId(), containerBookingId)
|
||||
|| !validOrderChild(split.loadedChild(), "LOADED", source.orderId(), loadingPlanId,
|
||||
containerBookingId, loadedPackageCount)
|
||||
|| !sourceLoadedMatches
|
||||
|| !remainderMatches) {
|
||||
throw conflict("订单服务返回的父子订单、柜次或数量不一致");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user