feat(fleet): bind quote versions and reconcile actual return quantities
This commit is contained in:
+27
-5
@@ -5,6 +5,7 @@ import com.baiyue.lastleg.delivery.entity.DeliveryOrder;
|
||||
import com.baiyue.lastleg.delivery.mapper.DeliveryOrderMapper;
|
||||
import com.baiyue.lastleg.delivery.mapper.DeliveryOperationMapper;
|
||||
import com.baiyue.lastleg.delivery.mapper.OutboundOrderMapper;
|
||||
import com.baiyue.lastleg.delivery.model.DeliveryCargoQuantities;
|
||||
import com.baiyue.lastleg.dispatch.entity.DispatchOrder;
|
||||
import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper;
|
||||
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
||||
@@ -159,17 +160,26 @@ public class DispatchFleetAdapter implements FleetDispatchGateway {
|
||||
var outbound = lock ? outbounds.lockByDispatch(dispatch.getCustomerId(), dispatch.getId()) : outbounds.findByDispatch(dispatch.getCustomerId(), dispatch.getId());
|
||||
var rows = outbound == null ? java.util.List.<DeliveryOrder>of() : lock
|
||||
? deliveries.lockByOutbound(dispatch.getCustomerId(), outbound.getId()) : deliveries.findByOutbound(dispatch.getCustomerId(), outbound.getId());
|
||||
var outcomes = rows.stream().map(row -> new FleetCompletionModels.Outcome(dispatchNo, row.getDeliveryNo(), dispatch.getCustomerId(),
|
||||
if (outbound != null && (rows.stream().mapToLong(row -> Objects.requireNonNullElse(row.getPackageCount(), 0)).sum()
|
||||
!= Objects.requireNonNullElse(dispatch.getShippedPackageCount(), 0) || !Objects.equals(dispatch.getShippedPackageCount(), outbound.getPackageCount())))
|
||||
return new FleetCompletionModels.DispatchCompletion(dispatchNo, dispatch.getOverseasWarehouseId(), java.util.List.of(), "派送单数量未覆盖本次全部实发货物");
|
||||
var outcomes = rows.stream().map(row -> {
|
||||
var quantities = quantities(row, deliveryOperations.returnReceipts(dispatch.getCustomerId(), row.getId()));
|
||||
return new FleetCompletionModels.Outcome(dispatchNo, row.getDeliveryNo(), dispatch.getCustomerId(),
|
||||
"PRIVATE".equals(row.getDestinationType()) ? row.getDeliveryAddress() : first(row.getDestinationWarehouseCode(), row.getDestinationWarehouseName()),
|
||||
originallySigned(row) ? "DELIVERED" : row.getStatus(), Objects.requireNonNullElse(row.getPackageCount(), 0),
|
||||
originallySigned(row) ? instant(row.getSignedAt()) : "RETURNED".equals(row.getStatus())
|
||||
? instant(deliveryOperations.returnedAt(dispatch.getCustomerId(), row.getId())) : null)).toList();
|
||||
? instant(deliveryOperations.returnedAt(dispatch.getCustomerId(), row.getId())) : null,
|
||||
quantities.signed(), quantities.returned(), quantities.remaining());
|
||||
}).toList();
|
||||
String reason = null;
|
||||
if (!"DEPARTED".equals(dispatch.getStatus()) || outbound == null || !"OUTBOUNDED".equals(outbound.getStatus())) reason = "排车出库尚未完成";
|
||||
else if (outcomes.isEmpty()) reason = "缺少对应派送单";
|
||||
else if (outcomes.stream().mapToLong(FleetCompletionModels.Outcome::packages).sum() != Objects.requireNonNullElse(dispatch.getShippedPackageCount(), 0)
|
||||
|| !Objects.equals(dispatch.getShippedPackageCount(), outbound.getPackageCount())) reason = "派送单数量未覆盖本次全部实发货物";
|
||||
else if (outcomes.stream().anyMatch(row -> row.packages() <= 0 || !java.util.Set.of("DELIVERED", "RETURNED").contains(row.status()) || row.terminalAt() == null))
|
||||
else if (outcomes.stream().anyMatch(row -> row.packages() <= 0 || row.remainingPackages() != 0
|
||||
|| row.signedPackages() + row.returnedPackages() != row.packages()
|
||||
|| !java.util.Set.of("DELIVERED", "RETURNED").contains(row.status()) || row.terminalAt() == null))
|
||||
reason = "所有派送单须已签收,或完成真实退回入仓";
|
||||
return new FleetCompletionModels.DispatchCompletion(dispatchNo, dispatch.getOverseasWarehouseId(), outcomes, reason);
|
||||
}
|
||||
@@ -194,17 +204,25 @@ public class DispatchFleetAdapter implements FleetDispatchGateway {
|
||||
|| !Objects.equals(row.getOutboundOrderId(), outbound.getId())
|
||||
|| !Objects.equals(row.getOverseasWarehouseId(), dispatch.getOverseasWarehouseId())
|
||||
|| row.getPackageCount() == null || row.getPackageCount() <= 0 || row.getVersion() == null
|
||||
|| row.getStatus() == null || !java.util.Set.of("WAIT_DELIVERY", "DELIVERED", "RETURN_PENDING", "RETURNED").contains(row.getStatus()))
|
||||
|| row.getStatus() == null || !java.util.Set.of("WAIT_DELIVERY", "DELIVERING", "REJECTED", "DELIVERED", "RETURN_PENDING", "RETURNED").contains(row.getStatus()))
|
||||
throw conflict("派送货物归属或执行状态与原始发运不一致");
|
||||
Instant terminal = originallySigned(row) ? instant(row.getSignedAt()) : "RETURNED".equals(row.getStatus())
|
||||
? instant(deliveryOperations.returnedAt(dispatch.getCustomerId(), row.getId())) : null;
|
||||
if (("DELIVERED".equals(row.getStatus()) || "RETURNED".equals(row.getStatus())) && terminal == null)
|
||||
throw conflict("派送终态缺少真实签收或退回完成证据");
|
||||
var receipts = deliveryOperations.returnReceipts(dispatch.getCustomerId(), row.getId());
|
||||
var quantities = quantities(row, receipts);
|
||||
if (terminal != null && quantities.remaining() != 0) throw conflict("派送终态数量未覆盖原实发货物");
|
||||
String key = destination(row.getDestinationType(), row.getDestinationWarehouseCode(), null,
|
||||
row.getDeliveryAddress(), row.getPostalCode());
|
||||
if (key == null) throw conflict("派送单缺少真实卸货目的地");
|
||||
var cargo = new com.baiyue.lastleg.fleet.exception.FleetHandoverPolicy.Delivery(dispatch.getCustomerId(),
|
||||
dispatchNo, row.getDeliveryNo(), key, row.getPackageCount(), terminal);
|
||||
dispatchNo, row.getDeliveryNo(), key, row.getPackageCount(), terminal,
|
||||
originallySigned(row) ? java.util.List.of() : receipts.stream().map(receipt -> {
|
||||
if (receipt.dispatchItemId() == null || receipt.palletId() == null) throw conflict("实际退回缺少原发运实托明细归属");
|
||||
return new com.baiyue.lastleg.fleet.exception.FleetHandoverPolicy.ReturnedCargo(
|
||||
receipt.dispatchItemId().toString(), receipt.palletId().toString(), Math.toIntExact(receipt.packages()), instant(receipt.receivedAt()));
|
||||
}).toList());
|
||||
facts.add(new com.baiyue.lastleg.fleet.exception.FleetTransitEvidence.Delivery(cargo, row.getStatus(), row.getVersion(),
|
||||
new com.baiyue.lastleg.fleet.exception.FleetTransitEvidence.Transport(row.getVehiclePlate(), row.getDriverName(), row.getDriverPhone())));
|
||||
packages = Math.addExact(packages, row.getPackageCount());
|
||||
@@ -236,6 +254,10 @@ public class DispatchFleetAdapter implements FleetDispatchGateway {
|
||||
}
|
||||
|
||||
private static Instant instant(LocalDateTime value) { return value == null ? null : value.atZone(ZoneId.systemDefault()).toInstant(); }
|
||||
private static DeliveryCargoQuantities quantities(DeliveryOrder row, java.util.List<com.baiyue.lastleg.delivery.model.DeliveryReturnReceiptFact> receipts) {
|
||||
try { return DeliveryCargoQuantities.from(row, receipts); }
|
||||
catch (IllegalArgumentException error) { throw conflict(error.getMessage()); }
|
||||
}
|
||||
private static boolean originallySigned(DeliveryOrder order) {
|
||||
return order.getSignedAt() != null && java.util.Set.of("DELIVERED", "RETURN_PENDING", "RETURNED").contains(order.getStatus());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user