Merge pull request 'develop' (#246) from develop into master
Reviewed-on: http://git.xdadan.loc/tanex/emis-service/pulls/246
This commit is contained in:
commit
f377b55361
@ -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<EmisTransLine> 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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<EmisTmsSiteBatchMiss> 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<String> 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("取消确认成功");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<EmisTmsSiteBatchMissStatistics> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import lombok.Data;
|
||||
|
||||
/**
|
||||
* TMS漏组批次扫描记录对象
|
||||
*
|
||||
*
|
||||
* @author heyu
|
||||
*/
|
||||
@Data
|
||||
@ -36,4 +36,7 @@ public class EmisTmsSiteBatchMissRecord extends BaseEntity {
|
||||
/** 失败运单号列表 */
|
||||
private String failedBillCodes;
|
||||
|
||||
}
|
||||
/** 扫描版本 */
|
||||
private String scanVersion;
|
||||
|
||||
}
|
||||
|
||||
@ -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<EmisTmsSiteBatchMiss> selectEmisTmsSiteBatchMissList(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss);
|
||||
|
||||
/**
|
||||
* 查询TMS漏组批次信息列表_v2
|
||||
*
|
||||
* @param emisTmsSiteBatchMiss TMS漏组批次信息
|
||||
* @return TMS漏组批次信息集合
|
||||
*/
|
||||
public List<EmisTmsSiteBatchMiss> 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<EmisTmsSiteBatchMiss> list);
|
||||
|
||||
/**
|
||||
* 批量插入TMS漏组批次信息--V2
|
||||
*
|
||||
* @param list TMS漏组批次信息列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchInsertEmisTmsSiteBatchMissV2(List<EmisTmsSiteBatchMiss> list);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lineCode
|
||||
@ -87,10 +103,19 @@ public interface EmisTmsSiteBatchMissMapper {
|
||||
*/
|
||||
void deleteByBillCodes(@Param("billCodes") List<String> billCodes);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param billCodes
|
||||
*/
|
||||
void deleteByBillCodesV2(@Param("billCodes") List<String> billCodes);
|
||||
|
||||
void deleteReally(String lineCode);
|
||||
|
||||
void deleteReallyV2(String lineCode);
|
||||
|
||||
/**
|
||||
* 根据运单号批量查询TMS漏组批次信息
|
||||
*/
|
||||
List<EmisWaybill> selectByBillCodes(@Param("billCodes") List<String> billCodes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -23,6 +23,15 @@ public interface EmisTmsSiteBatchMissStatisticsMapper {
|
||||
List<EmisTmsSiteBatchMissStatistics> selectStatisticsList(
|
||||
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
|
||||
/**
|
||||
* 查询漏组批次统计列表--V2
|
||||
*
|
||||
* @param emisTmsSiteBatchMissStatistics 查询条件对象
|
||||
* @return 统计结果列表
|
||||
*/
|
||||
List<EmisTmsSiteBatchMissStatistics> selectStatisticsListV2(
|
||||
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
|
||||
/**
|
||||
* 查询漏组详细数据列表(按月份分组)
|
||||
*
|
||||
@ -31,6 +40,14 @@ public interface EmisTmsSiteBatchMissStatisticsMapper {
|
||||
*/
|
||||
List<EmisTmsSiteBatchMiss> selectDetailDataByMonth(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
|
||||
/**
|
||||
* 查询漏组详细数据列表(按月份分组)
|
||||
*
|
||||
* @param emisTmsSiteBatchMissStatistics 查询条件
|
||||
* @return 详细数据列表
|
||||
*/
|
||||
List<EmisTmsSiteBatchMiss> selectDetailDataByMonthV2(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
|
||||
/**
|
||||
* 分页查询漏组详细数据列表(按月份分组)- 性能优化版本
|
||||
*
|
||||
@ -51,4 +68,12 @@ public interface EmisTmsSiteBatchMissStatisticsMapper {
|
||||
* @return 总记录数
|
||||
*/
|
||||
long countDetailDataByMonth(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
|
||||
/**
|
||||
* 统计漏组详细数据总数
|
||||
*
|
||||
* @param emisTmsSiteBatchMissStatistics 查询条件
|
||||
* @return 总记录数
|
||||
*/
|
||||
long countDetailDataByMonthV2(EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
}
|
||||
|
||||
@ -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<String> failedBillCodes, int totalBatchStatusRecords, int totalMissRecords) {
|
||||
List<String> 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);
|
||||
}
|
||||
|
||||
@ -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<EmisTmsSiteBatchMiss> selectEmisTmsSiteBatchMissList(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss);
|
||||
|
||||
/**
|
||||
* 查询TMS漏组批次信息列表_v2
|
||||
*
|
||||
* @param emisTmsSiteBatchMiss TMS漏组批次信息
|
||||
* @return TMS漏组批次信息集合
|
||||
*/
|
||||
public List<EmisTmsSiteBatchMiss> selectEmisTmsSiteBatchMissListV2(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss);
|
||||
|
||||
/**
|
||||
* 新增TMS漏组批次信息
|
||||
*
|
||||
@ -90,4 +99,21 @@ public interface IEmisTmsSiteBatchMissService {
|
||||
* @param billCodes 运单号列表
|
||||
*/
|
||||
void cancelConfirmBatch(List<String> billCodes) throws EmisBizError;
|
||||
|
||||
/**
|
||||
* 批量取消确认组批次--V2:
|
||||
* 1) 根据运单号列表删除运单组批次状态数据
|
||||
* 2) 重新扫描运单组批次状态
|
||||
*
|
||||
* @param billCodes 运单号列表
|
||||
*/
|
||||
void cancelConfirmBatchV2(List<String> billCodes) throws EmisBizError;
|
||||
|
||||
/**
|
||||
* 定时扫描运单货物组批次是否正确录入-V2
|
||||
*
|
||||
*/
|
||||
void autoScanSiteBatchV2(String lineCode);
|
||||
|
||||
void scanSiteBatchByWaybillsV2(List<EmisWaybill> emisWaybills);
|
||||
}
|
||||
|
||||
@ -24,6 +24,15 @@ public interface IEmisTmsSiteBatchMissStatisticsService {
|
||||
List<EmisTmsSiteBatchMissStatistics> selectStatisticsList(
|
||||
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics);
|
||||
|
||||
/**
|
||||
* 查询漏组批次统计列表--V2
|
||||
*
|
||||
* @param emisTmsSiteBatchMissStatistics 查询条件
|
||||
* @return 统计结果列表
|
||||
*/
|
||||
List<EmisTmsSiteBatchMissStatistics> 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);
|
||||
}
|
||||
|
||||
@ -114,6 +114,13 @@ public interface IEmisTmsSiteBatchService extends IDataAuditService
|
||||
*/
|
||||
void scanSiteBatch(String batchNo);
|
||||
|
||||
/**
|
||||
* 根据批次号扫描组批次--V2
|
||||
*
|
||||
* @param batchNo
|
||||
*/
|
||||
void scanSiteBatchV2(String batchNo);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param emisTmsSiteBatch
|
||||
|
||||
@ -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<EmisTmsSiteBatchMiss> selectEmisTmsSiteBatchMissListV2(EmisTmsSiteBatchMiss emisTmsSiteBatchMiss) {
|
||||
log.info("Selecting TMS site batch miss list with params: {}", emisTmsSiteBatchMiss);
|
||||
List<EmisTmsSiteBatchMiss> 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<String> billCodes) throws EmisBizError {
|
||||
if (billCodes == null || billCodes.isEmpty()) {
|
||||
throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "运单号不能为空");
|
||||
}
|
||||
|
||||
// 1) 彻底删除运单组批次状态数据
|
||||
emisWaybillBatchStatusMapper.deleteByBillCodes(billCodes);
|
||||
|
||||
// 2) 批量查询运单信息
|
||||
List<EmisWaybill> 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<EmisTransPlanRule> treeRules = this.selectEmisTransPlanRuleTree(lineCode);
|
||||
if (treeRules.isEmpty()) {
|
||||
log.info("No trans plan rules found, skip auto scan");
|
||||
List<EmisWaybill> waybills = emisWaybillMapper.selectWaybillListBySiteBatchStatus(0, 100000,
|
||||
lineCode);
|
||||
if (waybills.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<EmisTmsSiteBatchMiss> 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<Future<ProcessResult>> processFutures = new ArrayList<>();
|
||||
List<Future<EmisBaseService.ProcessResult>> processFutures = new ArrayList<>();
|
||||
|
||||
for (List<EmisWaybill> batch : batches) {
|
||||
processFutures.add(executorService.submit(() -> processWaybillBatch(batch, transPlanRulesByLineCode)));
|
||||
@ -346,9 +409,9 @@ public class EmisTmsSiteBatchMissServiceImpl extends EmisBaseService implements
|
||||
List<EmisTmsSiteBatchMiss> allMissRecords = new ArrayList<>();
|
||||
int timeoutMinutes = 10; // 10分钟超时
|
||||
|
||||
for (Future<ProcessResult> future : processFutures) {
|
||||
for (Future<EmisBaseService.ProcessResult> 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<EmisTransPlanRule> selectEmisTransPlanRuleTreeV2(String lineCode) {
|
||||
EmisTransPlanRule emisTransPlanRule = new EmisTransPlanRule();
|
||||
emisTransPlanRule.setLineCode(lineCode);
|
||||
List<EmisTransPlanRule> allRules = emisTransPlanRuleMapper.selectRulesForAllScan(emisTransPlanRule);
|
||||
// List<EmisTransPlanRule> 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<String> failedBillCodes = new ArrayList<>();
|
||||
|
||||
// 获取所有线路规划
|
||||
List<EmisTransPlanRule> treeRules = this.selectEmisTransPlanRuleTreeV2(lineCode);
|
||||
if (treeRules.isEmpty()) {
|
||||
log.info("No trans plan rules found, skip auto scan v2");
|
||||
return;
|
||||
}
|
||||
|
||||
// 按线路编码分组
|
||||
Map<String, List<EmisTransPlanRule>> 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<Future<List<EmisWaybill>>> futures = new ArrayList<>();
|
||||
|
||||
// 先查询所有数据
|
||||
while (true) {
|
||||
List<EmisWaybill> waybills = emisWaybillMapper.selectWaybillListBySiteBatchStatus(offset, pageSize,
|
||||
lineCode);
|
||||
if (waybills.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
futures.add(executorService.submit(() -> waybills));
|
||||
offset += pageSize;
|
||||
}
|
||||
|
||||
// 等待所有查询完成并收集结果
|
||||
List<EmisWaybill> allWaybills = new ArrayList<>();
|
||||
for (Future<List<EmisWaybill>> future : futures) {
|
||||
try {
|
||||
List<EmisWaybill> waybills = future.get();
|
||||
allWaybills.addAll(waybills);
|
||||
totalProcessed += waybills.size();
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting waybill results", e);
|
||||
}
|
||||
}
|
||||
|
||||
int batchSize = 1000;
|
||||
List<List<EmisWaybill>> 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<Future<ProcessResult>> processFutures = new ArrayList<>();
|
||||
|
||||
for (List<EmisWaybill> batch : batches) {
|
||||
processFutures.add(executorService.submit(() -> processWaybillBatchV2(batch, transPlanRulesByLineCode)));
|
||||
}
|
||||
|
||||
// 添加超时机制,避免长时间阻塞
|
||||
List<EmisWaybillBatchStatus> allBatchStatus = new ArrayList<>();
|
||||
List<EmisTmsSiteBatchMiss> allMissRecords = new ArrayList<>();
|
||||
int timeoutMinutes = 10; // 10分钟超时
|
||||
|
||||
for (Future<ProcessResult> 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<String, EmisWaybillBatchStatus> batchStatusMap = allBatchStatus.stream()
|
||||
.collect(Collectors.toMap(
|
||||
EmisWaybillBatchStatus::getBillCode,
|
||||
v -> v,
|
||||
(existing, replacement) -> existing));
|
||||
List<EmisWaybillBatchStatus> uniqueBatchStatus = new ArrayList<>(batchStatusMap.values());
|
||||
|
||||
Map<String, EmisTmsSiteBatchMiss> missMap = allMissRecords.stream()
|
||||
.collect(Collectors.toMap(
|
||||
r -> r.getBillCode() + "_" + r.getMissReason(),
|
||||
v -> v,
|
||||
(existing, replacement) -> existing));
|
||||
List<EmisTmsSiteBatchMiss> 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<EmisWaybillBatchStatus> 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<EmisTmsSiteBatchMiss> 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<EmisWaybill> emisWaybills) {
|
||||
try {
|
||||
if (CollectionUtil.isEmpty(emisWaybills)) {
|
||||
return;
|
||||
}
|
||||
List<String> billCodes = emisWaybills.stream().map(EmisWaybill::getBillCode).collect(Collectors.toList());
|
||||
if (CollectionUtil.isEmpty(billCodes)) {
|
||||
return;
|
||||
}
|
||||
List<String> 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<String> failedBillCodes = new ArrayList<>();
|
||||
|
||||
// 获取所有线路规划
|
||||
List<EmisTransPlanRule> treeRules = this.selectEmisTransPlanRuleTree(lineCodes);
|
||||
if (treeRules.isEmpty()) {
|
||||
log.info("No trans plan rules found, skip auto scan v2");
|
||||
return;
|
||||
}
|
||||
|
||||
// 按线路编码分组
|
||||
Map<String, List<EmisTransPlanRule>> transPlanRulesByLineCode = treeRules.stream()
|
||||
.collect(Collectors.groupingBy(EmisTransPlanRule::getLineCode));
|
||||
|
||||
// 直接处理运单批次
|
||||
ProcessResult result = processWaybillBatchV2(emisWaybills, transPlanRulesByLineCode);
|
||||
successCount += result.getSuccessCount();
|
||||
failCount += result.getFailCount();
|
||||
failedBillCodes.addAll(result.getFailedBillCodes());
|
||||
|
||||
// 批量插入运单组批次状态记录
|
||||
List<EmisWaybillBatchStatus> batchStatusList = result.getBatchStatusList();
|
||||
List<EmisTmsSiteBatchMiss> missRecords = result.getMissRecords();
|
||||
if (!batchStatusList.isEmpty()) {
|
||||
filterBatchStatusList(batchStatusList, missRecords);
|
||||
}
|
||||
|
||||
// 批量插入运单组批次状态记录
|
||||
if (!batchStatusList.isEmpty()) {
|
||||
emisWaybillBatchStatusMapper.batchInsertEmisWaybillBatchStatus(result.getBatchStatusList());
|
||||
totalBatchStatusRecords += result.getBatchStatusList().size();
|
||||
}
|
||||
|
||||
// 批量保存漏组记录
|
||||
if (!missRecords.isEmpty()) {
|
||||
List<EmisTmsSiteBatchMiss> 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<String> failedBillCodes;
|
||||
private final List<EmisWaybillBatchStatus> batchStatusList;
|
||||
private final List<EmisTmsSiteBatchMiss> missRecords;
|
||||
|
||||
public ProcessResult(int successCount, int failCount, List<String> failedBillCodes,
|
||||
List<EmisWaybillBatchStatus> batchStatusList, List<EmisTmsSiteBatchMiss> 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<String> getFailedBillCodes() {
|
||||
return failedBillCodes;
|
||||
}
|
||||
|
||||
public List<EmisWaybillBatchStatus> getBatchStatusList() {
|
||||
return batchStatusList;
|
||||
}
|
||||
|
||||
public List<EmisTmsSiteBatchMiss> getMissRecords() {
|
||||
return missRecords;
|
||||
}
|
||||
}
|
||||
|
||||
public ProcessResult processWaybillBatchV2(List<EmisWaybill> waybills,
|
||||
Map<String, List<EmisTransPlanRule>> transPlanRulesByLineCode) {
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
List<String> failedBillCodes = new ArrayList<>();
|
||||
List<EmisTmsSiteBatchMiss> missRecords = new ArrayList<>();
|
||||
List<EmisWaybillBatchStatus> batchStatusList = new ArrayList<>();
|
||||
|
||||
// 获取所有运单号
|
||||
List<String> billCodes = waybills.stream()
|
||||
.map(EmisWaybill::getBillCode)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 一次性查询所有运单对应的组批次信息
|
||||
List<EmisTmsSiteBatch> siteBatches = emisTmsSiteBatchMapper
|
||||
.selectEmisTmsSiteBatchListByBillCodes(billCodes);
|
||||
|
||||
// 按运单号分组
|
||||
Map<String, List<EmisTmsSiteBatch>> 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<EmisTransPlanRule> 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<EmisTransPlanRule> 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<EmisTmsSiteBatch> 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<String, EmisTmsSiteBatch> 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<String> 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<String> 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<String> 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<EmisTransPlanRule> ruleList, List<EmisTmsSiteBatch> waybillBatches,
|
||||
EmisWaybill waybill, List<EmisTmsSiteBatchMiss> missRecords, String startSiteCode) {
|
||||
if (StringUtils.isBlank(startSiteCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 当前起始网点下的规则
|
||||
List<EmisTransPlanRule> 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<EmisTransPlanRule> ruleList,
|
||||
List<EmisTmsSiteBatch> waybillBatches,
|
||||
EmisWaybill waybill,
|
||||
List<EmisTmsSiteBatchMiss> missRecords,
|
||||
String startSiteCode,
|
||||
Set<String> visitedSiteCodes) {
|
||||
|
||||
if (StringUtils.isBlank(startSiteCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 防止环路递归
|
||||
if (!visitedSiteCodes.add(startSiteCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 当前起始网点下的规则
|
||||
List<EmisTransPlanRule> 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<EmisTransPlanRule> 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<EmisTmsSiteBatch> 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<EmisTransPlanRule> 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<EmisTmsSiteBatchMiss> missRecords,
|
||||
List<EmisTransPlanRule> ruleList) {
|
||||
if (CollectionUtil.isEmpty(ruleList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 按规则 ID 去重,避免重复生成同一规则的漏组
|
||||
List<EmisTransPlanRule> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -55,6 +55,21 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询漏组批次统计列表
|
||||
*/
|
||||
@Override
|
||||
public List<EmisTmsSiteBatchMissStatistics> selectStatisticsListV2(
|
||||
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) {
|
||||
log.info("查询漏组批次统计列表,startSiteCode: {}, billMonth: {}",
|
||||
emisTmsSiteBatchMissStatistics.getStartSiteCode(), emisTmsSiteBatchMissStatistics.getBillMonth());
|
||||
|
||||
List<EmisTmsSiteBatchMissStatistics> 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<EmisTmsSiteBatchMissStatistics> statisticsList = selectStatisticsListV2(emisTmsSiteBatchMissStatistics);
|
||||
|
||||
// 转换为导出格式
|
||||
List<EmisTmsSiteBatchMissStatisticsExport> 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<EmisTmsSiteBatchMiss> 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<EmisTmsSiteBatchMissExport> exportData = allData.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(this::convertToExportDto)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
log.info("转换后数据条数: {}", exportData.size());
|
||||
|
||||
// 按月份分组数据
|
||||
Map<String, List<EmisTmsSiteBatchMissExport>> 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<String> 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<EmisTmsSiteBatchMissExport> 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截图字段进行映射
|
||||
|
||||
@ -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<EmisWaybill> waybills = emisTmsSiteBatchDtlMapper.selectEmisWayBillByBatchNo(batchNo);
|
||||
if (CollectionUtil.isEmpty(waybills)) {
|
||||
return;
|
||||
}
|
||||
emisTmsSiteBatchMissService.scanSiteBatchByWaybillsV2(waybills);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int addAll(EmisTmsSiteBatch emisTmsSiteBatch) throws EmisBizError {
|
||||
|
||||
@ -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'
|
||||
</sql>
|
||||
|
||||
<sql id="selectEmisTmsSiteBatchMissVoV2">
|
||||
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'
|
||||
</sql>
|
||||
|
||||
<!-- <select id="selectEmisTmsSiteBatchMissList" parameterType="EmisTmsSiteBatchMiss" resultMap="EmisTmsSiteBatchMissResult">-->
|
||||
<!-- <include refid="selectEmisTmsSiteBatchMissVo"/>-->
|
||||
<!-- <where>-->
|
||||
@ -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"
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
<select id="selectEmisTmsSiteBatchMissListV2" parameterType="EmisTmsSiteBatchMiss" resultMap="EmisTmsSiteBatchMissResult">
|
||||
<choose>
|
||||
<when test="missCount == -4 or missCount == -7">
|
||||
<!-- 当missCount=-4时,查询emis_waybill_batch_status表 -->
|
||||
select
|
||||
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,
|
||||
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,
|
||||
w.send_country, c1.name as send_country_name, w.destination_code, s2.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.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,
|
||||
null as manager, null as trans_manager,
|
||||
w.payee, w.salesmen, u.emp_name as registerManName,
|
||||
(SELECT GROUP_CONCAT(s.site_name ORDER BY FIND_IN_SET(s.site_code, w.start_site_code))
|
||||
FROM emis_site s
|
||||
WHERE FIND_IN_SET(s.site_code, w.start_site_code) AND s.del_flag = 0) as start_site_name,
|
||||
(SELECT GROUP_CONCAT(s.site_name ORDER BY FIND_IN_SET(s.site_code, w.next_site_code))
|
||||
FROM emis_site s
|
||||
WHERE FIND_IN_SET(s.site_code, w.next_site_code) AND s.del_flag = 0) as next_site_name,
|
||||
null as supplier_name,
|
||||
(SELECT GROUP_CONCAT(p.prod_name)
|
||||
FROM emis_trans_product p
|
||||
WHERE FIND_IN_SET(p.prod_code, w.product_type)
|
||||
AND p.del_flag = '0') as product_type_name,
|
||||
b.remark as manual_remark,b.bl_manual
|
||||
from emis_waybill_batch_status b
|
||||
inner join emis_waybill w on b.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_country c1 on w.send_country=c1.code and c1.del_flag=0
|
||||
left join emis_site s2 on w.dispatch_underling_site_code=s2.site_code and s2.del_flag=0
|
||||
left join emis_trans_line l on w.trans_line_type=l.line_code and l.del_flag=0
|
||||
left join emis_country c2 on w.receive_country=c2.code and c2.del_flag=0
|
||||
left join sys_user u on w.register_man_code=u.emp_code and u.del_flag='0'
|
||||
<where>
|
||||
b.site_batch_status = '1'
|
||||
<if test="billCode != null and billCode != '' and ( params.billCodeSortList == null or (params.billCodeSortList != null and params.billCodeSortList.size() == 1 ) )">
|
||||
and ( b.`bill_code`=#{billCode} or b.bill_code like concat('%',#{billCode}) )
|
||||
</if>
|
||||
<if test="missCount == -7">
|
||||
AND (b.bl_manual = '2' or b.bl_manual = '3')
|
||||
</if>
|
||||
<if test="params.billCodeSortList != null and params.billCodeSortList.size() > 1 ">
|
||||
and b.bill_code in
|
||||
<foreach collection="params.billCodeSortList" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="lineCode != null and lineCode != ''">
|
||||
AND w.trans_line_type = #{lineCode}
|
||||
</if>
|
||||
<if test="productType != null and productType != ''">
|
||||
AND FIND_IN_SET(#{productType}, w.product_type)
|
||||
</if>
|
||||
<if test="startSiteCode != null and startSiteCode != ''">
|
||||
AND (
|
||||
w.start_site_code REGEXP REPLACE(#{startSiteCode}, ',', '|')
|
||||
)
|
||||
</if>
|
||||
<if test="nextSiteCode != null and nextSiteCode != ''">
|
||||
AND (
|
||||
w.next_site_code REGEXP REPLACE(#{nextSiteCode}, ',', '|')
|
||||
)
|
||||
</if>
|
||||
<if test="blIsQuestion != null and blIsQuestion != ''">
|
||||
AND w.bl_is_question = #{blIsQuestion}
|
||||
</if>
|
||||
<if test="sendSiteCode != null and sendSiteCode != ''">
|
||||
AND w.send_site_code = #{sendSiteCode}
|
||||
</if>
|
||||
<if test="params.beginSendDate != null and params.beginSendDate != ''">
|
||||
and w.send_date <![CDATA[ >= ]]> #{params.beginSendDate}
|
||||
</if>
|
||||
<if test="params.endSendDate != null and params.endSendDate != ''">
|
||||
and w.send_date <![CDATA[ <= ]]> #{params.endSendDate}
|
||||
</if>
|
||||
<if test="params.privSiteCode != null and params.privSiteCode != '88888'">
|
||||
and (w.start_site_code=#{params.privSiteCode} or w.send_site_code=#{params.privSiteCode})
|
||||
</if>
|
||||
<if test="payee != null and payee != ''">
|
||||
AND w.payee like concat('%', #{payee}, '%')
|
||||
</if>
|
||||
<if test="salesmen != null and salesmen != ''">
|
||||
AND w.salesmen like concat('%', #{salesmen}, '%')
|
||||
</if>
|
||||
<if test="registerManName != null and registerManName != ''">
|
||||
AND u.emp_name like concat('%', #{registerManName}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</when>
|
||||
<otherwise>
|
||||
<include refid="selectEmisTmsSiteBatchMissVoV2"/>
|
||||
<where>
|
||||
m.del_flag = '0'
|
||||
<if test="missCount != null">
|
||||
<choose>
|
||||
<when test="missCount == -1">
|
||||
AND m.miss_type = 2
|
||||
</when>
|
||||
<when test="missCount == -2">
|
||||
AND m.miss_type = 3
|
||||
</when>
|
||||
<when test="missCount == -3">
|
||||
AND m.miss_type = 1
|
||||
</when>
|
||||
<when test="missCount == -6">
|
||||
AND m.miss_type = 4
|
||||
</when>
|
||||
<when test="missCount == 1">
|
||||
AND m.miss_type = 0
|
||||
</when>
|
||||
<!-- <when test="missCount == -5">-->
|
||||
<!-- AND m.bill_code IN (-->
|
||||
<!-- SELECT bill_code-->
|
||||
<!-- FROM emis_tms_site_batch_miss-->
|
||||
<!-- WHERE del_flag = '0'-->
|
||||
<!-- GROUP BY bill_code-->
|
||||
<!-- HAVING COUNT(*) > 9-->
|
||||
<!-- )-->
|
||||
<!-- </when>-->
|
||||
<!-- <when test="missCount > 0">-->
|
||||
<!-- AND m.bill_code IN (-->
|
||||
<!-- SELECT bill_code-->
|
||||
<!-- FROM emis_tms_site_batch_miss-->
|
||||
<!-- WHERE del_flag = '0'-->
|
||||
<!-- GROUP BY bill_code-->
|
||||
<!-- HAVING COUNT(*) = #{missCount}-->
|
||||
<!-- )-->
|
||||
<!-- AND m.miss_type = 0-->
|
||||
<!-- </when>-->
|
||||
</choose>
|
||||
</if>
|
||||
<if test="billCode != null and billCode != '' and ( params.billCodeSortList == null or (params.billCodeSortList != null and params.billCodeSortList.size() == 1 ) )">
|
||||
and ( m.`bill_code`=#{billCode} or m.bill_code like concat('%',#{billCode}) )
|
||||
</if>
|
||||
<if test="params.billCodeSortList != null and params.billCodeSortList.size() > 1 ">
|
||||
and m.bill_code in
|
||||
<foreach collection="params.billCodeSortList" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="missReason != null and missReason != ''">
|
||||
AND m.miss_reason like concat('%', #{missReason}, '%')
|
||||
</if>
|
||||
<if test="manager != null and manager != ''">
|
||||
AND (
|
||||
m.manager REGEXP REPLACE(#{manager}, ',', '|')
|
||||
)
|
||||
</if>
|
||||
<if test="transManager != null and transManager != ''">
|
||||
AND k.trans_manager like concat('%', #{transManager}, '%')
|
||||
</if>
|
||||
<if test="params.privSiteCode != null and params.privSiteCode != '88888'">
|
||||
and (w.start_site_code=#{params.privSiteCode} or w.send_site_code=#{params.privSiteCode} or m.start_site_code=#{params.privSiteCode} or m.next_site_code=#{params.privSiteCode})
|
||||
</if>
|
||||
<if test="lineCode != null and lineCode != ''">
|
||||
AND m.line_code = #{lineCode}
|
||||
</if>
|
||||
<if test="productType != null and productType != ''">
|
||||
AND FIND_IN_SET(#{productType}, m.product_type)
|
||||
</if>
|
||||
<if test="startSiteCode != null and startSiteCode != ''">
|
||||
AND (
|
||||
m.start_site_code REGEXP REPLACE(#{startSiteCode}, ',', '|')
|
||||
)
|
||||
</if>
|
||||
<if test="nextSiteCode != null and nextSiteCode != ''">
|
||||
AND (
|
||||
m.next_site_code REGEXP REPLACE(#{nextSiteCode}, ',', '|')
|
||||
)
|
||||
</if>
|
||||
<if test="supplierCode != null and supplierCode != ''">
|
||||
AND FIND_IN_SET(#{supplierCode}, m.supplier_code)
|
||||
</if>
|
||||
<if test="startDate != null">
|
||||
AND m.start_date = #{startDate}
|
||||
</if>
|
||||
<if test="endDate != null">
|
||||
AND m.end_date = #{endDate}
|
||||
</if>
|
||||
<if test="blIsQuestion != null and blIsQuestion != ''">
|
||||
AND w.bl_is_question = #{blIsQuestion}
|
||||
</if>
|
||||
<if test="sendSiteCode != null and sendSiteCode != ''">
|
||||
AND w.send_site_code = #{sendSiteCode}
|
||||
</if>
|
||||
<if test="params.beginSendDate != null and params.beginSendDate != ''">
|
||||
and w.send_date <![CDATA[ >= ]]> #{params.beginSendDate}
|
||||
</if>
|
||||
<if test="params.endSendDate != null and params.endSendDate != ''">
|
||||
and w.send_date <![CDATA[ <= ]]> #{params.endSendDate}
|
||||
</if>
|
||||
<if test="payee != null and payee != ''">
|
||||
AND w.payee like concat('%', #{payee}, '%')
|
||||
</if>
|
||||
<if test="salesmen != null and salesmen != ''">
|
||||
AND w.salesmen like concat('%', #{salesmen}, '%')
|
||||
</if>
|
||||
<if test="registerManName != null and registerManName != ''">
|
||||
AND u.emp_name like concat('%', #{registerManName}, '%')
|
||||
</if>
|
||||
</where>
|
||||
order by m.bill_code desc
|
||||
</otherwise>
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
<select id="selectEmisTmsSiteBatchMissById" parameterType="Long" resultMap="EmisTmsSiteBatchMissResult">
|
||||
<include refid="selectEmisTmsSiteBatchMissVo"/>
|
||||
where m.id = #{id} and m.del_flag = '0'
|
||||
@ -414,6 +663,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
</delete>
|
||||
|
||||
<delete id="deleteReallyV2">
|
||||
delete from emis_tms_site_batch_miss_v2
|
||||
<if test="lineCode != null and lineCode != ''">
|
||||
where line_code = #{lineCode}
|
||||
</if>
|
||||
</delete>
|
||||
|
||||
<update id="deleteByBillCodes">
|
||||
update emis_tms_site_batch_miss set del_flag = '1'
|
||||
where bill_code in
|
||||
@ -422,6 +678,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<update id="deleteByBillCodesV2">
|
||||
update emis_tms_site_batch_miss_v2 set del_flag = '1'
|
||||
where bill_code in
|
||||
<foreach collection="billCodes" item="billCode" open="(" separator="," close=")">
|
||||
#{billCode}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<insert id="batchInsertEmisTmsSiteBatchMiss" parameterType="java.util.List">
|
||||
insert into emis_tms_site_batch_miss
|
||||
(trans_plan_rule_id, bill_code, miss_reason, line_code,manager, product_type,
|
||||
@ -454,6 +718,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<insert id="batchInsertEmisTmsSiteBatchMissV2" parameterType="java.util.List">
|
||||
insert into emis_tms_site_batch_miss_v2
|
||||
(trans_plan_rule_id, bill_code, miss_reason, line_code,manager, product_type,
|
||||
start_site_code, next_site_code, supplier_code, start_date, end_date,
|
||||
create_by, create_time, update_by, update_time, remark,
|
||||
create_site, update_site, miss_type)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{item.transPlanRuleId,jdbcType=BIGINT},
|
||||
#{item.billCode,jdbcType=VARCHAR},
|
||||
#{item.missReason,jdbcType=VARCHAR},
|
||||
#{item.lineCode,jdbcType=VARCHAR},
|
||||
#{item.manager,jdbcType=VARCHAR},
|
||||
#{item.productType,jdbcType=VARCHAR},
|
||||
#{item.startSiteCode,jdbcType=VARCHAR},
|
||||
#{item.nextSiteCode,jdbcType=VARCHAR},
|
||||
#{item.supplierCode,jdbcType=VARCHAR},
|
||||
#{item.startDate,jdbcType=TIMESTAMP},
|
||||
#{item.endDate,jdbcType=TIMESTAMP},
|
||||
#{item.createBy,jdbcType=VARCHAR},
|
||||
#{item.createTime,jdbcType=TIMESTAMP},
|
||||
#{item.updateBy,jdbcType=VARCHAR},
|
||||
#{item.updateTime,jdbcType=TIMESTAMP},
|
||||
#{item.remark,jdbcType=VARCHAR},
|
||||
#{item.createSite,jdbcType=VARCHAR},
|
||||
#{item.updateSite,jdbcType=VARCHAR},
|
||||
#{item.missType,jdbcType=VARCHAR}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="selectByBillCodeCount" parameterType="Integer" resultMap="EmisTmsSiteBatchMissResult">
|
||||
SELECT t.*
|
||||
FROM emis_tms_site_batch_miss t
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMissRecordMapper">
|
||||
|
||||
|
||||
<resultMap type="EmisTmsSiteBatchMissRecord" id="EmisTmsSiteBatchMissRecordResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="totalProcessed" column="total_processed"/>
|
||||
@ -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}
|
||||
)
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
@ -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)
|
||||
</select>
|
||||
|
||||
<select id="selectStatisticsListV2" parameterType="EmisTmsSiteBatchMissStatistics" resultMap="EmisTmsSiteBatchMissStatisticsResult">
|
||||
SELECT
|
||||
COALESCE(bm.start_site_code, w.start_site_code, w.send_site_code) as start_site_code,
|
||||
s.site_name as start_site_name,
|
||||
STR_TO_DATE(CONCAT(DATE_FORMAT(w.send_date, '%Y-%m'), '-01'), '%Y-%m-%d') as bill_month,
|
||||
COUNT(*) as ticket_count
|
||||
FROM emis_tms_site_batch_miss_v2 bm
|
||||
LEFT JOIN emis_waybill w ON bm.bill_code = w.bill_code AND w.del_flag = '0'
|
||||
LEFT JOIN emis_site s ON COALESCE(bm.start_site_code, w.start_site_code, w.send_site_code) = s.site_code AND s.del_flag = '0'
|
||||
WHERE bm.del_flag = '0'
|
||||
<if test="startSiteCode != null and startSiteCode != ''">
|
||||
AND COALESCE(bm.start_site_code, w.start_site_code, w.send_site_code) = #{startSiteCode}
|
||||
</if>
|
||||
<if test="startTime != null and startTime != ''">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
<if test="(startTime == null or startTime == '') and (endTime == null or endTime == '')">
|
||||
<if test="billMonth != null">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
|
||||
</if>
|
||||
</if>
|
||||
GROUP BY COALESCE(bm.start_site_code, w.start_site_code, w.send_site_code), s.site_name, DATE_FORMAT(w.send_date, '%Y-%m')
|
||||
ORDER BY w.send_date, COALESCE(bm.start_site_code, w.start_site_code, w.send_site_code)
|
||||
</select>
|
||||
|
||||
<select id="selectDetailDataByMonth" parameterType="EmisTmsSiteBatchMiss" resultMap="com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMissMapper.EmisTmsSiteBatchMissResult">
|
||||
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.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,
|
||||
@ -93,13 +121,67 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
ORDER BY w.send_date DESC, m.bill_code
|
||||
</select>
|
||||
|
||||
<select id="selectDetailDataByMonthV2" parameterType="EmisTmsSiteBatchMiss" resultMap="com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMissMapper.EmisTmsSiteBatchMissResult">
|
||||
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 s.name
|
||||
FROM emis_supplier s
|
||||
WHERE FIND_IN_SET(s.code, m.supplier_code)
|
||||
AND s.del_flag = '0'
|
||||
LIMIT 1) as supplier_name,
|
||||
(SELECT p.prod_name
|
||||
FROM emis_trans_product p
|
||||
WHERE FIND_IN_SET(p.prod_code, m.product_type)
|
||||
AND p.del_flag = '0'
|
||||
LIMIT 1) 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'
|
||||
WHERE m.del_flag = '0'
|
||||
<if test="startSiteCode != null and startSiteCode != ''">
|
||||
AND COALESCE(m.start_site_code, w.start_site_code, w.send_site_code) = #{startSiteCode}
|
||||
</if>
|
||||
<if test="startTime != null and startTime != ''">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
<if test="(startTime == null or startTime == '') and (endTime == null or endTime == '')">
|
||||
<if test="billMonth != null">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
|
||||
</if>
|
||||
</if>
|
||||
ORDER BY w.send_date DESC, m.bill_code
|
||||
</select>
|
||||
|
||||
<!-- 分页查询漏组详细数据列表(按月份分组)- 性能优化版本 -->
|
||||
<select id="selectDetailDataByMonthWithPaging" resultMap="com.xdadan.erp.emis.mapper.EmisTmsSiteBatchMissMapper.EmisTmsSiteBatchMissResult">
|
||||
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.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,
|
||||
@ -171,4 +253,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 统计漏组详细数据总数 -->
|
||||
<select id="countDetailDataByMonthV2" parameterType="EmisTmsSiteBatchMissStatistics" resultType="long">
|
||||
SELECT COUNT(*)
|
||||
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'
|
||||
WHERE m.del_flag = '0'
|
||||
<if test="startSiteCode != null and startSiteCode != ''">
|
||||
AND COALESCE(m.start_site_code, w.start_site_code, w.send_site_code) = #{startSiteCode}
|
||||
</if>
|
||||
<if test="startTime != null and startTime != ''">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
<if test="(startTime == null or startTime == '') and (endTime == null or endTime == '')">
|
||||
<if test="billMonth != null">
|
||||
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
|
||||
</if>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@ -3925,9 +3925,10 @@
|
||||
</insert>
|
||||
|
||||
<select id="selectWaybillListBySiteBatchStatus" resultMap="EmisWaybillResult">
|
||||
select a.*,k.trans_type
|
||||
select a.*,k.trans_type,start.site_name as start_site_name
|
||||
from emis_waybill a
|
||||
left join emis_trans_line k on a.trans_line_type=k.line_code and k.del_flag='0'
|
||||
left join emis_site start on a.start_site_code=start.site_code and start.del_flag='0'
|
||||
where a.del_flag = '0'
|
||||
<if test="lineCode != null and lineCode != ''">
|
||||
and a.trans_line_type = #{lineCode}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user