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 a4aa217b8..07072f950 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 @@ -28,6 +28,7 @@ import com.xdadan.erp.emis.domain.exception.EmisBizError; import com.xdadan.erp.emis.domain.stat.BillPayStatInfo; import com.xdadan.erp.emis.domain.stat.OpenBillStatInfo; import com.xdadan.erp.emis.domain.vo.AddressParseResult; +import com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMissMapper; import com.xdadan.erp.emis.service.*; import com.xdadan.erp.emis.service.kefu.RL7moorService; import com.xdadan.erp.emis.service.print.IXddTplPrint; @@ -140,6 +141,9 @@ public class EmisCommonController extends EmisBaseController @Autowired private IEmisTransLineService emisTransLineService; + @Autowired + private EmisTmsSiteBatchMissMapper emisTmsSiteBatchMissMapper; + /** * 在线支付回调 * @param method @@ -903,6 +907,42 @@ public class EmisCommonController extends EmisBaseController return AjaxResult.success("发送成功"); } + /** + * 定时扫描运单货物组批次是否正确录入-V2 + * + * @return + */ + @GetMapping("/autoScanSiteBatchV2") + public AjaxResult autoScanSiteBatchV2(String lineCode) { + String statusKey = "autoScanSiteBatchV2_status"; + log.info("autoScanSiteBatchV2 start"); + + // 检查任务是否正在执行 + String currentStatus = redissonService.getStr(statusKey); + if ("RUNNING".equals(currentStatus)) { + log.warn("autoScanSiteBatchV2 is already running, request rejected"); + return AjaxResult.error("任务正在执行中,请稍后再试"); + } + + try { + // 设置任务状态为运行中,设置较长的过期时间(30分钟) + // 这样即使异步任务没有正确清除状态,也会在30分钟后自动过期 + redissonService.setStr(statusKey, "RUNNING", 1800); + + // 异步执行任务 + emisTmsSiteBatchMissService.autoScanSiteBatchV2(lineCode); + log.info("autoScanSiteBatchV2 async task started"); + + return AjaxResult.success("异步任务已启动,请稍后查看执行结果"); + + } catch (Exception ex) { + ex.printStackTrace(); + log.error("autoScanSiteBatchV2 exception:" + ex.getMessage()); + // 如果启动失败,清除状态 + redissonService.setStr(statusKey, "", 0); + return AjaxResult.error("任务启动失败:" + ex.getMessage()); + } + } /** * 定时扫描运单货物组批次是否正确录入 @@ -929,6 +969,7 @@ public class EmisCommonController extends EmisBaseController // 如果lineCode为空,查询所有线路的lineCode,去重后循环调用 if (StringUtils.isEmpty(lineCode)) { log.info("lineCode is empty, querying all line codes"); + emisTmsSiteBatchMissMapper.deleteReally(lineCode); EmisTransLine queryLine = new EmisTransLine(); // queryLine.setStatus(1); // 只查询启用的线路 List lineList = emisTransLineService.selectEmisTransLineList(queryLine); @@ -959,6 +1000,7 @@ public class EmisCommonController extends EmisBaseController log.info("autoScanSiteBatch async task started for all line codes"); return AjaxResult.success("异步任务已启动,共处理 " + lineCodeSet.size() + " 个线路,请稍后查看执行结果"); } else { + emisTmsSiteBatchMissMapper.deleteReally(lineCode); // 异步执行任务 emisTmsSiteBatchMissService.autoScanSiteBatch(lineCode); log.info("autoScanSiteBatch async task started for lineCode: {}", lineCode); 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 25c00c9fd..44e1601b2 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 @@ -116,6 +116,19 @@ public class EmisTmsSiteBatchController extends EmisBaseController } + /** + * 根据批次号扫描组批次--V2 + * + * @return + */ + @GetMapping("/scanSiteBatchV2") +// @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatch:scanSiteBatch')") + public AjaxResult scanSiteBatchV2(String batchNo) { + emisTmsSiteBatchService.scanSiteBatchV2(batchNo); + return AjaxResult.success("发送成功"); + + } + /** * 批次明细 * @param emisTmsSiteBatch diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissController.java index 7c7b3ae64..11baca6d4 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissController.java @@ -74,6 +74,24 @@ public class EmisTmsSiteBatchMissController extends EmisBaseController { } } + /** + * 查询TMS漏组批次信息列表 + */ + @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchMiss:listV2')") + @GetMapping("/list/v2") + public TableDataInfo listV2(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss) { + startPage(); + setPrivParams(emisTmsSiteBatchMiss); + + List list = emisTmsSiteBatchMissService.selectEmisTmsSiteBatchMissListV2(emisTmsSiteBatchMiss); + if(emisTmsSiteBatchMiss.getParams().containsKey("blZExport")){ + List exportList=getCompressExportList(list); + return getDataTable(exportList); + }else { + return getDataTable(list); + } + } + /** * 导出TMS漏组批次信息列表 */ @@ -218,4 +236,50 @@ public class EmisTmsSiteBatchMissController extends EmisBaseController { emisTmsSiteBatchMissService.cancelConfirmBatch(billCodes); return AjaxResult.success("取消确认成功"); } + + /** + * 批量取消确认组批次--v2 + */ + @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchMiss:cancelConfirmV2')") + @Log(title = "TMS漏组批次信息", businessType = BusinessType.UPDATE) + @PostMapping("/cancelConfirmBatchV2") + public AjaxResult cancelConfirmBatchV2(@RequestBody EmisTmsSiteBatchMiss req) throws EmisBizError { + Object listObj = req.getParams() != null ? req.getParams().get("billCodeList") : null; + if (listObj == null) { + return AjaxResult.error("参数缺失:billCodeList"); + } + List billCodes; + if (listObj instanceof List) { + List tmp = (List) listObj; + billCodes = new java.util.ArrayList<>(); + for (Object o : tmp) { + if (o != null) { + String s = String.valueOf(o).trim(); + if (!s.isEmpty()) { + billCodes.add(s); + } + } + } + } else if (listObj instanceof String) { + String str = ((String) listObj).trim(); + if (str.isEmpty()) { + billCodes = java.util.Collections.emptyList(); + } else { + String[] arr = str.split(","); + billCodes = new java.util.ArrayList<>(arr.length); + for (String a : arr) { + if (a != null) { + String s = a.trim(); + if (!s.isEmpty()) { + billCodes.add(s); + } + } + } + } + } else { + return AjaxResult.error("参数格式错误:billCodeList"); + } + emisTmsSiteBatchMissService.cancelConfirmBatchV2(billCodes); + return AjaxResult.success("取消确认成功"); + } } diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissStatisticsController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissStatisticsController.java index eef6a9c0a..ab7749d9c 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissStatisticsController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisTmsSiteBatchMissStatisticsController.java @@ -51,6 +51,26 @@ public class EmisTmsSiteBatchMissStatisticsController extends BaseController { } } + /** + * 查询漏组批次统计列表--v2 + */ + @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchMissStatistics:listV2')") + @GetMapping("/list/v2") + public TableDataInfo listV2(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) { + try { + startPage(); + List list = statisticsService + .selectStatisticsListV2(emisTmsSiteBatchMissStatistics); + return getDataTable(list); + } catch (Exception e) { + log.error("查询漏组批次统计列表失败", e); + TableDataInfo tableDataInfo = getDataTable(new ArrayList<>()); + tableDataInfo.setCode(500); + tableDataInfo.setMsg("查询失败:" + e.getMessage()); + return tableDataInfo; + } + } + /** * 导出漏组详细数据(按月份分sheet) * 优化版本:支持异步处理、流式导出、缓存优化 @@ -85,6 +105,40 @@ public class EmisTmsSiteBatchMissStatisticsController extends BaseController { } } + /** + * 导出漏组详细数据(按月份分sheet)--V2 + * 优化版本:支持异步处理、流式导出、缓存优化 + */ + @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchMissStatistics:exportDetailV2')") + @Log(title = "漏组详细数据导出", businessType = BusinessType.EXPORT) + @PostMapping("/exportDetailV2") + public void exportDetailV2(HttpServletResponse response, + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) { + try { + // 设置响应头,支持流式传输 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "0"); + + // 异步流式导出,避免内存溢出 + statisticsService.exportDetailDataByMonthStreamV2(response, emisTmsSiteBatchMissStatistics); + } catch (Exception e) { + log.error("导出漏组详细数据失败", e); + try { + // 检查响应是否已经开始 + if (!response.isCommitted()) { + response.reset(); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write("{\"success\":false,\"message\":\"导出失败:" + e.getMessage() + "\"}"); + } + } catch (Exception ex) { + log.error("写入错误信息失败", ex); + } + } + } + /** * 导出漏组批次统计查询接口数据 */ @@ -104,4 +158,24 @@ public class EmisTmsSiteBatchMissStatisticsController extends BaseController { } } } + + /** + * 导出漏组批次统计查询接口数据 + */ + @PreAuthorize("@ss.hasPermi('emis:emisTmsSiteBatchMissStatistics:exportStatisticsV2')") + @Log(title = "漏组批次统计导出", businessType = BusinessType.EXPORT) + @PostMapping("/exportStatisticsV2") + public void exportStatisticsV2(HttpServletResponse response, + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) { + try { + statisticsService.exportStatisticsDataV2(response, emisTmsSiteBatchMissStatistics); + } catch (Exception e) { + log.error("导出漏组批次统计数据失败", e); + try { + response.getWriter().write("导出失败:" + e.getMessage()); + } catch (Exception ex) { + log.error("写入错误信息失败", ex); + } + } + } } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatchMissRecord.java b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatchMissRecord.java index ac4c7bc61..aa13d834d 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatchMissRecord.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/EmisTmsSiteBatchMissRecord.java @@ -5,7 +5,7 @@ import lombok.Data; /** * TMS漏组批次扫描记录对象 - * + * * @author heyu */ @Data @@ -36,4 +36,7 @@ public class EmisTmsSiteBatchMissRecord extends BaseEntity { /** 失败运单号列表 */ private String failedBillCodes; -} \ No newline at end of file + /** 扫描版本 */ + private String scanVersion; + +} diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissMapper.java b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissMapper.java index 27b563971..c145bfde6 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissMapper.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissMapper.java @@ -7,13 +7,13 @@ import org.apache.ibatis.annotations.Param; /** * TMS漏组批次信息Mapper接口 - * + * * @author heyu */ public interface EmisTmsSiteBatchMissMapper { /** * 查询TMS漏组批次信息 - * + * * @param id TMS漏组批次信息主键 * @return TMS漏组批次信息 */ @@ -21,15 +21,23 @@ public interface EmisTmsSiteBatchMissMapper { /** * 查询TMS漏组批次信息列表 - * + * * @param emisTmsSiteBatchMiss TMS漏组批次信息 * @return TMS漏组批次信息集合 */ public List selectEmisTmsSiteBatchMissList(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss); + /** + * 查询TMS漏组批次信息列表_v2 + * + * @param emisTmsSiteBatchMiss TMS漏组批次信息 + * @return TMS漏组批次信息集合 + */ + public List selectEmisTmsSiteBatchMissListV2(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss); + /** * 新增TMS漏组批次信息 - * + * * @param emisTmsSiteBatchMiss TMS漏组批次信息 * @return 结果 */ @@ -37,7 +45,7 @@ public interface EmisTmsSiteBatchMissMapper { /** * 修改TMS漏组批次信息 - * + * * @param emisTmsSiteBatchMiss TMS漏组批次信息 * @return 结果 */ @@ -45,7 +53,7 @@ public interface EmisTmsSiteBatchMissMapper { /** * 删除TMS漏组批次信息 - * + * * @param id TMS漏组批次信息主键 * @return 结果 */ @@ -53,7 +61,7 @@ public interface EmisTmsSiteBatchMissMapper { /** * 批量删除TMS漏组批次信息 - * + * * @param ids 需要删除的数据主键集合 * @return 结果 */ @@ -61,12 +69,20 @@ public interface EmisTmsSiteBatchMissMapper { /** * 批量插入TMS漏组批次信息 - * + * * @param list TMS漏组批次信息列表 * @return 结果 */ public int batchInsertEmisTmsSiteBatchMiss(List list); + /** + * 批量插入TMS漏组批次信息--V2 + * + * @param list TMS漏组批次信息列表 + * @return 结果 + */ + public int batchInsertEmisTmsSiteBatchMissV2(List list); + /** * * @param lineCode @@ -87,10 +103,19 @@ public interface EmisTmsSiteBatchMissMapper { */ void deleteByBillCodes(@Param("billCodes") List billCodes); + /** + * + * @param billCodes + */ + void deleteByBillCodesV2(@Param("billCodes") List billCodes); + void deleteReally(String lineCode); + void deleteReallyV2(String lineCode); + /** * 根据运单号批量查询TMS漏组批次信息 */ List selectByBillCodes(@Param("billCodes") List billCodes); -} \ No newline at end of file + +} diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissStatisticsMapper.java b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissStatisticsMapper.java index 120c32606..8404c515c 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissStatisticsMapper.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisTmsSiteBatchMissStatisticsMapper.java @@ -23,6 +23,15 @@ public interface EmisTmsSiteBatchMissStatisticsMapper { List selectStatisticsList( EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** + * 查询漏组批次统计列表--V2 + * + * @param emisTmsSiteBatchMissStatistics 查询条件对象 + * @return 统计结果列表 + */ + List selectStatisticsListV2( + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** * 查询漏组详细数据列表(按月份分组) * @@ -31,6 +40,14 @@ public interface EmisTmsSiteBatchMissStatisticsMapper { */ List selectDetailDataByMonth(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** + * 查询漏组详细数据列表(按月份分组) + * + * @param emisTmsSiteBatchMissStatistics 查询条件 + * @return 详细数据列表 + */ + List selectDetailDataByMonthV2(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** * 分页查询漏组详细数据列表(按月份分组)- 性能优化版本 * @@ -51,4 +68,12 @@ public interface EmisTmsSiteBatchMissStatisticsMapper { * @return 总记录数 */ long countDetailDataByMonth(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + + /** + * 统计漏组详细数据总数 + * + * @param emisTmsSiteBatchMissStatistics 查询条件 + * @return 总记录数 + */ + long countDetailDataByMonthV2(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); } 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 f53c39360..91f44b892 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 @@ -4669,7 +4669,7 @@ public class EmisBaseService { // 保存扫描记录 saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes, totalBatchStatusRecords, - totalMissRecords); + totalMissRecords,"1"); log.info( "Auto scan completed. Total processed: {}, Success: {}, Failed: {}, Time taken: {}ms, Batch status records: {}, Miss records: {}", @@ -4744,7 +4744,7 @@ public class EmisBaseService { } public void saveRecord(int totalProcessed, int successCount, int failCount, long processTime, - List failedBillCodes, int totalBatchStatusRecords, int totalMissRecords) { + List failedBillCodes, int totalBatchStatusRecords, int totalMissRecords,String scanVersion) { EmisTmsSiteBatchMissRecord record = new EmisTmsSiteBatchMissRecord(); record.setTotalProcessed(totalProcessed); record.setSuccessCount(successCount); @@ -4757,6 +4757,7 @@ public class EmisBaseService { record.setCreateBy("system"); record.setCreateTime(new Date()); record.setCreateSite("88888"); + record.setScanVersion(scanVersion); emisTmsSiteBatchMissRecordMapper.insertEmisTmsSiteBatchMissRecord(record); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissService.java index b9ba06898..86aa77c94 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissService.java @@ -2,6 +2,7 @@ package com.xdadan.erp.emis.service; import java.util.List; import com.xdadan.erp.emis.domain.EmisTmsSiteBatchMiss; +import com.xdadan.erp.emis.domain.EmisWaybill; import com.xdadan.erp.emis.domain.exception.EmisBizError; /** @@ -26,6 +27,14 @@ public interface IEmisTmsSiteBatchMissService { */ public List selectEmisTmsSiteBatchMissList(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss); + /** + * 查询TMS漏组批次信息列表_v2 + * + * @param emisTmsSiteBatchMiss TMS漏组批次信息 + * @return TMS漏组批次信息集合 + */ + public List selectEmisTmsSiteBatchMissListV2(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss); + /** * 新增TMS漏组批次信息 * @@ -90,4 +99,21 @@ public interface IEmisTmsSiteBatchMissService { * @param billCodes 运单号列表 */ void cancelConfirmBatch(List billCodes) throws EmisBizError; + + /** + * 批量取消确认组批次--V2: + * 1) 根据运单号列表删除运单组批次状态数据 + * 2) 重新扫描运单组批次状态 + * + * @param billCodes 运单号列表 + */ + void cancelConfirmBatchV2(List billCodes) throws EmisBizError; + + /** + * 定时扫描运单货物组批次是否正确录入-V2 + * + */ + void autoScanSiteBatchV2(String lineCode); + + void scanSiteBatchByWaybillsV2(List emisWaybills); } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissStatisticsService.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissStatisticsService.java index 2d464eef2..9155293f6 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissStatisticsService.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/IEmisTmsSiteBatchMissStatisticsService.java @@ -24,6 +24,15 @@ public interface IEmisTmsSiteBatchMissStatisticsService { List selectStatisticsList( EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** + * 查询漏组批次统计列表--V2 + * + * @param emisTmsSiteBatchMissStatistics 查询条件 + * @return 统计结果列表 + */ + List selectStatisticsListV2( + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** * 流式导出漏组详细数据(按月份分sheet)- 性能优化版本 * 支持大数据量导出,避免内存溢出 @@ -34,6 +43,16 @@ public interface IEmisTmsSiteBatchMissStatisticsService { void exportDetailDataByMonthStream(HttpServletResponse response, EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** + * 流式导出漏组详细数据(按月份分sheet)- 性能优化版本 + * 支持大数据量导出,避免内存溢出 + * + * @param response HTTP响应 + * @param emisTmsSiteBatchMissStatistics 查询条件 + */ + void exportDetailDataByMonthStreamV2(HttpServletResponse response, + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + /** * 导出漏组批次统计查询接口数据 * @@ -42,4 +61,13 @@ public interface IEmisTmsSiteBatchMissStatisticsService { */ void exportStatisticsData(HttpServletResponse response, EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); + + /** + * 导出漏组批次统计查询接口数据 + * + * @param response HTTP响应 + * @param emisTmsSiteBatchMissStatistics 查询条件 + */ + void exportStatisticsDataV2(HttpServletResponse response, + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics); } 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 7c3fe649d..83bdbbc98 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 @@ -114,6 +114,13 @@ public interface IEmisTmsSiteBatchService extends IDataAuditService */ void scanSiteBatch(String batchNo); + /** + * 根据批次号扫描组批次--V2 + * + * @param batchNo + */ + void scanSiteBatchV2(String batchNo); + /** * * @param emisTmsSiteBatch 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 ca80fd4b0..59e4fe731 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 @@ -20,6 +20,7 @@ import com.xdadan.erp.emis.utils.WaybillHelper; import jodd.util.StringUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -137,6 +138,31 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements return list; } + /** + * 查询TMS漏组批次信息列表_v2 + * + * @param emisTmsSiteBatchMiss TMS漏组批次信息 + * @return TMS漏组批次信息 + */ + @Override + public List selectEmisTmsSiteBatchMissListV2(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss) { + log.info("Selecting TMS site batch miss list with params: {}", emisTmsSiteBatchMiss); + List list = null; + // 如果单号不为空,则去除其他参数 + if (!StringUtils.isEmpty(emisTmsSiteBatchMiss.getBillCode())) { + emisTmsSiteBatchMiss.setBillCode(WaybillHelper.formatQueryValue(emisTmsSiteBatchMiss.getBillCode())); + String[] billCodeSortList = emisTmsSiteBatchMiss.getBillCode().split(","); + if (billCodeSortList.length > 1) { + emisTmsSiteBatchMiss.getParams().put("billCodeSortList", Arrays.asList(billCodeSortList)); + } + list = emisTmsSiteBatchMissMapper.selectEmisTmsSiteBatchMissListV2(emisTmsSiteBatchMiss); + } else { + list = emisTmsSiteBatchMissMapper.selectEmisTmsSiteBatchMissListV2(emisTmsSiteBatchMiss); + } + + return list; + } + /** * 新增TMS漏组批次信息 * @@ -208,6 +234,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements // 1) 逻辑删除漏组批次数据 emisTmsSiteBatchMissMapper.deleteByBillCodes(billCodes); + emisTmsSiteBatchMissMapper.deleteByBillCodesV2(billCodes); // 2) 新增运单组批次状态 site_batch_status=1(幂等:insert ignore) Date now = new Date(); @@ -249,6 +276,29 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements // 3) 调用scanSiteBatchByWaybills重新扫描 if (!waybills.isEmpty()) { this.scanSiteBatchByWaybills(waybills); + this.scanSiteBatchByWaybillsV2(waybills); + } + } + + /** + * 批量取消确认组批次--V2 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelConfirmBatchV2(List billCodes) throws EmisBizError { + if (billCodes == null || billCodes.isEmpty()) { + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "运单号不能为空"); + } + + // 1) 彻底删除运单组批次状态数据 + emisWaybillBatchStatusMapper.deleteByBillCodes(billCodes); + + // 2) 批量查询运单信息 + List waybills = emisWaybillMapper.selectEmisWaybillListByBillCodes(billCodes); + + // 3) 调用scanSiteBatchByWaybills重新扫描 + if (!waybills.isEmpty()) { + this.scanSiteBatchByWaybillsV2(waybills); } } @@ -257,7 +307,6 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements public void autoScanSiteBatch(String lineCode) { ExecutorService executorService = null; try { - emisTmsSiteBatchMissMapper.deleteReally(lineCode); long startTime = System.currentTimeMillis(); int pageSize = 1000; int offset = 0; @@ -272,6 +321,20 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements List treeRules = this.selectEmisTransPlanRuleTree(lineCode); if (treeRules.isEmpty()) { log.info("No trans plan rules found, skip auto scan"); + List waybills = emisWaybillMapper.selectWaybillListBySiteBatchStatus(0, 100000, + lineCode); + if (waybills.isEmpty()) { + return; + } + List missRecords = waybills.stream().map(waybill -> { + EmisTmsSiteBatchMiss miss = createMissRecord(waybill); + miss.setMissReason("当前线路没有创建对应的线路规划"); + miss.setMissType("1"); + miss.setLineCode(waybill.getTransLineType()); + miss.setProductType(waybill.getProductType()); + return miss; + }).collect(Collectors.toList()); + emisTmsSiteBatchMissMapper.batchInsertEmisTmsSiteBatchMiss(missRecords); return; } @@ -282,7 +345,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements // 创建线程池 int processors = Runtime.getRuntime().availableProcessors() ; executorService = new ThreadPoolExecutor( - processors/2, // 核心线程数 + 1, // 核心线程数 processors, // 最大线程数 60L, // 空闲线程存活时间 TimeUnit.SECONDS, // 时间单位 @@ -335,7 +398,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements batches.size(), batchSize, allWaybills.size()); // 复用现有线程池 - List> processFutures = new ArrayList<>(); + List> processFutures = new ArrayList<>(); for (List batch : batches) { processFutures.add(executorService.submit(() -> processWaybillBatch(batch, transPlanRulesByLineCode))); @@ -346,9 +409,9 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements List allMissRecords = new ArrayList<>(); int timeoutMinutes = 10; // 10分钟超时 - for (Future future : processFutures) { + for (Future future : processFutures) { try { - ProcessResult result = future.get(timeoutMinutes, TimeUnit.MINUTES); + EmisBaseService.ProcessResult result = future.get(timeoutMinutes, TimeUnit.MINUTES); successCount += result.getSuccessCount(); failCount += result.getFailCount(); failedBillCodes.addAll(result.getFailedBillCodes()); @@ -406,7 +469,7 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements // 保存扫描记录 saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes, totalBatchStatusRecords, - totalMissRecords); + totalMissRecords,"1"); log.info( "Auto scan completed. Total processed: {}, Success: {}, Failed: {}, Time taken: {}ms, Batch status records: {}, Miss records: {}", @@ -451,4 +514,718 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements return tree; } + public List selectEmisTransPlanRuleTreeV2(String lineCode) { + EmisTransPlanRule emisTransPlanRule = new EmisTransPlanRule(); + emisTransPlanRule.setLineCode(lineCode); + List allRules = emisTransPlanRuleMapper.selectRulesForAllScan(emisTransPlanRule); +// List tree = buildTree(allRules, new EmisTransPlanRule()); + return allRules; + } + + @Async + @Override + public void autoScanSiteBatchV2(String lineCode) { + ExecutorService executorService = null; + try { + emisTmsSiteBatchMissMapper.deleteReallyV2(lineCode); + long startTime = System.currentTimeMillis(); + int pageSize = 1000; + int offset = 0; + int totalProcessed = 0; + int successCount = 0; + int failCount = 0; + int totalBatchStatusRecords = 0; + int totalMissRecords = 0; + List failedBillCodes = new ArrayList<>(); + + // 获取所有线路规划 + List treeRules = this.selectEmisTransPlanRuleTreeV2(lineCode); + if (treeRules.isEmpty()) { + log.info("No trans plan rules found, skip auto scan v2"); + return; + } + + // 按线路编码分组 + Map> transPlanRulesByLineCode = treeRules.stream() + .collect(Collectors.groupingBy(EmisTransPlanRule::getLineCode)); + + // 创建线程池 + int processors = Runtime.getRuntime().availableProcessors() ; + executorService = new ThreadPoolExecutor( + 1, // 核心线程数 + processors, // 最大线程数 + 60L, // 空闲线程存活时间 + TimeUnit.SECONDS, // 时间单位 + new LinkedBlockingQueue<>(), // 工作队列 + r -> { + Thread t = new Thread(r); + t.setName("emis-scan-" + t.getId()); + t.setDaemon(false); + return t; + } // 线程工厂 + ); + List>> futures = new ArrayList<>(); + + // 先查询所有数据 + while (true) { + List waybills = emisWaybillMapper.selectWaybillListBySiteBatchStatus(offset, pageSize, + lineCode); + 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); + } + } + + int batchSize = 1000; + List> batches = new ArrayList<>(); + for (int i = 0; i < allWaybills.size(); i += batchSize) { + int end = Math.min(i + batchSize, allWaybills.size()); + batches.add(allWaybills.subList(i, end)); + } + + if (CollectionUtil.isEmpty(batches)) { + log.info("No waybills to process, skip batch processing"); + return; + } + + log.info("Processing {} batches with batch size: {}, total waybills: {}", + batches.size(), batchSize, allWaybills.size()); + + // 复用现有线程池 + List> processFutures = new ArrayList<>(); + + for (List batch : batches) { + processFutures.add(executorService.submit(() -> processWaybillBatchV2(batch, transPlanRulesByLineCode))); + } + + // 添加超时机制,避免长时间阻塞 + List allBatchStatus = new ArrayList<>(); + List allMissRecords = new ArrayList<>(); + int timeoutMinutes = 10; // 10分钟超时 + + for (Future future : processFutures) { + try { + ProcessResult result = future.get(timeoutMinutes, TimeUnit.MINUTES); + successCount += result.getSuccessCount(); + failCount += result.getFailCount(); + failedBillCodes.addAll(result.getFailedBillCodes()); + allBatchStatus.addAll(result.getBatchStatusList()); + allMissRecords.addAll(result.getMissRecords()); + } catch (TimeoutException e) { + log.error("Batch processing timeout after {} minutes", timeoutMinutes); + future.cancel(true); // 取消超时任务 + } catch (Exception e) { + log.error("Error processing batch", e); + } + } + + // 全局去重 + 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()) { + filterBatchStatusList(uniqueBatchStatus, uniqueMissRecords); + } + + // 批量插入 - 每次插入5000条 + if (!uniqueBatchStatus.isEmpty()) { + int insertBatchSize = 5000; + for (int i = 0; i < uniqueBatchStatus.size(); i += insertBatchSize) { + int end = Math.min(i + insertBatchSize, uniqueBatchStatus.size()); + List batch = uniqueBatchStatus.subList(i, end); + emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(batch); + totalBatchStatusRecords += batch.size(); + } + } + if (!uniqueMissRecords.isEmpty()) { + int insertBatchSize = 5000; + for (int i = 0; i < uniqueMissRecords.size(); i += insertBatchSize) { + int end = Math.min(i + insertBatchSize, uniqueMissRecords.size()); + List batch = uniqueMissRecords.subList(i, end); + emisTmsSiteBatchMissMapper.batchInsertEmisTmsSiteBatchMissV2(batch); + totalMissRecords += batch.size(); + } + } + + long endTime = System.currentTimeMillis(); + long processTime = endTime - startTime; + + // 保存扫描记录 + saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes, totalBatchStatusRecords, + totalMissRecords,"2"); + + log.info( + "Auto scan v2 completed. Total processed: {}, Success: {}, Failed: {}, Time taken: {}ms, Batch status records: {}, Miss records: {}", + totalProcessed, successCount, failCount, processTime, + totalBatchStatusRecords, totalMissRecords); + if (CollectionUtil.isNotEmpty(failedBillCodes)) { + log.warn("Failed bill codes: {}", failedBillCodes); + } + } catch (Exception e) { + log.error("Error in autoScanSiteBatch v2", e); + } finally { + // 确保线程池资源释放 + if (executorService != null && !executorService.isShutdown()) { + executorService.shutdown(); + try { + if (!executorService.awaitTermination(30, TimeUnit.SECONDS)) { + log.warn("Thread pool did not terminate gracefully, forcing shutdown"); + executorService.shutdownNow(); + } + } catch (InterruptedException e) { + log.error("Thread pool shutdown interrupted", e); + executorService.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + // 清除任务状态 + try { + String statusKey = "autoScanSiteBatchV2_status"; + redissonService.setStr(statusKey, "", 0); + log.info("autoScanSiteBatch v2 task status cleared"); + } catch (Exception e) { + log.error("Failed to clear autoScanSiteBatch status", e); + } + } + } + + public void scanSiteBatchByWaybillsV2(List emisWaybills) { + try { + if (CollectionUtil.isEmpty(emisWaybills)) { + return; + } + List billCodes = emisWaybills.stream().map(EmisWaybill::getBillCode).collect(Collectors.toList()); + if (CollectionUtil.isEmpty(billCodes)) { + return; + } + List lineCodes = emisWaybills.stream().map(EmisWaybill::getTransLineType).distinct() + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(lineCodes)) { + return; + } + emisTmsSiteBatchMissMapper.deleteByBillCodesV2(billCodes); + long startTime = System.currentTimeMillis(); + int totalProcessed = emisWaybills.size(); + int successCount = 0; + int failCount = 0; + int totalBatchStatusRecords = 0; + int totalMissRecords = 0; + List failedBillCodes = new ArrayList<>(); + + // 获取所有线路规划 + List treeRules = this.selectEmisTransPlanRuleTree(lineCodes); + if (treeRules.isEmpty()) { + log.info("No trans plan rules found, skip auto scan v2"); + return; + } + + // 按线路编码分组 + Map> transPlanRulesByLineCode = treeRules.stream() + .collect(Collectors.groupingBy(EmisTransPlanRule::getLineCode)); + + // 直接处理运单批次 + ProcessResult result = processWaybillBatchV2(emisWaybills, transPlanRulesByLineCode); + successCount += result.getSuccessCount(); + failCount += result.getFailCount(); + failedBillCodes.addAll(result.getFailedBillCodes()); + + // 批量插入运单组批次状态记录 + List batchStatusList = result.getBatchStatusList(); + List missRecords = result.getMissRecords(); + if (!batchStatusList.isEmpty()) { + filterBatchStatusList(batchStatusList, missRecords); + } + + // 批量插入运单组批次状态记录 + if (!batchStatusList.isEmpty()) { + emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(result.getBatchStatusList()); + totalBatchStatusRecords += result.getBatchStatusList().size(); + } + + // 批量保存漏组记录 + if (!missRecords.isEmpty()) { + List filteredRecords = missRecords.stream() + .collect(Collectors.collectingAndThen( + Collectors.toMap( + record -> record.getBillCode() + "_" + record.getMissReason(), + record -> record, + (existing, replacement) -> existing), + map -> new ArrayList<>(map.values()))); + emisTmsSiteBatchMissMapper.batchInsertEmisTmsSiteBatchMissV2(filteredRecords); + totalMissRecords += filteredRecords.size(); + } + + long endTime = System.currentTimeMillis(); + long processTime = endTime - startTime; + + // 保存扫描记录 + saveRecord(totalProcessed, successCount, failCount, processTime, failedBillCodes, totalBatchStatusRecords, + totalMissRecords,"2"); + + log.info( + "Auto scan V2 completed. Total processed: {}, Success: {}, Failed: {}, Time taken: {}ms, Batch status records: {}, Miss records: {}", + totalProcessed, successCount, failCount, processTime, + totalBatchStatusRecords, totalMissRecords); + if (CollectionUtil.isNotEmpty(failedBillCodes)) { + log.warn("Failed bill codes: {}", failedBillCodes); + } + } catch (Exception e) { + log.error("Error in autoScanSiteBatch V2", e); + } + } + + public static class ProcessResult { + private final int successCount; + private final int failCount; + private final List failedBillCodes; + private final List batchStatusList; + private final List missRecords; + + public ProcessResult(int successCount, int failCount, List failedBillCodes, + List batchStatusList, List missRecords) { + this.successCount = successCount; + this.failCount = failCount; + this.failedBillCodes = failedBillCodes; + this.batchStatusList = batchStatusList; + this.missRecords = missRecords; + } + + public int getSuccessCount() { + return successCount; + } + + public int getFailCount() { + return failCount; + } + + public List getFailedBillCodes() { + return failedBillCodes; + } + + public List getBatchStatusList() { + return batchStatusList; + } + + public List getMissRecords() { + return missRecords; + } + } + + public ProcessResult processWaybillBatchV2(List waybills, + Map> transPlanRulesByLineCode) { + int successCount = 0; + int failCount = 0; + List failedBillCodes = new ArrayList<>(); + List missRecords = new ArrayList<>(); + List batchStatusList = new ArrayList<>(); + + // 获取所有运单号 + List billCodes = waybills.stream() + .map(EmisWaybill::getBillCode) + .collect(Collectors.toList()); + + // 一次性查询所有运单对应的组批次信息 + List siteBatches = emisTmsSiteBatchMapper + .selectEmisTmsSiteBatchListByBillCodes(billCodes); + + // 按运单号分组 + Map> siteBatchesByBillCode = new HashMap<>(); + for (EmisTmsSiteBatch batch : siteBatches) { + if (batch.getBatchDtlList() != null) { + for (EmisTmsSiteBatchDtl dtl : batch.getBatchDtlList()) { + siteBatchesByBillCode.computeIfAbsent(dtl.getBillCode(), k -> new ArrayList<>()).add(batch); + } + } + } + + for (EmisWaybill waybill : waybills) { + try { + // 获取运单对应的线路规划 + List ruleListByTransLineType = transPlanRulesByLineCode + .get(waybill.getTransLineType()); + if (CollectionUtil.isEmpty(ruleListByTransLineType)) { + // 创建漏组记录 + EmisTmsSiteBatchMiss miss = createMissRecord(waybill); + miss.setMissReason("当前线路没有创建对应的线路规划"); + miss.setMissType("1"); + miss.setLineCode(waybill.getTransLineType()); + miss.setProductType(waybill.getProductType()); + missRecords.add(miss); + successCount++; + continue; + } + + List ruleListByProductType = ruleListByTransLineType.stream() + .filter(i -> StringUtils.isNotBlank(i.getProductType()) + && i.getProductType().contains(waybill.getProductType())) + .collect(Collectors.toList()); + + if (CollectionUtil.isEmpty(ruleListByProductType)) { + // 创建漏组记录 + EmisTmsSiteBatchMiss miss = createMissRecord(waybill); + miss.setMissReason("当前线路没有创建对应的产品类型"); + miss.setMissType("1"); + miss.setLineCode(waybill.getTransLineType()); + miss.setProductType(waybill.getProductType()); + missRecords.add(miss); + successCount++; + continue; + } + + // 获取运单对应的组批次信息 + List waybillBatches = siteBatchesByBillCode.get(waybill.getBillCode()); + if (CollectionUtil.isEmpty(waybillBatches)) { + // 创建漏组记录 + EmisTmsSiteBatchMiss miss = createMissRecord(waybill); + + miss.setMissReason(waybill.getStartSiteName() +" 尚未完成组批次,请尽快完成,避免影响下一程同事组批次进度" ); + miss.setLineCode(waybill.getTransLineType()); + miss.setProductType(waybill.getProductType()); + miss.setStartSiteCode(waybill.getStartSiteCode()); + miss.setNextSiteCode(""); + miss.setMissType("0"); + + missRecords.add(miss); + successCount++; + continue; + } + + // 合并相同起始网点和下一网点的批次 + Map mergedBatches = new HashMap<>(); + int status2Index = 0; + for (EmisTmsSiteBatch batch : waybillBatches) { + if (StringUtils.isAnyBlank(batch.getStartSiteCode(), batch.getNextSiteCode(), + batch.getSupplierCode())) { + continue; + } + + // 检查明细列表中是否有waybillBatchStatus=2的记录,如果有则不合并 + boolean hasWaybillBatchStatus2 = false; + if (batch.getBatchDtlList() != null && !batch.getBatchDtlList().isEmpty()) { + for (EmisTmsSiteBatchDtl dtl : batch.getBatchDtlList()) { + if ("2".equals(dtl.getWaybillBatchStatus())||"1".equals(dtl.getWaybillBatchStatus())) { + hasWaybillBatchStatus2 = true; + break; + } + } + } + + // 如果有waybillBatchStatus=2的记录,不合并supplierCode,但添加到mergedBatches + if (hasWaybillBatchStatus2) { + String specialKey = batch.getStartSiteCode() + "_" + batch.getNextSiteCode() + "_S2_" + + (status2Index++); + EmisTmsSiteBatch newBatch = new EmisTmsSiteBatch(); + BeanUtils.copyProperties(batch, newBatch); + Set supplierSet = new TreeSet<>(); + if (StringUtils.isNotBlank(batch.getSupplierCode())) { + supplierSet.addAll(Arrays.asList(batch.getSupplierCode().split(","))); + } + newBatch.setSupplierCode(String.join(",", supplierSet)); + mergedBatches.put(specialKey, newBatch); + continue; + } + + String key = batch.getStartSiteCode() + "_" + batch.getNextSiteCode(); + if (mergedBatches.containsKey(key)) { + EmisTmsSiteBatch existingBatch = mergedBatches.get(key); + // 合并supplierCode,去重、排序 + Set supplierSet = new TreeSet<>(); + if (StringUtils.isNotBlank(existingBatch.getSupplierCode())) { + supplierSet.addAll(Arrays.asList(existingBatch.getSupplierCode().split(","))); + } + if (StringUtils.isNotBlank(batch.getSupplierCode())) { + supplierSet.addAll(Arrays.asList(batch.getSupplierCode().split(","))); + } + // 新建一个新的Batch对象,复制属性,保证线程安全 + EmisTmsSiteBatch newBatch = new EmisTmsSiteBatch(); + BeanUtils.copyProperties(existingBatch, newBatch); + newBatch.setSupplierCode(String.join(",", supplierSet)); + mergedBatches.put(key, newBatch); + } else { + // 新建对象,避免外部引用被修改 + EmisTmsSiteBatch newBatch = new EmisTmsSiteBatch(); + BeanUtils.copyProperties(batch, newBatch); + Set supplierSet = new TreeSet<>(); + if (StringUtils.isNotBlank(batch.getSupplierCode())) { + supplierSet.addAll(Arrays.asList(batch.getSupplierCode().split(","))); + } + newBatch.setSupplierCode(String.join(",", supplierSet)); + mergedBatches.put(key, newBatch); + } + } + waybillBatches = new ArrayList<>(mergedBatches.values()); + + // 检查运单是否匹配线路规划树 + String startSiteCode = StringUtil.isBlank(waybill.getStartSiteCode()) ? waybill.getSendSiteCode() : waybill.getStartSiteCode(); + boolean isAnyBranchMatched = checkBranchMatchV2(ruleListByProductType, waybillBatches, waybill, + missRecords,startSiteCode); + + if (isAnyBranchMatched) { + // 创建批次状态记录 + EmisWaybillBatchStatus batchStatus = new EmisWaybillBatchStatus(); + batchStatus.setBillCode(waybill.getBillCode()); + batchStatus.setSiteBatchStatus("1"); // 1表示匹配成功 +// batchStatus.setBlManual("1"); + Date now = new Date(); + batchStatus.setCreateBy("system"); + batchStatus.setCreateTime(now); + batchStatus.setCreateSite("88888"); + batchStatusList.add(batchStatus); + } + successCount++; + } catch (Exception e) { + log.error("Failed to process waybill: {}", waybill.getBillCode(), e); + failCount++; + failedBillCodes.add(waybill.getBillCode()); + } + } + + return new ProcessResult(successCount, failCount, failedBillCodes, batchStatusList, + missRecords); + } + + private EmisTmsSiteBatchMiss createMissRecord(EmisWaybill waybill) { + EmisTmsSiteBatchMiss miss = new EmisTmsSiteBatchMiss(); + miss.setBillCode(waybill.getBillCode()); + Date now = new Date(); + miss.setCreateBy("system"); + miss.setCreateTime(now); + miss.setCreateSite("88888"); + miss.setStartSiteCode(waybill.getStartSiteCode()); + miss.setNextSiteCode(waybill.getDestinationCode()); + return miss; + } + + /** + * 检查一个分支是否完全匹配(按起始网点递归向下遍历) + * + * @param ruleList 线路规划规则列表(同一线路+产品类型) + * @param waybillBatches 运单批次列表(已按起始/下一网点合并) + * @param waybill 运单 + * @param missRecords 漏组记录集合 + * @param startSiteCode 当前起始网点 + * @return 是否存在任意一条完全匹配的路径 + */ + private boolean checkBranchMatchV2(List ruleList, List waybillBatches, + EmisWaybill waybill, List missRecords, String startSiteCode) { + if (StringUtils.isBlank(startSiteCode)) { + return false; + } + + // 当前起始网点下的规则 + List currentRules = ruleList.stream() + .filter(rule -> StringUtils.equals(rule.getStartSiteCode(), startSiteCode)) + .collect(Collectors.toList()); + + if (CollectionUtil.isEmpty(currentRules)) { + EmisTmsSiteBatchMiss miss = createMissRecord(waybill); + + miss.setMissReason(waybill.getStartSiteName() +" 尚未完成组批次,请尽快完成,避免影响下一程同事组批次进度" ); + miss.setLineCode(waybill.getTransLineType()); + miss.setProductType(waybill.getProductType()); + miss.setStartSiteCode(startSiteCode); + miss.setNextSiteCode(""); + miss.setMissType("0"); + + missRecords.add(miss); + return false; + } + // 使用包装方法,内部带 visitedSite 防止死循环 + return checkBranchMatchV2(ruleList, waybillBatches, waybill, missRecords, startSiteCode, new HashSet<>()); + } + + /** + * 真正的递归实现,增加 visitedSiteCode 防止起始网点出现环路导致死递归。 + */ + private boolean checkBranchMatchV2(List ruleList, + List waybillBatches, + EmisWaybill waybill, + List missRecords, + String startSiteCode, + Set visitedSiteCodes) { + + if (StringUtils.isBlank(startSiteCode)) { + return false; + } + + // 防止环路递归 + if (!visitedSiteCodes.add(startSiteCode)) { + return false; + } + + // 当前起始网点下的规则 + List currentRules = ruleList.stream() + .filter(rule -> StringUtils.equals(rule.getStartSiteCode(), startSiteCode)) + .collect(Collectors.toList()); + + // 当前起始网点下没有配置规则,认为本分支到此结束,不再校验 + if (CollectionUtil.isEmpty(currentRules)) { + return true; + } + boolean hasNextSite = false; + for (EmisTransPlanRule rule : currentRules) { + // 当前下一网点下的规则 + List nextRules = ruleList.stream() + .filter(r -> StringUtils.equals(r.getStartSiteCode(), rule.getNextSiteCode())) + .collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(nextRules)) { + hasNextSite = true; + break; + } + } + // 检查是否为特殊运输线路类型或清关类型 + boolean isSpecialTransLine = "004".equals(waybill.getTransLineType()) && + ("24401".equals(waybill.getProductType()) || "24402".equals(waybill.getProductType())); + boolean isSpecialCustomsClear = "2".equals(waybill.getCustomsClear()) && "2".equals(waybill.getTransType()); + if ((isSpecialTransLine || isSpecialCustomsClear) && !hasNextSite && currentRules.get(0).getStartSiteName().contains("机场")) { + return true; + } + + // 当前起点对应的所有批次 + List startBatches = waybillBatches.stream() + .filter(batch -> startSiteCode.equals(batch.getStartSiteCode())) + .collect(Collectors.toMap( + // 以起始网点、下一网点、供应商的组合作为key进行去重 + batch -> StringUtils.defaultString(batch.getStartSiteCode()) + "_" + + StringUtils.defaultString(batch.getNextSiteCode()) + "_" + + StringUtils.defaultString(batch.getSupplierCode()), + batch -> batch, + // 如果key重复,保留第一个 + (existing, replacement) -> existing + )) + .values() + .stream() + .collect(Collectors.toList()); + + // 没有任何批次从该网点发出,则这些规则都视为漏组 + if (CollectionUtil.isEmpty(startBatches)) { + setMissRecordsV2(waybill, missRecords, currentRules); + return false; + } + + if(startBatches.size()>1){ + setMissRecordsV2(waybill, missRecords, currentRules); + return false; + } + + EmisTmsSiteBatch startBatch = startBatches.get(0); + + boolean anyPathMatched = false; + + // 找到与当前批次(nextSiteCode + supplier)完全匹配的规则 + List matchedRules = currentRules.stream() + .filter(rule -> StringUtils.equals(rule.getNextSiteCode(), startBatch.getNextSiteCode()) + && compareSupplierCodes(rule.getSupplierCode(), startBatch.getSupplierCode()) && startBatch.getEtd().before(rule.getEndDate()) + && !startBatch.getEtd().before(rule.getStartDate())) + .collect(Collectors.toList()); + + // 如果该批次在当前起点下没有任何匹配规则,则当前起点下的规则整体视为漏组 + if (CollectionUtil.isEmpty(matchedRules)) { + setMissRecordsV2(waybill, missRecords, currentRules); + return anyPathMatched; + } + + // 存在匹配规则,则沿着下一网点继续递归校验 + boolean childMatched = checkBranchMatchV2(ruleList, waybillBatches, waybill, + missRecords, startBatch.getNextSiteCode(), visitedSiteCodes); + + if (childMatched) { + anyPathMatched = true; + // 已经有一条路径完全匹配,可以直接返回 + } + + return anyPathMatched; + } + + /** + * 按 V2 规则生成漏组记录: + * 循环 ruleList,为每一个 EmisTransPlanRule 生成一条 miss 记录。 + * 参考 EmisBaseService.setMissRecords 中设置 miss 的逻辑。 + */ + private void setMissRecordsV2(EmisWaybill waybill, + List missRecords, + List ruleList) { + if (CollectionUtil.isEmpty(ruleList)) { + return; + } + + // 按规则 ID 去重,避免重复生成同一规则的漏组 + List distinctRules = ruleList.stream() + .filter(Objects::nonNull) + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(EmisTransPlanRule::getId))), + ArrayList::new)); + +// for (EmisTransPlanRule rule : distinctRules) { +// if (rule == null) { +// continue; +// } +// EmisTmsSiteBatchMiss miss = createMissRecord(waybill); +// +// String supplierNames = rule.getSupplierName(); +// String missReasonDetail = String.format("%s-%s-%s", +// StringUtils.defaultString(rule.getStartSiteName(), rule.getStartSiteCode()), +// StringUtils.defaultString(rule.getNextSiteName(), rule.getNextSiteCode()), +// StringUtils.defaultString(supplierNames, rule.getSupplierCode())); +// miss.setMissReason("组批次有遗漏/错误,请根据推荐路线排查: " + missReasonDetail); +// +// // 参考 EmisBaseService.setRule 填充规则相关字段 +// miss.setTransPlanRuleId(rule.getId()); +// miss.setLineCode(rule.getLineCode()); +// miss.setProductType(waybill.getProductType()); +// miss.setStartSiteCode(rule.getStartSiteCode()); +// miss.setNextSiteCode(rule.getNextSiteCode()); +// miss.setManager(rule.getManager()); +// miss.setSupplierCode(rule.getSupplierCode()); +// miss.setStartDate(rule.getStartDate()); +// miss.setEndDate(rule.getEndDate()); +// miss.setMissType("0"); +// +// missRecords.add(miss); +// } + + EmisTransPlanRule rule = distinctRules.get(0); + EmisTmsSiteBatchMiss miss = createMissRecord(waybill); + + miss.setMissReason(rule.getStartSiteName() +" 尚未完成组批次,请尽快完成,避免影响下一程同事组批次进度" ); + + // 参考 EmisBaseService.setRule 填充规则相关字段 + miss.setTransPlanRuleId(rule.getId()); + miss.setLineCode(rule.getLineCode()); + miss.setProductType(waybill.getProductType()); + miss.setStartSiteCode(rule.getStartSiteCode()); + miss.setNextSiteCode(""); + miss.setManager(rule.getManager()); +// miss.setSupplierCode(rule.getSupplierCode()); + miss.setStartDate(rule.getStartDate()); + miss.setEndDate(rule.getEndDate()); + miss.setMissType("0"); + + missRecords.add(miss); + } + } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissStatisticsServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissStatisticsServiceImpl.java index 36236454e..11f6b8f64 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissStatisticsServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisTmsSiteBatchMissStatisticsServiceImpl.java @@ -55,6 +55,21 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa return result; } + /** + * 查询漏组批次统计列表 + */ + @Override + public List selectStatisticsListV2( + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) { + log.info("查询漏组批次统计列表,startSiteCode: {}, billMonth: {}", + emisTmsSiteBatchMissStatistics.getStartSiteCode(), emisTmsSiteBatchMissStatistics.getBillMonth()); + + List result = statisticsMapper + .selectStatisticsListV2(emisTmsSiteBatchMissStatistics); + + return result; + } + /** * 导出漏组批次统计查询接口数据 */ @@ -89,6 +104,40 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa } } + /** + * 导出漏组批次统计查询接口数据 + */ + @Override + public void exportStatisticsDataV2(HttpServletResponse response, + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) { + try { + // 设置响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode("漏组批次统计汇总_" + System.currentTimeMillis(), "UTF-8").replaceAll("\\+", + "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + // 查询统计数据 + List statisticsList = selectStatisticsListV2(emisTmsSiteBatchMissStatistics); + + // 转换为导出格式 + List exportList = convertToExportFormat(statisticsList); + + // 添加合计行 + addTotalRow(exportList); + + // 导出Excel + EasyExcel.write(response.getOutputStream(), EmisTmsSiteBatchMissStatisticsExport.class) + .sheet("漏组批次统计汇总") + .doWrite(exportList); + + } catch (IOException e) { + log.error("导出漏组批次统计数据失败", e); + throw new RuntimeException("导出失败:" + e.getMessage()); + } + } + /** * 转换为导出格式 */ @@ -363,6 +412,136 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa } } + /** + * 流式导出漏组详细数据(按月份分sheet)- 性能优化版本 + * 支持大数据量导出,避免内存溢出 + */ + @Override + public void exportDetailDataByMonthStreamV2(HttpServletResponse response, + EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) { + long startTime = System.currentTimeMillis(); + try { + // 设置响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode("漏组详细数据_" + System.currentTimeMillis(), "UTF-8").replaceAll("\\+", + "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + // 先获取总记录数,用于进度跟踪 + long totalCount = statisticsMapper.countDetailDataByMonthV2(emisTmsSiteBatchMissStatistics); + log.info("开始流式导出漏组详细数据,总记录数: {}, 查询条件: {}", totalCount, emisTmsSiteBatchMissStatistics); + + if (totalCount == 0) { + // 创建空Excel + EasyExcel.write(response.getOutputStream(), EmisTmsSiteBatchMiss.class) + .sheet("无数据") + .doWrite(new ArrayList<>()); + return; + } + + // 简化版本:直接查询所有数据并导出,避免复杂的流式处理 + // 如果数据量很大,可以考虑分批处理 + List allData = statisticsMapper + .selectDetailDataByMonthV2(emisTmsSiteBatchMissStatistics); + + log.info("查询到数据条数: {}", allData != null ? allData.size() : 0); + + if (allData == null || allData.isEmpty()) { + EasyExcel.write(response.getOutputStream(), EmisTmsSiteBatchMissExport.class) + .sheet("无数据") + .doWrite(new ArrayList<>()); + return; + } + + // 转换为专门的导出DTO,避免Map类型问题 + List exportData = allData.stream() + .filter(Objects::nonNull) + .map(this::convertToExportDto) + .collect(Collectors.toList()); + + log.info("转换后数据条数: {}", exportData.size()); + + // 按月份分组数据 + Map> dataByMonth = exportData.stream() + .collect(Collectors.groupingBy(item -> { + if (item.getSendDate() != null) { + synchronized (MONTH_FORMAT) { + return MONTH_FORMAT.format(item.getSendDate()); + } + } + return "未知月份"; + })); + + // 创建Excel写入器 + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build(); + + // 按月份从小到大排序 + List sortedMonths = dataByMonth.keySet().stream() + .filter(month -> !"未知月份".equals(month)) + .sorted() + .collect(Collectors.toList()); + + // 如果有未知月份,放在最后 + if (dataByMonth.containsKey("未知月份")) { + sortedMonths.add("未知月份"); + } + + int sheetIndex = 0; + for (String month : sortedMonths) { + List monthData = dataByMonth.get(month); + + if (monthData != null && !monthData.isEmpty()) { + // 创建sheet,使用月份作为sheet名称 + String sheetName = month + "月"; + WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex, sheetName) + .head(EmisTmsSiteBatchMissExport.class) + .build(); + + // 写入数据 + excelWriter.write(monthData, writeSheet); + sheetIndex++; + log.info("写入{}月数据,条数: {}", month, monthData.size()); + } + } + + // 关闭写入器 + excelWriter.finish(); + log.info("Excel写入成功,共创建{}个sheet", sheetIndex); + + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + log.info("流式导出完成,总处理记录数: {}, 耗时: {}ms, 平均处理速度: {}/s", + allData.size(), duration, allData.size() > 0 ? (allData.size() * 1000 / duration) : 0); + + } catch (IOException e) { + long endTime = System.currentTimeMillis(); + log.error("流式导出漏组详细数据失败,耗时: {}ms", endTime - startTime, e); + // 不抛出异常,避免重复处理响应 + try { + if (!response.isCommitted()) { + response.reset(); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write("{\"success\":false,\"message\":\"导出失败:" + e.getMessage() + "\"}"); + } + } catch (Exception ex) { + log.error("写入错误响应失败", ex); + } + } catch (Exception e) { + long endTime = System.currentTimeMillis(); + log.error("流式导出漏组详细数据发生未知错误,耗时: {}ms", endTime - startTime, e); + try { + if (!response.isCommitted()) { + response.reset(); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write("{\"success\":false,\"message\":\"导出失败:" + e.getMessage() + "\"}"); + } + } catch (Exception ex) { + log.error("写入错误响应失败", ex); + } + } + } + /** * 将EmisTmsSiteBatchMiss转换为EmisTmsSiteBatchMissExport用于导出 * 根据实际Excel截图字段进行映射 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 f5d2480fe..902b73f4d 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 @@ -27,6 +27,7 @@ import com.xdadan.erp.emis.mapper.EmisTmsSiteBatchLogMapper; import com.xdadan.erp.emis.mapper.EmisWaybillMapper; import com.xdadan.erp.emis.mapper.EmisTmsCostFeeMapper; import com.xdadan.erp.emis.service.EmisBaseService; +import com.xdadan.erp.emis.service.IEmisTmsSiteBatchMissService; import jodd.util.StringUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -71,6 +72,9 @@ public class EmisTmsSiteBatchServiceImpl extends EmisBaseService implements IEmi @Autowired private EmisTmsCostFeeMapper emisTmsCostFeeMapper; + @Autowired + private IEmisTmsSiteBatchMissService emisTmsSiteBatchMissService; + /** * 获取稽核数据 * @@ -512,6 +516,20 @@ public class EmisTmsSiteBatchServiceImpl extends EmisBaseService implements IEmi scanSiteBatchByWaybills(waybills); } + @Override + @Async + public void scanSiteBatchV2(String batchNo) { + log.info("start scan site batch V2 ,batchNo:{}", batchNo); + if (StringUtil.isBlank(batchNo)) { + return; + } + List waybills = emisTmsSiteBatchDtlMapper.selectEmisWayBillByBatchNo(batchNo); + if (CollectionUtil.isEmpty(waybills)) { + return; + } + emisTmsSiteBatchMissService.scanSiteBatchByWaybillsV2(waybills); + } + @Override @Transactional public int addAll(EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError { diff --git a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml index ab385207b..abfd63b4f 100644 --- a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissMapper.xml @@ -91,6 +91,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" left join sys_user u on w.register_man_code=u.emp_code and u.del_flag='0' + + select + m.id, m.bill_code, m.miss_reason, m.create_time, m.update_time, m.remark, m.del_flag, + m.line_code, m.product_type, + COALESCE(m.start_site_code, w.start_site_code, w.send_site_code) as start_site_code, + COALESCE(m.next_site_code, w.destination_code) as 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, s4.site_name as dispatch_underling_site_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, + w.product_type,w.problem_type,w.virtual_remark,w.dispatch_underling_site_code, + w.payment_type, w.parcel_qty, w.bill_weight, w.total_volume, w.volume_weight, + w.settlement_weight, w.freight, w.remark as waybill_remark, w.fee_remark, m.manager, k.trans_manager, + w.payee, w.salesmen, u.emp_name as registerManName, + (SELECT GROUP_CONCAT(s.name) + FROM emis_supplier s + WHERE FIND_IN_SET(s.code, m.supplier_code) + AND s.del_flag = '0') as supplier_name, + (SELECT GROUP_CONCAT(p.prod_name) + FROM emis_trans_product p + WHERE FIND_IN_SET(p.prod_code, m.product_type) + AND p.del_flag = '0') as product_type_name + from emis_tms_site_batch_miss_v2 m + left join emis_waybill w on m.bill_code = w.bill_code and w.del_flag='0' + left join emis_site s1 on w.send_site_code=s1.site_code and s1.del_flag=0 + left join emis_site s2 on COALESCE(m.start_site_code, w.start_site_code, w.send_site_code)=s2.site_code and s2.del_flag=0 + left join emis_site s3 on COALESCE(m.next_site_code, w.destination_code)=s3.site_code and s3.del_flag=0 + left join emis_country c1 on w.send_country=c1.code and c1.del_flag='0' + left join emis_country c2 on w.receive_country=c2.code and c2.del_flag='0' + left join emis_site s4 on w.dispatch_underling_site_code=s4.site_code and s4.del_flag=0 + left join emis_trans_line k on w.trans_line_type=k.line_code and k.del_flag='0' + left join emis_trans_plan_rule r on m.trans_plan_rule_id=r.id and r.del_flag='0' + left join emis_trans_line l on m.line_code=l.line_code and l.del_flag='0' + left join sys_user u on w.register_man_code=u.emp_code and u.del_flag='0' + + @@ -148,8 +184,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" b.bill_code, null as id, '已组批次成功' as miss_reason, null as create_by, null as create_time, null as update_by, null as update_time, null as remark, '0' as del_flag, - w.trans_line_type as line_code, w.product_type, - COALESCE(null, w.start_site_code, w.send_site_code) as start_site_code, + w.trans_line_type as line_code, w.product_type, + COALESCE(null, w.start_site_code, w.send_site_code) as start_site_code, COALESCE(null, w.destination_code) as next_site_code, null as supplier_code, null as start_date, null as end_date, '0' as miss_type, w.send_site_code, s1.site_name as send_site_name, @@ -350,6 +386,219 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + SELECT t.* FROM emis_tms_site_batch_miss t diff --git a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissRecordMapper.xml b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissRecordMapper.xml index e5a696fd1..0b7bba3b9 100644 --- a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissRecordMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissRecordMapper.xml @@ -3,7 +3,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + @@ -29,7 +29,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" failed_bill_codes, create_by, create_time, - create_site + create_site, + scan_version ) values ( #{totalProcessed}, #{successCount}, @@ -40,8 +41,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{failedBillCodes}, #{createBy}, #{createTime}, - #{createSite} + #{createSite}, + #{scanVersion} ) - \ No newline at end of file + diff --git a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissStatisticsMapper.xml b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissStatisticsMapper.xml index e48ceaedd..c5ebd6653 100644 --- a/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissStatisticsMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisTmsSiteBatchMissStatisticsMapper.xml @@ -39,12 +39,40 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ORDER BY w.send_date, COALESCE(bm.start_site_code, w.start_site_code, w.send_site_code) + + + + + + + diff --git a/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml b/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml index 5446dc83d..e34b1075e 100644 --- a/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml @@ -3925,9 +3925,10 @@