修改提交

This commit is contained in:
2026-09-08 17:58:42 +08:00
parent f0939c91c3
commit 2a27e28f26
67 changed files with 2590 additions and 110 deletions
@@ -7,6 +7,8 @@ import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@@ -28,7 +30,19 @@ public final class DeliveryRequests {
@Size(max = 128) String appointmentAccount,
@Size(max = 128) String sellerName,
@Size(max = 1000) String remark,
@NotNull @Valid @Size(min = 1, max = 20) List<FeeItem> fees) {}
@NotNull @Valid @Size(min = 1, max = 20) List<FeeItem> fees,
Map<String, List<@NotBlank @Size(max = 128) String>> palletCartonMarks) {
public Transfer(String idempotencyKey, LocalDateTime plannedDeliveryAt, String deliveryMethod, String waybillNo,
String carrierName, String pickupMethod, String loadingType, String vehicleType, String vehicleSize,
String driverName, String driverPhone, String vehiclePlate, String appointmentAccount,
String sellerName, String remark, List<FeeItem> fees) {
this(idempotencyKey, plannedDeliveryAt, deliveryMethod, waybillNo, carrierName, pickupMethod, loadingType,
vehicleType, vehicleSize, driverName, driverPhone, vehiclePlate, appointmentAccount, sellerName, remark, fees, Map.of());
}
}
public record PalletCartonSelection(@NotBlank @Size(max = 128) String palletNo,
@NotNull @Size(min = 1, max = 500) List<@NotBlank @Size(max = 128) String> cartonMarks) {}
public record FeeItem(@NotBlank @Size(max = 64) String feeType,
@NotBlank @Size(max = 8) String currency,
@@ -41,12 +55,6 @@ public final class DeliveryRequests {
String driverName, String deliveryMethod,
LocalDateTime plannedFrom, LocalDateTime plannedTo) {
public Query { if (page == 0) page = 1; if (size == 0) size = 20; }
public Query(long page, long size, String documentNo, String warehouseId, String status,
String dispatchNo, String waybillNo, String vehiclePlate, String driverName,
String deliveryMethod, LocalDateTime plannedFrom, LocalDateTime plannedTo) {
this(page, size, documentNo, null, warehouseId, status, dispatchNo, waybillNo, vehiclePlate,
driverName, deliveryMethod, plannedFrom, plannedTo);
}
}
public record PalletQuery(@Min(1) long page, @Min(1) @Max(200) long size,
@@ -59,7 +67,12 @@ public final class DeliveryRequests {
@Size(max=1000) String remark,
@NotBlank @Size(max=255) String idempotencyKey) {}
public record OneClickItem(@NotNull Long inventoryPositionId, @NotNull @Min(1) Long packages,
@NotBlank @Size(max=128) String sku) {}
@NotBlank @Size(max=128) String sku,
@Size(max=200) List<@NotBlank @Size(max=128) String> cartonMarks) {
public OneClickItem(Long inventoryPositionId, Long packages, String sku) {
this(inventoryPositionId, packages, sku, Collections.emptyList());
}
}
public record PdaPick(@NotNull Long outboundPalletItemId, @NotNull Long inventoryPositionId,
@NotNull @Min(1) Long packages, @NotBlank @Size(max=255) String idempotencyKey) {}
public record PdaComplete(@NotBlank @Size(max=255) String idempotencyKey) {}
@@ -40,7 +40,9 @@ public final class DeliveryResponses {
public record DeliveryDetail(DeliveryRow order, List<DeliverySku> skus,
List<DeliveryFeeRow> fees, List<DeliveryOperationRow> operations) {}
public record OutboundDetail(OutboundRow outbound, DeliveryRow delivery) {}
public record OutboundPalletRow(Long id, String palletNo, String cartonMarks, String skuCode, String inboundCode,
Integer packageCount, Integer pickedPackageCount, String status) {}
public record OutboundDetail(OutboundRow outbound, DeliveryRow delivery, List<OutboundPalletRow> pallets) {}
public record PdaTask(Long id, String taskNo, String status, String outboundNo, LocalDateTime pushedAt, LocalDateTime completedAt) {}
public record PdaPickPosition(Long inventoryPositionId, String palletNo, String cartonMark,
String skuCode, String inboundCode, long availablePackages,
@@ -24,6 +24,7 @@ public class OutboundPalletItem {
private Integer pickedPackageCount;
private String status;
private String skuCode;
private String cartonMarks;
private String orderRefs;
private String inboundCode;
private LocalDateTime createdAt;
@@ -26,6 +26,7 @@ import com.baiyue.lastleg.entity.LastlegOrderDetail;
import com.baiyue.lastleg.inboundplan.entity.InboundPlanLine;
import com.baiyue.lastleg.inboundplan.entity.InboundPlanPalletAllocation;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanLineMapper;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanCartonMapper;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanPalletAllocationMapper;
import com.baiyue.lastleg.delivery.entity.OutboundPdaTask;
import com.baiyue.lastleg.delivery.entity.OutboundPdaPick;
@@ -78,6 +79,7 @@ public class DeliveryTransferService {
@Resource private DropshipSkuInventoryMapper dropshipSkuInventory;
@Resource private InboundPlanPalletAllocationMapper planAllocations;
@Resource private InboundPlanLineMapper planLines;
@Resource private InboundPlanCartonMapper inboundCartons;
@Resource private LastlegOrderMapper tailOrders;
@Resource private LastlegOrderStatusHistoryMapper histories;
@Resource private LastlegOrderDetailMapper tailOrderDetails;
@@ -156,6 +158,15 @@ public class DeliveryTransferService {
item.setDestinationWarehouseCode(source.getDestinationWarehouseCode());
item.setDestinationWarehouseName(source.getDestinationWarehouseName());
item.setPackageCount(Objects.requireNonNullElse(source.getPackageCount(), 0)); item.setPickedPackageCount(0); item.setStatus("WAIT_PICK");
List<String> requestedMarks = request.palletCartonMarks() == null ? List.of() : request.palletCartonMarks().getOrDefault(source.getPalletNo(), List.of());
if (!requestedMarks.isEmpty()) {
if (requestedMarks.size() != Objects.requireNonNullElse(source.getPackageCount(), 0)) throw conflict("Selected carton mark count must equal pallet package count");
item.setCartonMarks(String.join(",", requestedMarks.stream().distinct().toList()));
} else if (source.getWarehousePalletId() != null) {
String marks = inboundCartons.listByPallet(customerId, source.getWarehousePalletId()).stream()
.map(c -> c.getCartonMark()).filter(StringUtils::hasText).distinct().collect(java.util.stream.Collectors.joining(","));
item.setCartonMarks(StringUtils.hasText(marks) ? marks : null);
}
item.setOrderRefs(source.getOrderRefs()); item.setInboundCode(source.getInboundCode()); item.setCreatedAt(now);
outboundPallets.insert(item);
}
@@ -230,7 +241,7 @@ public class DeliveryTransferService {
InventoryPosition position = inventoryPositions.selectById(input.inventoryPositionId());
if (position == null || !customerId.equals(position.getCustomerId())) throw notFound("Inventory position not found");
OutboundPalletItem item = new OutboundPalletItem(); item.setId(IdWorker.getId()); item.setCustomerId(customerId); item.setOutboundOrderId(outbound.getId());
item.setWarehousePalletId(position.getPalletId()); item.setPalletNo(position.getPalletNo()); item.setPackageCount(input.packages().intValue()); item.setPickedPackageCount(0); item.setStatus("WAIT_PICK"); item.setSkuCode(input.sku().trim()); item.setCreatedAt(now);
item.setWarehousePalletId(position.getPalletId()); item.setPalletNo(position.getPalletNo()); item.setPackageCount(input.packages().intValue()); item.setPickedPackageCount(0); item.setStatus("WAIT_PICK"); item.setSkuCode(input.sku().trim()); item.setCartonMarks(String.join(",", input.cartonMarks() == null ? List.of() : input.cartonMarks())); item.setCreatedAt(now);
outboundPallets.insert(item);
}
outbound.setOverseasWarehouseId(selectedWarehouseId); outboundOrders.updateById(outbound);
@@ -258,6 +269,15 @@ public class DeliveryTransferService {
String key = profile.getId() + "\u0000" + input.sku().trim();
requestedPackages.merge(key, input.packages(), Long::sum);
profiles.put(key, profile);
if (input.cartonMarks() != null && !input.cartonMarks().isEmpty()) {
if (input.cartonMarks().size() != input.packages() || new HashSet<>(input.cartonMarks()).size() != input.cartonMarks().size()) {
throw conflict("Specified carton marks must be unique and equal the package count");
}
List<DropshipCarton> selected = dropshipCartons.listProfile(customerId, profile.getId()).stream()
.filter(carton -> "AVAILABLE".equals(carton.getStatus()) && input.sku().trim().equals(carton.getSkuCode())
&& input.cartonMarks().contains(carton.getCartonMark())).toList();
if (selected.size() != input.cartonMarks().size()) throw conflict("Specified carton marks are unavailable");
}
}
for (Map.Entry<String, Long> requested : requestedPackages.entrySet()) {
String sku = requested.getKey().substring(requested.getKey().indexOf('\u0000') + 1);
@@ -305,7 +325,11 @@ public class DeliveryTransferService {
}
DropshipOrderProfile profile = dropshipProfiles.findPosition(customerId, request.inventoryPositionId());
if (profile == null) throw conflict("Scanned pallet is not one-click dropship inventory");
List<DropshipCarton> cartons = dropshipCartons.lockAvailable(customerId, profile.getId(), item.getSkuCode(), request.packages());
List<DropshipCarton> cartons = StringUtils.hasText(item.getCartonMarks())
? Arrays.stream(item.getCartonMarks().split(",")).map(String::trim).filter(StringUtils::hasText)
.map(mark -> dropshipCartons.findByProfileAndMark(customerId, profile.getId(), mark)).filter(Objects::nonNull)
.filter(carton -> "AVAILABLE".equals(carton.getStatus()) && item.getSkuCode().equals(carton.getSkuCode())).toList()
: dropshipCartons.lockAvailable(customerId, profile.getId(), item.getSkuCode(), request.packages());
if (cartons.size() != request.packages()) throw conflict("Insufficient available one-click dropship cartons");
InventoryCommandRequests.Move move = new InventoryCommandRequests.Move(request.inventoryPositionId(), request.packages(), outbound.getOutboundNo(), outbound.getOutboundNo(), null, request.idempotencyKey() + ":ALLOCATE", null);
inventoryCommands.allocate(customerId, operatorId, move);
@@ -481,7 +505,9 @@ public class DeliveryTransferService {
if (outbound == null) throw notFound("Outbound order not found");
String customerId = outbound.getCustomerId();
DeliveryOrder delivery = requireDelivery(customerId, outbound.getId());
return new DeliveryResponses.OutboundDetail(outboundRow(outbound), deliveryRow(delivery));
List<DeliveryResponses.OutboundPalletRow> pallets = outboundPallets.findByOutbound(customerId, outbound.getId()).stream()
.map(item -> new DeliveryResponses.OutboundPalletRow(item.getId(), item.getPalletNo(), item.getCartonMarks(), item.getSkuCode(), item.getInboundCode(), item.getPackageCount(), item.getPickedPackageCount(), item.getStatus())).toList();
return new DeliveryResponses.OutboundDetail(outboundRow(outbound), deliveryRow(delivery), pallets);
}
public PageResult<DeliveryResponses.DeliveryRow> deliveryPage(String customerId, DeliveryRequests.Query query) {