demand: 新增查询批次详情接口-件数、重量、体积根据历史数据做扣减 批量扫描漏组批次/根据批次号扫描漏组批次始发网点无锡、张家港,南京市场部、南京分拨中心支持互换

committer: heyu
This commit is contained in:
aike 2025-08-07 09:28:01 +08:00
parent f693328b06
commit cfeda75ee7
3 changed files with 173 additions and 24 deletions

View File

@ -68,6 +68,15 @@ public class EmisTmsSiteBatchDtlController extends EmisBaseController
return getDataTable(list);
}
/**
* 查询批次详情-件数、重量体积根据历史数据做扣减
*/
// @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchDtl:getBatchDtl')")
@GetMapping("/getBatchDtl")
public AjaxResult getBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError {
return AjaxResult.success(emisTmsSiteBatchDtlService.getBatchDtl(emisTmsSiteBatchDtl));
}
/**
* 导出一级网点TMS组批次明细列表
*/

View File

@ -67,4 +67,11 @@ public interface IEmisTmsSiteBatchDtlService
* @return 结果
*/
public int deleteEmisTmsSiteBatchDtlById(Long id);
/**
*
* @param emisTmsSiteBatchDtl
* @return
*/
EmisTmsSiteBatchDtl getBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError;
}

View File

@ -1,27 +1,31 @@
/**
* @Project: emis
* @Title: EmisTmsSiteBatchDtlServiceImpl.java
* @author linfso
* @date 2024-03-01 08:54:57
* @Copyright: ShangHai Duta 2022 All rights reserved.
* @version v1.0
* @Description: <p> 一级网点TMS组批次明细 实体类 </p>
*/
/**
* @Project: emis
* @Title: EmisTmsSiteBatchDtlServiceImpl.java
* @author linfso
* @date 2024-03-01 08:54:57
* @Copyright: ShangHai Duta 2022 All rights reserved.
* @version v1.0
* @Description: <p> 一级网点TMS组批次明细 实体类 </p>
*/
package com.xdadan.erp.emis.service.impl;
import java.util.List;
import java.util.Objects;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollectionUtil;
import com.xdadan.erp.emis.domain.EmisTmsSiteBatch;
import com.xdadan.erp.emis.domain.EmisTransPlanRule;
import com.xdadan.erp.emis.domain.EmisWaybill;
import com.xdadan.erp.emis.domain.enumtype.EmisBizErrorType;
import com.xdadan.erp.emis.domain.exception.EmisBizError;
import com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMapper;
import com.xdadan.erp.emis.mapper.EmisTransPlanRuleMapper;
import com.xdadan.erp.emis.mapper.EmisWaybillMapper;
import com.xdadan.erp.emis.service.IEmisTmsSiteBatchService;
import jodd.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xdadan.erp.emis.domain.EmisTmsSiteBatchDtl;
@ -35,8 +39,7 @@ import com.xdadan.erp.emis.service.IEmisTmsSiteBatchDtlService;
* @date 2024-03-01 08:54:57
*/
@Service
public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlService
{
public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlService {
@Autowired
private EmisTmsSiteBatchDtlMapper emisTmsSiteBatchDtlMapper;
@ -49,6 +52,9 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
@Autowired
private IEmisTmsSiteBatchService emisTmsSiteBatchService;
@Autowired
private EmisTransPlanRuleMapper emisTransPlanRuleMapper;
/**
* 查询一级网点TMS组批次明细
*
@ -56,8 +62,7 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
* @return 一级网点TMS组批次明细
*/
@Override
public EmisTmsSiteBatchDtl selectEmisTmsSiteBatchDtlById(Long id)
{
public EmisTmsSiteBatchDtl selectEmisTmsSiteBatchDtlById(Long id) {
return emisTmsSiteBatchDtlMapper.selectEmisTmsSiteBatchDtlById(id);
}
@ -68,8 +73,7 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
* @return 一级网点TMS组批次明细
*/
@Override
public List<EmisTmsSiteBatchDtl> selectEmisTmsSiteBatchDtlList(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl)
{
public List<EmisTmsSiteBatchDtl> selectEmisTmsSiteBatchDtlList(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) {
return emisTmsSiteBatchDtlMapper.selectEmisTmsSiteBatchDtlList(emisTmsSiteBatchDtl);
}
@ -81,7 +85,8 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
*/
@Override
public int insertEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError {
EmisTmsSiteBatch oldSiteBatch = emisTmsSiteBatchMapper.selectTmsSiteBatchByBatchNo(emisTmsSiteBatchDtl.getBatchNo());
EmisTmsSiteBatch oldSiteBatch = emisTmsSiteBatchMapper
.selectTmsSiteBatchByBatchNo(emisTmsSiteBatchDtl.getBatchNo());
emisTmsSiteBatchService.checkSiteBatch(oldSiteBatch, emisTmsSiteBatchDtl);
return emisTmsSiteBatchDtlMapper.insertEmisTmsSiteBatchDtl(emisTmsSiteBatchDtl);
}
@ -93,8 +98,7 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
* @return 结果
*/
@Override
public int updateEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl)
{
public int updateEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) {
return emisTmsSiteBatchDtlMapper.updateEmisTmsSiteBatchDtl(emisTmsSiteBatchDtl);
}
@ -105,8 +109,7 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
* @return 结果
*/
@Override
public int deleteEmisTmsSiteBatchDtlByIds(Long[] ids)
{
public int deleteEmisTmsSiteBatchDtlByIds(Long[] ids) {
return emisTmsSiteBatchDtlMapper.deleteEmisTmsSiteBatchDtlByIds(ids);
}
@ -117,9 +120,139 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi
* @return 结果
*/
@Override
public int deleteEmisTmsSiteBatchDtlById(Long id)
{
public int deleteEmisTmsSiteBatchDtlById(Long id) {
return emisTmsSiteBatchDtlMapper.deleteEmisTmsSiteBatchDtlById(id);
}
@Override
public EmisTmsSiteBatchDtl getBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError {
// 参数校验
if (emisTmsSiteBatchDtl == null || emisTmsSiteBatchDtl.getParams() == null) {
throw new EmisBizError(EmisBizErrorType.FAIL, "参数不能为空");
}
String billCode = emisTmsSiteBatchDtl.getBillCode();
String startSiteCode = (String) emisTmsSiteBatchDtl.getParams().get("startSiteCode");
String nextSiteCode = (String) emisTmsSiteBatchDtl.getParams().get("nextSiteCode");
String supplierCode = (String) emisTmsSiteBatchDtl.getParams().get("supplierCode");
// 参数校验
if (StringUtils.isBlank(billCode)) {
throw new EmisBizError(EmisBizErrorType.FAIL, "运单号不能为空");
}
if (StringUtils.isBlank(startSiteCode)) {
throw new EmisBizError(EmisBizErrorType.FAIL, "起始网点编码不能为空");
}
if (StringUtils.isBlank(nextSiteCode)) {
throw new EmisBizError(EmisBizErrorType.FAIL, "下一网点编码不能为空");
}
// 查询运单信息
EmisWaybill emisWaybill = emisWaybillMapper.selectEmisWaybillByBillCode(billCode);
if (emisWaybill == null) {
return null;
}
// 创建返回结果对象
EmisTmsSiteBatchDtl result = new EmisTmsSiteBatchDtl();
result.setWaybillDetail(emisWaybill);
// 查询运输计划规则
EmisTransPlanRule emisTransPlanRule = new EmisTransPlanRule();
emisTransPlanRule.setStartSiteCode(startSiteCode);
emisTransPlanRule.setNextSiteCode(nextSiteCode);
emisTransPlanRule.setSupplierCode(supplierCode);
emisTransPlanRule.setLineCode(emisWaybill.getTransLineType());
emisTransPlanRule.setProductType(emisWaybill.getProductType());
List<EmisTransPlanRule> rules = emisTransPlanRuleMapper.checkTransPlanRule(emisTransPlanRule);
// 根据起始网点、下一网点和运单号查询TMS组批次
List<EmisTmsSiteBatch> existingBatches = emisTmsSiteBatchMapper.selectTmsSiteBatchBySiteAndBillCode(
startSiteCode,
nextSiteCode,
billCode,
null);
// 计算运单的件数、重量、体积
Integer waybillParcelQty = emisWaybill.getParcelQty() != null ? emisWaybill.getParcelQty() : 0;
BigDecimal waybillWeight = emisWaybill.getBillWeight() != null ? emisWaybill.getBillWeight()
: BigDecimal.ZERO;
BigDecimal waybillVolume = emisWaybill.getTotalVolume() != null ? emisWaybill.getTotalVolume()
: BigDecimal.ZERO;
// 如果没有现有批次,直接使用运单的原始值
if (CollectionUtil.isEmpty(existingBatches)) {
result.setBatchParcelQty(waybillParcelQty);
result.setBatchWeight(waybillWeight);
result.setBatchVolume(waybillVolume);
return result;
}
// 检查rule.supplierCode是否包含多个供应商编码(用逗号隔开)
if (CollectionUtil.isNotEmpty(rules) && StringUtils.isNotBlank(rules.get(0).getSupplierCode())
&& rules.get(0).getSupplierCode().contains(",")) {
// 将supplierCode按逗号分割成数组
String[] supplierCodes = rules.get(0).getSupplierCode().split(",");
List<String> supplierCodeList = Arrays.asList(supplierCodes);
// 检查现有批次中是否有supplierCode在rule.supplierCode内
boolean hasMatchingSupplier = existingBatches.stream()
.anyMatch(batch -> supplierCodeList.contains(batch.getSupplierCode()));
if (hasMatchingSupplier) {
// 找到匹配的批次,检查重量、体积、件数是否一致
EmisTmsSiteBatch matchingBatch = existingBatches.stream()
.filter(batch -> supplierCodeList.contains(batch.getSupplierCode()))
.findFirst()
.orElse(null);
if (Objects.nonNull(matchingBatch)) {
result.setBatchParcelQty(
matchingBatch.getTotalParcelQty() != null ? matchingBatch.getTotalParcelQty() : 0);
result.setBatchWeight(
matchingBatch.getTotalWeight() != null ? matchingBatch.getTotalWeight() : BigDecimal.ZERO);
result.setBatchVolume(
matchingBatch.getTotalVolume() != null ? matchingBatch.getTotalVolume() : BigDecimal.ZERO);
return result;
}
}
}
// 将existingBatches根据起始网点、下一网点、批次重量、件数、体积分组去重
Map<String, List<EmisTmsSiteBatch>> groupedBatches = existingBatches.stream()
.filter(Objects::nonNull) // 过滤空值
.collect(Collectors.groupingBy(batch -> {
// 构建分组键,包含所有相关字段
BigDecimal totalWeight = batch.getTotalWeight() != null ? batch.getTotalWeight() : BigDecimal.ZERO;
Integer totalParcelQty = batch.getTotalParcelQty() != null ? batch.getTotalParcelQty() : 0;
BigDecimal totalVolume = batch.getTotalVolume() != null ? batch.getTotalVolume() : BigDecimal.ZERO;
return batch.getStartSiteCode() + "_" + batch.getNextSiteCode() + "_" +
totalWeight + "_" + totalParcelQty + "_" + totalVolume;
}));
// 计算去重后的批次总重量、总件数、总体积
BigDecimal totalWeight = groupedBatches.values().stream()
.map(batchList -> batchList.get(0).getTotalWeight())
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
Integer totalParcelQty = groupedBatches.values().stream()
.map(batchList -> batchList.get(0).getTotalParcelQty())
.filter(Objects::nonNull)
.reduce(0, Integer::sum);
BigDecimal totalVolume = groupedBatches.values().stream()
.map(batchList -> batchList.get(0).getTotalVolume())
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 设置批次明细的件数、重量、体积(运单值减去已存在批次的总和)
result.setBatchParcelQty(Math.max(0, waybillParcelQty - totalParcelQty));
result.setBatchWeight(waybillWeight.subtract(totalWeight).max(BigDecimal.ZERO));
result.setBatchVolume(waybillVolume.subtract(totalVolume).max(BigDecimal.ZERO));
return result;
}
}