暂存提交
This commit is contained in:
+42
@@ -11,16 +11,44 @@ public record FirstLegLoadingPlanCompletedV1(
|
||||
|
||||
public record Order(
|
||||
String sourceInboundId, String rootInboundId,
|
||||
String sourceOrderId, String sourceOrderNo, String rootOrderId,
|
||||
String inboundCode, String destinationWarehouseId,
|
||||
String destinationWarehouseCode, String destinationWarehouseName,
|
||||
int packageCount, Integer productQuantity, Integer palletCount,
|
||||
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
||||
List<Item> items, String customerId, String orderType, List<PalletSnapshot> pallets) {
|
||||
public Order {
|
||||
items = items == null ? List.of() : items;
|
||||
orderType = orderType == null || orderType.isBlank() ? "FIRST_LEG" : orderType;
|
||||
pallets = pallets == null ? List.of() : pallets;
|
||||
}
|
||||
public Order(String sourceInboundId, String rootInboundId,
|
||||
String sourceOrderId, String sourceOrderNo, String rootOrderId,
|
||||
String inboundCode, String destinationWarehouseId,
|
||||
String destinationWarehouseCode, String destinationWarehouseName,
|
||||
int packageCount, Integer productQuantity, Integer palletCount,
|
||||
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
||||
List<Item> items) {
|
||||
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
||||
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
||||
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
||||
grossWeightKg, netWeightKg, volumeCbm, items, null, "FIRST_LEG", List.of());
|
||||
}
|
||||
}
|
||||
|
||||
public record Item(
|
||||
String sourceInboundDetailId, String skuCode,
|
||||
String productNameZh, String productNameEn,
|
||||
int packageCount, Integer productQuantity, Integer palletCount,
|
||||
BigDecimal grossWeightKg, BigDecimal netWeightKg,
|
||||
BigDecimal dimensionalWeightKg, BigDecimal volumeCbm,
|
||||
String destinationWarehouseId, String destinationWarehouseCode,
|
||||
String destinationWarehouseName, String fbaTrackingNo,
|
||||
String shipmentNo, String shippingMark, String palletNo, List<String> cartonMarks) {
|
||||
public Item {
|
||||
cartonMarks = cartonMarks == null ? List.of() : cartonMarks;
|
||||
}
|
||||
public Item(String sourceInboundDetailId, String skuCode,
|
||||
String productNameZh, String productNameEn,
|
||||
int packageCount, Integer productQuantity, Integer palletCount,
|
||||
BigDecimal grossWeightKg, BigDecimal netWeightKg,
|
||||
@@ -28,5 +56,19 @@ public record FirstLegLoadingPlanCompletedV1(
|
||||
String destinationWarehouseId, String destinationWarehouseCode,
|
||||
String destinationWarehouseName, String fbaTrackingNo,
|
||||
String shipmentNo, String shippingMark) {
|
||||
this(sourceInboundDetailId, skuCode, productNameZh, productNameEn, packageCount,
|
||||
productQuantity, palletCount, grossWeightKg, netWeightKg,
|
||||
dimensionalWeightKg, volumeCbm, destinationWarehouseId,
|
||||
destinationWarehouseCode, destinationWarehouseName, fbaTrackingNo,
|
||||
shipmentNo, shippingMark, null, List.of());
|
||||
}
|
||||
}
|
||||
|
||||
/** 一键代发入仓单的托盘冻结快照。 */
|
||||
public record PalletSnapshot(String palletNo, List<SkuPackageSnapshot> skuPackages) {}
|
||||
|
||||
/** 托盘下 SKU、箱数、数量及箱唛冻结快照。 */
|
||||
public record SkuPackageSnapshot(String skuCode, String productName,
|
||||
int packageCount, int productQuantity,
|
||||
List<String> cartonMarks) {}
|
||||
}
|
||||
|
||||
+21
@@ -26,4 +26,25 @@ class FirstLegLoadingPlanCompletedV1Test {
|
||||
assertThat(mapper.readValue(json, FirstLegLoadingPlanCompletedV1.class)).isEqualTo(payload);
|
||||
assertThat(json).contains("2088000000000000003", "sourceInboundDetailId");
|
||||
}
|
||||
|
||||
@Test
|
||||
void dropshipPayloadKeepsMultiplePalletsAndCartonMarks() throws Exception {
|
||||
var sku1 = new FirstLegLoadingPlanCompletedV1.SkuPackageSnapshot(
|
||||
"SKU-1", "产品1", 2, 20, List.of("BOX-001", "BOX-002"));
|
||||
var sku2 = new FirstLegLoadingPlanCompletedV1.SkuPackageSnapshot(
|
||||
"SKU-2", "产品2", 1, 5, List.of("BOX-003"));
|
||||
var order = new FirstLegLoadingPlanCompletedV1.Order("100", "100", "200", "FL-200", "200",
|
||||
"RK-100", "300", "ONT8", "ONT8", 3, 25, 2, BigDecimal.ONE,
|
||||
BigDecimal.ONE, BigDecimal.ONE, List.of(), "9001", "ONE_CLICK_DROPSHIP",
|
||||
List.of(new FirstLegLoadingPlanCompletedV1.PalletSnapshot("PLT-01", List.of(sku1)),
|
||||
new FirstLegLoadingPlanCompletedV1.PalletSnapshot("PLT-02", List.of(sku2))));
|
||||
var payload = new FirstLegLoadingPlanCompletedV1("1", "LP-1", "2", "CONT-1", null,
|
||||
"3", "海外仓", List.of(order));
|
||||
|
||||
String json = mapper.writeValueAsString(payload);
|
||||
FirstLegLoadingPlanCompletedV1 restored = mapper.readValue(json, FirstLegLoadingPlanCompletedV1.class);
|
||||
|
||||
assertThat(restored).isEqualTo(payload);
|
||||
assertThat(json).contains("ONE_CLICK_DROPSHIP", "PLT-01", "BOX-003", "customerId");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public interface LoadingCompletedEventMapper {
|
||||
COALESCE(o.root_inbound_id, o.id) AS root_inbound_id,
|
||||
o.order_id AS source_order_id, o.order_no AS source_order_no,
|
||||
COALESCE(root_order.order_id, o.order_id) AS root_order_id,
|
||||
o.inbound_code, o.destination_warehouse_id, o.destination_code AS destination_warehouse_code,
|
||||
o.inbound_code, o.business_type, o.destination_warehouse_id, o.destination_code AS destination_warehouse_code,
|
||||
o.destination_name AS destination_warehouse_name,
|
||||
i.inbound_detail_id AS source_inbound_detail_id, i.sku_code,
|
||||
i.product_name_zh, i.product_name_en, i.package_count, i.product_quantity,
|
||||
@@ -36,6 +36,27 @@ public interface LoadingCompletedEventMapper {
|
||||
""")
|
||||
List<Row> rows(@Param("planId") long planId);
|
||||
|
||||
/** 读取一键代发托盘及其箱唛快照;普通订单不会使用该结果。 */
|
||||
@Select("""
|
||||
SELECT i.account_id, i.inbound_id AS source_inbound_id,
|
||||
a.pallet_code, a.allocation_no, a.picked_package_count AS allocated_package_count,
|
||||
i.inbound_detail_id AS source_inbound_detail_id, i.sku_code,
|
||||
i.product_name_zh, i.package_count, i.product_quantity,
|
||||
label.box_code
|
||||
FROM fl_loading_plan_item i
|
||||
JOIN fl_inbound_pallet_allocation a
|
||||
ON a.tenant_id = i.account_id AND a.inbound_id = i.inbound_id
|
||||
AND a.allocation_status IN ('CONFIRMED','TRANSFERRED','RELEASED')
|
||||
AND a.picked_package_count > 0
|
||||
LEFT JOIN fl_inbound_carton_label label
|
||||
ON label.tenant_id = i.account_id AND label.inbound_id = i.inbound_id
|
||||
AND label.inbound_detail_id = i.inbound_detail_id AND label.batch_status = 'ACTIVE'
|
||||
WHERE i.loading_plan_id = #{planId} AND i.deleted = 0
|
||||
ORDER BY i.account_id, i.inbound_id, a.allocation_no,
|
||||
i.inbound_detail_id, label.carton_index, label.id
|
||||
""")
|
||||
List<PalletRow> palletRows(@Param("planId") long planId);
|
||||
|
||||
@Getter @Setter
|
||||
class Row {
|
||||
private Long loadingPlanId; private String planNo; private Long containerBookingId;
|
||||
@@ -49,5 +70,14 @@ public interface LoadingCompletedEventMapper {
|
||||
private Integer productQuantity; private Integer palletCount; private BigDecimal grossWeightKg;
|
||||
private BigDecimal netWeightKg; private BigDecimal dimensionalWeightKg; private BigDecimal volumeCbm;
|
||||
private String fbaTrackingNo; private String shipmentNo; private String shippingMark;
|
||||
private String businessType;
|
||||
}
|
||||
|
||||
@Getter @Setter
|
||||
class PalletRow {
|
||||
private Long accountId; private Long sourceInboundId; private String palletCode;
|
||||
private Integer allocationNo; private Integer allocatedPackageCount;
|
||||
private Long sourceInboundDetailId; private String skuCode; private String productNameZh;
|
||||
private Integer packageCount; private Integer productQuantity; private String boxCode;
|
||||
}
|
||||
}
|
||||
|
||||
+78
-6
@@ -14,6 +14,7 @@ import com.baiyue.firstleg.entity.InboundOutboxEntity;
|
||||
import com.baiyue.firstleg.mapper.InboundOutboxMapper;
|
||||
import com.baiyue.firstleg.mapper.LoadingCompletedEventMapper;
|
||||
import com.baiyue.firstleg.mapper.LoadingCompletedEventMapper.Row;
|
||||
import com.baiyue.firstleg.mapper.LoadingCompletedEventMapper.PalletRow;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -29,6 +30,7 @@ import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/** 在装柜完成事务内按客户写跨区业务 Outbox。 */
|
||||
@Service
|
||||
@@ -41,17 +43,20 @@ public class LoadingCompletedOutboxService {
|
||||
public void publish(long planId) {
|
||||
List<Row> rows = snapshotMapper.rows(planId);
|
||||
if (rows.isEmpty()) throw new BizException(ResultCode.CONFLICT, "装柜计划没有最终实装入仓单,不能生成尾程交接事件");
|
||||
List<PalletRow> palletRows = snapshotMapper.palletRows(planId);
|
||||
rows.stream().collect(java.util.stream.Collectors.groupingBy(Row::getAccountId,
|
||||
java.util.TreeMap::new, java.util.stream.Collectors.toList()))
|
||||
.forEach((accountId, accountRows) -> insert(envelope(accountId, accountRows)));
|
||||
.forEach((accountId, accountRows) -> insert(envelope(accountId, accountRows,
|
||||
palletRows.stream().filter(item -> accountId.equals(item.getAccountId())).toList())));
|
||||
}
|
||||
|
||||
private EventEnvelope envelope(long accountId, List<Row> rows) {
|
||||
private EventEnvelope envelope(long accountId, List<Row> rows, List<PalletRow> palletRows) {
|
||||
Row first = rows.get(0);
|
||||
Map<Long, List<Row>> byInbound = rows.stream().collect(java.util.stream.Collectors.groupingBy(
|
||||
Row::getSourceInboundId, java.util.TreeMap::new, java.util.stream.Collectors.toList()));
|
||||
List<FirstLegLoadingPlanCompletedV1.Order> orders = byInbound.values().stream()
|
||||
.map(this::order).toList();
|
||||
.map(value -> order(value, palletRows.stream()
|
||||
.filter(item -> Objects.equals(item.getSourceInboundId(), value.get(0).getSourceInboundId())).toList())).toList();
|
||||
var payload = new FirstLegLoadingPlanCompletedV1(String.valueOf(first.getLoadingPlanId()),
|
||||
first.getPlanNo(), string(first.getContainerBookingId()), first.getContainerNo(), first.getCabinetNo(),
|
||||
string(first.getWarehouseId()), first.getWarehouseName(), orders);
|
||||
@@ -65,7 +70,7 @@ public class LoadingCompletedOutboxService {
|
||||
traceId, eventKey, null, payloadNode, hash).requireValid();
|
||||
}
|
||||
|
||||
private FirstLegLoadingPlanCompletedV1.Order order(List<Row> values) {
|
||||
private FirstLegLoadingPlanCompletedV1.Order order(List<Row> values, List<PalletRow> palletRows) {
|
||||
List<Row> sorted = values.stream().sorted(Comparator.comparing(Row::getSourceInboundDetailId)).toList();
|
||||
Row first = sorted.get(0);
|
||||
List<FirstLegLoadingPlanCompletedV1.Item> items = sorted.stream().map(row ->
|
||||
@@ -75,14 +80,81 @@ public class LoadingCompletedOutboxService {
|
||||
row.getVolumeCbm(), string(row.getDestinationWarehouseId()), row.getDestinationWarehouseCode(),
|
||||
row.getDestinationWarehouseName(), row.getFbaTrackingNo(), row.getShipmentNo(), row.getShippingMark()))
|
||||
.toList();
|
||||
String orderType = dropship(first.getBusinessType()) ? "ONE_CLICK_DROPSHIP" : "FIRST_LEG";
|
||||
List<FirstLegLoadingPlanCompletedV1.PalletSnapshot> pallets = dropship(first.getBusinessType())
|
||||
? palletSnapshots(sorted, palletRows) : List.of();
|
||||
if ("ONE_CLICK_DROPSHIP".equals(orderType) && pallets.isEmpty()) {
|
||||
throw new BizException(ResultCode.CONFLICT, "一键代发入仓单缺少托盘冻结快照");
|
||||
}
|
||||
return new FirstLegLoadingPlanCompletedV1.Order(string(first.getSourceInboundId()),
|
||||
string(first.getRootInboundId()), string(first.getSourceOrderId()), first.getSourceOrderNo(),
|
||||
string(first.getRootOrderId()), first.getInboundCode(), string(first.getDestinationWarehouseId()),
|
||||
first.getDestinationWarehouseCode(), first.getDestinationWarehouseName(), sumInt(sorted, Row::getPackageCount),
|
||||
sumNullableInt(sorted, Row::getProductQuantity), sumNullableInt(sorted, Row::getPalletCount),
|
||||
sum(sorted, Row::getGrossWeightKg), sum(sorted, Row::getNetWeightKg), sum(sorted, Row::getVolumeCbm), items);
|
||||
sumNullableInt(sorted, Row::getProductQuantity), "ONE_CLICK_DROPSHIP".equals(orderType)
|
||||
? pallets.size() : 0, sum(sorted, Row::getGrossWeightKg), sum(sorted, Row::getNetWeightKg),
|
||||
sum(sorted, Row::getVolumeCbm), items, string(first.getAccountId()), orderType, pallets);
|
||||
}
|
||||
|
||||
private List<FirstLegLoadingPlanCompletedV1.PalletSnapshot> palletSnapshots(List<Row> values, List<PalletRow> source) {
|
||||
if (source.isEmpty()) return List.of();
|
||||
Map<String, List<PalletRow>> byPallet = source.stream().collect(java.util.stream.Collectors.groupingBy(
|
||||
p -> (p.getAllocationNo() == null ? "" : p.getAllocationNo()) + "|" + p.getPalletCode(),
|
||||
LinkedHashMap::new, java.util.stream.Collectors.toList()));
|
||||
int loadedPackages = byPallet.values().stream().map(list -> list.get(0)).map(PalletRow::getAllocatedPackageCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum();
|
||||
if (loadedPackages != sumInt(values, Row::getPackageCount)) {
|
||||
throw new BizException(ResultCode.CONFLICT, "一键代发实装箱数与托盘已拣箱数不一致");
|
||||
}
|
||||
Map<Long, DetailSnapshot> details = new LinkedHashMap<>();
|
||||
values.stream().sorted(Comparator.comparing(Row::getSourceInboundDetailId)).forEach(row ->
|
||||
details.putIfAbsent(row.getSourceInboundDetailId(), new DetailSnapshot(row.getSourceInboundDetailId(),
|
||||
row.getSkuCode(), row.getProductNameZh(), row.getPackageCount(), row.getProductQuantity(), new ArrayList<>())));
|
||||
source.stream().filter(item -> item.getBoxCode() != null).forEach(item -> {
|
||||
DetailSnapshot detail = details.get(item.getSourceInboundDetailId());
|
||||
if (detail != null && !detail.marks().contains(item.getBoxCode())) detail.marks().add(item.getBoxCode());
|
||||
});
|
||||
Map<Long, Integer> remainingPackages = details.values().stream().collect(java.util.stream.Collectors.toMap(
|
||||
DetailSnapshot::detailId, DetailSnapshot::packageCount, (a,b)->a, LinkedHashMap::new));
|
||||
Map<Long, Integer> remainingMarks = details.values().stream().collect(java.util.stream.Collectors.toMap(
|
||||
DetailSnapshot::detailId, ignored -> 0, (a,b)->a, LinkedHashMap::new));
|
||||
List<FirstLegLoadingPlanCompletedV1.PalletSnapshot> result = new ArrayList<>();
|
||||
for (List<PalletRow> palletRows : byPallet.values()) {
|
||||
PalletRow first = palletRows.get(0);
|
||||
int capacity = first.getAllocatedPackageCount() == null ? 0 : first.getAllocatedPackageCount();
|
||||
List<FirstLegLoadingPlanCompletedV1.SkuPackageSnapshot> sku = new ArrayList<>();
|
||||
for (DetailSnapshot detail : details.values()) {
|
||||
int remaining = remainingPackages.getOrDefault(detail.detailId(), 0);
|
||||
if (capacity <= 0 || remaining <= 0) continue;
|
||||
int count = Math.min(capacity, remaining);
|
||||
int totalQuantity = detail.productQuantity() == null ? count
|
||||
: (int) Math.round((double) detail.productQuantity() * count / Math.max(1, detail.packageCount()));
|
||||
int markStart = remainingMarks.getOrDefault(detail.detailId(), 0);
|
||||
int markEnd = Math.min(detail.marks().size(), markStart + count);
|
||||
List<String> marks = new ArrayList<>(detail.marks().subList(markStart, markEnd));
|
||||
if (marks.size() != count) throw new BizException(ResultCode.CONFLICT, "一键代发箱唛数量与托盘箱数不一致");
|
||||
sku.add(new FirstLegLoadingPlanCompletedV1.SkuPackageSnapshot(detail.skuCode(),
|
||||
detail.productName(), count, totalQuantity, marks));
|
||||
remainingPackages.put(detail.detailId(), remaining - count);
|
||||
remainingMarks.put(detail.detailId(), markEnd);
|
||||
capacity -= count;
|
||||
}
|
||||
if (!sku.isEmpty()) result.add(new FirstLegLoadingPlanCompletedV1.PalletSnapshot(
|
||||
first.getPalletCode() == null ? "PALLET-" + first.getAllocationNo() : first.getPalletCode(), sku));
|
||||
}
|
||||
if (remainingPackages.values().stream().mapToInt(Integer::intValue).sum() != 0) {
|
||||
throw new BizException(ResultCode.CONFLICT, "一键代发托盘未覆盖全部实装货物明细");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean dropship(String value) {
|
||||
return value != null && ("ONE_CLICK_DROPSHIP".equalsIgnoreCase(value)
|
||||
|| value.toUpperCase(java.util.Locale.ROOT).contains("DROPSHIP"));
|
||||
}
|
||||
|
||||
private record DetailSnapshot(Long detailId, String skuCode, String productName,
|
||||
Integer packageCount, Integer productQuantity, List<String> marks) {}
|
||||
|
||||
private void insert(EventEnvelope envelope) {
|
||||
InboundOutboxEntity value = new InboundOutboxEntity();
|
||||
value.setId(IdWorker.getId()); value.setTenantId(Long.valueOf(envelope.tenantId()));
|
||||
|
||||
+32
@@ -6,6 +6,7 @@ import com.baiyue.firstleg.entity.InboundOutboxEntity;
|
||||
import com.baiyue.firstleg.mapper.InboundOutboxMapper;
|
||||
import com.baiyue.firstleg.mapper.LoadingCompletedEventMapper;
|
||||
import com.baiyue.firstleg.mapper.LoadingCompletedEventMapper.Row;
|
||||
import com.baiyue.firstleg.mapper.LoadingCompletedEventMapper.PalletRow;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -48,6 +49,29 @@ class LoadingCompletedOutboxServiceTest {
|
||||
assertThat(rows.get(0).getEventKey()).isEqualTo("FIRSTLEG_LOADING_COMPLETED:90:11:1");
|
||||
}
|
||||
|
||||
@Test void publishesDropshipPalletSkuAndCartonSnapshots() throws Exception {
|
||||
Row first = row(11, 100, 101); first.setBusinessType("ONE_CLICK_DROPSHIP");
|
||||
first.setPackageCount(2); first.setProductQuantity(20); first.setSkuCode("SKU-A");
|
||||
Row second = row(11, 100, 102); second.setBusinessType("ONE_CLICK_DROPSHIP");
|
||||
second.setPackageCount(1); second.setProductQuantity(5); second.setSkuCode("SKU-B");
|
||||
when(snapshots.rows(90L)).thenReturn(List.of(first, second));
|
||||
when(snapshots.palletRows(90L)).thenReturn(List.of(
|
||||
pallet(11,100,1,"PLT-01",2,101,"SKU-A",2,20,"BOX-001"),
|
||||
pallet(11,100,1,"PLT-01",2,101,"SKU-A",2,20,"BOX-002"),
|
||||
pallet(11,100,2,"PLT-02",1,102,"SKU-B",1,5,"BOX-003")));
|
||||
|
||||
service.publish(90L);
|
||||
|
||||
ArgumentCaptor<InboundOutboxEntity> captor = ArgumentCaptor.forClass(InboundOutboxEntity.class);
|
||||
verify(outbox).insert(captor.capture());
|
||||
EventEnvelope event = mapper.readValue(captor.getValue().getPayloadJson(), EventEnvelope.class);
|
||||
assertThat(event.payload().at("/orders/0/orderType").asText()).isEqualTo("ONE_CLICK_DROPSHIP");
|
||||
assertThat(event.payload().at("/orders/0/customerId").asText()).isEqualTo("11");
|
||||
assertThat(event.payload().at("/orders/0/pallets")).hasSize(2);
|
||||
assertThat(event.payload().at("/orders/0/pallets/0/skuPackages/0/cartonMarks")).hasSize(2);
|
||||
assertThat(event.payload().at("/orders/0/palletCount").asInt()).isEqualTo(2);
|
||||
}
|
||||
|
||||
private Row row(long account,long inbound,long detail) {
|
||||
Row r=new Row(); r.setLoadingPlanId(90L); r.setPlanNo("P90"); r.setContainerBookingId(91L);
|
||||
r.setAggregateVersion(8); r.setContainerNo("CONT"); r.setCabinetNo("CAB"); r.setWarehouseId(92L);
|
||||
@@ -58,4 +82,12 @@ class LoadingCompletedOutboxServiceTest {
|
||||
r.setPackageCount(1); r.setProductQuantity(10); r.setPalletCount(1); r.setGrossWeightKg(BigDecimal.ONE);
|
||||
r.setNetWeightKg(BigDecimal.ONE); r.setVolumeCbm(BigDecimal.ONE); return r;
|
||||
}
|
||||
|
||||
private PalletRow pallet(long account,long inbound,int allocation,String palletNo,int allocated,
|
||||
long detail,String sku,int packages,int quantity,String boxCode) {
|
||||
PalletRow row = new PalletRow(); row.setAccountId(account); row.setSourceInboundId(inbound);
|
||||
row.setAllocationNo(allocation); row.setPalletCode(palletNo); row.setAllocatedPackageCount(allocated);
|
||||
row.setSourceInboundDetailId(detail); row.setSkuCode(sku); row.setProductNameZh("产品");
|
||||
row.setPackageCount(packages); row.setProductQuantity(quantity); row.setBoxCode(boxCode); return row;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user