完善单元格合并逻辑

This commit is contained in:
2026-06-27 14:10:56 +08:00
parent 66d2b33db5
commit fa333ff557
4 changed files with 96 additions and 20 deletions

View File

@@ -142,6 +142,13 @@ public class ErpPurchasePlanController extends BaseController {
return R.ok(iErpPurchasePlanService.queryDeliveryList(planId));
}
/** 刷新到货:拿已上传卷号去 WMS 钢卷表实时复核,签收入库的自动翻为已到货(无需重传) */
@PutMapping("/{planId}/refreshArrival")
public R<Void> refreshArrival(@PathVariable Long planId) {
iErpPurchasePlanService.refreshProgress(planId);
return R.ok();
}
/** 某计划的到货上传批次(每次上传一条,可回看) */
@GetMapping("/{planId}/deliveryBatches")
public R<List<ErpPurchasePlanDeliveryBatchVo>> deliveryBatches(@PathVariable Long planId) {

View File

@@ -46,6 +46,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -340,7 +341,31 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
if (valid.isEmpty()) {
throw new ServiceException("未解析到有效到货数据,请检查文件内容或列名是否与模板一致");
}
// 2) kg→t 单位判定(文件级:单卷重量最大值超阈值视为 kg
// 2) 牌号校验:到货表里的牌号必须都在本计划「采购要求」的牌号范围内
List<ErpPurchasePlanItem> planItems = itemMapper.selectList(Wrappers.lambdaQuery(ErpPurchasePlanItem.class)
.eq(ErpPurchasePlanItem::getPlanId, planId));
Set<String> reqGrades = planItems.stream()
.map(it -> normCoil(it.getGrade()))
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
if (!reqGrades.isEmpty()) {
Set<String> badGrades = new LinkedHashSet<>();
for (ErpPurchasePlanDeliveryImportVo r : valid) {
String g = normCoil(r.getGrade());
if (StringUtils.isBlank(g)) {
badGrades.add("(空牌号)");
} else if (!reqGrades.contains(g)) {
badGrades.add(r.getGrade().trim());
}
}
if (!badGrades.isEmpty()) {
String allow = planItems.stream().map(ErpPurchasePlanItem::getGrade)
.filter(StringUtils::isNotBlank).map(String::trim).distinct().collect(Collectors.joining(""));
throw new ServiceException("到货表中的牌号 [" + String.join("", badGrades)
+ "] 不在本计划采购要求的牌号范围内(仅允许:" + allow + "),请核对后重新上传");
}
}
// 3) kg→t 单位判定(文件级:单卷重量最大值超阈值视为 kg
BigDecimal maxCoil = valid.stream()
.map(ErpPurchasePlanDeliveryImportVo::getCoilWeight)
.filter(w -> w != null)
@@ -348,7 +373,7 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
.orElse(BigDecimal.ZERO);
boolean kgConverted = maxCoil.compareTo(KG_THRESHOLD) > 0;
// 3) 卷号去 WMS 钢卷表校验:存在且 data_type<>10 即视为已实际到货入库
// 4) 卷号去 WMS 钢卷表校验:存在且 data_type<>10 即视为已实际到货入库
List<String> uploadCoilNos = valid.stream()
.map(ErpPurchasePlanDeliveryImportVo::getCoilNo)
.filter(StringUtils::isNotBlank)
@@ -358,13 +383,13 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
: baseMapper.selectExistingSupplierCoilNos(uploadCoilNos).stream()
.map(this::normCoil).collect(Collectors.toSet());
// 4) 先建批次(每次上传存档,可随时回看)
// 5) 先建批次(每次上传存档,可随时回看)
ErpPurchasePlanDeliveryBatch batch = new ErpPurchasePlanDeliveryBatch();
batch.setPlanId(planId);
batch.setFileName(StringUtils.isNotBlank(fileName) ? fileName : "到货表");
deliveryBatchMapper.insert(batch);
// 5) 合并单元格向下填充 + 单位换算 + 落库 + WMS到货标记
// 6) 合并单元格向下填充 + 单位换算 + 落库 + WMS到货标记
String lastTruckNo = null;
BigDecimal lastTruckWeight = null;
Integer lastPieceCount = null;
@@ -401,10 +426,10 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
matched++;
}
}
// 6) 汇总刷新进度
// 7) 汇总刷新进度
refreshProgress(planId);
// 7) 回填批次统计行数、WMS确认到货卷数、上传后进度快照
// 8) 回填批次统计行数、WMS确认到货卷数、上传后进度快照
ErpPurchasePlan after = baseMapper.selectById(planId);
batch.setRowCount(count);
batch.setMatchedCount(matched);
@@ -492,13 +517,29 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService {
if (plan == null) {
return;
}
// 到货 = 累计所有上传批次中 WMS 已确认到货(arrived=1)的卷
// 到货 = 累计所有上传批次中 WMS 已确认到货的卷
// 每次刷新都拿卷号去 WMS 钢卷表实时复核:之前未到、后来签收入库的,这里会自动翻成已到货,无需重新上传。
List<ErpPurchasePlanDelivery> deliveries = deliveryMapper.selectList(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class)
.eq(ErpPurchasePlanDelivery::getPlanId, planId));
List<String> coilNos = deliveries.stream()
.map(ErpPurchasePlanDelivery::getCoilNo)
.filter(StringUtils::isNotBlank)
.map(String::trim)
.collect(Collectors.toList());
Set<String> wmsArrivedSet = coilNos.isEmpty() ? new HashSet<>()
: baseMapper.selectExistingSupplierCoilNos(coilNos).stream()
.map(this::normCoil).collect(Collectors.toSet());
int arrivedCount = 0;
BigDecimal arrivedWeight = BigDecimal.ZERO;
for (ErpPurchasePlanDelivery d : deliveries) {
if (d.getArrived() != null && d.getArrived() == 1) {
int nowArrived = StringUtils.isNotBlank(d.getCoilNo()) && wmsArrivedSet.contains(normCoil(d.getCoilNo())) ? 1 : 0;
// 状态有变化才回写,减少无谓更新
if (d.getArrived() == null || d.getArrived() != nowArrived) {
d.setArrived(nowArrived);
deliveryMapper.updateById(d);
}
if (nowArrived == 1) {
arrivedCount++;
arrivedWeight = arrivedWeight.add(d.getCoilWeight() == null ? BigDecimal.ZERO : d.getCoilWeight());
}