优化
This commit is contained in:
@@ -23,11 +23,14 @@ public interface PendingReviewOrderClient {
|
||||
@RequestParam(required = false) String inboundCode,
|
||||
@RequestParam(required = false) String createdStart,
|
||||
@RequestParam(required = false) String createdEnd,
|
||||
@RequestParam(required = false) String expectedArrivalStart,
|
||||
@RequestParam(required = false) String expectedArrivalEnd,
|
||||
@RequestParam(required = false) List<Long> excludedOrderIds,
|
||||
@RequestParam long page,
|
||||
@RequestParam long size);
|
||||
|
||||
record Row(Long orderId, String orderNo, String inboundCode, Long customerId,
|
||||
String customerName, Long warehouseId, String channelCode, String channelName,
|
||||
int totalPackageCount, LocalDateTime createdAt, String mainStatus) {}
|
||||
int totalPackageCount, LocalDateTime createdAt, LocalDateTime expectedArrivalAt,
|
||||
String mainStatus) {}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ public final class SmartLoadingDtos { private SmartLoadingDtos(){}
|
||||
@NotEmpty @Size(max=9) List<@NotBlank String> channelGroupCodes,
|
||||
@Positive Long warehouseId, @Positive Long customerId, @Size(max=40) String inboundCode,
|
||||
LocalDate createdStart, LocalDate createdEnd,
|
||||
LocalDate expectedArrivalStart, LocalDate expectedArrivalEnd,
|
||||
@Size(max=4) List<@NotNull CandidateOrderStatus> orderStatuses,
|
||||
@Min(1) long page, @Min(1) @Max(200) long size) {
|
||||
public InboundCandidateQuery {
|
||||
|
||||
+12
-10
@@ -82,9 +82,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
SELECT tenant_id,measurement_id,inbound_detail_id,SUM(package_count) package_count,
|
||||
COALESCE(SUM(COALESCE(total_volume_cbm,COALESCE(unit_volume_cbm,0)*package_count))
|
||||
/ NULLIF(SUM(package_count),0),0) unit_volume_cbm
|
||||
FROM fl_inbound_measurement_item
|
||||
WHERE inbound_detail_id IS NOT NULL AND package_count>0
|
||||
GROUP BY tenant_id,measurement_id,inbound_detail_id
|
||||
FROM fl_inbound_measurement_item
|
||||
WHERE inbound_detail_id IS NOT NULL AND package_count>0
|
||||
GROUP BY tenant_id,measurement_id,inbound_detail_id
|
||||
) measured
|
||||
JOIN fl_inbound_measurement batch ON batch.id=measured.measurement_id
|
||||
AND batch.tenant_id=measured.tenant_id
|
||||
@@ -104,7 +104,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
GROUP BY carton.tenant_id,carton.inbound_id,batch.id,carton.inbound_detail_id,
|
||||
batch.total_volume_cbm,source.total_package_count
|
||||
) i ON i.tenant_id=o.tenant_id AND i.inbound_id=o.id AND i.measurement_id=m.id
|
||||
WHERE o.warehouse_id=#{warehouseId} AND o.process_status='WAIT_SPLIT'
|
||||
WHERE (#{warehouseId} IS NULL OR o.warehouse_id=#{warehouseId}) AND o.process_status='WAIT_SPLIT'
|
||||
AND o.actual_gross_weight_kg IS NOT NULL AND o.actual_net_weight_kg IS NOT NULL
|
||||
AND (o.inbound_role='MASTER' OR (o.split_purpose='REMAINDER' AND o.split_status='NOT_SPLIT'))
|
||||
AND i.package_count>COALESCE((SELECT SUM(li.package_count) FROM fl_loading_plan_item li
|
||||
@@ -118,7 +118,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
AND split_item.source_inbound_detail_id=i.inbound_detail_id),0)
|
||||
ORDER BY o.inbounded_at ASC, o.id ASC, i.inbound_detail_id ASC
|
||||
""")
|
||||
List<Candidate> candidates(@Param("warehouseId") long warehouseId);
|
||||
List<Candidate> candidates(@Param("warehouseId") Long warehouseId);
|
||||
|
||||
@Select("""
|
||||
<script>
|
||||
@@ -194,6 +194,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
</if>
|
||||
<if test="query.createdStart != null">AND MIN(eligible.createdAt)>=#{query.createdStart}</if>
|
||||
<if test="query.createdEnd != null">AND MIN(eligible.createdAt)<DATE_ADD(#{query.createdEnd},INTERVAL 1 DAY)</if>
|
||||
<if test="query.expectedArrivalStart != null">AND MIN(eligible.expectedArrivalAt)>=#{query.expectedArrivalStart}</if>
|
||||
<if test="query.expectedArrivalEnd != null">AND MIN(eligible.expectedArrivalAt)<DATE_ADD(#{query.expectedArrivalEnd},INTERVAL 1 DAY)</if>
|
||||
ORDER BY sortArrivalAt IS NULL,sortArrivalAt,sortInboundId
|
||||
</script>
|
||||
""")
|
||||
@@ -363,9 +365,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
SELECT tenant_id,measurement_id,inbound_detail_id,SUM(package_count) package_count,
|
||||
COALESCE(SUM(COALESCE(total_volume_cbm,COALESCE(unit_volume_cbm,0)*package_count))
|
||||
/ NULLIF(SUM(package_count),0),0) unit_volume_cbm
|
||||
FROM fl_inbound_measurement_item
|
||||
WHERE inbound_detail_id IS NOT NULL AND package_count>0
|
||||
GROUP BY tenant_id,measurement_id,inbound_detail_id
|
||||
FROM fl_inbound_measurement_item
|
||||
WHERE inbound_detail_id IS NOT NULL AND package_count>0
|
||||
GROUP BY tenant_id,measurement_id,inbound_detail_id
|
||||
) measured
|
||||
JOIN fl_inbound_measurement batch ON batch.id=measured.measurement_id
|
||||
AND batch.tenant_id=measured.tenant_id
|
||||
@@ -385,7 +387,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
GROUP BY carton.tenant_id,carton.inbound_id,batch.id,carton.inbound_detail_id,
|
||||
batch.total_volume_cbm,source.total_package_count
|
||||
) i ON i.tenant_id=o.tenant_id AND i.inbound_id=o.id AND i.measurement_id=m.id
|
||||
WHERE o.warehouse_id=#{warehouseId} AND o.id=#{inboundId}
|
||||
WHERE o.id=#{inboundId}
|
||||
AND (o.process_status='WAIT_SPLIT' OR (o.process_status='LOADING' AND EXISTS (
|
||||
SELECT 1 FROM fl_loading_plan_item same_plan_item
|
||||
WHERE same_plan_item.loading_plan_id=#{planId}
|
||||
@@ -398,7 +400,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
|
||||
AND i.inbound_detail_id=#{detailId}
|
||||
ORDER BY m.id DESC LIMIT 1 FOR UPDATE
|
||||
""")
|
||||
Candidate candidate(@Param("planId") long planId,@Param("warehouseId") long warehouseId,
|
||||
Candidate candidate(@Param("planId") long planId,
|
||||
@Param("inboundId") long inboundId,@Param("detailId") long detailId);
|
||||
|
||||
@Select("""
|
||||
|
||||
@@ -39,7 +39,7 @@ public class SmartLoadingRepository {
|
||||
@Resource private SmartLoadingCandidateMapper candidates;
|
||||
@Resource private InboundOrderMapper inbounds;
|
||||
|
||||
public List<Candidate> candidates(long warehouseId) { return candidates.candidates(warehouseId); }
|
||||
public List<Candidate> candidates(Long warehouseId) { return candidates.candidates(warehouseId); }
|
||||
public PageResult<CandidateUnit> globalCandidateUnits(InboundCandidateQuery query,
|
||||
Set<String> actualChannels) {
|
||||
return PageResult.from(candidates.globalCandidateUnits(
|
||||
@@ -62,8 +62,8 @@ public class SmartLoadingRepository {
|
||||
public List<Long> occupiedOrderIds(InboundCandidateQuery query, Set<String> actualChannels) {
|
||||
return candidates.occupiedOrderIds(query, actualChannels);
|
||||
}
|
||||
public Candidate candidate(long planId, long warehouseId, long inboundId, long detailId) {
|
||||
return candidates.candidate(planId, warehouseId, inboundId, detailId);
|
||||
public Candidate candidate(long planId, long inboundId, long detailId) {
|
||||
return candidates.candidate(planId, inboundId, detailId);
|
||||
}
|
||||
public Integer measuredPackageCount(long accountId, long inboundId, long detailId) {
|
||||
return candidates.measuredPackageCount(accountId, inboundId, detailId);
|
||||
|
||||
@@ -113,6 +113,16 @@ public class SmartLoadingService {
|
||||
return grouped.values().stream().map(this::inboundCandidate).toList();
|
||||
}
|
||||
|
||||
private List<InboundCandidate> recommendationCandidates(ContainerBookingEntity booking) {
|
||||
List<Candidate> values = repository.candidates(null).stream()
|
||||
.filter(candidate -> sameChannel(booking, candidate) && sameCustomerScope(booking, candidate)).toList();
|
||||
Map<Long, List<Candidate>> grouped = enrichColoadCandidates(booking,
|
||||
repository.planByBooking(booking.getId()), values).stream()
|
||||
.collect(java.util.stream.Collectors.groupingBy(Candidate::inboundId, LinkedHashMap::new,
|
||||
java.util.stream.Collectors.toList()));
|
||||
return grouped.values().stream().map(this::inboundCandidate).toList();
|
||||
}
|
||||
|
||||
/** Global workbench candidates. A co-load group is one paging unit and can never be split across pages. */
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<InboundCandidate> inboundCandidates(InboundCandidateQuery query) {
|
||||
@@ -120,6 +130,10 @@ public class SmartLoadingService {
|
||||
&& query.createdStart().isAfter(query.createdEnd())) {
|
||||
throw validation("创建开始日期不能晚于结束日期");
|
||||
}
|
||||
if (query.expectedArrivalStart() != null && query.expectedArrivalEnd() != null
|
||||
&& query.expectedArrivalStart().isAfter(query.expectedArrivalEnd())) {
|
||||
throw validation("预计到货开始日期不能晚于结束日期");
|
||||
}
|
||||
Set<String> actualChannels = actualChannels(query.channelGroupCodes());
|
||||
EnumSet<CandidateOrderStatus> selected = query.orderStatuses().isEmpty()
|
||||
? EnumSet.allOf(CandidateOrderStatus.class)
|
||||
@@ -188,6 +202,7 @@ public class SmartLoadingService {
|
||||
try {
|
||||
response = pendingReviewOrders.page(internalToken, List.copyOf(actualChannels), query.warehouseId(),
|
||||
query.customerId(), query.inboundCode(), isoDate(query.createdStart()), isoDate(query.createdEnd()),
|
||||
isoDate(query.expectedArrivalStart()), isoDate(query.expectedArrivalEnd()),
|
||||
repository.occupiedOrderIds(query, actualChannels), page, size);
|
||||
} catch (RuntimeException exception) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "待审核订单服务暂时不可用");
|
||||
@@ -201,7 +216,7 @@ public class SmartLoadingService {
|
||||
row.warehouseId(), row.channelCode(), row.channelName(), null, null, null,
|
||||
row.customerName(), null, row.totalPackageCount(), null, null, null, null,
|
||||
null, null, null, null, false, true, null,
|
||||
"PENDING_REVIEW", null, List.of())).toList();
|
||||
"PENDING_REVIEW", row.expectedArrivalAt(), List.of())).toList();
|
||||
return new PageResult<>(records, source.page(), source.size(), source.total(), source.pages());
|
||||
}
|
||||
|
||||
@@ -238,7 +253,8 @@ public class SmartLoadingService {
|
||||
List<CandidateOrderStatus> statuses,
|
||||
long page, long size) {
|
||||
return new InboundCandidateQuery(source.channelGroupCodes(), source.warehouseId(), source.customerId(),
|
||||
source.inboundCode(), source.createdStart(), source.createdEnd(), statuses, page, size);
|
||||
source.inboundCode(), source.createdStart(), source.createdEnd(), source.expectedArrivalStart(),
|
||||
source.expectedArrivalEnd(), statuses, page, size);
|
||||
}
|
||||
|
||||
public PageResult<WorkbenchContainer> containers(WorkbenchContainerQuery query) {
|
||||
@@ -414,8 +430,7 @@ public class SmartLoadingService {
|
||||
if (replay != null) return replay;
|
||||
LoadingPlanEntity plan = editing(planId, request.expectedVersion(), operatorId, operatorName);
|
||||
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
|
||||
Candidate candidate = repository.candidate(planId, booking.getWarehouseId(), request.inboundId(),
|
||||
request.inboundDetailId());
|
||||
Candidate candidate = repository.candidate(planId, request.inboundId(), request.inboundDetailId());
|
||||
if (candidate == null) throw conflict("入库货物不存在或尚未完成入库");
|
||||
if (!wholeGroupAssignment) requireStandalone(candidate.accountId(), candidate.inboundId());
|
||||
requireSameCustomerScope(booking, candidate);
|
||||
@@ -786,7 +801,7 @@ public class SmartLoadingService {
|
||||
LoadingPlanEntity plan = editing(planId, request.expectedVersion(), operatorId, operatorName);
|
||||
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
|
||||
Set<Long> visitedGroups = new HashSet<>();
|
||||
for (InboundCandidate candidate : inboundCandidates(plan.getContainerBookingId(), booking.getWarehouseId())) {
|
||||
for (InboundCandidate candidate : recommendationCandidates(booking)) {
|
||||
if (candidate.coLoadGroupId() != null) {
|
||||
if (!visitedGroups.add(candidate.coLoadGroupId()) || StringUtils.hasText(candidate.blockReason())) {
|
||||
continue;
|
||||
@@ -845,8 +860,7 @@ public class SmartLoadingService {
|
||||
throw conflict("计划箱数不能低于已拣货箱数");
|
||||
}
|
||||
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
|
||||
Candidate candidate = repository.candidate(planId, booking.getWarehouseId(), item.getInboundId(),
|
||||
item.getInboundDetailId());
|
||||
Candidate candidate = repository.candidate(planId, item.getInboundId(), item.getInboundDetailId());
|
||||
int currentPackageCount = item.getPackageCount() == null ? 0 : item.getPackageCount();
|
||||
OrderCargoClient.CargoBinding cargo;
|
||||
int maxPackageCount;
|
||||
@@ -1128,12 +1142,12 @@ public class SmartLoadingService {
|
||||
}
|
||||
|
||||
private List<Candidate> availableCandidates(ContainerBookingEntity booking) {
|
||||
return repository.candidates(booking.getWarehouseId()).stream()
|
||||
return repository.candidates(null).stream()
|
||||
.filter(candidate -> sameChannel(booking, candidate) && sameCustomerScope(booking, candidate)).toList();
|
||||
}
|
||||
|
||||
private List<Candidate> manualCandidates(ContainerBookingEntity booking) {
|
||||
return repository.candidates(booking.getWarehouseId()).stream()
|
||||
return repository.candidates(null).stream()
|
||||
.filter(candidate -> sameCustomerScope(booking, candidate)).toList();
|
||||
}
|
||||
|
||||
@@ -1291,7 +1305,7 @@ public class SmartLoadingService {
|
||||
try {
|
||||
ApiResponse<PageResult<PendingReviewOrderClient.Row>> response = pendingReviewOrders.page(
|
||||
internalToken, null, null, request.customerId(), request.inboundCode(), null, null,
|
||||
null, 1, 2);
|
||||
null, null, null, 1, 2);
|
||||
if (response == null || !response.successful() || response.data() == null) throw unavailable();
|
||||
return response.data().records().stream()
|
||||
.filter(row -> Objects.equals(row.orderId(), request.orderId())
|
||||
@@ -1374,7 +1388,6 @@ public class SmartLoadingService {
|
||||
private record DeclaredCargo(OrderCargoClient.CargoBinding cargo) {}
|
||||
private void checkRouteAndCapacity(ContainerBookingEntity b,List<LoadingPlanItemEntity> lines,Candidate c,
|
||||
int count, boolean requireSameDestination){
|
||||
if (!Objects.equals(b.getWarehouseId(), c.warehouseId())) throw validation("装柜仓库不一致");
|
||||
if (requireSameDestination && StringUtils.hasText(b.getDestinationWarehouseCode())
|
||||
&& !Objects.equals(b.getDestinationWarehouseCode(), c.destinationWarehouseCode())) {
|
||||
throw validation("目的仓/港不一致");
|
||||
|
||||
Reference in New Issue
Block a user