提交
This commit is contained in:
+9
@@ -74,6 +74,15 @@ public class MerchantRelabelApplicationController {
|
||||
if ("ITEM".equalsIgnoreCase(scope)) return ApiResponse.success(service.uploadItemFile(customer(user), relabelNo, itemId == null ? 0L : itemId, operatorLong(user), file));
|
||||
return ApiResponse.success(service.uploadTotalFile(customer(user), relabelNo, operatorLong(user), file, kind));
|
||||
}
|
||||
/** 按登录客户及申请绑定关系读取贴标资料,禁止跨客户或跨明细下载。 */
|
||||
@GetMapping("/{relabelNo}/files/{fileId}/download")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RELABEL_LIST + "')")
|
||||
public ResponseEntity<byte[]> downloadFile(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@PathVariable String relabelNo, @PathVariable long fileId, @RequestParam String scope,
|
||||
@RequestParam(required = false) Long itemId) {
|
||||
var file = service.downloadFile(customer(user), relabelNo, scope, itemId, fileId);
|
||||
return download(file.content(), file.fileName(), file.contentType());
|
||||
}
|
||||
@GetMapping("/{relabelNo}/shipping-label/{fileId}/download")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RELABEL_LIST + "')")
|
||||
public ResponseEntity<byte[]> downloadShippingLabel(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
|
||||
+11
@@ -134,6 +134,17 @@ public class RelabelApplicationController {
|
||||
return ResponseEntity.ok().cacheControl(org.springframework.http.CacheControl.noStore()).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());
|
||||
}
|
||||
/** 平台按申请绑定关系读取客户上传的面单。 */
|
||||
@GetMapping("/{relabelNo}/shipping-label/{fileId}/download")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.RELABEL_ORDER_LIST + "')")
|
||||
public ResponseEntity<byte[]> downloadShippingLabel(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@PathVariable String relabelNo, @PathVariable long fileId) {
|
||||
requirePlatform(user);
|
||||
var file = service.downloadShippingLabel(service.customerId(relabelNo), relabelNo, fileId);
|
||||
return ResponseEntity.ok().cacheControl(org.springframework.http.CacheControl.noStore())
|
||||
.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());
|
||||
}
|
||||
@GetMapping("/{relabelNo}/completion-photos/{fileId}/download")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.RELABEL_ORDER_LIST + "')")
|
||||
public ResponseEntity<byte[]> downloadCompletionPhoto(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
|
||||
+12
@@ -20,6 +20,7 @@ import org.springframework.web.server.ResponseStatusException;
|
||||
public class WarehouseTransferController {
|
||||
public static final String MANAGE_PERMISSION = "lastleg:warehouse-transfer:manage";
|
||||
@Resource private WarehouseTransferService service;
|
||||
@Resource private com.baiyue.lastleg.transfer.service.WarehouseTransferForecastService forecasts;
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<WarehouseTransferResponses.Detail> create(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@@ -41,6 +42,17 @@ public class WarehouseTransferController {
|
||||
return ApiResponse.success(service.detail(scope(user, customerId), transferNo));
|
||||
}
|
||||
|
||||
/** 平台人员在测量完成前追加整单预报箱,沿用统一锁单及箱唛生成规则。 */
|
||||
@PostMapping("/{transferNo}/increase-forecast-cartons")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.WAREHOUSE_TRANSFER_APPROVE + "')")
|
||||
public ApiResponse<WarehouseTransferResponses.Detail> increaseForecastCartons(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam String customerId, @PathVariable String transferNo,
|
||||
@Valid @RequestBody WarehouseTransferRequests.IncreaseForecastCartons request) {
|
||||
if (user == null || !"PLATFORM".equals(user.appCode()) || user.tenantId() == null || user.tenantId() != 0L)
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Platform identity is required");
|
||||
return ApiResponse.success(forecasts.increase(scope(user, customerId), transferNo, operator(user), request));
|
||||
}
|
||||
|
||||
@GetMapping("/{transferNo}/carton-label")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_LIST + "')")
|
||||
public ApiResponse<WarehouseTransferResponses.Label> cartonLabel(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
|
||||
+1
-3
@@ -105,11 +105,9 @@ public final class WarehouseTransferRequests {
|
||||
public record Outbound(@NotBlank @Size(max = 255) String idempotencyKey,
|
||||
@Size(max = 1000) String remark) {}
|
||||
|
||||
/** 仅增加既有SKU的预报箱数,携带原箱数用于并发核对及重试去重。 */
|
||||
/** 仅增加整单预报箱数,箱内SKU由PDA清点确定,携带原箱数用于并发核对及重试去重。 */
|
||||
public record IncreaseForecastCartons(
|
||||
@Positive @Max(5000) int expectedPackageCount,
|
||||
@NotNull Long transferItemId,
|
||||
@Min(0) @Max(5000) int expectedItemPackageCount,
|
||||
@Positive @Max(5000) int packageCount
|
||||
) {}
|
||||
|
||||
|
||||
+5
-18
@@ -6,7 +6,6 @@ import com.baiyue.lastleg.transfer.entity.*;
|
||||
import com.baiyue.lastleg.transfer.mapper.*;
|
||||
import com.baiyue.lastleg.entity.LastlegOrder;
|
||||
import com.baiyue.lastleg.entity.LastlegInboundOrder;
|
||||
import com.baiyue.lastleg.entity.LastlegOrderDetail;
|
||||
import com.baiyue.lastleg.entity.LastlegOrderStatusHistory;
|
||||
import com.baiyue.lastleg.mapper.*;
|
||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlanLine;
|
||||
@@ -20,11 +19,11 @@ import java.util.List;
|
||||
@Repository
|
||||
public class TransferForecastRepository {
|
||||
@Resource private WarehouseTransferOrderMapper transfers;
|
||||
@Resource private WarehouseTransferItemMapper items;
|
||||
|
||||
@Resource private WarehouseTransferCartonMapper cartons;
|
||||
@Resource private LastlegOrderMapper orders;
|
||||
@Resource private LastlegInboundOrderMapper inboundOrders;
|
||||
@Resource private LastlegOrderDetailMapper orderDetails;
|
||||
|
||||
@Resource private LastlegOrderStatusHistoryMapper histories;
|
||||
@Resource private InboundPlanLineMapper planLines;
|
||||
|
||||
@@ -33,26 +32,19 @@ public class TransferForecastRepository {
|
||||
return transfers.lockNo(customerId, transferNo);
|
||||
}
|
||||
|
||||
/** 按创建顺序读取预报明细,保持关联尾程明细的序号稳定。 */
|
||||
public List<WarehouseTransferItem> items(String customerId, Long transferId) {
|
||||
return items.selectList(new LambdaQueryWrapper<WarehouseTransferItem>()
|
||||
.eq(WarehouseTransferItem::getCustomerId, customerId)
|
||||
.eq(WarehouseTransferItem::getTransferOrderId, transferId).orderByAsc(WarehouseTransferItem::getId));
|
||||
}
|
||||
|
||||
/** 读取原箱号用于确定新增编号,不删除或重建原箱。 */
|
||||
public List<WarehouseTransferCarton> cartons(String customerId, Long transferId) {
|
||||
return cartons.listOrder(customerId, transferId);
|
||||
}
|
||||
|
||||
/** 追加预报箱并同步各预报口径;清点数据保留,整单清点确认失效。 */
|
||||
public void append(WarehouseTransferOrder transfer, WarehouseTransferItem item, int itemIndex,
|
||||
public void append(WarehouseTransferOrder transfer,
|
||||
List<WarehouseTransferCarton> added, LocalDateTime now, String operatorId) {
|
||||
String customerId = transfer.getCustomerId();
|
||||
var order = orders.selectOne(new LambdaQueryWrapper<LastlegOrder>()
|
||||
.eq(LastlegOrder::getCustomerId, customerId).eq(LastlegOrder::getId, transfer.getLastlegOrderId()));
|
||||
if (order == null) throw new IllegalStateException("转运关联尾程订单不存在");
|
||||
items.updateById(item);
|
||||
|
||||
transfers.updateById(transfer);
|
||||
for (var carton : added) cartons.insert(carton);
|
||||
cartons.update(null, new LambdaUpdateWrapper<WarehouseTransferCarton>()
|
||||
@@ -65,18 +57,13 @@ public class TransferForecastRepository {
|
||||
inboundOrders.update(null, new LambdaUpdateWrapper<LastlegInboundOrder>()
|
||||
.eq(LastlegInboundOrder::getCustomerId, customerId).eq(LastlegInboundOrder::getId, transfer.getInboundOrderId())
|
||||
.set(LastlegInboundOrder::getPackageCount, transfer.getPackageCount()).set(LastlegInboundOrder::getUpdatedAt, now));
|
||||
int updated = orderDetails.update(null, new LambdaUpdateWrapper<LastlegOrderDetail>()
|
||||
.eq(LastlegOrderDetail::getCustomerId, customerId).eq(LastlegOrderDetail::getOrderId, transfer.getLastlegOrderId())
|
||||
.eq(LastlegOrderDetail::getSourceInboundDetailId, transfer.getTransferNo() + ":" + itemIndex)
|
||||
.set(LastlegOrderDetail::getPackageCount, item.getPackageCount()));
|
||||
if (updated != 1) throw new IllegalStateException("转运关联尾程货物明细不完整");
|
||||
planLines.update(null, new LambdaUpdateWrapper<InboundPlanLine>()
|
||||
.eq(InboundPlanLine::getCustomerId, customerId).eq(InboundPlanLine::getOrderId, transfer.getLastlegOrderId())
|
||||
.set(InboundPlanLine::getRequiredPackageCount, transfer.getPackageCount()));
|
||||
var history = new LastlegOrderStatusHistory(); history.setCustomerId(customerId); history.setOrderId(transfer.getLastlegOrderId());
|
||||
history.setFromStatus(order.getCurrentStatus()); history.setToStatus(order.getCurrentStatus());
|
||||
history.setEventId(transfer.getTransferNo()); history.setCreatedAt(now);
|
||||
history.setRemark("客户增加预报箱数,补充箱唛" + added.size() + "个;操作人:" + operatorId);
|
||||
history.setRemark("增加预报箱数,补充箱唛" + added.size() + "个;操作人:" + operatorId);
|
||||
histories.insert(history);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-12
@@ -29,17 +29,13 @@ public class WarehouseTransferForecastService {
|
||||
if (transfer == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "转运单不存在");
|
||||
if (!transferNo.equals(transfer.getInboundCode()) || !Set.of("PENDING_REVIEW", "WAIT_PDA_RECEIVING").contains(transfer.getStatus()))
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "仅测量完成前的外来转运单可增加预报箱数");
|
||||
var items = repository.items(customerId, transfer.getId());
|
||||
var item = items.stream().filter(row -> row.getId().equals(request.transferItemId())).findFirst()
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "SKU不属于当前转运单"));
|
||||
int addedCount = request.packageCount() - request.expectedItemPackageCount();
|
||||
long total = (long) request.expectedPackageCount() + addedCount;
|
||||
int addedCount = request.packageCount() - request.expectedPackageCount();
|
||||
int total = request.packageCount();
|
||||
if (addedCount <= 0 || total > 5000 || request.expectedPackageCount() <= 0)
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "只能增加预报箱数,整单最多5000箱");
|
||||
// 相同目标值视为已完成的重试;不同原快照则要求刷新,避免多端覆盖。
|
||||
if (item.getPackageCount() == request.packageCount() && transfer.getPackageCount() == total)
|
||||
return transfers.detail(customerId, transferNo);
|
||||
if (transfer.getPackageCount() != request.expectedPackageCount() || item.getPackageCount() != request.expectedItemPackageCount())
|
||||
// 相同目标值重试不再生成箱唛;不同原快照必须刷新,防止并发覆盖。
|
||||
if (transfer.getPackageCount() == total) return transfers.detail(customerId, transferNo);
|
||||
if (transfer.getPackageCount() != request.expectedPackageCount())
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "预报箱数已变化,请刷新后重试");
|
||||
var existing = repository.cartons(customerId, transfer.getId());
|
||||
int index = existing.stream().mapToInt(WarehouseTransferCarton::getCartonIndex).max().orElse(0);
|
||||
@@ -47,13 +43,14 @@ public class WarehouseTransferForecastService {
|
||||
var added = new ArrayList<WarehouseTransferCarton>();
|
||||
for (int i = 0; i < addedCount; i++) {
|
||||
var carton = new WarehouseTransferCarton(); carton.setId(IdWorker.getId()); carton.setCustomerId(customerId);
|
||||
carton.setTransferOrderId(transfer.getId()); carton.setTransferItemId(item.getId());
|
||||
carton.setTransferOrderId(transfer.getId());
|
||||
// 预报箱仅代表一个箱唛,不预先绑定SKU,实收箱内明细由PDA记录。
|
||||
carton.setCartonMark(LastlegOrderNoGenerator.compactCartonMark(carton.getId()));
|
||||
carton.setCartonIndex(++index); carton.setTotalCartons((int) total); carton.setStatus("EXPECTED");
|
||||
carton.setCreatedAt(now); carton.setUpdatedAt(now); added.add(carton);
|
||||
}
|
||||
item.setPackageCount(request.packageCount()); transfer.setPackageCount((int) total); transfer.setUpdatedAt(now);
|
||||
repository.append(transfer, item, items.indexOf(item), added, now, operatorId);
|
||||
transfer.setPackageCount(total); transfer.setUpdatedAt(now);
|
||||
repository.append(transfer, added, now, operatorId);
|
||||
return transfers.detail(customerId, transferNo);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-8
@@ -410,9 +410,13 @@ public class WarehouseTransferService {
|
||||
inboundOrders.updateById(inbound);
|
||||
}
|
||||
|
||||
// 草稿可能已打印箱唛,编辑时保留已有序号对应的编号,只追加或移除尾部箱子。
|
||||
Map<Integer, WarehouseTransferCarton> originalCartons = transferCartons.listOrder(customerId, transfer.getId())
|
||||
.stream().collect(Collectors.toMap(WarehouseTransferCarton::getCartonIndex, Function.identity()));
|
||||
transferCartons.delete(new LambdaQueryWrapper<WarehouseTransferCarton>()
|
||||
.eq(WarehouseTransferCarton::getCustomerId, customerId)
|
||||
.eq(WarehouseTransferCarton::getTransferOrderId, transfer.getId()));
|
||||
.eq(WarehouseTransferCarton::getTransferOrderId, transfer.getId())
|
||||
.gt(WarehouseTransferCarton::getCartonIndex, request.packageCount()));
|
||||
transferItems.delete(new LambdaQueryWrapper<WarehouseTransferItem>()
|
||||
.eq(WarehouseTransferItem::getCustomerId, customerId)
|
||||
.eq(WarehouseTransferItem::getTransferOrderId, transfer.getId()));
|
||||
@@ -431,8 +435,16 @@ public class WarehouseTransferService {
|
||||
List<String> customerMarks = splitMarks(source.shippingMark());
|
||||
for (int itemCarton = 0; itemCarton < source.packageCount(); itemCarton++) {
|
||||
cartonIndex++;
|
||||
insertTransferCarton(customerId, transfer.getId(), itemId, transferNo, cartonIndex,
|
||||
request.packageCount(), itemCarton < customerMarks.size() ? customerMarks.get(itemCarton) : null, now);
|
||||
var existingCarton = originalCartons.get(cartonIndex);
|
||||
String customerMark = itemCarton < customerMarks.size() ? customerMarks.get(itemCarton) : null;
|
||||
if (existingCarton == null) {
|
||||
insertTransferCarton(customerId, transfer.getId(), itemId, transferNo, cartonIndex,
|
||||
request.packageCount(), customerMark, now);
|
||||
} else {
|
||||
existingCarton.setTransferItemId(itemId); existingCarton.setTotalCartons(request.packageCount());
|
||||
existingCarton.setCustomerCartonMark(customerMark); existingCarton.setUpdatedAt(now);
|
||||
transferCartons.updateById(existingCarton);
|
||||
}
|
||||
}
|
||||
insertOrderDetail(customerId, order.getId(), transferNo, index, source, request, now);
|
||||
}
|
||||
@@ -698,12 +710,11 @@ public class WarehouseTransferService {
|
||||
return cartonLabel(transfer.getCustomerId(), transferNo);
|
||||
}
|
||||
|
||||
/** 提交预报后打印整单固定箱唛,测量及未收状态不改变箱号集合。 */
|
||||
/** 保存草稿后即可打印整单固定箱唛,测量及未收状态不改变箱号集合。 */
|
||||
@Transactional(readOnly = true)
|
||||
public WarehouseTransferResponses.Label cartonLabel(String customerId, String transferNo) {
|
||||
WarehouseTransferOrder transfer = transfers.findNo(customerId, transferNo);
|
||||
if (transfer == null) throw notFound("Warehouse transfer order not found");
|
||||
if (DRAFT.equals(transfer.getStatus())) throw conflict("Submit the warehouse transfer order before printing carton labels");
|
||||
List<WarehouseTransferResponses.Carton> cartons = transferCartons.listOrder(customerId, transfer.getId()).stream()
|
||||
.map(value -> new WarehouseTransferResponses.Carton(value.getCartonMark(), value.getCustomerCartonMark(), value.getCartonIndex(), value.getTotalCartons(), value.getStatus(), value.getTransferItemId(), value.getTransferPalletId(), value.getLengthCm(), value.getWidthCm(), value.getHeightCm(), value.getGrossWeightKg(), value.getCountedQuantity(), value.getDiscrepancyReason(), value.getCountedBy(), value.getCountedAt(), cartonContents(value))).toList();
|
||||
StringBuilder labels = new StringBuilder();
|
||||
@@ -930,8 +941,6 @@ public class WarehouseTransferService {
|
||||
var carton = byMark.get(input.cartonMark());
|
||||
if (carton == null || !seen.add(input.cartonMark()))
|
||||
throw badRequest("箱号不属于本单或重复填写");
|
||||
var item = byItem.get(carton.getTransferItemId());
|
||||
if (item == null) throw badRequest("箱子申报明细不属于本单");
|
||||
if (input.items() == null || input.items().isEmpty() || input.items().size() > 200)
|
||||
throw badRequest("每箱必须填写 1 至 200 行 SKU");
|
||||
Set<String> skuCodes = new java.util.HashSet<>();
|
||||
@@ -941,7 +950,7 @@ public class WarehouseTransferService {
|
||||
|| !skuCodes.add(line.skuCode())) throw badRequest("箱内 SKU 必须来自本单预报,同箱不能重复");
|
||||
if (line.quantity() <= 0 || line.quantity() > Integer.MAX_VALUE) throw badRequest("每行 SKU 必须填写有效实点件数");
|
||||
}
|
||||
if (!skuCodes.contains(item.getSkuCode())) throw badRequest("请保留箱子原申报 SKU,可添加其他本单 SKU");
|
||||
// 箱内实际SKU以PDA清点为准,允许混箱或调整,仍须属于当前单预报。
|
||||
if (input.length() == null || input.width() == null
|
||||
|| input.height() == null || input.weight() == null || input.length().signum() <= 0 || input.width().signum() <= 0
|
||||
|| input.height().signum() <= 0 || input.weight().signum() <= 0) throw badRequest("每箱必须填写有效尺寸、重量和实点件数");
|
||||
@@ -963,6 +972,7 @@ public class WarehouseTransferService {
|
||||
var declared = byItem.values().stream().filter(value -> value.getSkuCode().equals(line.skuCode())).findFirst().orElseThrow();
|
||||
return new WarehouseTransferResponses.CartonItem(declared.getId(), line.skuCode(), line.quantity());
|
||||
}).toList();
|
||||
carton.setTransferItemId(contents.get(0).transferItemId());
|
||||
try { carton.setSkuItemsJson(objectMapper.writeValueAsString(contents)); }
|
||||
catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new IllegalStateException("Cannot serialize carton contents", e); }
|
||||
carton.setCountedBy(operatorId); carton.setCountedAt(now); carton.setStatus("COUNTED");
|
||||
|
||||
@@ -2282,7 +2282,7 @@ CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_carton (
|
||||
transfer_pallet_id BIGINT NULL COMMENT '签收箱所属转运托盘事实ID',
|
||||
sku_items_json JSON NULL COMMENT '实收箱内SKU及逐项件数明细',
|
||||
id BIGINT NOT NULL COMMENT '预报箱主键', transfer_order_id BIGINT NOT NULL COMMENT '转运单ID',
|
||||
transfer_item_id BIGINT NOT NULL COMMENT '转运申报明细ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
transfer_item_id BIGINT NULL COMMENT '实际箱内首项SKU明细ID,预报补箱可为空', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
customer_carton_mark VARCHAR(255) NULL COMMENT '客户原箱唛,用于换标现场绑定',
|
||||
carton_mark VARCHAR(255) NOT NULL COMMENT '系统生成的一箱一码箱唛', carton_index INT NOT NULL COMMENT '全单箱序号',
|
||||
total_cartons INT NOT NULL COMMENT '首次生成时全单总箱数', status VARCHAR(32) NOT NULL DEFAULT 'EXPECTED' COMMENT '箱状态:EXPECTED待实收',
|
||||
|
||||
@@ -7,7 +7,7 @@ paths:
|
||||
/api/merchant/v1/last-leg/warehouse-transfers/{transferNo}/increase-forecast-cartons:
|
||||
post:
|
||||
summary: 测量完成前增加预报箱数并补充箱唛
|
||||
description: 客户身份及transfer:create权限;仅外来货物待审核或待PDA测量可用,按原预报快照追加既有SKU的箱数,原箱唛与件数不变。补箱及PDA完工锁定同一订单;成功后PDA刷新继续清点,无新增表字段。
|
||||
description: 客户身份及transfer:create权限;仅外来货物待审核或待PDA测量可用,按原预报快照追加整单箱数,不绑定SKU,实际箱内SKU由PDA清点确定,原箱唛与件数不变。补箱及PDA完工锁定同一订单;成功后PDA刷新继续清点。
|
||||
parameters:
|
||||
- {name: transferNo, in: path, required: true, schema: {type: string}}
|
||||
requestBody:
|
||||
@@ -16,14 +16,33 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [expectedPackageCount, transferItemId, expectedItemPackageCount, packageCount]
|
||||
required: [expectedPackageCount, packageCount]
|
||||
properties:
|
||||
expectedPackageCount: {type: integer, minimum: 1, maximum: 5000, description: 修改前整单预报箱数}
|
||||
transferItemId: {type: integer, format: int64, description: 当前单既有SKU明细}
|
||||
expectedItemPackageCount: {type: integer, minimum: 0, maximum: 5000, description: 修改前该SKU预报箱数}
|
||||
packageCount: {type: integer, minimum: 1, maximum: 5000, description: 增加后该SKU预报箱数}
|
||||
packageCount: {type: integer, minimum: 1, maximum: 5000, description: 增加后整单预报箱数}
|
||||
responses:
|
||||
'200': {description: 返回补箱后的转运详情,相同原快照和目标箱数重试不重复生成箱唛}
|
||||
/api/platform/v1/last-leg/warehouse-transfers/{transferNo}/increase-forecast-cartons:
|
||||
post:
|
||||
summary: 平台在测量完成前增加整单预报箱数
|
||||
description: 平台身份及 platform:overseas-warehouse:warehouse-transfer:approve 权限;指定目标客户,沿用客户补箱的状态、并发及幂等规则,不改变SKU预报件数。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: transferNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: customerId, in: query, required: true, schema: { type: string } }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [expectedPackageCount, packageCount]
|
||||
properties:
|
||||
expectedPackageCount: { type: integer, minimum: 1, maximum: 5000 }
|
||||
packageCount: { type: integer, minimum: 1, maximum: 5000 }
|
||||
responses:
|
||||
'200': { description: 补箱后的转运详情 }
|
||||
'409': { description: 已完成测量或原预报箱数过期 }
|
||||
/api/pda/v1/last-leg/warehouse-transfers/{transferNo}/carton-label:
|
||||
get:
|
||||
summary: PDA读取转运箱标签
|
||||
@@ -1796,6 +1815,31 @@ paths:
|
||||
- { name: itemId, in: query, required: false, schema: { type: integer, format: int64 } }
|
||||
requestBody: { required: true, content: { multipart/form-data: { schema: { type: object, required: [file], properties: { file: { type: string, format: binary } } } } } }
|
||||
responses: { '200': { description: 更新后的换标详情 }, '403': { description: 缺少换标文件维护权限 }, '409': { description: 状态或归属冲突 } }
|
||||
/api/merchant/v1/last-leg/relabel-applications/{relabelNo}/files/{fileId}/download:
|
||||
get:
|
||||
summary: 客户查看或下载申请已绑定的贴标文件
|
||||
description: 权限 merchant:overseas-warehouse:relabel:list;按登录客户隔离,并校验总文件或明细文件归属。响应禁止缓存。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: relabelNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: fileId, in: path, required: true, schema: { type: integer, format: int64, minimum: 1 } }
|
||||
- { name: scope, in: query, required: true, schema: { type: string, enum: [TOTAL, CARTON_TOTAL, SKU_TOTAL, ITEM] } }
|
||||
- { name: itemId, in: query, required: false, schema: { type: integer, format: int64 } }
|
||||
responses:
|
||||
'200': { description: 贴标 PDF, content: { application/pdf: { schema: { type: string, format: binary } } } }
|
||||
'403': { description: 缺少客户查询权限 }
|
||||
'404': { description: 申请或文件不存在或不属于当前客户 }
|
||||
/api/platform/v1/last-leg/relabel-applications/{relabelNo}/shipping-label/{fileId}/download:
|
||||
get:
|
||||
summary: 平台查看客户上传的换标面单
|
||||
description: 权限 platform:overseas-warehouse:relabel-order:list;校验平台身份及申请的面单绑定关系。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: relabelNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: fileId, in: path, required: true, schema: { type: integer, format: int64, minimum: 1 } }
|
||||
responses:
|
||||
'200': { description: 面单文件, content: { application/pdf: { schema: { type: string, format: binary } }, image/jpeg: { schema: { type: string, format: binary } }, image/png: { schema: { type: string, format: binary } } } }
|
||||
'404': { description: 文件未绑定当前申请 }
|
||||
/api/merchant/v1/last-leg/relabel-applications/{relabelNo}/shipping-label/{fileId}/download:
|
||||
get:
|
||||
summary: 下载换标快递面单
|
||||
|
||||
Reference in New Issue
Block a user