1
This commit is contained in:
@@ -51,6 +51,7 @@ public final class DispatchRequests {
|
||||
|
||||
public record Update(@Size(max = 64) String vehiclePlate, @Size(max = 128) String driverName,
|
||||
@Size(max = 64) String driverPhone, @Size(max = 255) String carrierName,
|
||||
LocalDateTime departAt,
|
||||
@Size(max = 64) String fbaAppointmentNo,
|
||||
@Size(max = 32) String fbaAppointmentStatus,
|
||||
@Size(max = 32) String vehicleAppointmentStatus,
|
||||
|
||||
+32
-4
@@ -29,6 +29,14 @@ public interface DispatchCandidateMapper {
|
||||
"MIN(l.order_id) AS orderId," +
|
||||
"MIN(ip.customer_id) AS customerId,MIN(o.customer_name) AS customerName," +
|
||||
"MIN(ip.plan_no) AS planNo,MIN(o.order_type) AS orderType,MIN(o.volume_weight_kg) AS volumeWeightKg," +
|
||||
"COALESCE(NULLIF(SUM(CASE WHEN COALESCE(l.volume_cbm,0)>0 THEN " +
|
||||
"COALESCE((SELECT SUM(d.gross_weight_kg) FROM ll_order_detail d WHERE d.customer_id=ip.customer_id AND d.order_id=l.order_id)," +
|
||||
"(SELECT inbound.gross_weight_kg FROM ll_inbound_order inbound WHERE inbound.id=l.order_id AND inbound.customer_id=ip.customer_id LIMIT 1),0) " +
|
||||
"* COALESCE(a.allocated_volume_cbm,0) / l.volume_cbm ELSE " +
|
||||
"COALESCE((SELECT SUM(d.gross_weight_kg) FROM ll_order_detail d WHERE d.customer_id=ip.customer_id AND d.order_id=l.order_id)," +
|
||||
"(SELECT inbound.gross_weight_kg FROM ll_inbound_order inbound WHERE inbound.id=l.order_id AND inbound.customer_id=ip.customer_id LIMIT 1),0) " +
|
||||
"/ NULLIF((SELECT COUNT(*) FROM ll_inbound_plan_pallet_allocation a2 WHERE a2.line_id=a.line_id),0) END),0)," +
|
||||
"MIN(o.volume_weight_kg)) AS grossWeightKg," +
|
||||
"MIN(ip.container_no) AS containerNo," +
|
||||
"(SELECT MAX(fa.appointment_at) FROM ll_inbound_fba_appointment_item fi " +
|
||||
"JOIN ll_inbound_fba_appointment fa ON fa.id=fi.appointment_id WHERE fi.line_id IN " +
|
||||
@@ -38,7 +46,13 @@ public interface DispatchCandidateMapper {
|
||||
"(SELECT pa.line_id FROM ll_inbound_plan_pallet_allocation pa WHERE pa.pallet_id=p.id)) AS expectedLoadingAt," +
|
||||
"CASE WHEN p.warehouse_pallet_id IS NOT NULL THEN (SELECT MIN(pos.overseas_warehouse_id) " +
|
||||
"FROM ll_inventory_position pos WHERE pos.customer_id=ip.customer_id AND pos.pallet_id=p.warehouse_pallet_id " +
|
||||
"AND pos.available_packages > 0) ELSE CAST(ip.overseas_warehouse_id AS CHAR) END AS overseasWarehouseId," +
|
||||
"AND pos.available_packages > 0) ELSE COALESCE(NULLIF(CAST(ip.overseas_warehouse_id AS CHAR),'')," +
|
||||
"(SELECT NULLIF(TRIM(source_order.overseas_warehouse_id),'') FROM ll_order source_order " +
|
||||
"WHERE source_order.id=ip.source_order_id AND source_order.customer_id=ip.customer_id LIMIT 1)) END AS overseasWarehouseId," +
|
||||
"CASE WHEN p.warehouse_pallet_id IS NOT NULL THEN (SELECT MIN(b.overseas_warehouse_code) " +
|
||||
"FROM ll_inventory_position pos JOIN ll_inventory_balance b ON b.id=pos.balance_id AND b.customer_id=pos.customer_id " +
|
||||
"WHERE pos.customer_id=ip.customer_id AND pos.pallet_id=p.warehouse_pallet_id AND pos.available_packages > 0) " +
|
||||
"ELSE MIN(o.overseas_warehouse_code) END AS overseasWarehouseCode," +
|
||||
"CASE WHEN p.warehouse_pallet_id IS NOT NULL THEN (SELECT MIN(b.overseas_warehouse_name) " +
|
||||
"FROM ll_inventory_position pos JOIN ll_inventory_balance b ON b.id=pos.balance_id AND b.customer_id=pos.customer_id " +
|
||||
"WHERE pos.customer_id=ip.customer_id AND pos.pallet_id=p.warehouse_pallet_id AND pos.available_packages > 0) " +
|
||||
@@ -115,6 +129,14 @@ public interface DispatchCandidateMapper {
|
||||
"MIN(l.order_id) AS orderId," +
|
||||
"MIN(ip.customer_id) AS customerId,MIN(o.customer_name) AS customerName," +
|
||||
"MIN(ip.plan_no) AS planNo,MIN(o.order_type) AS orderType,MIN(o.volume_weight_kg) AS volumeWeightKg," +
|
||||
"COALESCE(NULLIF(SUM(CASE WHEN COALESCE(l.volume_cbm,0)>0 THEN " +
|
||||
"COALESCE((SELECT SUM(d.gross_weight_kg) FROM ll_order_detail d WHERE d.customer_id=ip.customer_id AND d.order_id=l.order_id)," +
|
||||
"(SELECT inbound.gross_weight_kg FROM ll_inbound_order inbound WHERE inbound.id=l.order_id AND inbound.customer_id=ip.customer_id LIMIT 1),0) " +
|
||||
"* COALESCE(a.allocated_volume_cbm,0) / l.volume_cbm ELSE " +
|
||||
"COALESCE((SELECT SUM(d.gross_weight_kg) FROM ll_order_detail d WHERE d.customer_id=ip.customer_id AND d.order_id=l.order_id)," +
|
||||
"(SELECT inbound.gross_weight_kg FROM ll_inbound_order inbound WHERE inbound.id=l.order_id AND inbound.customer_id=ip.customer_id LIMIT 1),0) " +
|
||||
"/ NULLIF((SELECT COUNT(*) FROM ll_inbound_plan_pallet_allocation a2 WHERE a2.line_id=a.line_id),0) END),0)," +
|
||||
"MIN(o.volume_weight_kg)) AS grossWeightKg," +
|
||||
"MIN(ip.container_no) AS containerNo," +
|
||||
"(SELECT MAX(fa.appointment_at) FROM ll_inbound_fba_appointment_item fi " +
|
||||
"JOIN ll_inbound_fba_appointment fa ON fa.id=fi.appointment_id WHERE fi.line_id IN " +
|
||||
@@ -124,7 +146,13 @@ public interface DispatchCandidateMapper {
|
||||
"(SELECT pa.line_id FROM ll_inbound_plan_pallet_allocation pa WHERE pa.pallet_id=p.id)) AS expectedLoadingAt," +
|
||||
"CASE WHEN p.warehouse_pallet_id IS NOT NULL THEN (SELECT MIN(pos.overseas_warehouse_id) " +
|
||||
"FROM ll_inventory_position pos WHERE pos.customer_id=ip.customer_id AND pos.pallet_id=p.warehouse_pallet_id " +
|
||||
"AND pos.available_packages > 0) ELSE CAST(ip.overseas_warehouse_id AS CHAR) END AS overseasWarehouseId," +
|
||||
"AND pos.available_packages > 0) ELSE COALESCE(NULLIF(CAST(ip.overseas_warehouse_id AS CHAR),'')," +
|
||||
"(SELECT NULLIF(TRIM(source_order.overseas_warehouse_id),'') FROM ll_order source_order " +
|
||||
"WHERE source_order.id=ip.source_order_id AND source_order.customer_id=ip.customer_id LIMIT 1)) END AS overseasWarehouseId," +
|
||||
"CASE WHEN p.warehouse_pallet_id IS NOT NULL THEN (SELECT MIN(b.overseas_warehouse_code) " +
|
||||
"FROM ll_inventory_position pos JOIN ll_inventory_balance b ON b.id=pos.balance_id AND b.customer_id=pos.customer_id " +
|
||||
"WHERE pos.customer_id=ip.customer_id AND pos.pallet_id=p.warehouse_pallet_id AND pos.available_packages > 0) " +
|
||||
"ELSE MIN(o.overseas_warehouse_code) END AS overseasWarehouseCode," +
|
||||
"CASE WHEN p.warehouse_pallet_id IS NOT NULL THEN (SELECT MIN(b.overseas_warehouse_name) " +
|
||||
"FROM ll_inventory_position pos JOIN ll_inventory_balance b ON b.id=pos.balance_id AND b.customer_id=pos.customer_id " +
|
||||
"WHERE pos.customer_id=ip.customer_id AND pos.pallet_id=p.warehouse_pallet_id AND pos.available_packages > 0) " +
|
||||
@@ -185,8 +213,8 @@ public interface DispatchCandidateMapper {
|
||||
|
||||
@Select("<script>" +
|
||||
"SELECT NULL AS planId,NULL AS planPalletId,pos.pallet_id AS warehousePalletId,a.lastleg_order_id AS orderId," +
|
||||
"a.customer_id AS customerId,NULL AS customerName,NULL AS planNo,'RELABEL_APPLICATION' AS orderType,NULL AS volumeWeightKg,NULL AS containerNo," +
|
||||
"NULL AS appointmentAt,NULL AS expectedLoadingAt,a.overseas_warehouse_id AS overseasWarehouseId,MIN(ri.source_warehouse_name) AS overseasWarehouseName," +
|
||||
"a.customer_id AS customerId,NULL AS customerName,NULL AS planNo,'RELABEL_APPLICATION' AS orderType,NULL AS volumeWeightKg,NULL AS grossWeightKg,NULL AS containerNo," +
|
||||
"NULL AS appointmentAt,NULL AS expectedLoadingAt,a.overseas_warehouse_id AS overseasWarehouseId,MIN(ri.source_warehouse_code) AS overseasWarehouseCode,MIN(ri.source_warehouse_name) AS overseasWarehouseName," +
|
||||
"MIN(COALESCE(NULLIF(ri.source_inbound_order_no,''),NULLIF(a.customer_order_no,''),a.relabel_no)) AS orderNo,a.relabel_no AS orderRefs,MIN(ri.source_inbound_code) AS inboundCode,pos.pallet_no AS palletNo,NULL AS destinationWarehouseId," +
|
||||
"GROUP_CONCAT(DISTINCT ri.destination_fba_warehouse_code ORDER BY ri.destination_fba_warehouse_code SEPARATOR ',') AS destinationWarehouseCode," +
|
||||
"GROUP_CONCAT(DISTINCT ri.destination_fba_warehouse_code ORDER BY ri.destination_fba_warehouse_code SEPARATOR ',') AS destinationWarehouseName," +
|
||||
|
||||
+4
-2
@@ -13,10 +13,12 @@ public record DispatchPalletCandidate(
|
||||
String planNo,
|
||||
String orderType,
|
||||
BigDecimal volumeWeightKg,
|
||||
BigDecimal grossWeightKg,
|
||||
String containerNo,
|
||||
LocalDateTime appointmentAt,
|
||||
LocalDateTime expectedLoadingAt,
|
||||
String overseasWarehouseId,
|
||||
String overseasWarehouseCode,
|
||||
String overseasWarehouseName,
|
||||
String orderNo,
|
||||
String orderRefs,
|
||||
@@ -43,7 +45,7 @@ public record DispatchPalletCandidate(
|
||||
String destinationWarehouseCode, String destinationWarehouseName,
|
||||
String fbaWarehouseCode, Integer packageCount, BigDecimal volumeCbm,
|
||||
String sourceStage) {
|
||||
this(planId, planPalletId, warehousePalletId, orderId, null, null, null, null, null, null, null, null, overseasWarehouseId,
|
||||
this(planId, planPalletId, warehousePalletId, orderId, null, null, null, null, null, null, null, null, null, overseasWarehouseId, null,
|
||||
overseasWarehouseName, orderNo, orderRefs, inboundCode, palletNo, destinationWarehouseId,
|
||||
destinationWarehouseCode, destinationWarehouseName, fbaWarehouseCode, packageCount, volumeCbm,
|
||||
sourceStage, null, null, null, null, null, null, null);
|
||||
@@ -54,7 +56,7 @@ public record DispatchPalletCandidate(
|
||||
String destinationWarehouseId, String destinationWarehouseCode,
|
||||
String destinationWarehouseName, String fbaWarehouseCode, Integer packageCount,
|
||||
BigDecimal volumeCbm, String sourceStage) {
|
||||
this(planId, planPalletId, warehousePalletId, orderId, null, null, null, null, null, null, null, null, null, null, orderNo, orderRefs, inboundCode,
|
||||
this(planId, planPalletId, warehousePalletId, orderId, null, null, null, null, null, null, null, null, null, null, null, null, orderNo, orderRefs, inboundCode,
|
||||
palletNo, destinationWarehouseId, destinationWarehouseCode, destinationWarehouseName,
|
||||
fbaWarehouseCode, packageCount, volumeCbm, sourceStage, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@@ -536,6 +536,7 @@ public class DispatchService {
|
||||
dispatch.setDriverName(trimToNull(request.driverName()));
|
||||
dispatch.setDriverPhone(trimToNull(request.driverPhone()));
|
||||
dispatch.setCarrierName(trimToNull(request.carrierName()));
|
||||
dispatch.setDepartAt(request.departAt());
|
||||
dispatch.setRoute(itemRoute(assignedItems));
|
||||
dispatch.setFbaAppointmentNo(trimToNull(request.fbaAppointmentNo()));
|
||||
dispatch.setFbaAppointmentStatus(defaultStatus(request.fbaAppointmentStatus()));
|
||||
|
||||
+10
-1
@@ -12,6 +12,7 @@ public record InboundPlanListResponse(
|
||||
String inboundCode,
|
||||
String lxCode,
|
||||
String orderType,
|
||||
Long overseasWarehouseId,
|
||||
String overseasWarehouseCode,
|
||||
String overseasWarehouseName,
|
||||
String warehouseId,
|
||||
@@ -34,4 +35,12 @@ public record InboundPlanListResponse(
|
||||
String dispatchStatus,
|
||||
LocalDateTime createdAt,
|
||||
Integer version
|
||||
) { }
|
||||
) {
|
||||
public InboundPlanListResponse withReceivingWarehouse(String warehouseCode, String warehouseName) {
|
||||
return new InboundPlanListResponse(lineId, planId, planNo, customerId, orderId, inboundCode, lxCode,
|
||||
orderType, overseasWarehouseId, warehouseCode, warehouseName, warehouseId, this.warehouseCode,
|
||||
this.warehouseName, fbaWarehouseCode, customerName, packageCount, pickedPackageCount, volumeCbm,
|
||||
palletCount, assigned, mergeAllowed, urgent, status, appointmentNo, appointmentStatus, appointmentAt,
|
||||
expectedLoadingAt, dispatchStatus, createdAt, version);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ public interface InboundPlanQueryMapper {
|
||||
"<if test='q.inboundCode != null and q.inboundCode != \"\"'> AND l.inbound_code LIKE CONCAT('%',#{q.inboundCode},'%')</if>" +
|
||||
"<if test='q.lxCode != null and q.lxCode != \"\"'> AND o.lx_code LIKE CONCAT('%',#{q.lxCode},'%')</if>" +
|
||||
"<if test='q.status != null and q.status != \"\"'> AND p.status=#{q.status}</if>" +
|
||||
"<if test='q.overseasWarehouseId != null and q.overseasWarehouseId != \"\"'> AND o.overseas_warehouse_id=#{q.overseasWarehouseId}</if>" +
|
||||
"<if test='q.overseasWarehouseId != null and q.overseasWarehouseId != \"\"'> AND p.overseas_warehouse_id=#{q.overseasWarehouseId}</if>" +
|
||||
"<if test='q.destinationWarehouseCode != null and q.destinationWarehouseCode != \"\"'> AND l.destination_warehouse_code=#{q.destinationWarehouseCode}</if>" +
|
||||
"<if test='q.warehouse != null and q.warehouse != \"\"'> AND (l.destination_warehouse_id LIKE CONCAT('%',#{q.warehouse},'%') OR l.destination_warehouse_code LIKE CONCAT('%',#{q.warehouse},'%') OR l.destination_warehouse_name LIKE CONCAT('%',#{q.warehouse},'%'))</if>" +
|
||||
"<if test='q.fbaWarehouseCode != null and q.fbaWarehouseCode != \"\"'> AND l.fba_warehouse_code LIKE CONCAT('%',#{q.fbaWarehouseCode},'%')</if>" +
|
||||
@@ -38,7 +38,7 @@ public interface InboundPlanQueryMapper {
|
||||
|
||||
@Select("<script>SELECT l.id lineId,p.id planId,p.plan_no planNo,p.customer_id customerId," +
|
||||
"l.order_id orderId,l.inbound_code inboundCode,o.lx_code lxCode,o.order_type orderType," +
|
||||
"o.overseas_warehouse_code overseasWarehouseCode,o.overseas_warehouse_name overseasWarehouseName," +
|
||||
"p.overseas_warehouse_id overseasWarehouseId,o.overseas_warehouse_code overseasWarehouseCode,o.overseas_warehouse_name overseasWarehouseName," +
|
||||
"l.destination_warehouse_id warehouseId,l.destination_warehouse_code warehouseCode," +
|
||||
"l.destination_warehouse_name warehouseName,l.fba_warehouse_code fbaWarehouseCode," +
|
||||
"o.customer_name customerName,l.required_package_count packageCount," +
|
||||
|
||||
+11
@@ -179,10 +179,21 @@ public class InboundPlanService {
|
||||
long total = queryMapper.count(customerId, query);
|
||||
List<InboundPlanListResponse> records = total == 0 ? List.of() : queryMapper.rows(
|
||||
customerId, query, (query.page() - 1) * query.size(), query.size());
|
||||
Map<Long, WarehouseResourceGateway.WarehouseReference> receivingWarehouses = new HashMap<>();
|
||||
records = records.stream().map(record -> canonicalizeReceivingWarehouse(record, receivingWarehouses)).toList();
|
||||
long pages = total == 0 ? 0 : (total + query.size() - 1) / query.size();
|
||||
return new PageResult<>(records, query.page(), query.size(), total, pages);
|
||||
}
|
||||
|
||||
private InboundPlanListResponse canonicalizeReceivingWarehouse(InboundPlanListResponse record,
|
||||
Map<Long, WarehouseResourceGateway.WarehouseReference> cache) {
|
||||
Long warehouseId = record.overseasWarehouseId();
|
||||
if (warehouseId == null) return record.withReceivingWarehouse(null, null);
|
||||
WarehouseResourceGateway.WarehouseReference warehouse = cache.computeIfAbsent(warehouseId,
|
||||
id -> requiredReceivingWarehouse(String.valueOf(id)));
|
||||
return record.withReceivingWarehouse(warehouse.warehouseCode(), warehouse.warehouseName());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ContainerInboundPlanPreviewResponse previewContainer(String sourceContainerBookingId) {
|
||||
String bookingId = trimToNull(sourceContainerBookingId);
|
||||
|
||||
+27
-2
@@ -62,17 +62,42 @@ public interface InventoryQueryMapper {
|
||||
"<when test='q.inventoryStatus == \"PROCUREMENT\"'> AND b.procurement_packages > 0</when>" +
|
||||
"</choose>";
|
||||
|
||||
@Select("<script>SELECT * FROM ll_inventory_balance" + BALANCE_FILTER +
|
||||
@Select("<script>SELECT MIN(id) id," +
|
||||
"customer_id,MAX(customer_name) customer_name," +
|
||||
"overseas_warehouse_id,MAX(overseas_warehouse_code) overseas_warehouse_code," +
|
||||
"MAX(overseas_warehouse_name) overseas_warehouse_name," +
|
||||
"destination_warehouse_id,destination_warehouse_code," +
|
||||
"MAX(destination_warehouse_name) destination_warehouse_name," +
|
||||
"NULL inbound_order_id,NULL inbound_order_no,NULL inbound_code," +
|
||||
"sku_code,MAX(product_name_zh) product_name_zh,MAX(product_name_en) product_name_en," +
|
||||
"COALESCE(SUM(available_packages),0) available_packages," +
|
||||
"COALESCE(SUM(hold_packages),0) hold_packages," +
|
||||
"COALESCE(SUM(allocated_packages),0) allocated_packages," +
|
||||
"COALESCE(SUM(picked_packages),0) picked_packages," +
|
||||
"COALESCE(SUM(in_transit_packages),0) in_transit_packages," +
|
||||
"COALESCE(SUM(receiving_packages),0) receiving_packages," +
|
||||
"COALESCE(SUM(procurement_packages),0) procurement_packages," +
|
||||
"MAX(updated_at) updated_at FROM ll_inventory_balance" + BALANCE_FILTER +
|
||||
" GROUP BY customer_id,overseas_warehouse_id,destination_warehouse_id,destination_warehouse_code,sku_code" +
|
||||
" ORDER BY updated_at DESC,id DESC LIMIT #{limit} OFFSET #{offset}</script>")
|
||||
List<InventoryBalance> balances(@Param("customerId") String customerId,
|
||||
@Param("q") InventoryQueryRequests.BalanceQuery query,
|
||||
@Param("offset") long offset,
|
||||
@Param("limit") long limit);
|
||||
|
||||
@Select("<script>SELECT COUNT(*) FROM ll_inventory_balance" + BALANCE_FILTER + "</script>")
|
||||
@Select("<script>SELECT COUNT(*) FROM (SELECT 1 FROM ll_inventory_balance" + BALANCE_FILTER +
|
||||
" GROUP BY customer_id,overseas_warehouse_id,destination_warehouse_id,destination_warehouse_code,sku_code" +
|
||||
") grouped_balances</script>")
|
||||
long countBalances(@Param("customerId") String customerId,
|
||||
@Param("q") InventoryQueryRequests.BalanceQuery query);
|
||||
|
||||
@Select("<script>SELECT * FROM ll_inventory_balance" + BALANCE_FILTER +
|
||||
" ORDER BY updated_at DESC,id DESC LIMIT #{limit} OFFSET #{offset}</script>")
|
||||
List<InventoryBalance> sourceBalances(@Param("customerId") String customerId,
|
||||
@Param("q") InventoryQueryRequests.BalanceQuery query,
|
||||
@Param("offset") long offset,
|
||||
@Param("limit") long limit);
|
||||
|
||||
@Select("<script>SELECT COUNT(*) dimension_count," +
|
||||
"COALESCE(SUM(available_packages),0) available_packages," +
|
||||
"COALESCE(SUM(hold_packages),0) hold_packages," +
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ public class InventoryQueryService {
|
||||
final int batchSize = 1000;
|
||||
long offset = 0;
|
||||
while (true) {
|
||||
List<InventoryBalanceView> batch = mapper.balances(customerId, query, offset, batchSize).stream().map(this::balanceView).toList();
|
||||
List<InventoryBalanceView> batch = mapper.sourceBalances(customerId, query, offset, batchSize).stream().map(this::balanceView).toList();
|
||||
if (batch.isEmpty()) break;
|
||||
for (InventoryBalanceView v : batch) output.write((
|
||||
String.join(",", csv(v.customerId()), csv(v.customerName()), csv(v.overseasWarehouseCode()), csv(v.overseasWarehouseName()),
|
||||
|
||||
@@ -2,7 +2,11 @@ package com.baiyue.lastleg.model;
|
||||
|
||||
/** Standard main-process statuses for a last-leg order. */
|
||||
public enum LastlegOrderStatus {
|
||||
DRAFT("草稿"),
|
||||
PENDING_REVIEW("待审核"),
|
||||
APPROVED("审核通过"),
|
||||
DESTINATION_ASSIGNED("已分配目的仓"),
|
||||
INBOUND_PLANNED("已生成入库计划"),
|
||||
INBOUND_MEASURING("入库测量中"),
|
||||
PENDING_ASSIGNMENT("待分配"),
|
||||
PENDING_INBOUND("待入库"),
|
||||
@@ -16,6 +20,7 @@ public enum LastlegOrderStatus {
|
||||
PARTIALLY_RECEIVED("部分收货"),
|
||||
RECEIVED("已收货"),
|
||||
IN_TRANSIT("运输中"),
|
||||
PROCESSING("处理中"),
|
||||
COMPLETED("已完成"),
|
||||
CANCELLED("已取消"),
|
||||
PENDING_DELIVERY("待派送"),
|
||||
@@ -31,4 +36,13 @@ public enum LastlegOrderStatus {
|
||||
public String label() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public static String labelOf(String status) {
|
||||
if (status == null || status.isBlank()) return status;
|
||||
try {
|
||||
return valueOf(status).label();
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.baiyue.lastleg.mapper.LastlegOrderManualNodeMapper;
|
||||
import com.baiyue.lastleg.mapper.ReceivingWarehouseOperationMapper;
|
||||
import com.baiyue.lastleg.mapper.ContainerArrivalTimeOperationMapper;
|
||||
import com.baiyue.lastleg.model.LastlegOrderType;
|
||||
import com.baiyue.lastleg.model.LastlegOrderStatus;
|
||||
import com.baiyue.lastleg.shipping.entity.ContainerShippingGate;
|
||||
import com.baiyue.lastleg.shipping.mapper.ContainerShippingGateMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -584,12 +585,12 @@ public class LastlegOrderService {
|
||||
csv(order.getSourceOrderNo()), csv(order.getCustomerName()), csv(order.getOverseasWarehouseName()),
|
||||
csv(order.getTransferWarehouseName()), csv(order.getTransferWarehouseCode()), csv(order.getFbaWarehouseCode()),
|
||||
csv(order.getContainerNo()), csv(StringUtils.hasText(order.getSourceContainerBookingId())
|
||||
? containerNodes.get(order.getSourceContainerBookingId()) : null), csv(order.getAbnormal()), csv(order.getDetained()),
|
||||
? containerNodes.get(order.getSourceContainerBookingId()) : null), csv(yesOrNo(order.getAbnormal())), csv(yesOrNo(order.getDetained())),
|
||||
csv(order.getPalletCount()), csv(order.getPackageCount()), csv(order.getReceivedPackageCount()),
|
||||
csv(packageDifference(order)), csv(order.getVolumeCbm()), csv(order.getProductQuantity()),
|
||||
csv(order.getVolumeWeightKg()), csv(order.getEstimatedArrivalAt()), csv(order.getActualArrivalAt()),
|
||||
csv(order.getEstimatedWarehouseAt()), csv(order.getInboundOrderNo()), csv(order.getRelabelOrderNo()), csv(relabelBusinessStatus(order.getRelabelStatus())),
|
||||
csv(order.getPalletMergeFlag()), csv(order.getCurrentStatus()), csv(order.getSubOrderStatus()), csv(order.getPrivateRemark()),
|
||||
csv(order.getPalletMergeFlag()), csv(LastlegOrderStatus.labelOf(order.getCurrentStatus())), csv(order.getSubOrderStatus()), csv(order.getPrivateRemark()),
|
||||
csv(order.getCustomerRemark()), csv(order.getWarehouseRemark()))) + "\r\n";
|
||||
output.write(line.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
@@ -730,6 +731,11 @@ public class LastlegOrderService {
|
||||
? "COMPLETED" : "PENDING_PROCESSING";
|
||||
}
|
||||
|
||||
private static String yesOrNo(Boolean value) {
|
||||
if (value == null) return null;
|
||||
return value ? "是" : "否";
|
||||
}
|
||||
|
||||
private static Long parseLong(String value) {
|
||||
try { return StringUtils.hasText(value) ? Long.parseLong(value.trim()) : null; }
|
||||
catch (NumberFormatException ignored) { return null; }
|
||||
|
||||
@@ -1204,6 +1204,32 @@ CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment_item (
|
||||
KEY idx_ll_fba_appointment_item_order (order_id)
|
||||
) ENGINE=InnoDB COMMENT='FBA入仓预约明细';
|
||||
|
||||
-- Upgrade the pre-customer-scope appointment table created by older deployments.
|
||||
SET @ddl = (SELECT IF(
|
||||
NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_inbound_fba_appointment' AND column_name='customer_id')
|
||||
AND EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_inbound_fba_appointment' AND column_name='tenant_id'),
|
||||
'ALTER TABLE ll_inbound_fba_appointment CHANGE COLUMN tenant_id customer_id VARCHAR(128) NOT NULL COMMENT ''客户租户ID''',
|
||||
'SELECT 1'));
|
||||
PREPARE fba_appointment_customer_scope FROM @ddl; EXECUTE fba_appointment_customer_scope; DEALLOCATE PREPARE fba_appointment_customer_scope;
|
||||
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_inbound_fba_appointment' AND column_name='expected_loading_at'),
|
||||
'SELECT 1',
|
||||
'ALTER TABLE ll_inbound_fba_appointment ADD COLUMN expected_loading_at DATETIME(3) NULL COMMENT ''预计装车时间'' AFTER appointment_at'));
|
||||
PREPARE fba_appointment_expected_loading FROM @ddl; EXECUTE fba_appointment_expected_loading; DEALLOCATE PREPARE fba_appointment_expected_loading;
|
||||
|
||||
UPDATE ll_inbound_fba_appointment
|
||||
SET expected_loading_at=appointment_at
|
||||
WHERE expected_loading_at IS NULL;
|
||||
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_inbound_fba_appointment' AND column_name='expected_loading_at' AND is_nullable='YES'),
|
||||
'ALTER TABLE ll_inbound_fba_appointment MODIFY COLUMN expected_loading_at DATETIME(3) NOT NULL COMMENT ''预计装车时间''',
|
||||
'SELECT 1'));
|
||||
PREPARE fba_appointment_expected_loading_required FROM @ddl; EXECUTE fba_appointment_expected_loading_required; DEALLOCATE PREPARE fba_appointment_expected_loading_required;
|
||||
|
||||
ALTER TABLE ll_loading_order_status_history
|
||||
MODIFY COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '状态历史主键',
|
||||
MODIFY COLUMN order_id BIGINT NOT NULL COMMENT '尾程订单 ID',
|
||||
|
||||
@@ -463,7 +463,7 @@ paths:
|
||||
/api/platform/v1/last-leg/inbound-plans:
|
||||
get:
|
||||
summary: 平台分页查询海外入库订单
|
||||
description: 权限 platform:overseas-warehouse:inbound-order:list;列表中的 overseasWarehouseCode/overseasWarehouseName 只取尾程订单预分配接柜仓事实,warehouseCode/warehouseName 仍表示目的仓。
|
||||
description: 权限 platform:overseas-warehouse:inbound-order:list;列表中的 overseasWarehouseCode/overseasWarehouseName 按入库计划冻结接柜仓ID从海外仓权威目录解析,warehouseCode/warehouseName 仍表示目的仓。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: customerId, in: query, required: false, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||
@@ -2162,10 +2162,12 @@ components:
|
||||
planNo: { type: string, nullable: true }
|
||||
orderType: { type: string, nullable: true }
|
||||
volumeWeightKg: { type: number, nullable: true }
|
||||
grossWeightKg: { type: number, nullable: true, description: 候选托盘实际毛重(千克);按入库计划分配比例汇总,缺失时回退体积重 }
|
||||
containerNo: { type: string, nullable: true }
|
||||
appointmentAt: { type: string, format: date-time, nullable: true }
|
||||
expectedLoadingAt: { type: string, format: date-time, nullable: true }
|
||||
overseasWarehouseId: { type: string }
|
||||
overseasWarehouseCode: { type: string, nullable: true, description: 实际海外接柜仓编码,用于智能排车区域筛选 }
|
||||
overseasWarehouseName: { type: string }
|
||||
orderNo: { type: string }
|
||||
orderRefs: { type: string }
|
||||
@@ -2230,12 +2232,13 @@ components:
|
||||
palletIds: { type: array, items: { type: string } }
|
||||
DispatchUpdate:
|
||||
type: object
|
||||
description: 普通编辑字段;不包含 status、departAt 或路线,路线由已排托盘关联的 FBA 仓自动汇总。
|
||||
description: 普通编辑字段;不包含 status 或路线,路线由已排托盘关联的 FBA 仓自动汇总。
|
||||
properties:
|
||||
vehiclePlate: { type: string, nullable: true, maxLength: 64 }
|
||||
driverName: { type: string, nullable: true, maxLength: 128 }
|
||||
driverPhone: { type: string, nullable: true, maxLength: 64 }
|
||||
carrierName: { type: string, nullable: true, maxLength: 255 }
|
||||
departAt: { type: string, format: date-time, nullable: true }
|
||||
fbaAppointmentNo: { type: string, nullable: true, maxLength: 64 }
|
||||
fbaAppointmentStatus: { type: string, nullable: true, maxLength: 32 }
|
||||
vehicleAppointmentStatus: { type: string, nullable: true, maxLength: 32 }
|
||||
@@ -2918,8 +2921,9 @@ components:
|
||||
orderId: { type: string, pattern: '^[0-9]+$' }
|
||||
inboundCode: { type: string }
|
||||
orderType: { type: string, nullable: true }
|
||||
overseasWarehouseCode: { type: string, description: 接柜仓编码,取自尾程订单预分配接收仓事实 }
|
||||
overseasWarehouseName: { type: string, description: 接柜仓名称,取自尾程订单预分配接收仓事实 }
|
||||
overseasWarehouseId: { type: string, pattern: '^[0-9]+$', nullable: true, description: 入库计划冻结的接柜海外仓ID,不是FBA目的仓ID }
|
||||
overseasWarehouseCode: { type: string, description: 按入库计划冻结接柜仓ID从海外仓权威目录解析的编码 }
|
||||
overseasWarehouseName: { type: string, description: 按入库计划冻结接柜仓ID从海外仓权威目录解析的名称 }
|
||||
warehouseId: { type: string, nullable: true }
|
||||
warehouseCode: { type: string, nullable: true }
|
||||
warehouseName: { type: string, nullable: true }
|
||||
|
||||
Reference in New Issue
Block a user