This commit is contained in:
2026-08-27 11:07:57 +08:00
parent b4c46280de
commit 4612181ab0
19 changed files with 424 additions and 68 deletions
@@ -1,6 +1,7 @@
package com.baiyue.firstleg.client;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.GetMapping;
@@ -16,8 +17,17 @@ import java.util.List;
url = "${baiyue.clients.warehouse.url:}", path = "/internal/warehouse/v1")
public interface WarehousePalletLocationClient {
@GetMapping("/pallets/snapshots")
ApiResponse<List<PalletSnapshot>> palletSnapshots(
ApiResponse<PageResult<PalletSnapshot>> palletSnapshots(
@RequestHeader("X-Internal-Service-Token") String token,
@RequestParam("warehouseId") long warehouseId,
@RequestParam("page") long page,
@RequestParam("size") long size,
@RequestParam(value = "keyword", required = false) String keyword);
@GetMapping("/pallets/{palletId}/snapshot")
ApiResponse<PalletSnapshot> palletSnapshot(
@RequestHeader("X-Internal-Service-Token") String token,
@org.springframework.web.bind.annotation.PathVariable("palletId") long palletId,
@RequestParam("warehouseId") long warehouseId);
@PostMapping("/pallet-locations/reservations")
@@ -4,6 +4,7 @@ import jakarta.annotation.Resource;
import com.baiyue.common.audit.BusinessAudit;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.common.security.AuthenticatedUser;
@@ -18,8 +19,12 @@ import com.baiyue.firstleg.service.MeasurementSubmissionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -33,10 +38,10 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/** 平台后台入库测量录入、提交和 OCR 重量结果维护接口。 */
@Tag(name = "平台入库测量", description = "维护测量草稿、箱规明细和可追溯 OCR 重量结果。")
@Validated
@RestController
@RequestMapping("/api/platform/v1/first-leg/inbounds/{inboundId}")
public class PlatformInboundMeasurementController {
@@ -56,16 +61,19 @@ public class PlatformInboundMeasurementController {
}
@Operation(summary = "查询称重可选托盘快照",
description = "按入库单所属仓库返回未删除的托盘只读快照,不校验托盘状态或占用资格。")
description = "按入库单所属仓库分页返回当前有效托盘候选,支持编码或类型关键词;托盘可复用,不按预占或占用过滤。")
@GetMapping("/weight-pallet-options")
@PreAuthorize("hasAnyAuthority('platform:firstleg:inbound:measure:view',"
+ " 'platform:firstleg:inbound:weight:edit')")
public ApiResponse<List<InboundMeasurementResponses.PalletSnapshot>> weightPalletOptions(
public ApiResponse<PageResult<InboundMeasurementResponses.PalletSnapshot>> weightPalletOptions(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam long tenantId,
@PathVariable long inboundId) {
@PathVariable long inboundId,
@RequestParam(defaultValue = "1") @Min(1) long page,
@RequestParam(defaultValue = "20") @Min(1) @Max(100) long size,
@RequestParam(required = false) @Size(max = 50) String keyword) {
requirePlatformTenant(user, tenantId);
return ApiResponse.success(service.weightPalletOptions(tenantId, inboundId));
return ApiResponse.success(service.weightPalletOptions(tenantId, inboundId, page, size, keyword));
}
@BusinessAudit(event = "INBOUND_MEASUREMENT_DRAFT_SAVE", resourceType = "INBOUND",
@@ -4,6 +4,7 @@ import jakarta.annotation.Resource;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.client.OrderCargoClient;
import com.baiyue.firstleg.client.MeasurementImageClient;
@@ -73,14 +74,16 @@ public class InboundMeasurementService {
return toDetail(inbound, measurement, items, weights, review, declaration);
}
public List<InboundMeasurementResponses.PalletSnapshot> weightPalletOptions(
long tenantId, long inboundId) {
public PageResult<InboundMeasurementResponses.PalletSnapshot> weightPalletOptions(
long tenantId, long inboundId, long page, long size, String keyword) {
InboundOrderEntity inbound = requireInbound(tenantId, inboundId);
return loadPalletSnapshots(inbound).stream()
PageResult<WarehousePalletLocationClient.PalletSnapshot> source =
loadPalletSnapshotPage(inbound, page, size, keyword);
return new PageResult<>(source.records().stream()
.map(snapshot -> new InboundMeasurementResponses.PalletSnapshot(
snapshot.palletId(), snapshot.palletCode(), snapshot.palletType(),
snapshot.capacityCbm(), snapshot.tareWeightKg()))
.toList();
.toList(), source.page(), source.size(), source.total(), source.pages());
}
@Transactional
@@ -175,11 +178,8 @@ public class InboundMeasurementService {
if (repository.findWeightByFile(tenantId, inboundId, request.fileId()) != null) {
throw new BizException(ResultCode.CONFLICT, "同一称重图片不能重复计重");
}
WarehousePalletLocationClient.PalletSnapshot pallet = loadPalletSnapshots(inbound).stream()
.filter(snapshot -> snapshot.palletId() == request.palletId())
.findFirst()
.orElseThrow(() -> new BizException(ResultCode.VALIDATION_FAILED,
"所选托盘不属于当前入库仓库或已被删除"));
WarehousePalletLocationClient.PalletSnapshot pallet = loadPalletSnapshot(
inbound, request.palletId());
validatePalletSnapshot(pallet);
String unit = rawOcrUnit(request.ocrWeightUnit());
InboundWeightResultEntity weight = new InboundWeightResultEntity();
@@ -527,23 +527,43 @@ public class InboundMeasurementService {
weight.getAdjustedAt(), weight.getConfirmedBy(), weight.getConfirmedAt(), weight.getVersion());
}
private List<WarehousePalletLocationClient.PalletSnapshot> loadPalletSnapshots(
InboundOrderEntity inbound) {
private PageResult<WarehousePalletLocationClient.PalletSnapshot> loadPalletSnapshotPage(
InboundOrderEntity inbound, long page, long size, String keyword) {
if (inbound.getWarehouseId() == null || inbound.getWarehouseId() <= 0) {
throw new BizException(ResultCode.CONFLICT, "入库单未绑定有效仓库,无法选择称重托盘");
}
try {
ApiResponse<List<WarehousePalletLocationClient.PalletSnapshot>> response =
warehousePallets.palletSnapshots(internalToken, inbound.getWarehouseId());
ApiResponse<PageResult<WarehousePalletLocationClient.PalletSnapshot>> response =
warehousePallets.palletSnapshots(internalToken, inbound.getWarehouseId(), page, size, keyword);
if (response == null || !response.successful() || response.data() == null) {
String message = response == null || !StringUtils.hasText(response.message())
? "托盘快照查询失败" : response.message();
? "托盘候选查询失败" : response.message();
throw new BizException(response == null ? ResultCode.SERVICE_UNAVAILABLE
: ResultCode.of(response.code()), message);
}
return response.data();
} catch (FeignException exception) {
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "仓库服务暂不可用,无法查询托盘快照");
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "仓库服务暂不可用,无法查询托盘候选");
}
}
private WarehousePalletLocationClient.PalletSnapshot loadPalletSnapshot(
InboundOrderEntity inbound, long palletId) {
if (inbound.getWarehouseId() == null || inbound.getWarehouseId() <= 0) {
throw new BizException(ResultCode.CONFLICT, "入库单未绑定有效仓库,无法选择称重托盘");
}
try {
ApiResponse<WarehousePalletLocationClient.PalletSnapshot> response = warehousePallets.palletSnapshot(
internalToken, palletId, inbound.getWarehouseId());
if (response == null || !response.successful() || response.data() == null) {
String message = response == null || !StringUtils.hasText(response.message())
? "所选托盘当前不可用于该入库仓库" : response.message();
throw new BizException(response == null ? ResultCode.SERVICE_UNAVAILABLE
: ResultCode.of(response.code()), message);
}
return response.data();
} catch (FeignException exception) {
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "仓库服务暂不可用,无法校验托盘资格");
}
}