diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCommonController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCommonController.java index efa8f6d73..97b15f8f2 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCommonController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCommonController.java @@ -751,6 +751,30 @@ public class EmisCommonController extends EmisBaseController } + /** + * 处理历史虚拟单 + * @return + */ + @GetMapping("/handleHistoryVirtualWaybill") + public AjaxResult handleHistoryVirtualWaybill(){ + String lockKey="handleHistoryVirtualWaybill"; + log.info("handleHistoryVirtualWaybill start"); + + // 加锁查询 + redissonService.lock(lockKey,300); + try{ + emisWaybillService.handleHistoryVirtualWaybill(); + }catch(Exception ex){ + ex.printStackTrace(); + log.error("handleHistoryVirtualWaybill exception:"+ex.getMessage()); + } + log.info("handleHistoryVirtualWaybill end"); + + redissonService.unlock(lockKey); + return AjaxResult.success("发送成功"); + + } + /** * 自动出账触发 * @return diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCountryController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCountryController.java index aa26cfca8..251dcf99c 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCountryController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCountryController.java @@ -11,6 +11,7 @@ package com.xdadan.erp.web.emis; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -152,4 +153,8 @@ public class EmisCountryController extends EmisBaseController { return toAjax(emisCountryService.deleteEmisCountryByIds(ids)); } + + public static void main(String[] args) { + List list = new ArrayList(); + } } diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchController.java index 276b50297..b49685b38 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchController.java @@ -15,7 +15,7 @@ import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletResponse; -import com.alibaba.fastjson.JSONObject; +import com.xdadan.erp.emis.domain.exception.EmisBizError; import com.xdadan.erp.emis.utils.WaybillHelper; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -171,14 +171,24 @@ public class EmisTmsSiteBatchController extends EmisBaseController return toAjax(emisTmsSiteBatchService.insertEmisTmsSiteBatch(emisTmsSiteBatch)); } + + /** + * 新增一级网点TMS组批次 + */ + @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatch:addAll')") + @Log(title = "一级网点TMS组批次", businessType = BusinessType.INSERT) + @PostMapping("/addAll") + public AjaxResult addAll(@RequestBody EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError { + return toAjax(emisTmsSiteBatchService.addAll(emisTmsSiteBatch)); + } + /** * 修改一级网点TMS组批次 */ @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatch:edit')") @Log(title = "一级网点TMS组批次", businessType = BusinessType.UPDATE) @PutMapping - public AjaxResult edit(@RequestBody EmisTmsSiteBatch emisTmsSiteBatch) - { + public AjaxResult edit(@RequestBody EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError { return toAjax(emisTmsSiteBatchService.updateEmisTmsSiteBatch(emisTmsSiteBatch)); } diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchDtlController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchDtlController.java index 108d6aa29..327bb51e5 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchDtlController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchDtlController.java @@ -13,7 +13,11 @@ package com.xdadan.erp.web.emis; import java.util.List; import javax.servlet.http.HttpServletResponse; + +import com.alibaba.fastjson.JSONObject; +import com.xdadan.erp.emis.domain.exception.EmisBizError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -93,8 +97,7 @@ public class EmisTmsSiteBatchDtlController extends EmisBaseController @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchDtl:add')") @Log(title = "一级网点TMS组批次明细", businessType = BusinessType.INSERT) @PostMapping - public AjaxResult add(@RequestBody EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) - { + public AjaxResult add(@RequestBody EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError { return toAjax(emisTmsSiteBatchDtlService.insertEmisTmsSiteBatchDtl(emisTmsSiteBatchDtl)); } diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTransPlanRuleController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTransPlanRuleController.java index 03b269140..84cd5e2bc 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTransPlanRuleController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTransPlanRuleController.java @@ -35,10 +35,10 @@ public class EmisTransPlanRuleController extends EmisBaseController { private IEmisTransPlanRuleService emisTransPlanRuleService; @GetMapping("/listSimple") - @JacksonFilter(include = { - "transType", "productTypeName", "supplierCode", "supplierName" - }, value = EmisTransPlanRule.class, type = JacksonFilter.JscksonFilterType.RESPONSE) - @PreAuthorize("@ss.hasPermi('emis:emisTransPlanRule:listSimple')") +// @JacksonFilter(include = { +// "transType", "productTypeName", "supplierCode", "supplierName" +// }, value = EmisTransPlanRule.class, type = JacksonFilter.JscksonFilterType.RESPONSE) +// @PreAuthorize("@ss.hasPermi('emis:emisTransPlanRule:listSimple')") public TableDataInfo listSimple(EmisTransPlanRule emisTransPlanRule) { startPage(); List list = emisTransPlanRuleService.selectSupplierInfoByConditions(emisTransPlanRule); diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisWaybillController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisWaybillController.java index 12866de8d..7006ab32e 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisWaybillController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisWaybillController.java @@ -108,6 +108,17 @@ public class EmisWaybillController extends EmisBaseController return AjaxResult.success("操作成功", emisBaseService.checkWaybillIsExists(billCode)); } + /** + * 查询主单号列表 + */ + @GetMapping(value = "/getMasterEmisWaybills") + public TableDataInfo getMasterEmisWaybills(EmisWaybill emisWaybill){ + startPage(); + emisWaybill.getParams().put("privSiteCode", getLoginUser().getUser().getOwnerSiteCode()); + List list = emisWaybillService.selectMasterEmisWaybills(emisWaybill); + return getDataTable(list); + } + /** * 获取运单信息 */ diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatch.java b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatch.java index 9fa781163..8c4d3740a 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatch.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatch.java @@ -114,6 +114,7 @@ public class EmisTmsSiteBatch extends BaseEntity private String blEntering; private List batchDtlList; + private List loadingList; } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybill.java b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybill.java index 73bd785d6..8d316a266 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybill.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybill.java @@ -312,8 +312,12 @@ public class EmisWaybill extends BaseEntity /* 是否超长 */ private String blOverLong; - /* 是否虚拟单 */ + /* 是否虚拟单.0:否,1:是 */ private String blVirtual; + /* 主单号 */ + private String masterBillCode; + /* 虚拟单备注 */ + private String virtualRemark; /* 是否付款 */ private String blBill; @@ -404,6 +408,10 @@ public class EmisWaybill extends BaseEntity private String takePieceEmployeeCode; /* 发件网点代码 */ private String sendSiteCode; + /* 始发网点代码 */ + private String startSiteCode; + /* 始发网点名称 */ + private String startSiteName; /* 发件财务中心代码 */ private String sendCenterCode; /* 发货时间 - 取本地时间 */ diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybillAjustApply.java b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybillAjustApply.java index d4c33611a..e1ec1a602 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybillAjustApply.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisWaybillAjustApply.java @@ -46,6 +46,8 @@ public class EmisWaybillAjustApply extends BaseEntity private String applyManCode; /* 申请站点代码 */ private String applySiteCode; + /* 始发网点代码 */ + private String startSiteCode; /* 申请财务中心编码 */ private String applyFinanceCenterCode; /* 申请时间 */ diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/WaybillOrder.java b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/WaybillOrder.java index 7432882b2..f36fe3f16 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/WaybillOrder.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/WaybillOrder.java @@ -212,6 +212,10 @@ public class WaybillOrder implements Serializable { /* 发件网点代码 */ private String sendSiteCode; + /* 始发网点代码 */ + private String startSiteCode; + /* 始发网点名称 */ + private String startSiteName; /* 派件人代码 */ private String dispatchManCode; @@ -389,6 +393,12 @@ public class WaybillOrder implements Serializable { /* 箱量 */ private String boxQuantity; + /* 是否虚拟单 0:否,1:是,默认为0 */ + private String blVirtual; + /* 主单号 */ + private String masterBillCode; + /* 虚拟单备注 */ + private String virtualRemark; // 销售,回款 // private String salesmenName; @@ -446,6 +456,8 @@ public class WaybillOrder implements Serializable { voItem.setDeclareGoodsList(declareGoodsCvt.cvtToVoList(dbDecareGoodsList)); voItem.setDeclareAttachmentList(declareAttachmentCvt.cvtToVoList(dbDeclareAttachmentList)); + voItem.setStartSiteCode(dbWaybill.getStartSiteCode()); + voItem.setStartSiteName(dbWaybill.getStartSiteName()); // 收件人 Reciever reciever = new Reciever(); @@ -516,6 +528,10 @@ public class WaybillOrder implements Serializable { voItem.setPrintManName(dbWaybill.getPrintManName()); voItem.setPrintSiteName(dbWaybill.getPrintSiteName()); + voItem.setBlVirtual(dbWaybill.getBlVirtual()); + voItem.setMasterBillCode(dbWaybill.getMasterBillCode()); + voItem.setVirtualRemark(dbWaybill.getVirtualRemark()); + voItem.setOpenId(dbWaybill.getOpenId()); @@ -732,6 +748,11 @@ public class WaybillOrder implements Serializable { dbWaybill.setUserId(this.getUserId()); dbWaybill.setCustomerCode(this.getCustomerCode()); + // 虚拟单 + dbWaybill.setBlVirtual(this.getBlVirtual()); + dbWaybill.setMasterBillCode(this.getMasterBillCode()); + dbWaybill.setVirtualRemark(this.getVirtualRemark()); + // dbWaybill.setCustomerName(this.getCustomerName()); // dbWaybill.setReceiveCustomerCode(this.getReceiveCustomerCode()); // dbWaybill.setReceiveCustomerName(this.getReceiveCustomerName()); @@ -867,6 +888,8 @@ public class WaybillOrder implements Serializable { // dbWaybill.setRegisterManCode(this.getRegisterManCode()); dbWaybill.setTakePieceEmployeeCode(this.getTakePieceEmployeeCode()); dbWaybill.setSendSiteCode(this.getSendSiteCode()); + dbWaybill.setStartSiteCode(this.getStartSiteCode()); + dbWaybill.setStartSiteName(this.getStartSiteName()); dbWaybill.setSendDate(this.getSendDate()); dbWaybill.setSendSiteName(this.getSendSiteName()); diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTransPlanRuleMapper.java b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTransPlanRuleMapper.java index 5adeb04bb..004cd7f9c 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTransPlanRuleMapper.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTransPlanRuleMapper.java @@ -104,10 +104,11 @@ public interface EmisTransPlanRuleMapper { * 根据产品类型名称查询产品类型信息 * * @param productTypeNames 产品类型名称列表 - * @param code 线路编码 + * @param code 线路编码 * @return 产品类型信息列表 */ - public List> selectProductTypeInfoByNamesAndLineCode(@Param("productTypeNames") List productTypeNames, @Param("lineCode") String code); + public List> selectProductTypeInfoByNamesAndLineCode( + @Param("productTypeNames") List productTypeNames, @Param("lineCode") String code); /** * 根据网点名称查询网点信息 @@ -139,4 +140,30 @@ public interface EmisTransPlanRuleMapper { * @return */ List selectEmisTransPlanRuleByLineCodes(@Param("lineCodes") List lineCodes); + + /** + * + * @param emisTransPlanRule + * @return + */ + List selectRulesForAllScan(EmisTransPlanRule emisTransPlanRule); + + /** + * 分页查询供应商线路规划(多线程用) + * + * @param emisTransPlanRule 查询条件 + * @param offset 偏移量 + * @param limit 每页数量 + * @return 供应商线路规划集合 + */ + List selectRulesForAllScanPaged(@Param("emisTransPlanRule") EmisTransPlanRule emisTransPlanRule, + @Param("offset") int offset, @Param("limit") int limit); + + /** + * 查询总数(多线程分页用) + * + * @param emisTransPlanRule 查询条件 + * @return 总数 + */ + int countForAllScan(EmisTransPlanRule emisTransPlanRule); } \ No newline at end of file diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillMapper.java b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillMapper.java index 2792a8f40..d8ac6c2b8 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillMapper.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillMapper.java @@ -32,6 +32,8 @@ public interface EmisWaybillMapper extends BaseMapper public EmisWaybill selectEmisWaybillByBillCode(@Param("billCode")String billCode); + public EmisWaybill selectMasterWaybillByBillCode(@Param("billCode")String billCode); + public List selectWaybillStatByEmpCode(@Param("empCode")String empCode,@Param("waybillStatus")String waybillStatus); public List selectCommissionStatData(EmisWaybill emisWaybill); @@ -104,6 +106,8 @@ public interface EmisWaybillMapper extends BaseMapper @DataAuditLog(operateType= OperateType.UPDATE,serviceClass=EmisWaybillServiceImpl.class) public int updateEmisWaybill(EmisWaybill emisWaybill); + public int updateVirtualWaybill(EmisWaybill emisWaybill); + /** * 删除 @@ -304,4 +308,20 @@ public interface EmisWaybillMapper extends BaseMapper EmisWaybill selectCustEmisWaybillByBillCode(EmisWaybill queryWaybill); EmisWaybill selectEmisWaybillByCustOrderId(String custOrderId); + + /** + * 查询主单号列表 + * + * @param emisWaybill + * @return + */ + List selectMasterEmisWaybills(EmisWaybill emisWaybill); + + /** + * + * @param offset + * @param pageSize + * @return + */ + List selectHistoryVirtualWaybill(@Param("offset")int offset, @Param("pageSize")int pageSize); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillProblemInfoMapper.java b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillProblemInfoMapper.java index c19b4a7da..be638e97b 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillProblemInfoMapper.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisWaybillProblemInfoMapper.java @@ -80,4 +80,27 @@ public interface EmisWaybillProblemInfoMapper extends BaseMapper selectEmisWaybillProblemInfoByBillCodes(@Param("billCodes") List billCodes); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/EmisBaseService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/EmisBaseService.java index a83f1b4d5..b39f011a9 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/EmisBaseService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/EmisBaseService.java @@ -21,6 +21,7 @@ package com.xdadan.erp.emis.service; import com.xdadan.erp.emis.domain.enumtype.*; import com.xdadan.erp.emis.domain.exception.EmisBizError; import com.xdadan.erp.emis.domain.stat.ScanStatInfoDtl; + import com.xdadan.erp.emis.domain.vo.scan.ScanInfo; import com.xdadan.erp.emis.mapper.*; import com.xdadan.erp.emis.service.sms.AliyunSMSService; import com.xdadan.erp.emis.service.sms.Sms253Service; @@ -84,6 +85,9 @@ public class EmisBaseService { @Autowired protected EmisWaybillMapper emisWaybillMapper; + @Autowired + private IEmisCommissionProfitService emisCommissionProfitService; + @Autowired protected EmisWaybillFeeitemMapper emisWaybillFeeitemMapper; @@ -131,6 +135,8 @@ public class EmisBaseService { @Autowired private EmisWaybillProblemInfoMapper emisWaybillProblemInfoMapper; + @Autowired + private IEmisWaybillProblemInfoService emisWaybillProblemInfoService; @Autowired @@ -181,12 +187,12 @@ public class EmisBaseService { @Autowired private EmisWaybillBatchStatusMapper emisWaybillBatchStatusMapper; + @Autowired + private IEmisTmsScanRecordService emisTmsScanRecordService; + @Autowired private EmisTmsSiteBatchMissRecordMapper emisTmsSiteBatchMissRecordMapper; - private int totalBatchStatusRecords = 0; - private int totalMissRecords = 0; - private static SysUser emptySysUser = new SysUser(); static { @@ -2838,6 +2844,19 @@ public class EmisBaseService { } } + if (StringUtil.isNotBlank(waybill.getVirtualRemark())) { + // 取每个虚拟单号的后六位,用逗号拼接 + String[] codes = waybill.getVirtualRemark().split(","); + String shortCodes = Arrays.stream(codes) + .filter(s -> s != null && s.length() >= 6) + .map(s -> s.substring(s.length() - 6)) + .collect(Collectors.joining(",")); + remark = remark + " " + "该运单为主单,对应虚拟单为" + shortCodes; + } + // if (StringUtil.isNotBlank(waybill.getMasterBillCode())) { + // remark = remark + " " + "该运单为虚拟单,对应主单为" + waybill.getMasterBillCode(); + // } + order.put("remark",remark); // 备注拆分为多行 List remarkList=WaybillHelper.wrap(remark,40); @@ -3824,6 +3843,36 @@ public class EmisBaseService { } + /** + * 判断是否已确认账单 + * @param emisWaybill + * @return + */ + public boolean isConfirm(EmisWaybill emisWaybill) { + + // 财务已确认账单不允许修改 + List emisSettleSubBillList = getSettleSubBillListByBillCode(emisWaybill.getBillCode()); + if (CollectionUtil.isEmpty(emisSettleSubBillList)) { + return false; + } + EmisSettleSubBill emisSettleSubBill = emisSettleSubBillList.get(0); + if ("1".equals(emisSettleSubBill.getBlConfirmCenter())) { + // 财务确认出账明细锁账 + emisWaybill.setLockReason("财务已确认,不允许修改"); + return true; + } + + // 财务或业务确认不出账不允许修改 + if ("2".equals(emisSettleSubBill.getBlConfirmCenter()) + || "2".equals(emisSettleSubBill.getBlConfirmSite()) + ) { + // 财务确认出账明细锁账 + emisWaybill.setLockReason("已确认不出账,不允许修改"); + return true; + } + return false; + } + /** * 计算预估到达时间,根据产品时效来计算 * @param sendDate 开单时间 @@ -4066,31 +4115,75 @@ public class EmisBaseService { } } - /** - * 深度复制节点及其子节点 - * - * @param source 源节点 - * @return 复制后的新节点 - */ - private EmisTransPlanRule deepCopyNode(EmisTransPlanRule source) { - if (source == null) { - return null; - } + /** + * 深度复制节点及其子节点 + * + * @param source 源节点 + * @return 复制后的新节点 + */ + private EmisTransPlanRule deepCopyNode(EmisTransPlanRule source) { + return deepCopyNode(source, new HashSet<>(), new ArrayList<>()); + } - EmisTransPlanRule copy = new EmisTransPlanRule(); - BeanUtils.copyProperties(source, copy); + /** + * 深度复制节点及其子节点(带循环引用检测) + * + * @param source 源节点 + * @param visitedIds 已访问的节点ID集合 + * @param visitPath 访问路径,用于记录循环引用的路径 + * @return 复制后的新节点 + */ + private EmisTransPlanRule deepCopyNode(EmisTransPlanRule source, Set visitedIds, List visitPath) { + if (source == null) { + return null; + } - // 递归复制子节点 - if (source.getChildren() != null) { - List copiedChildren = new ArrayList<>(); - for (EmisTransPlanRule child : source.getChildren()) { - copiedChildren.add(deepCopyNode(child)); - } - copy.setChildren(copiedChildren); - } + // 检查循环引用 + if (visitedIds.contains(source.getId())) { + // 找到循环引用的起始位置 + int cycleStartIndex = visitPath.indexOf(source.getId()); + if (cycleStartIndex != -1) { + // 构建循环路径 + List cyclePath = visitPath.subList(cycleStartIndex, visitPath.size()); + cyclePath.add(source.getId()); - return copy; - } + // 构建详细的错误信息 + StringBuilder errorMsg = new StringBuilder(); + errorMsg.append("检测到循环引用!循环路径:"); + for (int i = 0; i < cyclePath.size(); i++) { + if (i > 0) { + errorMsg.append(" -> "); + } + errorMsg.append("节点ID:").append(cyclePath.get(i)); + } + errorMsg.append("\n循环引用发生在节点ID:").append(source.getId()); + errorMsg.append(",该节点在路径中重复出现"); + + throw new RuntimeException(errorMsg.toString()); + } + } + + // 添加到已访问集合和路径中 + visitedIds.add(source.getId()); + visitPath.add(source.getId()); + + EmisTransPlanRule copy = new EmisTransPlanRule(); + BeanUtils.copyProperties(source, copy); + + // 递归复制子节点 + if (source.getChildren() != null) { + List copiedChildren = new ArrayList<>(); + for (EmisTransPlanRule child : source.getChildren()) { + copiedChildren.add(deepCopyNode(child, visitedIds, visitPath)); + } + copy.setChildren(copiedChildren); + } + + // 从路径中移除当前节点(回溯) + visitPath.remove(visitPath.size() - 1); + + return copy; + } /** * 检查月结客户首次签约日期,首次签约之前开的不允许修改 @@ -4145,9 +4238,11 @@ public class EmisBaseService { } emisTmsSiteBatchMissMapper.deleteByBillCodes(billCodes); long startTime = System.currentTimeMillis(); - int totalProcessed = 0; + int totalProcessed = emisWaybills.size(); int successCount = 0; int failCount = 0; + int totalBatchStatusRecords = 0; + int totalMissRecords = 0; List failedBillCodes = new ArrayList<>(); // 获取所有线路规划 @@ -4169,7 +4264,7 @@ public class EmisBaseService { // 批量插入运单组批次状态记录 if (!result.getBatchStatusList().isEmpty()) { -// emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(result.getBatchStatusList()); + emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(result.getBatchStatusList()); totalBatchStatusRecords += result.getBatchStatusList().size(); } @@ -4190,7 +4285,7 @@ public class EmisBaseService { long processTime = endTime - startTime; // 保存扫描记录 - saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes); + saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes,totalBatchStatusRecords,totalMissRecords); log.info( "Auto scan completed. Total processed: {}, Success: {}, Failed: {}, Time taken: {}ms, Batch status records: {}, Miss records: {}", @@ -4205,7 +4300,7 @@ public class EmisBaseService { } private void saveRecord(int totalProcessed, int successCount, int failCount, long processTime, - List failedBillCodes) { + List failedBillCodes, int totalBatchStatusRecords, int totalMissRecords) { EmisTmsSiteBatchMissRecord record = new EmisTmsSiteBatchMissRecord(); record.setTotalProcessed(totalProcessed); record.setSuccessCount(successCount); @@ -4692,6 +4787,139 @@ public class EmisBaseService { } } + public void handleVirtual(EmisWaybill emisWaybillSave,EmisWaybill emisWaybillOld) throws EmisBizError { + if (!"1".equals(emisWaybillSave.getBlVirtual())) { + return; + } + updateMasterWaybill(emisWaybillSave,emisWaybillOld); + // 做问题件录入 + scanProblemInfo(emisWaybillSave,emisWaybillOld); + } + + public void scanProblemInfo(EmisWaybill emisWaybillSave, EmisWaybill emisWaybillOld) { + String dispatchOrSendManCode = ""; + if ("1".equals(emisWaybillSave.getPickupMethod())) { + dispatchOrSendManCode = emisWaybillSave.getOperateEmployeeCode(); + } else if ("2".equals(emisWaybillSave.getPickupMethod())) { + dispatchOrSendManCode = emisWaybillSave.getTakePieceEmployeeCode(); + } + ScanInfo scanInfoProm = new ScanInfo(); + List> scanDataPromList = new ArrayList<>(); + scanInfoProm.setOpType(2); + scanInfoProm.setScanType(ScanType.ISSUE.opCode); + + Map scanDatePromItem = new HashMap<>(); + scanDatePromItem.put("billCode", emisWaybillSave.getBillCode()); + if ("002".equals(emisWaybillSave.getTransLineType())) { + scanDatePromItem.put("problemType", "173"); + scanDatePromItem.put("remark", "出口虚拟面单"); + } else { + scanDatePromItem.put("problemType", "170"); + scanDatePromItem.put("remark", "返货虚拟面单"); + } + scanDatePromItem.put("notifySite", emisWaybillSave.getSendSiteCode()); + if (null == emisWaybillOld) { + scanDatePromItem.put("scanDate", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, emisWaybillSave.getSendDate())); + } else { + scanDatePromItem.put("scanDate", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getNowDate())); + } + scanDatePromItem.put("scanWeight", "0.0"); + scanDataPromList.add(scanDatePromItem); + scanInfoProm.setScanData(scanDataPromList); + emisTmsScanRecordService.scan(scanInfoProm, dispatchOrSendManCode, emisWaybillSave.getSendSiteCode()); + } + + public void updateMasterWaybill(EmisWaybill emisWaybillSave,EmisWaybill emisWaybillOld) throws EmisBizError { + EmisWaybill masterWaybill = checkVirtualParam(emisWaybillSave, emisWaybillOld); + String virtualRemark = masterWaybill.getVirtualRemark(); + String virtualBillCode = emisWaybillSave.getBillCode(); + String virtualBillCodeLastSix = virtualBillCode.substring(virtualBillCode.length() - 6); + if (StringUtil.isNotBlank(virtualRemark)) { + Set virtualBillSet = new LinkedHashSet<>(); + String[] codes = virtualRemark.split(","); + virtualBillSet.addAll(Arrays.asList(codes)); + virtualBillSet.add(virtualBillCodeLastSix); + virtualRemark = String.join(",", virtualBillSet); + } else { + virtualRemark = virtualBillCodeLastSix; + } + EmisWaybill emisWaybill = new EmisWaybill(); + emisWaybill.setVirtualRemark(virtualRemark); + emisWaybill.setId(masterWaybill.getId()); + emisWaybillMapper.updateEmisWaybill(emisWaybill); + } + + public EmisWaybill checkVirtualParam(EmisWaybill emisWaybillSave, EmisWaybill emisWaybillOld) throws EmisBizError { + if (StringUtil.isBlank(emisWaybillSave.getMasterBillCode())) { + throw new EmisBizError(EmisBizErrorType.FAIL, "主单号不能为空"); + } + if(StringUtil.isNotBlank(emisWaybillOld.getVirtualRemark())){ + throw new EmisBizError(EmisBizErrorType.FAIL, "主单不能改虚拟单"); + } + if (emisWaybillSave.getParcelQty() != 1) { + throw new EmisBizError(EmisBizErrorType.FAIL, "虚拟单件数只能为1"); + } + if (emisWaybillSave.getMasterBillCode().equals(emisWaybillSave.getBillCode())) { + throw new EmisBizError(EmisBizErrorType.FAIL, "运单号主单号不能相同"); + } + if (!"002".equals(emisWaybillSave.getTransLineType()) && !"012".equals(emisWaybillSave.getTransLineType()) + && !"014".equals(emisWaybillSave.getTransLineType())) { + throw new EmisBizError(EmisBizErrorType.FAIL, "虚拟单只支持线路为缅甸快递/缅甸快递进口/柬埔寨快递进口"); + } + EmisWaybill masterWaybill = emisWaybillMapper + .selectMasterWaybillByBillCode(emisWaybillSave.getMasterBillCode()); + if (Objects.isNull(masterWaybill)) { + throw new EmisBizError(EmisBizErrorType.FAIL, "主单号不存在"); + } + if (!emisWaybillSave.getReceiveCountry().equals(masterWaybill.getReceiveCountry()) + || !emisWaybillSave.getTransLineType().equals(masterWaybill.getTransLineType()) + || !emisWaybillSave.getProductType().equals(masterWaybill.getProductType())) { + throw new EmisBizError(EmisBizErrorType.FAIL, "主单和虚拟单线路不一致"); + } + if ("1".equals(masterWaybill.getBlVirtual())) { + throw new EmisBizError(EmisBizErrorType.FAIL, "虚拟单不能作为主单"); + } + if (!emisWaybillSave.getMasterBillCode().equals(emisWaybillOld.getMasterBillCode())) { + String virtualRemark = masterWaybill.getVirtualRemark() == null ? "" : masterWaybill.getVirtualRemark(); + long count = Arrays.stream(virtualRemark.split(",")) + .filter(s -> s != null && !s.trim().isEmpty()) + .count(); + if (count >= masterWaybill.getParcelQty()) { + throw new EmisBizError(EmisBizErrorType.FAIL, + emisWaybillSave.getMasterBillCode() + "最多只能绑定" + masterWaybill.getParcelQty() + "个虚拟单"); + } + } + + List batchList = emisTmsSiteBatchMapper.selectEmisTmsSiteBatchListByBillCodes( + Lists.newArrayList(Collections.singleton(emisWaybillSave.getMasterBillCode()))); + if (CollectionUtil.isNotEmpty(batchList)) { + throw new EmisBizError(EmisBizErrorType.FAIL, "该单号已经录入批次,请先在组批次中剔除该运单"); + } + return masterWaybill; + } + + public void handleVirtualForUpdate(EmisWaybill emisWaybillSave, EmisWaybill emisWaybillOld) throws EmisBizError { + if (!StringUtils.isEmpty(emisWaybillSave.getBlVirtual()) && "1".equals(emisWaybillSave.getBlVirtual())) { + handleVirtual(emisWaybillSave, emisWaybillOld); + } else { + String masterBillCode = emisWaybillOld.getMasterBillCode(); + if (StringUtil.isNotBlank(masterBillCode)) { + String virtualBillCodeLastSix = emisWaybillSave.getBillCode() + .substring(emisWaybillSave.getBillCode().length() - 6); + EmisWaybill masterWaybill = emisWaybillMapper + .selectEmisWaybillByBillCode(masterBillCode); + List filterVirtualRemark = Arrays.stream(masterWaybill.getVirtualRemark().split(",")) + .filter(i -> !i.equals(virtualBillCodeLastSix)).collect(Collectors.toList()); + String virtualRemark = String.join(",", filterVirtualRemark); + masterWaybill.setVirtualRemark(virtualRemark); + emisWaybillMapper.updateEmisWaybill(masterWaybill); + emisWaybillProblemInfoService.deleteEmisWaybillProblemInfoByBillCode(emisWaybillSave.getBillCode()); + // 重新计算提成 + emisCommissionProfitService.reCalcProfitByBillCode(emisWaybillSave.getBillCode()); + } + } + } + public static void main(String[] args) throws ParseException { // Date startDate = new Date("202"); Date startDate= new SimpleDateFormat("yyyy-MM-dd").parse("2025-05-11"); diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchDtlService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchDtlService.java index bbc825002..48b43cfa2 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchDtlService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchDtlService.java @@ -11,8 +11,9 @@ package com.xdadan.erp.emis.service; import java.util.List; import com.xdadan.erp.emis.domain.EmisTmsSiteBatchDtl; +import com.xdadan.erp.emis.domain.exception.EmisBizError; -/** + /** * @ClassName EmisTmsSiteBatchDtlService * @Description 一级网点TMS组批次明细 * @author linfso @@ -41,7 +42,7 @@ public interface IEmisTmsSiteBatchDtlService * @param emisTmsSiteBatchDtl 一级网点TMS组批次明细 * @return 结果 */ - public int insertEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl); + public int insertEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError; /** * 修改一级网点TMS组批次明细 diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchService.java index 3c3cbbbd0..946b29d4e 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchService.java @@ -11,8 +11,10 @@ package com.xdadan.erp.emis.service; import java.util.List; import com.xdadan.erp.emis.domain.EmisTmsSiteBatch; +import com.xdadan.erp.emis.domain.EmisTmsSiteBatchDtl; +import com.xdadan.erp.emis.domain.exception.EmisBizError; -/** + /** * @ClassName EmisTmsSiteBatchService * @Description 一级网点TMS组批次 * @author linfso @@ -57,7 +59,14 @@ public interface IEmisTmsSiteBatchService * @param emisTmsSiteBatch 一级网点TMS组批次 * @return 结果 */ - public int insertEmisTmsSiteBatch(EmisTmsSiteBatch emisTmsSiteBatch); + public int insertEmisTmsSiteBatch(EmisTmsSiteBatch emisTmsSiteBatch) ; + + /** + * + * @param oldSiteBatch + * @param billCode + */ + public void checkSiteBatch(EmisTmsSiteBatch oldSiteBatch, String billCode) throws EmisBizError; /** * 修改一级网点TMS组批次 @@ -65,7 +74,7 @@ public interface IEmisTmsSiteBatchService * @param emisTmsSiteBatch 一级网点TMS组批次 * @return 结果 */ - public int updateEmisTmsSiteBatch(EmisTmsSiteBatch emisTmsSiteBatch); + public int updateEmisTmsSiteBatch(EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError; /** * 批量删除一级网点TMS组批次 @@ -89,4 +98,11 @@ public interface IEmisTmsSiteBatchService * @param batchNo */ void scanSiteBatch(String batchNo); + + /** + * + * @param emisTmsSiteBatch + * @return + */ + int addAll(EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError; } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillProblemInfoService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillProblemInfoService.java index d0a0d606a..3652637d4 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillProblemInfoService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillProblemInfoService.java @@ -67,4 +67,12 @@ public interface IEmisWaybillProblemInfoService * @return 结果 */ public int deleteEmisWaybillProblemInfoById(Long id); + + /** + * 删除问题件信息 + * + * @param billCode + * @return 结果 + */ + public void deleteEmisWaybillProblemInfoByBillCode(String billCode); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillService.java index faae8d221..f2e9e2fad 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisWaybillService.java @@ -289,4 +289,17 @@ public interface IEmisWaybillService extends IDataAuditService * @throws EmisBizError 业务异常 */ void updateWaybillInfo(JSONObject orderData, String appId) throws EmisBizError; + + /** + * 查询主单号 + * + * @param emisWaybill + * @return + */ + List selectMasterEmisWaybills(EmisWaybill emisWaybill); + + /** + * + */ + void handleHistoryVirtualWaybill(); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchDtlServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchDtlServiceImpl.java index 84ea31494..9cba692e6 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchDtlServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchDtlServiceImpl.java @@ -11,6 +11,17 @@ package com.xdadan.erp.emis.service.impl; import java.util.List; +import java.util.Objects; + +import cn.hutool.core.collection.CollectionUtil; +import com.xdadan.erp.emis.domain.EmisTmsSiteBatch; +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.EmisWaybillMapper; +import com.xdadan.erp.emis.service.IEmisTmsSiteBatchService; +import jodd.util.StringUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.xdadan.erp.emis.domain.EmisTmsSiteBatchDtl; @@ -29,6 +40,15 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi @Autowired private EmisTmsSiteBatchDtlMapper emisTmsSiteBatchDtlMapper; + @Autowired + private EmisWaybillMapper emisWaybillMapper; + + @Autowired + private EmisTmsSiteBatchMapper emisTmsSiteBatchMapper; + + @Autowired + private IEmisTmsSiteBatchService emisTmsSiteBatchService; + /** * 查询一级网点TMS组批次明细 * @@ -60,8 +80,9 @@ public class EmisTmsSiteBatchDtlServiceImpl implements IEmisTmsSiteBatchDtlServi * @return 结果 */ @Override - public int insertEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) - { + public int insertEmisTmsSiteBatchDtl(EmisTmsSiteBatchDtl emisTmsSiteBatchDtl) throws EmisBizError { + EmisTmsSiteBatch oldSiteBatch = emisTmsSiteBatchMapper.selectTmsSiteBatchByBatchNo(emisTmsSiteBatchDtl.getBatchNo()); + emisTmsSiteBatchService.checkSiteBatch(oldSiteBatch, emisTmsSiteBatchDtl.getBillCode()); return emisTmsSiteBatchDtlMapper.insertEmisTmsSiteBatchDtl(emisTmsSiteBatchDtl); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissServiceImpl.java index 71b8cfc2c..39b2de422 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissServiceImpl.java @@ -48,9 +48,6 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements @Autowired private EmisTmsSiteBatchMissRecordMapper emisTmsSiteBatchMissRecordMapper; - private int totalBatchStatusRecords = 0; - private int totalMissRecords = 0; - /** * 查询TMS漏组批次信息 * @@ -142,6 +139,8 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements int totalProcessed = 0; int successCount = 0; int failCount = 0; + int totalBatchStatusRecords = 0; + int totalMissRecords = 0; List failedBillCodes = new ArrayList<>(); // 获取所有线路规划 @@ -162,7 +161,8 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements // 先查询所有数据 while (true) { - List waybills = emisWaybillMapper.selectWaybillListBySiteBatchStatus(offset, pageSize,lineCode); + List waybills = emisWaybillMapper.selectWaybillListBySiteBatchStatus(offset, pageSize, + lineCode); if (waybills.isEmpty()) { break; } @@ -192,6 +192,10 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements batches.add(allWaybills.subList(i, end)); } + if (CollectionUtil.isEmpty(batches)) { + return; + } + // 创建新的线程池处理数据 executorService = Executors.newFixedThreadPool(processors); List> processFutures = new ArrayList<>(); @@ -201,44 +205,52 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements } // 收集处理结果 + List allBatchStatus = new ArrayList<>(); + List allMissRecords = new ArrayList<>(); for (Future future : processFutures) { try { ProcessResult result = future.get(); successCount += result.getSuccessCount(); failCount += result.getFailCount(); failedBillCodes.addAll(result.getFailedBillCodes()); - - // 批量插入运单组批次状态记录 - if (!result.getBatchStatusList().isEmpty()) { - emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(result.getBatchStatusList()); - totalBatchStatusRecords += result.getBatchStatusList().size(); - } - - // 批量保存漏组记录 - if (!result.getMissRecords().isEmpty()) { - List filteredRecords = result.getMissRecords().stream() - .collect(Collectors.collectingAndThen( - Collectors.toMap( - record -> record.getBillCode() + "_" + record.getMissReason(), - record -> record, - (existing, replacement) -> existing), - map -> new ArrayList<>(map.values()))); - emisTmsSiteBatchMissMapper.batchInsertEmisTmsSiteBatchMiss(filteredRecords); - totalMissRecords += filteredRecords.size(); - } + allBatchStatus.addAll(result.getBatchStatusList()); + allMissRecords.addAll(result.getMissRecords()); } catch (Exception e) { log.error("Error processing batch", e); } } - // 关闭线程池 - executorService.shutdown(); + // 全局去重 + Map batchStatusMap = allBatchStatus.stream() + .collect(Collectors.toMap( + EmisWaybillBatchStatus::getBillCode, + v -> v, + (existing, replacement) -> existing)); + List uniqueBatchStatus = new ArrayList<>(batchStatusMap.values()); + + Map missMap = allMissRecords.stream() + .collect(Collectors.toMap( + r -> r.getBillCode() + "_" + r.getMissReason(), + v -> v, + (existing, replacement) -> existing)); + List uniqueMissRecords = new ArrayList<>(missMap.values()); + + // 批量插入 + if (!uniqueBatchStatus.isEmpty()) { + emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(uniqueBatchStatus); + totalBatchStatusRecords += uniqueBatchStatus.size(); + } + if (!uniqueMissRecords.isEmpty()) { + emisTmsSiteBatchMissMapper.batchInsertEmisTmsSiteBatchMiss(uniqueMissRecords); + totalMissRecords += uniqueMissRecords.size(); + } long endTime = System.currentTimeMillis(); long processTime = endTime - startTime; // 保存扫描记录 - saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes); + saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes, totalBatchStatusRecords, + totalMissRecords); log.info( "Auto scan completed. Total processed: {}, Success: {}, Failed: {}, Time taken: {}ms, Batch status records: {}, Miss records: {}", @@ -253,7 +265,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements } private void saveRecord(int totalProcessed, int successCount, int failCount, long processTime, - List failedBillCodes) { + List failedBillCodes, int totalBatchStatusRecords, int totalMissRecords) { EmisTmsSiteBatchMissRecord record = new EmisTmsSiteBatchMissRecord(); record.setTotalProcessed(totalProcessed); record.setSuccessCount(successCount); @@ -385,6 +397,10 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements // 合并相同起始网点和下一网点的批次 Map mergedBatches = new HashMap<>(); for (EmisTmsSiteBatch batch : waybillBatches) { + if (StringUtils.isAnyBlank(batch.getStartSiteCode(), batch.getNextSiteCode(), + batch.getSupplierCode())) { + continue; + } String key = batch.getStartSiteCode() + "_" + batch.getNextSiteCode(); if (mergedBatches.containsKey(key)) { EmisTmsSiteBatch existingBatch = mergedBatches.get(key); @@ -426,11 +442,33 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements } public List selectEmisTransPlanRuleTree(String lineCode) { - log.info("Start querying supplier route plan tree"); + log.info("Start querying supplier route plan tree (multi-threaded)"); EmisTransPlanRule emisTransPlanRule = new EmisTransPlanRule(); emisTransPlanRule.setLineCode(lineCode); - List list = emisTransPlanRuleMapper.selectEmisTransPlanRuleList(emisTransPlanRule); - List tree = buildTree(list); + int pageSize = 100; + int total = emisTransPlanRuleMapper.countForAllScan(emisTransPlanRule); + int pageCount = (total + pageSize - 1) / pageSize; + int processors = Runtime.getRuntime().availableProcessors(); + ExecutorService executor = Executors.newFixedThreadPool(processors); + List>> futures = new ArrayList<>(); + for (int i = 0; i < pageCount; i++) { + int offset = i * pageSize; + futures.add(executor.submit( + () -> emisTransPlanRuleMapper.selectRulesForAllScanPaged(emisTransPlanRule, offset, pageSize))); + } + List allRules = new ArrayList<>(); + for (Future> future : futures) { + try { + List rules = future.get(); + if (rules != null) { + allRules.addAll(rules); + } + } catch (Exception e) { + log.error("Error getting trans plan rule results", e); + } + } + executor.shutdown(); + List tree = buildTree(allRules); log.info("Queried supplier route plan tree, node count={}", tree != null ? tree.size() : 0); return tree; } @@ -518,7 +556,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements } private boolean checkRule(EmisTransPlanRule rule, List waybillBatches, - List list) { + List list) { // 检查当前节点是否匹配 boolean currentMatch = false; for (EmisTmsSiteBatch batch : waybillBatches) { @@ -617,7 +655,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements * 递归检查下一级节点 */ private boolean checkNextLevel(Set currentLevelRules, - List waybillBatches, List list) { + List waybillBatches, List list) { // 如果当前级为空,说明已经到底了,返回true if (currentLevelRules.isEmpty()) { return true; @@ -708,7 +746,8 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements .anyMatch( filterRule -> filterRule.getStartSiteCode().equals(childRule.getStartSiteCode()) && filterRule.getNextSiteCode().equals(childRule.getNextSiteCode()) && - compareSupplierCodes(filterRule.getSupplierCode(), childRule.getSupplierCode()))); + compareSupplierCodes(filterRule.getSupplierCode(), + childRule.getSupplierCode()))); if (!hasMatchedChild) { // 如果所有子节点都不匹配,为每个子节点创建漏组记录 diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchServiceImpl.java index 01ad53532..06ab69066 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchServiceImpl.java @@ -12,15 +12,17 @@ package com.xdadan.erp.emis.service.impl; import java.util.Date; import java.util.List; +import java.util.Objects; import cn.hutool.core.collection.CollectionUtil; import com.xdadan.erp.common.core.redis.RedissonService; import com.xdadan.erp.common.utils.DateUtils; import com.xdadan.erp.common.utils.SecurityUtils; -import com.xdadan.erp.emis.domain.EmisSite; -import com.xdadan.erp.emis.domain.EmisTmsSiteBatchDtl; -import com.xdadan.erp.emis.domain.EmisWaybill; +import com.xdadan.erp.emis.domain.*; +import com.xdadan.erp.emis.domain.enumtype.EmisBizErrorType; +import com.xdadan.erp.emis.domain.exception.EmisBizError; import com.xdadan.erp.emis.mapper.EmisTmsSiteBatchDtlMapper; +import com.xdadan.erp.emis.mapper.EmisTmsSiteBatchLoadingMapper; import com.xdadan.erp.emis.service.EmisBaseService; import jodd.util.StringUtil; import lombok.extern.slf4j.Slf4j; @@ -28,7 +30,6 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import com.xdadan.erp.emis.domain.EmisTmsSiteBatch; import com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMapper; import com.xdadan.erp.emis.service.IEmisTmsSiteBatchService; import org.springframework.transaction.annotation.Transactional; @@ -50,6 +51,9 @@ public class EmisTmsSiteBatchServiceImpl extends EmisBaseService implements IEmi @Autowired private EmisTmsSiteBatchDtlMapper emisTmsSiteBatchDtlMapper; + @Autowired + private EmisTmsSiteBatchLoadingMapper emisTmsSiteBatchLoadingMapper; + @Autowired RedissonService redissonService; @@ -124,6 +128,26 @@ public class EmisTmsSiteBatchServiceImpl extends EmisBaseService implements IEmi return 1; } + public void checkSiteBatch(EmisTmsSiteBatch oldSiteBatch, String billCode) throws EmisBizError { + EmisWaybill emisWaybill = emisWaybillMapper.selectEmisWaybillByBillCode(billCode); + if (Objects.nonNull(emisWaybill) && StringUtil.isNotBlank(emisWaybill.getVirtualRemark())) { + throw new EmisBizError(EmisBizErrorType.FAIL, billCode + "已绑定虚拟单,无法录入批次"); + } + checkUnique(oldSiteBatch, billCode); + } + + private void checkUnique(EmisTmsSiteBatch oldSiteBatch, String billCode) throws EmisBizError { + EmisTmsSiteBatch emisTmsSiteBatch = new EmisTmsSiteBatch(); + emisTmsSiteBatch.setStartSiteCode(oldSiteBatch.getStartSiteCode()); + emisTmsSiteBatch.setNextSiteCode(oldSiteBatch.getNextSiteCode()); + emisTmsSiteBatch.setSupplierCode(oldSiteBatch.getSupplierCode()); + emisTmsSiteBatch.getParams().put("billCode", billCode); + List batchList = emisTmsSiteBatchMapper.selectEmisTmsSiteBatchList(emisTmsSiteBatch); + if (CollectionUtil.isNotEmpty(batchList)) { + throw new EmisBizError(EmisBizErrorType.FAIL, billCode + "已组批次,不要重复组"); + } + } + /** * 修改一级网点TMS组批次 * @@ -131,8 +155,11 @@ public class EmisTmsSiteBatchServiceImpl extends EmisBaseService implements IEmi * @return 结果 */ @Override - public int updateEmisTmsSiteBatch(EmisTmsSiteBatch emisTmsSiteBatch) - { + public int updateEmisTmsSiteBatch(EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError { + List emisWaybills = emisTmsSiteBatchDtlMapper.selectEmisWayBillByBatchNo(emisTmsSiteBatch.getBatchNo()); + for (EmisWaybill emisWaybill : emisWaybills) { + checkUnique(emisTmsSiteBatch, emisWaybill.getBillCode()); + } return emisTmsSiteBatchMapper.updateEmisTmsSiteBatch(emisTmsSiteBatch); } @@ -174,4 +201,28 @@ public class EmisTmsSiteBatchServiceImpl extends EmisBaseService implements IEmi scanSiteBatchByWaybills(waybills); } + @Override + @Transactional + public int addAll(EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError { + // 插入明细数据 + if (!CollectionUtils.isEmpty(emisTmsSiteBatch.getBatchDtlList())) { + for (EmisTmsSiteBatchDtl itemDtl : emisTmsSiteBatch.getBatchDtlList()) { + checkSiteBatch(emisTmsSiteBatch, itemDtl.getBillCode()); + itemDtl.setBatchNo(emisTmsSiteBatch.getBatchNo()); + emisTmsSiteBatchDtlMapper.insertEmisTmsSiteBatchDtl(itemDtl); + } + } + if (!CollectionUtils.isEmpty(emisTmsSiteBatch.getLoadingList())) { + for (EmisTmsSiteBatchLoading batchLoading : emisTmsSiteBatch.getLoadingList()) { + batchLoading.setBatchNo(emisTmsSiteBatch.getBatchNo()); + emisTmsSiteBatchLoadingMapper.insertEmisTmsSiteBatchLoading(batchLoading); + } + } + + // 插入主批次数据 + emisTmsSiteBatchMapper.insertEmisTmsSiteBatch(emisTmsSiteBatch); + + return 1; + } + } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTransPlanRuleServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTransPlanRuleServiceImpl.java index 2147b20d1..f933798a9 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTransPlanRuleServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTransPlanRuleServiceImpl.java @@ -210,6 +210,15 @@ public class EmisTransPlanRuleServiceImpl extends EmisBaseService implements IEm if (existingRules != null && !existingRules.isEmpty()) { throw new EmisBizError(EmisBizErrorType.EXISTS, "已存在相同的规则配置"); } + EmisTransPlanRule emisTransPlanRule1 = new EmisTransPlanRule(); + emisTransPlanRule1.setLineCode(emisTransPlanRule.getLineCode()); + emisTransPlanRule1.setProductType(emisTransPlanRule.getProductType()); + emisTransPlanRule1.setStartSiteCode(emisTransPlanRule.getNextSiteCode()); + emisTransPlanRule1.setNextSiteCode(emisTransPlanRule.getStartSiteCode()); + List existingRules1 = emisTransPlanRuleMapper.checkDuplicate(emisTransPlanRule); + if (existingRules1 != null && !existingRules1.isEmpty()) { + throw new EmisBizError(EmisBizErrorType.EXISTS, "已存在相同的规则配置"); + } } private static void checkName(EmisTransPlanRule emisTransPlanRule) throws EmisBizError { @@ -233,6 +242,9 @@ public class EmisTransPlanRuleServiceImpl extends EmisBaseService implements IEm if (StringUtil.isBlank(emisTransPlanRule.getSupplierName())) { throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "供应商名称不能为空"); } + if(emisTransPlanRule.getStartSiteName().equals(emisTransPlanRule.getNextSiteName())){ + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "同一产品类型下起始网点、下一网点不能相同"); + } } private static void checkCode(EmisTransPlanRule emisTransPlanRule) throws EmisBizError { @@ -254,6 +266,9 @@ public class EmisTransPlanRuleServiceImpl extends EmisBaseService implements IEm if (StringUtil.isBlank(emisTransPlanRule.getSupplierCode())) { throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "供应商名称不能为空"); } + if(emisTransPlanRule.getStartSiteCode().equals(emisTransPlanRule.getNextSiteCode())){ + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "同一产品类型下起始网点、下一网点不能相同"); + } } private static void checkDate(EmisTransPlanRule emisTransPlanRule) throws EmisBizError { diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillAjustApplyServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillAjustApplyServiceImpl.java index d39439579..b2761e6e3 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillAjustApplyServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillAjustApplyServiceImpl.java @@ -12,6 +12,7 @@ package com.xdadan.erp.emis.service.impl; import java.util.Date; import java.util.List; +import java.util.Objects; import com.alibaba.fastjson.JSONObject; import com.xdadan.erp.common.core.domain.entity.SysUser; @@ -139,6 +140,11 @@ public class EmisWaybillAjustApplyServiceImpl extends EmisBaseService implements checkUseQuotaCredit(emisWaybillOld, getEmisWaybillNewFromJson(emisWaybillAjustApply)); } + // 校验虚拟单逻辑 + if ("1".equals(getEmisWaybillNewFromJson(emisWaybillAjustApply).getBlVirtual())) { + checkVirtualParam(getEmisWaybillNewFromJson(emisWaybillAjustApply),emisWaybillOld); + } + // 插入数据 emisWaybillAjustApply.setApplyDate(new Date()); emisWaybillAjustApplyMapper.insertEmisWaybillAjustApply(emisWaybillAjustApply); @@ -236,8 +242,11 @@ public class EmisWaybillAjustApplyServiceImpl extends EmisBaseService implements emisWaybillAjustApply.setDestConfirmNote(inputObj.getDestConfirmNote()); emisWaybillAjustApply.setDestConfirmManCode(getCurrentUser().getEmpCode()); + emisWaybillAjustApplyMapper.auditDestNoPass(emisWaybillAjustApply); + + return 1; } @@ -353,6 +362,9 @@ public class EmisWaybillAjustApplyServiceImpl extends EmisBaseService implements throw new EmisBizError(EmisBizErrorType.FAIL,"单号不存在!"); } + // 处理虚拟件逻辑 + handleVirtualForUpdate(emisWaybillSave, emisWaybillOld); + recordWaybillOperLog( emisWaybillAjustApply.getBillCode(), WaybillOperLogType.SITE_MODIFY_APPLY, diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillProblemInfoServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillProblemInfoServiceImpl.java index ae0f7fbe3..f28bb5650 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillProblemInfoServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillProblemInfoServiceImpl.java @@ -152,6 +152,38 @@ public class EmisWaybillProblemInfoServiceImpl extends EmisBaseService implement } + /** + * 批量删除问题件 + * + * @param billCode + * @return 结果 + */ + @Override + public void deleteEmisWaybillProblemInfoByBillCode(String billCode) { + EmisWaybillProblemInfo emisWaybillProblemInfo = emisWaybillProblemInfoMapper.selectEmisWaybillProblemInfoByBillCode(billCode); + if (emisWaybillProblemInfo == null) { + return; + } + + // 删除该问题件的扫描轨迹 + emisTmsScanRecordMapper.deletePromScanRecord(emisWaybillProblemInfo.getId().toString(), emisWaybillProblemInfo.getMainBillCode()); + + // 删除问题件 + emisWaybillProblemInfoMapper.deleteEmisWaybillProblemInfoById(emisWaybillProblemInfo.getId()); + + // 获取运单信息 + EmisWaybill waybill = getWaybillByBillCode(emisWaybillProblemInfo.getBillCode()); + if (!"6".equals(waybill.getPaymentType())) { + // 重新计算提成 + emisCommissionProfitService.reCalcProfitByBillCode(emisWaybillProblemInfo.getBillCode()); + } + + // 删除运单的问题件记录 + EmisWaybill emisWaybill = new EmisWaybill(); + emisWaybill.setBillCode(emisWaybillProblemInfo.getMainBillCode()); + emisWaybillMapper.cancelProblemRegister(emisWaybill); + } + /** * 删除问题件信息 * diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillServiceImpl.java index b6e70fb08..0fdeb703b 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisWaybillServiceImpl.java @@ -64,10 +64,10 @@ package com.xdadan.erp.emis.service.impl; import java.math.RoundingMode; import java.net.URLEncoder; import java.text.DecimalFormat; - import java.time.LocalDate; - import java.time.ZoneId; - import java.time.format.DateTimeParseException; import java.util.*; + import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + import java.util.concurrent.Future; import java.util.stream.Collectors; /** @@ -135,6 +135,15 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb @Autowired private EmisCustomerSignMapper emisCustomerSignMapper; + @Autowired + private EmisTmsSiteBatchMapper emisTmsSiteBatchMapper; + + @Autowired + private EmisWaybillProblemInfoMapper emisWaybillProblemInfoMapper; + + @Autowired + private EmisSettleSubBillMapper emisSettleSubBillMapper; + /** * 获取稽核数据 * @param id @@ -862,6 +871,16 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb // throw new EmisBizError(EmisBizErrorType.PARAM_ERROR1, "货值必填"); } + // 始发网点 + if(StringUtil.isBlank(emisWaybillSave.getStartSiteName())){ + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR1, "始发网点不能为空"); + } + EmisSite site = getSiteByName(emisWaybillSave.getStartSiteName()); + if(site==null){ + throw new EmisBizError(EmisBizErrorType.NOT_EXISTS, "始发网点不正确"); + } + emisWaybillSave.setStartSiteCode(site.getSiteCode()); + // 线路转换 EmisTransLine transLine=getTransLineByName(emisWaybillSave.getTransLineType()); if(transLine==null){ @@ -1480,6 +1499,12 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb // 检查月结客户首次签约日期,首次签约之前开的不允许修改 checkFirstSigningDay(emisWaybillOld, emisWaybillSave); +// // 校验账单确认状态 +// checkSettleSubBill(emisWaybillSave); + + // 处理虚拟件逻辑 + handleVirtualForUpdate(emisWaybillSave, emisWaybillOld); + // 修改运单 reUpdateWayBill(emisWaybillOld, emisWaybillSave,true,false); @@ -1500,6 +1525,16 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb return 1; } + private void checkSettleSubBill(EmisWaybill emisWaybillSave) throws EmisBizError { + List emisSettleSubBillList = emisSettleSubBillMapper.selectSettleSubBillListByBillCode(emisWaybillSave.getBillCode()); + if (CollectionUtil.isEmpty(emisSettleSubBillList) || Objects.isNull(emisSettleSubBillList.get(0))) { + return; + } + if ("1".equals(emisSettleSubBillList.get(0).getBlConfirmCenter()) || "1".equals(emisSettleSubBillList.get(0).getBlConfirmSite())) { + throw new EmisBizError(EmisBizErrorType.BILL_LOCK, "账单已确认,无法修改,需要先取消确认才能修改"); + } + } + /** * 下单接口Oms * @param emisWaybillSave @@ -3091,6 +3126,11 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb // 检查信用额度 checkUseQuotaCredit(null,emisWaybillSave); + // 虚拟件逻辑 + if ("1".equals(emisWaybillSave.getBlVirtual())) { + updateMasterWaybill(emisWaybillSave,new EmisWaybill()); + } + //插入新单 emisWaybillMapper.insertEmisWaybill(emisWaybillSave); @@ -3194,30 +3234,9 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb e.printStackTrace(); } - // 是否是虚拟问题件 - try { - if (!StringUtils.isEmpty(emisWaybillSave.getBlVirtual())) { - if ("1".equals(emisWaybillSave.getBlVirtual())) { - // 做问题件录入 - ScanInfo scanInfoProm = new ScanInfo(); - List> scanDataPromList = new ArrayList<>(); - scanInfoProm.setOpType(2); - scanInfoProm.setScanType(ScanType.ISSUE.opCode); - - Map scanDatePromItem = new HashMap<>(); - scanDatePromItem.put("billCode",emisWaybillSave.getBillCode()); - scanDatePromItem.put("problemType","173"); - scanDatePromItem.put("notifySite",emisWaybillSave.getSendSiteCode()); - scanDatePromItem.put("scanDate", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,emisWaybillSave.getSendDate())); - scanDatePromItem.put("scanWeight", "0.0"); - scanDatePromItem.put("remark", "出口虚拟面单"); - scanDataPromList.add(scanDatePromItem); - scanInfoProm.setScanData(scanDataPromList); - emisTmsScanRecordService.scan(scanInfoProm,dispatchOrSendManCode,emisWaybillSave.getSendSiteCode()); - } - } - } catch (Exception e) { - e.printStackTrace(); + // 问题件逻辑 + if ("1".equals(emisWaybillSave.getBlVirtual())) { + scanProblemInfo(emisWaybillSave, null); } // 运单立即重新出账 @@ -3229,7 +3248,7 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb // reCalcUseQuotaCredit(null, emisWaybillSave); // 重新计算提成 - if (!"6".equals(emisWaybillSave.getPaymentType())) { + if (!"6".equals(emisWaybillSave.getPaymentType()) && !"1".equals(emisWaybillSave.getBlVirtual())) { emisCommissionProfitService.reCalcProfitByBillCode(emisWaybillSave.getBillCode()); } @@ -5811,8 +5830,263 @@ public class EmisWaybillServiceImpl extends EmisBaseService implements IEmisWayb reUpdateWayBillByOms(oldWaybill, waybillUpdate); } + @Override + public List selectMasterEmisWaybills(EmisWaybill emisWaybill) { + return emisWaybillMapper.selectMasterEmisWaybills(emisWaybill); + } + @Override + @Async + public void handleHistoryVirtualWaybill() { + try { + long startTime = System.currentTimeMillis(); + int pageSize = 1000; + int offset = 0; + int totalProcessed = 0; + int successCount = 0; + int failCount = 0; + List failedBillCodes = new ArrayList<>(); + List failedBills = new ArrayList<>(); + List filterForProblemCodes = new ArrayList<>(); + + // 创建线程池 + int processors = Runtime.getRuntime().availableProcessors(); + ExecutorService executorService = Executors.newFixedThreadPool(processors); + List>> futures = new ArrayList<>(); + + // 先查询所有数据 + while (true) { + List waybills = emisWaybillMapper.selectHistoryVirtualWaybill(offset, pageSize); + if (waybills.isEmpty()) { + break; + } + futures.add(executorService.submit(() -> waybills)); + offset += pageSize; + } + + // 等待所有查询完成并收集结果 + List allWaybills = new ArrayList<>(); + for (Future> future : futures) { + try { + List waybills = future.get(); + allWaybills.addAll(waybills); + totalProcessed += waybills.size(); + } catch (Exception e) { + log.error("Error getting waybill results", e); + } + } + + // 关闭线程池 + executorService.shutdown(); + + // 按1000条数据分组处理 + List> batches = new ArrayList<>(); + for (int i = 0; i < allWaybills.size(); i += pageSize) { + int end = Math.min(i + pageSize, allWaybills.size()); + batches.add(allWaybills.subList(i, end)); + } + + // 处理每个批次 + for (List batch : batches) { + for (EmisWaybill waybill : batch) { + try { + String remark = waybill.getRemark(); + if (StringUtils.isNotEmpty(remark)) { + String masterBillCode = extractMasterBillCode(remark); + if (StringUtil.isBlank(masterBillCode)) { + masterBillCode = extractMasterBillCode(waybill.getFeeRemark()); + } + if (StringUtil.isBlank(masterBillCode)) { + failedBillCodes.add(waybill.getBillCode()); + failedBills.add(waybill); + log.error("masterBillCode is null,billCode:{}", waybill.getBillCode()); + failCount++; + continue; + } + waybill.setMasterBillCode(masterBillCode); + // 更新运单信息 + updateWaybill(waybill); + successCount++; + } + } catch (Exception e) { + log.error("处理运单失败,运单号:{},错误:{}", waybill.getBillCode(), e.getMessage()); + failCount++; + failedBillCodes.add(waybill.getBillCode()); + failedBills.add(waybill); + } + } + } + + // 修正:handleProblem返回统计结果 + ProblemHandleResult problemResult = handleProblem(failedBillCodes, filterForProblemCodes, failedBills, + successCount, failCount); + if (problemResult != null) { + successCount = problemResult.successCount; + failCount = problemResult.failCount; + filterForProblemCodes = problemResult.filterForProblemCodes; + } + + long endTime = System.currentTimeMillis(); + long processTime = endTime - startTime; + + log.debug("处理完成,总处理数:{},成功数:{},失败数:{},耗时:{}ms", totalProcessed, successCount, failCount, processTime); + + if (CollectionUtil.isNotEmpty(failedBillCodes)) { + log.debug("Failed bill codes ({}): {}", failedBillCodes.size(), failedBillCodes); + } + if (CollectionUtil.isNotEmpty(filterForProblemCodes)) { + log.debug("Failed for problemCodes ({}): {}", filterForProblemCodes.size(), filterForProblemCodes); + } + } catch (Exception e) { + log.error("Error in autoScanSiteBatch", e); + } + } + + // 新增内部类用于返回统计结果 + private static class ProblemHandleResult { + int successCount; + int failCount; + List filterForProblemCodes; + + ProblemHandleResult(int successCount, int failCount, List filterForProblemCodes) { + this.successCount = successCount; + this.failCount = failCount; + this.filterForProblemCodes = filterForProblemCodes; + } + } + + // 修改handleProblem返回统计结果 + private ProblemHandleResult handleProblem(List failedBillCodes, List filterForProblemCodes, + List failedBills, int successCount, int failCount) { + if (CollectionUtil.isEmpty(failedBillCodes)) { + return new ProblemHandleResult(successCount, failCount, filterForProblemCodes); + } + List emisWaybillProblemInfos = emisWaybillProblemInfoMapper + .selectEmisWaybillProblemInfoByBillCodes(failedBillCodes); + if (emisWaybillProblemInfos == null) { + log.error("emisWaybillProblemInfos is null"); + return new ProblemHandleResult(successCount, failCount, filterForProblemCodes); + } + for (EmisWaybillProblemInfo emisWaybillProblemInfo : emisWaybillProblemInfos) { + try { + String remark = emisWaybillProblemInfo.getProblemCause(); + if (StringUtil.isBlank(remark)) { + filterForProblemCodes.add(emisWaybillProblemInfo.getBillCode()); + continue; + } + String masterBillCode = extractMasterBillCode(remark); + if (StringUtil.isBlank(masterBillCode)) { + filterForProblemCodes.add(emisWaybillProblemInfo.getBillCode()); + continue; + } + List fiterBills = failedBills.stream() + .filter(i -> i.getBillCode().equals(emisWaybillProblemInfo.getBillCode())) + .collect(Collectors.toList()); + EmisWaybill waybill = new EmisWaybill(); + waybill.setMasterBillCode(masterBillCode); + waybill.setId(fiterBills.get(0).getId()); + waybill.setBillCode(emisWaybillProblemInfo.getBillCode()); + // 更新运单信息 + updateWaybill(waybill); + successCount++; + failCount--; + } catch (Exception e) { + log.error("处理问题件失败,运单号:{},错误:{}", emisWaybillProblemInfo.getBillCode(), e.getMessage()); + filterForProblemCodes.add(emisWaybillProblemInfo.getBillCode()); + } + } + return new ProblemHandleResult(successCount, failCount, filterForProblemCodes); + } + + private void updateWaybill(EmisWaybill virtualWaybill) { + EmisWaybill masterWaybill = emisWaybillMapper + .selectMasterWaybillByBillCode(virtualWaybill.getMasterBillCode()); + String virtualRemark = masterWaybill.getVirtualRemark(); + String virtualBillCode = virtualWaybill.getBillCode(); + if (StringUtil.isNotBlank(virtualRemark)) { + Set virtualBillSet = new LinkedHashSet<>(); + String[] codes = virtualRemark.split(","); + virtualBillSet.addAll(Arrays.asList(codes)); + virtualBillSet.add(virtualBillCode); + virtualRemark = String.join(",", virtualBillSet); + } else { + virtualRemark = virtualBillCode; + } + EmisWaybill updateMasterWaybill = new EmisWaybill(); + updateMasterWaybill.setVirtualRemark(virtualRemark); + updateMasterWaybill.setId(masterWaybill.getId()); + emisWaybillMapper.updateVirtualWaybill(updateMasterWaybill); + + EmisWaybill updateVirtualWaybill = new EmisWaybill(); + updateVirtualWaybill.setMasterBillCode(virtualWaybill.getMasterBillCode()); + updateVirtualWaybill.setId(virtualWaybill.getId()); + updateVirtualWaybill.setBlVirtual("1"); + emisWaybillMapper.updateVirtualWaybill(updateVirtualWaybill); + } + + private String extractMasterBillCode(String remark) { + if (StringUtils.isEmpty(remark)) { + return null; + } + + // 原有规则:查找T7080开头的主单号 + int startIndex = remark.indexOf("T7080"); + if (startIndex != -1) { + String subStr = remark.substring(startIndex); + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("T7080\\d+"); + java.util.regex.Matcher matcher = pattern.matcher(subStr); + if (matcher.find()) { + return matcher.group(); + } + } + + // 新规则:查找主单相关关键词后的内容,直到最后一位数字为止,且不能包含汉字 + String[] keywords = { "主单为", "主单是", "主单位", "主单号", "主单", "真实单号" }; + for (String keyword : keywords) { + int idx = remark.indexOf(keyword); + if (idx != -1) { + int start = idx + keyword.length(); + // 从关键词后开始,提取到最后一个数字为止 + StringBuilder sb = new StringBuilder(); + boolean hasDigit = false; + for (int i = start; i < remark.length(); i++) { + char c = remark.charAt(i); + // 如果遇到汉字则停止 + if (Character.toString(c).matches("[\u4e00-\u9fa5]")) { + break; + } + // 允许字母、数字、-、_等常见单号字符 + if (Character.isLetterOrDigit(c) || c == '-' || c == '_' || c == '/') { + sb.append(c); + if (Character.isDigit(c)) { + hasDigit = true; + } + } else if (sb.length() > 0) { + // 如果已经开始提取,遇到其他字符则停止 + break; + } + } + // 去除首尾空格 + String candidate = sb.toString().trim(); + // 必须包含数字,且不能包含汉字 + if (hasDigit && !candidate.matches(".*[\u4e00-\u9fa5].*")) { + // 只保留最后一位是数字的部分 + int lastDigitIdx = -1; + for (int i = candidate.length() - 1; i >= 0; i--) { + if (Character.isDigit(candidate.charAt(i))) { + lastDigitIdx = i; + break; + } + } + if (lastDigitIdx != -1) { + return candidate.substring(0, lastDigitIdx + 1); + } + } + } + } + return null; + } public static void main(String[] args) { diff --git a/emis-biz/src/main/resources/mapper/EmisCreditSalesmenMapper.xml b/emis-biz/src/main/resources/mapper/EmisCreditSalesmenMapper.xml index 2e59897f1..bc6958f55 100644 --- a/emis-biz/src/main/resources/mapper/EmisCreditSalesmenMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisCreditSalesmenMapper.xml @@ -175,6 +175,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and a.trans_line_type=c.line_code and a.payee=#{salesmen} and FIND_IN_SET(c.trans_type,#{transType}) + and FIND_IN_SET(a.payment_status,'0,2') and a.send_date ]]> #{startDate} and a.send_date #{endDate} diff --git a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchDtlMapper.xml b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchDtlMapper.xml index c0cc5735f..9db188fac 100644 --- a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchDtlMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchDtlMapper.xml @@ -191,5 +191,6 @@ left join emis_tms_site_batch_dtl b on a.bill_code = b.bill_code and b.del_flag = '0' where b.batch_no = #{batchNo} and a.del_flag = '0' + and a.send_date ]]> '2025-01-01 00:00:00' \ No newline at end of file diff --git a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml index d9a609293..4005615bf 100644 --- a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml @@ -43,12 +43,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + select m.id, m.bill_code, m.miss_reason, m.create_by, m.create_time, m.update_by, m.update_time, m.remark, m.del_flag, - m.line_code, m.product_type, m.start_site_code, m.next_site_code, m.supplier_code, m.start_date, m.end_date, + m.line_code, m.product_type, m.start_site_code, m.next_site_code, m.supplier_code, m.start_date, m.end_date,m.miss_type, w.send_site_code, s1.site_name as send_site_name,s2.site_name as start_site_name,s3.site_name as next_site_name, w.send_country, c1.name as send_country_name, w.destination_code, n.dest_name as destination_name,w.bl_is_question, l.line_name as line_name, w.receive_country, c2.name as receive_country_name, w.send_date, w.bl_sign, w.sign_date, @@ -148,11 +149,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" GROUP BY bill_code HAVING COUNT(*) = #{missCount} ) + AND m.miss_type = 0 - AND m.bill_code = #{billCode} + AND m.bill_code REGEXP REPLACE(#{billCode}, '\n', '|') AND m.miss_reason like concat('%', #{missReason}, '%') @@ -197,6 +199,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and w.send_date #{params.endSendDate} + order by m.bill_code desc + + + + + + \ No newline at end of file diff --git a/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml b/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml index 0767a2514..36d700ee6 100644 --- a/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml @@ -12,6 +12,8 @@ + + @@ -225,6 +227,10 @@ + + + + @@ -288,7 +294,7 @@ a.id,a.order_sn, a.cust_order_id, a.bill_code, a.order_status, a.waybill_status, a.order_type, a.order_date, a.user_id, a.customer_code, a.customer_name, a.open_id, a.receive_name, a.receive_company, a.receive_mobile, a.receive_tel, a.receive_country, a.receive_province, a.receive_city, - a.receive_county, a.receive_town, a.receive_address, a.receive_postcode, a.receive_pcd, a.send_name, a.send_company, + a.receive_county, a.receive_town, a.receive_address, a.receive_postcode, a.receive_pcd, a.send_name, a.send_company,a.start_site_code, a.send_mobile, a.send_tel, a.send_country, a.send_province, a.send_city, a.send_county, a.send_town, a.send_address, a.send_postcode, a.send_pcd, a.payment_type, a.calc_fee_type, a.cust_no, a.cust_name, a.trans_line_type, a.product_type, a.time_type, a.meter_type, a.carry_type, a.customs_clear, a.customs_eclaration, a.estimate_date, a.pack_type, a.dispatch_method, @@ -298,7 +304,7 @@ a.goods_type, a.goods_info, a.goods_pics, a.bl_prepare_in_freight, a.prepare_in_est_fee, a.prepare_in_real_fee, a.prepare_in_express, a.prepare_in_bill_code, a.prepare_in_remark, a.prepare_in_supplier, a.total_weight, a.total_volume, a.parcel_qty, a.bill_weight, a.volume_weight, a.currency, - a.settlement_weight, a.scan_weight, a.fee_weight, a.freight, a.real_payment_type, a.real_fee, a.bl_special_quote, + a.settlement_weight, a.scan_weight, a.fee_weight, a.freight, a.real_payment_type, a.real_fee, a.bl_special_quote,a.bl_virtual,a.master_bill_code,a.virtual_remark, a.bl_over_long, a.bl_bill, a.bl_bill_text, a.bl_over_weight, a.over_weight_number, a.fee_remark, a.third_code, a.real_value, a.bl_insure, a.insure_value, a.insure_value_currency, a.insure_fee_currency, a.insure_fee, a.insure_remark, a.insure_site_code, a.insure_date, a.bl_print, a.print_man_code, a.print_site, a.print_date, a.print_count, a.bl_disp_fd, @@ -337,6 +343,7 @@ w.site_name as current_site_name, x.site_name as next_site_name, y.site_name as last_site_name, + start.site_name as start_site_name, z.type_name as problem_type_name, k.trans_type as trans_type @@ -374,6 +381,7 @@ left join emis_site a1 on a.send_center_code=a1.site_code and a1.del_flag='0' left join emis_site a2 on a.destination_center_code=a2.site_code and a2.del_flag='0' + left join emis_site start on a.start_site_code=start.site_code and start.del_flag='0' left join emis_customer_user a3 on a.customer_code=a3.customer_code and a3.del_flag='0' left join emis_site seaway1 on a.departure_port=seaway1.site_code and seaway1.del_flag='0' left join emis_site seaway2 on a.destination_port=seaway2.site_code and seaway2.del_flag='0' @@ -384,7 +392,7 @@ select - a.id,a.order_sn, a.cust_order_id, a.bill_code,a.bill_code_sub, a.order_status, a.waybill_status, + a.id,a.order_sn, a.cust_order_id, a.bill_code,a.bill_code_sub, a.order_status, a.waybill_status,a.bl_virtual,a.master_bill_code,a.virtual_remark,a.start_site_code, a.order_type, a.order_date, a.user_id, a.customer_code, a.customer_name, a.open_id, a.receive_name, a.receive_company, a.receive_mobile, a.receive_tel, a.receive_country, a.receive_province, a.receive_city, a.receive_county, a.receive_town, a.receive_address, a.receive_postcode, a.receive_pcd, a.send_name, a.send_company, @@ -437,6 +445,7 @@ x.site_name as next_site_name, y.site_name as last_site_name, z.type_name as problem_type_name, + start.site_name as start_site_name, k.trans_type as trans_type @@ -477,6 +486,7 @@ left join emis_customer_user a3 on a.customer_code=a3.customer_code and a3.del_flag='0' left join emis_site seaway1 on a.departure_port=seaway1.site_code and seaway1.del_flag='0' left join emis_site seaway2 on a.destination_port=seaway2.site_code and seaway2.del_flag='0' + left join emis_site start on a.start_site_code=start.site_code and start.del_flag='0' @@ -490,6 +500,16 @@ limit 1 + + + + + + + + + + insert into emis_waybill_problem_info @@ -250,6 +265,13 @@ update emis_waybill_problem_info set del_flag='1' where id = #{id} + + update emis_waybill_problem_info + set del_flag='1' + where bill_code = #{billCode} + and (problem_type = '170' or problem_type = '173') + + update emis_waybill_problem_info set del_flag='1' where id in