|
|
|
@@ -6,6 +6,7 @@ import com.baiyue.common.core.api.ResultCode;
|
|
|
|
|
import com.baiyue.common.core.exception.BizException;
|
|
|
|
|
import com.baiyue.common.event.ContainerNumbers;
|
|
|
|
|
import com.baiyue.firstleg.client.PrintPdfClient;
|
|
|
|
|
import com.baiyue.firstleg.client.WarehouseMasterDataClient;
|
|
|
|
|
import com.baiyue.firstleg.dto.LoadingListDtos.PalletLabel;
|
|
|
|
|
import com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelGroup;
|
|
|
|
|
import com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelManifest;
|
|
|
|
@@ -34,12 +35,13 @@ import java.util.Locale;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
|
|
|
|
|
/** 散货托盘码是柜号与 FBA 仓维度的稳定业务标识;一件代发继续使用装箱打托事实。 */
|
|
|
|
|
/** 散货托盘码按真实柜号、FBA 地址内部编号和仓内序号组成;一件代发继续使用装箱打托事实。 */
|
|
|
|
|
@Service
|
|
|
|
|
public class LoadingPalletLabelService {
|
|
|
|
|
private static final BigDecimal PAGE_MM = new BigDecimal("100");
|
|
|
|
|
@Resource private LoadingPalletLabelMapper mapper;
|
|
|
|
|
@Resource private PrintPdfClient printClient;
|
|
|
|
|
@Resource private WarehouseMasterDataClient warehouseClient;
|
|
|
|
|
@Resource private ObjectMapper objectMapper;
|
|
|
|
|
@Value("${baiyue.security.internal-service-token}") private String internalToken;
|
|
|
|
|
|
|
|
|
@@ -58,11 +60,13 @@ public class LoadingPalletLabelService {
|
|
|
|
|
List<SourceRow> standard = sources.stream().filter(row -> !"ONE_CLICK_DROPSHIP".equals(row.getFulfillmentType()))
|
|
|
|
|
.filter(row -> "FBA".equals(row.getDestinationType()))
|
|
|
|
|
.filter(row -> Objects.requireNonNullElse(row.getPalletCount(), 0) > 0).toList();
|
|
|
|
|
if (standard.stream().anyMatch(row -> !StringUtils.hasText(row.getDestinationWarehouseCode()))) {
|
|
|
|
|
throw new BizException(ResultCode.CONFLICT, "散货明细缺少 FBA 仓编码,不能生成托盘码");
|
|
|
|
|
if (standard.stream().anyMatch(row -> row.getDestinationWarehouseId() == null
|
|
|
|
|
|| !StringUtils.hasText(row.getDestinationWarehouseCode()))) {
|
|
|
|
|
throw new BizException(ResultCode.CONFLICT, "散货明细缺少 FBA 仓信息,不能生成托盘码");
|
|
|
|
|
}
|
|
|
|
|
Map<Long, String> internalCodes = resolveInternalCodes(standard);
|
|
|
|
|
List<LabelRow> existing = mapper.labels(planId);
|
|
|
|
|
List<LabelRow> expected = expected(first, standard, containerNo);
|
|
|
|
|
List<LabelRow> expected = expected(first, standard, containerNo, internalCodes);
|
|
|
|
|
if (existing.isEmpty()) {
|
|
|
|
|
expected.forEach(row -> { if (mapper.insert(row) != 1) throw new BizException(ResultCode.CONFLICT, "托盘码生成失败,请刷新后重试"); });
|
|
|
|
|
existing = mapper.labels(planId);
|
|
|
|
@@ -91,19 +95,21 @@ public class LoadingPalletLabelService {
|
|
|
|
|
catch (FeignException | NoFallbackAvailableException exception) { throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "打印服务暂不可用,请稍后重试"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<LabelRow> expected(SourceRow plan, List<SourceRow> sources, String containerNo) {
|
|
|
|
|
Map<String, Integer> indexes = new LinkedHashMap<>();
|
|
|
|
|
private List<LabelRow> expected(SourceRow plan, List<SourceRow> sources, String containerNo,
|
|
|
|
|
Map<Long, String> internalCodes) {
|
|
|
|
|
Map<Long, Integer> indexes = new LinkedHashMap<>();
|
|
|
|
|
List<LabelRow> result = new ArrayList<>();
|
|
|
|
|
for (SourceRow source : sources) {
|
|
|
|
|
String code = source.getDestinationWarehouseCode().trim().toUpperCase(Locale.ROOT);
|
|
|
|
|
String warehouseCode = source.getDestinationWarehouseCode().trim().toUpperCase(Locale.ROOT);
|
|
|
|
|
String internalCode = internalCodes.get(source.getDestinationWarehouseId());
|
|
|
|
|
for (int local = 0; local < source.getPalletCount(); local++) {
|
|
|
|
|
int index = indexes.merge(code, 1, Integer::sum);
|
|
|
|
|
int index = indexes.merge(source.getDestinationWarehouseId(), 1, Integer::sum);
|
|
|
|
|
if (index > 999) throw new BizException(ResultCode.CONFLICT, "单柜同一 FBA 仓托盘数不能超过 999");
|
|
|
|
|
LabelRow row = new LabelRow(); row.setLabelId(IdWorker.getId()); row.setPlanId(plan.getPlanId());
|
|
|
|
|
row.setItemId(source.getItemId()); row.setAccountId(source.getAccountId()); row.setInboundId(source.getInboundId());
|
|
|
|
|
row.setInboundCode(source.getInboundCode()); row.setContainerNo(containerNo);
|
|
|
|
|
row.setDestinationWarehouseCode(code); row.setDestinationWarehouseName(source.getDestinationWarehouseName());
|
|
|
|
|
row.setPalletIndex(index); row.setPalletCode(containerNo + "-" + code + "-" + String.format("%03d", index));
|
|
|
|
|
row.setDestinationWarehouseCode(warehouseCode); row.setDestinationWarehouseName(source.getDestinationWarehouseName());
|
|
|
|
|
row.setPalletIndex(index); row.setPalletCode(containerNo + "-" + internalCode + "-" + String.format("%03d", index));
|
|
|
|
|
if (row.getPalletCode().length() > 128) throw new BizException(ResultCode.CONFLICT, "托盘码长度超过系统限制");
|
|
|
|
|
result.add(row);
|
|
|
|
|
}
|
|
|
|
@@ -111,6 +117,37 @@ public class LoadingPalletLabelService {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Map<Long, String> resolveInternalCodes(List<SourceRow> sources) {
|
|
|
|
|
Map<Long, String> codes = new LinkedHashMap<>();
|
|
|
|
|
Map<String, Long> owners = new LinkedHashMap<>();
|
|
|
|
|
for (SourceRow source : sources) {
|
|
|
|
|
long warehouseId = source.getDestinationWarehouseId();
|
|
|
|
|
if (codes.containsKey(warehouseId)) continue;
|
|
|
|
|
WarehouseMasterDataClient.Warehouse warehouse;
|
|
|
|
|
try {
|
|
|
|
|
ApiResponse<WarehouseMasterDataClient.Detail> response = warehouseClient.active(internalToken, 0L, warehouseId);
|
|
|
|
|
warehouse = response == null || !response.successful() || response.data() == null
|
|
|
|
|
? null : response.data().warehouse();
|
|
|
|
|
} catch (FeignException | NoFallbackAvailableException exception) {
|
|
|
|
|
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "仓库主数据暂不可用,请稍后重试");
|
|
|
|
|
}
|
|
|
|
|
if (warehouse == null || !"FBA".equals(warehouse.warehouseType())) {
|
|
|
|
|
throw new BizException(ResultCode.CONFLICT, "目的 FBA 仓不存在或未启用");
|
|
|
|
|
}
|
|
|
|
|
String internalCode = normalize(warehouse.internalCode());
|
|
|
|
|
if (internalCode == null) {
|
|
|
|
|
throw new BizException(ResultCode.CONFLICT, "FBA 仓“" + warehouse.warehouseCode() + "”未配置内部编号");
|
|
|
|
|
}
|
|
|
|
|
internalCode = internalCode.toUpperCase(Locale.ROOT);
|
|
|
|
|
Long owner = owners.putIfAbsent(internalCode, warehouseId);
|
|
|
|
|
if (owner != null && owner != warehouseId) {
|
|
|
|
|
throw new BizException(ResultCode.CONFLICT, "同柜 FBA 仓内部编号重复,请先修正仓库主数据");
|
|
|
|
|
}
|
|
|
|
|
codes.put(warehouseId, internalCode);
|
|
|
|
|
}
|
|
|
|
|
return codes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void requireSame(List<LabelRow> expected, List<LabelRow> actual) {
|
|
|
|
|
List<String> left = expected.stream().map(this::identity).toList();
|
|
|
|
|
List<String> right = actual.stream().map(this::identity).toList();
|
|
|
|
@@ -122,12 +159,19 @@ public class LoadingPalletLabelService {
|
|
|
|
|
Map<String, List<LabelRow>> grouped = rows.stream().collect(java.util.stream.Collectors.groupingBy(
|
|
|
|
|
LabelRow::getDestinationWarehouseCode, LinkedHashMap::new, java.util.stream.Collectors.toList()));
|
|
|
|
|
List<PalletLabelGroup> groups = grouped.values().stream().map(values -> new PalletLabelGroup(
|
|
|
|
|
values.get(0).getDestinationWarehouseCode(), values.get(0).getDestinationWarehouseName(), values.size(),
|
|
|
|
|
values.get(0).getDestinationWarehouseCode(), internalCode(values.get(0)),
|
|
|
|
|
values.get(0).getDestinationWarehouseName(), values.size(),
|
|
|
|
|
values.stream().map(this::label).toList())).toList();
|
|
|
|
|
String containerNo = rows.isEmpty() ? plan.getContainerNo() : rows.get(0).getContainerNo();
|
|
|
|
|
return new PalletLabelManifest(plan.getPlanId(), plan.getPlanNo(), containerNo, rows.size(), groups);
|
|
|
|
|
}
|
|
|
|
|
private PalletLabel label(LabelRow row) { return new PalletLabel(row.getLabelId(), row.getItemId(), row.getAccountId(), row.getInboundId(), row.getInboundCode(), row.getContainerNo(), row.getDestinationWarehouseCode(), row.getDestinationWarehouseName(), row.getPalletIndex(), row.getPalletCode()); }
|
|
|
|
|
private PalletLabel label(LabelRow row) { return new PalletLabel(row.getLabelId(), row.getItemId(), row.getAccountId(), row.getInboundId(), row.getInboundCode(), row.getContainerNo(), row.getDestinationWarehouseCode(), internalCode(row), row.getDestinationWarehouseName(), row.getPalletIndex(), row.getPalletCode()); }
|
|
|
|
|
private String internalCode(LabelRow row) {
|
|
|
|
|
String prefix = row.getContainerNo() + "-";
|
|
|
|
|
String suffix = "-" + String.format("%03d", row.getPalletIndex());
|
|
|
|
|
String palletCode = row.getPalletCode();
|
|
|
|
|
return palletCode.substring(prefix.length(), palletCode.length() - suffix.length());
|
|
|
|
|
}
|
|
|
|
|
private static String normalize(String value) { return value == null || value.isBlank() ? null : value.trim(); }
|
|
|
|
|
|
|
|
|
|
private ResponseEntity<byte[]> requirePdf(ResponseEntity<byte[]> response) {
|
|
|
|
|