Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
2026-09-09 12:20:05 +08:00
19 changed files with 325 additions and 13 deletions
@@ -14,6 +14,11 @@ import org.springframework.http.HttpStatus;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.ContentDisposition;
import org.springframework.http.ResponseEntity;
import org.springframework.http.MediaType;
import java.nio.charset.StandardCharsets;
import org.springframework.web.server.ResponseStatusException;
@RestController
@@ -55,6 +60,29 @@ public class RelabelApplicationController {
requirePlatform(user);
return ApiResponse.success(service.changeStatus(null, relabelNo, operator(user), request));
}
@PostMapping(value = "/{relabelNo}/files", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@PreAuthorize("hasAuthority('" + OverseasPermissions.RELABEL_ORDER_CREATE + "')")
public ApiResponse<RelabelResponses.Detail> uploadFile(@AuthenticationPrincipal AuthenticatedUser user,
@PathVariable String relabelNo, @RequestParam String scope, @RequestParam(required = false) Long itemId,
@RequestPart("file") MultipartFile file) {
requirePlatform(user);
String customerId = service.customerId(relabelNo);
return ApiResponse.success("ITEM".equalsIgnoreCase(scope)
? service.uploadItemFile(customerId, relabelNo, itemId == null ? 0L : itemId, operatorLong(user), file)
: service.uploadTotalFile(customerId, relabelNo, operatorLong(user), file));
}
@GetMapping("/{relabelNo}/files/{fileId}/download")
@PreAuthorize("hasAuthority('" + OverseasPermissions.RELABEL_ORDER_LIST + "')")
public ResponseEntity<byte[]> downloadFile(@AuthenticationPrincipal AuthenticatedUser user,
@PathVariable String relabelNo, @PathVariable long fileId, @RequestParam String scope,
@RequestParam(required = false) Long itemId) {
requirePlatform(user);
var file = service.downloadFile(service.customerId(relabelNo), relabelNo, scope, itemId, fileId);
return ResponseEntity.ok().header("Content-Disposition", ContentDisposition.inline().filename(file.fileName(), StandardCharsets.UTF_8).build().toString())
.contentType(org.springframework.http.MediaType.parseMediaType(file.contentType())).contentLength(file.content().length).body(file.content());
}
private void requirePlatform(AuthenticatedUser user) {
if (user == null || user.tenantId() == null) throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
if (!"PLATFORM".equals(user.appCode()) || user.tenantId() != 0L) {
@@ -69,4 +97,5 @@ public class RelabelApplicationController {
return value;
}
private String operator(AuthenticatedUser user) { return user.userId() == null ? user.username() : String.valueOf(user.userId()); }
private long operatorLong(AuthenticatedUser user) { return user.userId() == null ? 0L : user.userId(); }
}
@@ -11,6 +11,7 @@ public final class RelabelResponses {
String customerOrderNo, String overseasWarehouseId, LocalDateTime labelDeadline,
String contactName, String contactPhone, String status, int itemCount,
int totalPackageCount, int notifiedPackageCount, String skuCodes,
String totalFileId, String totalFileName, String totalFileUrl,
BigDecimal chargeAmount, String chargeCurrency, String walletStatus,
String walletErrorMessage,
LocalDateTime createdAt) {}
@@ -21,6 +21,9 @@ public class RelabelApplication {
private String contactName;
private String contactPhone;
private String remark;
private String totalFileId;
private String totalFileName;
private String totalFileUrl;
private String status;
private Integer itemCount;
private Integer totalPackageCount;
@@ -0,0 +1,58 @@
package com.baiyue.lastleg.relabel.gateway;
import com.baiyue.lastleg.config.LastlegRestClientFactory;
import com.baiyue.lastleg.config.LastlegRestClientProperties;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ResponseStatusException;
import java.io.IOException;
@Component
public class HttpRelabelDocumentFileGateway implements RelabelDocumentFileGateway {
@Resource private RestClient.Builder restClientBuilder;
@Resource private LastlegRestClientFactory restClientFactory;
@Resource private LastlegRestClientProperties restClientProperties;
@Value("${baiyue.clients.file.url:http://127.0.0.1:9205}") private String baseUrl;
@Value("${baiyue.security.internal-service-token:}") private String internalToken;
private RestClient client;
@PostConstruct void initializeClient() { client = restClientFactory.build(restClientBuilder, baseUrl, restClientProperties.getRelabelPhotoFile()); }
@Override public UploadedFile upload(String customerId, String businessType, String businessId, long operatorId, MultipartFile file) {
MultipartBodyBuilder body = new MultipartBodyBuilder();
try { body.part("file", new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { return file.getOriginalFilename(); } })
.contentType(file.getContentType() == null ? MediaType.APPLICATION_PDF : MediaType.parseMediaType(file.getContentType())); }
catch (IOException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "无法读取换标PDF", e); }
MetadataEnvelope response = client.post().uri("/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}", tenantId(customerId), businessType, businessId)
.header("X-Internal-Service-Token", internalToken).header("X-Operator-Id", String.valueOf(operatorId))
.contentType(MediaType.MULTIPART_FORM_DATA).body(body.build()).retrieve()
.onStatus(HttpStatusCode::isError, (request, result) -> { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "换标PDF上传失败"); })
.body(MetadataEnvelope.class);
requireSuccess(response, "换标PDF上传失败"); Metadata data = response == null ? null : response.data();
if (data == null || data.fileId() == null) throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "文件服务未返回换标PDF信息");
return new UploadedFile(data.fileId(), data.fileName(), data.contentType(), data.sizeBytes() == null ? 0 : data.sizeBytes());
}
@Override public DownloadedFile download(String customerId, String businessType, String businessId, long fileId) {
ResponseEntity<byte[]> response = client.get().uri("/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}/{fileId}/content", tenantId(customerId), businessType, businessId, fileId)
.header("X-Internal-Service-Token", internalToken).retrieve().onStatus(HttpStatusCode::isError, (request, result) -> {
throw new ResponseStatusException(result.getStatusCode().is4xxClientError() ? HttpStatus.NOT_FOUND : HttpStatus.SERVICE_UNAVAILABLE, "换标PDF读取失败");
}).toEntity(byte[].class);
String name = response.getHeaders().getContentDisposition().getFilename();
return new DownloadedFile(response.getBody() == null ? new byte[0] : response.getBody(), name == null ? fileId + ".pdf" : name,
response.getHeaders().getContentType() == null ? MediaType.APPLICATION_PDF_VALUE : response.getHeaders().getContentType().toString());
}
private long tenantId(String value) { try { return Long.parseLong(value); } catch (NumberFormatException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "客户ID格式无效", e); } }
private static void requireSuccess(MetadataEnvelope response, String message) { if (response == null || !"200".equals(response.code())) throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, message); }
private record MetadataEnvelope(String code, String message, Metadata data) { }
private record Metadata(Long fileId, String fileName, String contentType, Long sizeBytes) { }
}
@@ -0,0 +1,11 @@
package com.baiyue.lastleg.relabel.gateway;
import org.springframework.web.multipart.MultipartFile;
public interface RelabelDocumentFileGateway {
UploadedFile upload(String customerId, String businessType, String businessId, long operatorId, MultipartFile file);
DownloadedFile download(String customerId, String businessType, String businessId, long fileId);
record UploadedFile(long fileId, String fileName, String contentType, long sizeBytes) { }
record DownloadedFile(byte[] content, String fileName, String contentType) { }
}
@@ -366,6 +366,16 @@ public class RelabelApplicationService implements WalletResultHandler {
private LastlegOrder insertTailOrder(String customerId, RelabelRequests.Create request, String requestHash,
String relabelNo, String warehouseId, int packageCount,
LocalDateTime now) {
String customerOrderNo = request.customerOrderNo().trim();
LastlegOrder existingReturn = orders.selectOne(new LambdaQueryWrapper<LastlegOrder>()
.eq(LastlegOrder::getCustomerId, customerId).eq(LastlegOrder::getOrderType, "RETURN_RELABEL")
.and(w -> w.eq(LastlegOrder::getSourceOrderNo, customerOrderNo).or().eq(LastlegOrder::getOrderNo, customerOrderNo))
.last("LIMIT 1"));
if (existingReturn != null) {
existingReturn.setRelabelOrderNo(relabelNo); existingReturn.setRelabelStatus(PENDING_PROCESSING);
existingReturn.setSubOrderStatus("RETURN_RELABEL:" + PENDING_PROCESSING); existingReturn.setPackageCount(packageCount);
existingReturn.setUpdatedAt(now); orders.updateById(existingReturn); return existingReturn;
}
LastlegOrder order = new LastlegOrder();
order.setId(IdWorker.getId());
order.setOrderNo(orderNoGenerator.next("RELABEL", warehouseId, order.getId()));
@@ -47,4 +47,5 @@ public class PlatformReturnInventoryController {
public ApiResponse<ReturnInventoryResponses.Label> label(@PathVariable String cartonMark) {
return ApiResponse.success(service.platformLabel(cartonMark));
}
}
@@ -13,6 +13,7 @@ public final class ReturnInventoryResponses {
public record SummaryItem(String overseasWarehouseId, String skuCode, String productNameZh,
long totalQuantity, long availableQuantity, long cartonQuantity, LocalDateTime updatedAt) { }
public record CartonDetail(String cartonMark, String customerId, String overseasWarehouseId, String sourceBatchNo, String sourceReturnNo, String status,
String fbaCartonMark, String destinationWarehouseCode, String destinationWarehouseName, String relabelNo, String relabelStatus,
int skuTypes, long totalQuantity, BigDecimal length, BigDecimal width, BigDecimal height,
BigDecimal weight, LocalDateTime receivedAt, List<CartonItem> items) { }
public record CartonItem(String skuCode, String productNameZh, long quantity) { }
@@ -27,6 +28,7 @@ public final class ReturnInventoryResponses {
long totalQuantity, long availableQuantity, long cartonQuantity, LocalDateTime updatedAt) { }
public record PlatformCarton(String customerId, String overseasWarehouseId, String cartonMark, String sourceReturnNo,
String sourceBatchNo, String status, int skuTypes, long totalQuantity,
String fbaCartonMark, String destinationWarehouseCode, String destinationWarehouseName, String relabelNo, String relabelStatus,
BigDecimal length, BigDecimal width, BigDecimal height, BigDecimal weight,
LocalDateTime createdAt) { }
public record PlatformMovement(String customerId, String overseasWarehouseId, String skuCode, String productNameZh,
@@ -14,6 +14,7 @@ public final class ReturnOrderRequests {
private ReturnOrderRequests() { }
public record Create(@NotBlank @Size(max = 128) String overseasWarehouseId,
@Size(max = 128) String customerReferenceNo,
boolean needRelabel,
@Size(max = 1000) String remark,
@NotBlank @Size(max = 255) String idempotencyKey,
@NotEmpty @Size(max = 500) List<@Valid Item> items) { }
@@ -5,8 +5,9 @@ import java.util.List;
public final class ReturnOrderResponses {
private ReturnOrderResponses() { }
public record Summary(String returnNo, String overseasWarehouseId, String customerReferenceNo, String status,
int skuTypes, long expectedQuantity, long receivedQuantity, LocalDateTime createdAt) { }
public record Summary(String returnNo, String lastlegOrderNo, String overseasWarehouseId, String customerReferenceNo, String status,
int skuTypes, long expectedQuantity, long receivedQuantity, boolean needRelabel,
String relabelNo, String relabelStatus, LocalDateTime createdAt) { }
public record Item(String skuCode, String productNameZh, long expectedQuantity,
long receivedQuantity) { }
public record Detail(Summary order, String remark, List<Item> items, List<Receipt> receipts) { }
@@ -19,6 +19,13 @@ public class ReturnInventoryCarton {
private String sourceBatchNo;
private String sourceReturnNo;
private String cartonMark;
private String fbaCartonMark;
private String destinationWarehouseCode;
private String destinationWarehouseName;
private Long relabelApplicationId;
private String relabelNo;
private String relabelStatus;
private LocalDateTime relabelCompletedAt;
private String status;
private Integer skuTypes;
private Long totalQuantity;
@@ -15,6 +15,12 @@ public class ReturnOrder {
private String returnNo;
private String overseasWarehouseId;
private String customerReferenceNo;
private Boolean needRelabel;
private Long lastlegOrderId;
private String lastlegOrderNo;
private Long relabelApplicationId;
private String relabelNo;
private String relabelStatus;
private String status;
private Integer expectedSkuTypes;
private Long expectedQuantity;
@@ -128,7 +128,7 @@ public class ReturnInventoryService {
List<ReturnInventoryResponses.PlatformCarton> records = total == 0 ? List.of() : cartons.platformPage(customerId, warehouseId, cartonMark,
returnNo, status, sku, (request.page() - 1) * request.size(), request.size()).stream().map(carton -> new ReturnInventoryResponses.PlatformCarton(
carton.getCustomerId(), carton.getOverseasWarehouseId(), carton.getCartonMark(), carton.getSourceReturnNo(), carton.getSourceBatchNo(),
carton.getStatus(), carton.getSkuTypes() == null ? 0 : carton.getSkuTypes(), value(carton.getTotalQuantity()), carton.getLength(),
carton.getStatus(), carton.getSkuTypes() == null ? 0 : carton.getSkuTypes(), value(carton.getTotalQuantity()), carton.getFbaCartonMark(), carton.getDestinationWarehouseCode(), carton.getDestinationWarehouseName(), carton.getRelabelNo(), carton.getRelabelStatus(), carton.getLength(),
carton.getWidth(), carton.getHeight(), carton.getWeight(), carton.getCreatedAt())).toList();
return new PageResult<>(records, request.page(), request.size(), total, (total + request.size() - 1) / request.size());
}
@@ -220,6 +220,7 @@ public class ReturnInventoryService {
ReturnInventoryCarton carton = cartons.findReceipt(receipt.getId());
if (carton != null && AVAILABLE.equals(carton.getStatus())) sources.add(cartons.lockMark(carton.getCartonMark()));
}
if (sources.isEmpty()) throw conflict("所选退货单没有可合箱的库存箱");
Map<String, Long> requested = new LinkedHashMap<>();
Map<String, String> productNames = new LinkedHashMap<>();
for (ReturnInventoryRequests.ValidItem item : request.items()) {
@@ -231,7 +232,6 @@ public class ReturnInventoryService {
long total = 0;
for (ReturnInventoryCarton source : sources) {
List<ReturnInventoryCartonItem> sourceItems = cartonItems.listCarton(source.getId());
List<String> originalSkus = sourceItems.stream().map(item -> item.getSkuCode().toUpperCase(java.util.Locale.ROOT)).toList();
long sourceTotal = 0; int sourceTypes = 0;
for (ReturnInventoryCartonItem item : sourceItems) {
String sku = item.getSkuCode().toUpperCase(java.util.Locale.ROOT);
@@ -241,12 +241,12 @@ public class ReturnInventoryService {
productNames.putIfAbsent(sku, item.getProductNameZh());
item.setQuantity(item.getQuantity() - take);
if (item.getQuantity() == 0) cartonItems.deleteById(item.getId()); else cartonItems.updateById(item);
if (item.getQuantity() == 0) emptiedBySku.merge(sku, 1, Integer::sum);
}
if (item.getQuantity() > 0) { sourceTotal = Math.addExact(sourceTotal, item.getQuantity()); sourceTypes++; }
}
if (sourceTotal == 0) {
source.setStatus(MERGED); source.setMergedAt(now);
originalSkus.forEach(sku -> emptiedBySku.merge(sku, 1, Integer::sum));
}
source.setTotalQuantity(sourceTotal); source.setSkuTypes(sourceTypes); source.setUpdatedAt(now); cartons.updateById(source);
}
@@ -261,8 +261,11 @@ public class ReturnInventoryService {
ReturnInventoryCartonItem targetItem = new ReturnInventoryCartonItem();
targetItem.setId(IdWorker.getId()); targetItem.setCartonId(targetId); targetItem.setCustomerId(customerId); targetItem.setSkuCode(entry.getKey());
targetItem.setProductNameZh(productNames.get(entry.getKey())); targetItem.setQuantity(entry.getValue()); cartonItems.insert(targetItem);
// A SKU's carton count is the number of available physical cartons containing it:
// remove fully emptied source cartons, then add the one merged target carton.
long cartonDelta = 1L - emptiedBySku.getOrDefault(entry.getKey(), 0);
balances.adjust(IdWorker.getId(), customerId, target.getOverseasWarehouseId(), entry.getKey(), productNames.get(entry.getKey()), 0,
-entry.getValue(), 1L - emptiedBySku.getOrDefault(entry.getKey(), 0));
-entry.getValue(), cartonDelta);
}
operation.setResultCartonId(targetId); operation.setUpdatedAt(now); operations.updateById(operation);
return new ReturnInventoryResponses.MergeResult(target.getCartonMark(), requested.keySet().iterator().next(), total, label(target));
@@ -299,7 +302,7 @@ public class ReturnInventoryService {
List<ReturnInventoryResponses.CartonItem> items = cartonItems.listCarton(carton.getId()).stream()
.map(item -> new ReturnInventoryResponses.CartonItem(item.getSkuCode(), item.getProductNameZh(), item.getQuantity())).toList();
return new ReturnInventoryResponses.CartonDetail(carton.getCartonMark(), carton.getCustomerId(), carton.getOverseasWarehouseId(), carton.getSourceBatchNo(), carton.getSourceReturnNo(),
carton.getStatus(), carton.getSkuTypes() == null ? 0 : carton.getSkuTypes(), value(carton.getTotalQuantity()), carton.getLength(), carton.getWidth(), carton.getHeight(), carton.getWeight(), carton.getCreatedAt(), items);
carton.getStatus(), carton.getFbaCartonMark(), carton.getDestinationWarehouseCode(), carton.getDestinationWarehouseName(), carton.getRelabelNo(), carton.getRelabelStatus(), carton.getSkuTypes() == null ? 0 : carton.getSkuTypes(), value(carton.getTotalQuantity()), carton.getLength(), carton.getWidth(), carton.getHeight(), carton.getWeight(), carton.getCreatedAt(), items);
}
private static String printableHtml(ReturnInventoryCarton carton, List<ReturnInventoryResponses.CartonItem> items) {
@@ -20,6 +20,8 @@ import com.baiyue.lastleg.returnreceipt.mapper.ReturnReceiptBatchMapper;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnReceiptItemMapper;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnReceiptMapper;
import com.baiyue.lastleg.service.LastlegOrderNoGenerator;
import com.baiyue.lastleg.entity.LastlegOrder;
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
@@ -56,6 +58,7 @@ public class ReturnReceiptService {
@Resource private ReturnInventoryService inventory;
@Resource private LastlegOrderNoGenerator numbers;
@Resource private ObjectMapper objectMapper;
@Resource private LastlegOrderMapper lastlegOrders;
@Transactional
public ReturnOrderResponses.Detail create(String customerId, String operatorId, ReturnOrderRequests.Create request) {
@@ -75,7 +78,7 @@ public class ReturnReceiptService {
order.setId(IdWorker.getId()); order.setCustomerId(customerId);
order.setOverseasWarehouseId(text(request.overseasWarehouseId()));
order.setReturnNo(numbers.next("RETURN", order.getOverseasWarehouseId(), order.getId()));
order.setCustomerReferenceNo(text(request.customerReferenceNo())); order.setStatus(PENDING_RECEIPT);
order.setCustomerReferenceNo(text(request.customerReferenceNo())); order.setNeedRelabel(request.needRelabel()); order.setStatus(PENDING_RECEIPT);
order.setExpectedSkuTypes(skuCodes.size()); order.setExpectedQuantity(expected); order.setReceivedQuantity(0L);
order.setRemark(text(request.remark())); order.setIdempotencyKey(key); order.setRequestHash(requestHash);
order.setCreatedBy(text(operatorId)); order.setCreatedAt(now); order.setUpdatedAt(now);
@@ -85,6 +88,7 @@ public class ReturnReceiptService {
if (existing != null) return replayOrder(customerId, existing, requestHash);
throw concurrent;
}
createTailOrder(order, text(operatorId), now);
for (ReturnOrderRequests.Item input : request.items()) {
ReturnOrderItem item = new ReturnOrderItem();
item.setId(IdWorker.getId()); item.setReturnOrderId(order.getId()); item.setCustomerId(customerId);
@@ -95,6 +99,23 @@ public class ReturnReceiptService {
return detail(customerId, order.getReturnNo());
}
private void createTailOrder(ReturnOrder returnOrder, String operatorId, LocalDateTime now) {
LastlegOrder tail = new LastlegOrder();
tail.setId(IdWorker.getId());
tail.setOrderNo(numbers.next("RETURN_RELABEL", returnOrder.getOverseasWarehouseId(), tail.getId()));
tail.setCustomerId(returnOrder.getCustomerId()); tail.setOrderType("RETURN_RELABEL");
tail.setSourceRegion("CUSTOMER"); tail.setSourceOrderId(String.valueOf(returnOrder.getId()));
tail.setSourceOrderNo(returnOrder.getReturnNo()); tail.setOverseasWarehouseId(returnOrder.getOverseasWarehouseId());
tail.setCurrentStatus("PENDING_ASSIGNMENT"); tail.setSubOrderStatus(Boolean.TRUE.equals(returnOrder.getNeedRelabel()) ? "RETURN_RELABEL:PENDING_BINDING" : "RETURN_RELABEL:NOT_REQUIRED");
tail.setRelabelStatus(Boolean.TRUE.equals(returnOrder.getNeedRelabel()) ? "PENDING_BINDING" : "NOT_REQUIRED");
tail.setCustomerRemark(returnOrder.getRemark()); tail.setSourceEventId("RETURN_ORDER:" + returnOrder.getReturnNo());
tail.setSourceLoadingPlanId("RETURN_RELABEL"); tail.setCreatedAt(now); tail.setUpdatedAt(now);
lastlegOrders.insert(tail);
returnOrder.setLastlegOrderId(tail.getId()); returnOrder.setLastlegOrderNo(tail.getOrderNo());
returnOrder.setRelabelStatus(Boolean.TRUE.equals(returnOrder.getNeedRelabel()) ? "PENDING_BINDING" : "NOT_REQUIRED");
orders.updateById(returnOrder);
}
@Transactional(readOnly = true)
public PageResult<ReturnOrderResponses.Summary> page(String customerId, ReturnOrderRequests.Query query) {
LambdaQueryWrapper<ReturnOrder> w = new LambdaQueryWrapper<ReturnOrder>()
@@ -271,10 +292,10 @@ public class ReturnReceiptService {
return new PdaReturnReceiptResponses.Confirmed(order.getReturnNo(), receipt.getReceiptNo(), receipt.getReceiptBatchNo(), receipt.getCartonMark(),
order.getStatus(), completed, value(order.getExpectedQuantity()), value(order.getReceivedQuantity()), receipt.getSignedAt());
}
private ReturnOrderResponses.Summary summary(ReturnOrder order) { return new ReturnOrderResponses.Summary(order.getReturnNo(),
private ReturnOrderResponses.Summary summary(ReturnOrder order) { return new ReturnOrderResponses.Summary(order.getReturnNo(), order.getLastlegOrderNo(),
order.getOverseasWarehouseId(), order.getCustomerReferenceNo(), order.getStatus(),
order.getExpectedSkuTypes() == null ? 0 : order.getExpectedSkuTypes(), value(order.getExpectedQuantity()),
value(order.getReceivedQuantity()), order.getCreatedAt()); }
value(order.getReceivedQuantity()), Boolean.TRUE.equals(order.getNeedRelabel()), order.getRelabelNo(), order.getRelabelStatus(), order.getCreatedAt()); }
private ReturnOrderResponses.Item item(ReturnOrderItem item) { return new ReturnOrderResponses.Item(item.getSkuCode(),
item.getProductNameZh(), value(item.getExpectedQuantity()), value(item.getReceivedQuantity())); }
private PdaReturnReceiptResponses.Item pdaItem(ReturnOrderItem item) { return new PdaReturnReceiptResponses.Item(item.getSkuCode(),