diff --git a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCustomerUserController.java b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCustomerUserController.java index a6eaae39f..7e22b242b 100644 --- a/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCustomerUserController.java +++ b/emis-biz-web/src/main/java/com/xdadan/erp/web/emis/EmisCustomerUserController.java @@ -495,7 +495,19 @@ public class EmisCustomerUserController extends EmisBaseController setPrivParams(emisWaybill); List list = emisCustomerUserService .selectMonthlyCustomerShipmentStat(emisWaybill); - return getDataTable(list); + TableDataInfo dataTable = getDataTable(list); + + // 如果使用了应用层过滤(complianceStatType=3/4/5/6),需要手动设置总数 + if (emisWaybill.getParams() != null && emisWaybill.getParams().containsKey("_filteredTotal")) { + Object filteredTotal = emisWaybill.getParams().get("_filteredTotal"); + if (filteredTotal instanceof Long) { + dataTable.setTotal((Long) filteredTotal); + } else if (filteredTotal instanceof Number) { + dataTable.setTotal(((Number) filteredTotal).longValue()); + } + } + + return dataTable; } /** diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/MonthlyCustomerShipmentStatVO.java b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/MonthlyCustomerShipmentStatVO.java index c50600b31..a2b14e8de 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/MonthlyCustomerShipmentStatVO.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/domain/vo/MonthlyCustomerShipmentStatVO.java @@ -203,5 +203,14 @@ public class MonthlyCustomerShipmentStatVO implements Serializable { /* 创建日期(现金客户导出使用,对应 create_time) */ private String createTime; + + /* 是否达标;1:已达标,2:未达标 */ + private String blCompliance; + + /* 寄件月份 */ + private String sendMonth; + + /* 总运费 */ + private Integer totalBillFee; } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisCustomerUserMapper.java b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisCustomerUserMapper.java index 654e48412..f9a8da5fd 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisCustomerUserMapper.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/mapper/EmisCustomerUserMapper.java @@ -13,6 +13,8 @@ package com.xdadan.erp.emis.mapper; import java.util.List; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xdadan.erp.emis.domain.EmisCustomerUser; +import com.xdadan.erp.emis.domain.EmisWaybill; +import com.xdadan.erp.emis.domain.vo.MonthlyCustomerShipmentStatVO; import org.apache.ibatis.annotations.Param; /** * @ClassName EmisCustomerUserMapper @@ -134,4 +136,12 @@ public interface EmisCustomerUserMapper extends BaseMapper */ public int clearMoneyUserIdByMoneyUserIds(@Param("moneyUserIds") Long[] moneyUserIds); + /** + * 月结客户达标统计 + * + * @param emisWaybill 查询条件 + * @return + */ + List selectMonthlyCustomerShipmentStatIsCompliance(EmisWaybill emisWaybill); + } diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/excelCellStrategy/MonthlyShipmentStatExcelUtil.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/excelCellStrategy/MonthlyShipmentStatExcelUtil.java index eadb94b83..9209a80a1 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/excelCellStrategy/MonthlyShipmentStatExcelUtil.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/excelCellStrategy/MonthlyShipmentStatExcelUtil.java @@ -70,9 +70,31 @@ public class MonthlyShipmentStatExcelUtil { MonthlyCustomerShipmentStatVO::getOtherWeightCompareFlag) ); - private static final String[] BASE_HEADERS = {"客户名称", "首次签约日期", "总票数", "总重量", "销售联系人"}; + /** + * 默认(月结/现金)出货统计基础列(原有导出保持不变) + * 客户名称、首次签约日期(或创建日期)、总票数、总重量、销售联系人 + */ + private static final String[] BASE_HEADERS = { + "客户名称", "首次签约日期", "总票数", "总重量", "销售联系人" + }; private static final int[] BASE_WIDTHS = {28, 18, 12, 16, 24}; + /** + * 月结客户达标统计基础列(仅 statType=5 使用) + * + * 列顺序要求: + * 1)寄件月份 字段放在“首次签约日期”后边; + * 2)总运费 字段放在“总重量”后边; + * 3)是否达标 字段放在“寄件月份”后边; + * + * 最终基础表头顺序: + * 客户名称、首次签约日期、寄件月份、是否达标、总票数、总重量、总运费、销售联系人 + */ + private static final String[] COMPLIANCE_HEADERS = { + "客户名称", "首次签约日期", "寄件月份", "是否达标", "总票数", "总重量", "总运费", "销售联系人" + }; + private static final int[] COMPLIANCE_BASE_WIDTHS = {28, 18, 16, 12, 12, 16, 16, 24}; + private MonthlyShipmentStatExcelUtil() { } @@ -94,21 +116,36 @@ public class MonthlyShipmentStatExcelUtil { private static void exportInternal(HttpServletResponse response, List dataList, int statType, boolean moneyCustomer) { - boolean transportLayout = statType == 1 || statType == 3; + boolean transportLayout = statType == 1 || statType == 3 || statType == 5; boolean compareMode = statType == 3 || statType == 4; + // 是否为月结达标统计(仅 statType=5) + boolean complianceLayout = !moneyCustomer && statType == 5; List safeList = dataList == null ? new ArrayList<>() : dataList; // 为保证 Excel 导出稳定排序:先按总重量降序,再按总票数降序,最后按客户名称升序 - sortForExport(safeList); + if(!complianceLayout){ + sortForExport(safeList); + } List exportList = new ArrayList<>(safeList); exportList.add(buildTotalRow(safeList)); String sheetName = moneyCustomer ? "现金客户出货统计" : "月结客户出货统计"; - String[] headers = moneyCustomer - ? new String[]{"客户名称", "创建日期", "总票数", "总重量", "销售联系人"} - : BASE_HEADERS; + + + String[] headers; + int[] baseWidths; + if (moneyCustomer) { + headers = new String[]{"客户名称", "创建日期", "总票数", "总重量", "销售联系人"}; + baseWidths = BASE_WIDTHS; + } else if (complianceLayout) { + headers = COMPLIANCE_HEADERS; + baseWidths = COMPLIANCE_BASE_WIDTHS; + } else { + headers = BASE_HEADERS; + baseWidths = BASE_WIDTHS; + } try { SXSSFWorkbook workbook = new SXSSFWorkbook(200); @@ -131,7 +168,7 @@ public class MonthlyShipmentStatExcelUtil { // 样式缓存:避免在对比模式下创建过多样式导致超过Excel样式限制 Map styleCache = new HashMap<>(); - createHeader(sheet, headers, transportLayout ? TRANSPORT_GROUPS : COUNTRY_GROUPS, headerStyle); + createHeader(sheet, headers, baseWidths, transportLayout ? TRANSPORT_GROUPS : COUNTRY_GROUPS, headerStyle); int dataStartRow = 2; for (int i = 0; i < exportList.size(); i++) { @@ -143,17 +180,64 @@ public class MonthlyShipmentStatExcelUtil { int col = 0; // 客户名称:月结用 customerName;现金用 company String customerName = moneyCustomer ? vo.getCompany() : vo.getCustomerName(); - String dateValue = moneyCustomer ? vo.getCreateTime() : vo.getFirstSigningDay(); - col = writeTextCell(row, col, customerName, totalRow ? totalTextStyle : textStyle); - col = writeTextCell(row, col, dateValue, totalRow ? totalTextStyle : textStyle); - col = writeIntegerCell(row, col, vo.getTotalTickets(), vo.getTotalTicketsCompareFlag(), - totalRow ? totalNumberStyle : numberStyle, compareMode && !totalRow, workbook, - redArrowFont, greenArrowFont, blueArrowFont, styleCache); - col = writeDecimalCell(row, col, vo.getTotalWeight(), vo.getTotalWeightCompareFlag(), - totalRow ? totalDecimalStyle : decimalStyle, compareMode && !totalRow, workbook, - redArrowFont, greenArrowFont, blueArrowFont, styleCache); - col = writeTextCell(row, col, vo.getSalesmen(), totalRow ? totalTextStyle : textStyle); + + if (moneyCustomer) { + // 现金客户出货统计:保持原有列顺序不变 + String dateValue = vo.getCreateTime(); + col = writeTextCell(row, col, dateValue, totalRow ? totalTextStyle : textStyle); + col = writeIntegerCell(row, col, vo.getTotalTickets(), vo.getTotalTicketsCompareFlag(), + totalRow ? totalNumberStyle : numberStyle, compareMode && !totalRow, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + col = writeDecimalCell(row, col, vo.getTotalWeight(), vo.getTotalWeightCompareFlag(), + totalRow ? totalDecimalStyle : decimalStyle, compareMode && !totalRow, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + col = writeTextCell(row, col, vo.getSalesmen(), totalRow ? totalTextStyle : textStyle); + } else if (complianceLayout) { + // 月结客户达标统计:使用新增三列 + String dateValue = vo.getFirstSigningDay(); + // 首次签约日期 + col = writeTextCell(row, col, dateValue, totalRow ? totalTextStyle : textStyle); + // 寄件月份 + col = writeTextCell(row, col, vo.getSendMonth(), totalRow ? totalTextStyle : textStyle); + // 是否达标(1=已达标,2=未达标) + String complianceText; + if (vo.getBlCompliance() == null || vo.getBlCompliance().isEmpty()) { + complianceText = ""; + } else if ("1".equals(vo.getBlCompliance())) { + complianceText = "已达标"; + } else if ("2".equals(vo.getBlCompliance())) { + complianceText = "未达标"; + } else { + complianceText = vo.getBlCompliance(); + } + col = writeTextCell(row, col, complianceText, totalRow ? totalTextStyle : textStyle); + + // 总票数、总重量 + col = writeIntegerCell(row, col, vo.getTotalTickets(), vo.getTotalTicketsCompareFlag(), + totalRow ? totalNumberStyle : numberStyle, compareMode && !totalRow, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + col = writeDecimalCell(row, col, vo.getTotalWeight(), vo.getTotalWeightCompareFlag(), + totalRow ? totalDecimalStyle : decimalStyle, compareMode && !totalRow, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + // 总运费(达标统计专用) + col = writeIntegerCell(row, col, vo.getTotalBillFee(), null, + totalRow ? totalNumberStyle : numberStyle, false, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + // 销售联系人 + col = writeTextCell(row, col, vo.getSalesmen(), totalRow ? totalTextStyle : textStyle); + } else { + // 普通月结出货统计:保持原有 5 列 + String dateValue = vo.getFirstSigningDay(); + col = writeTextCell(row, col, dateValue, totalRow ? totalTextStyle : textStyle); + col = writeIntegerCell(row, col, vo.getTotalTickets(), vo.getTotalTicketsCompareFlag(), + totalRow ? totalNumberStyle : numberStyle, compareMode && !totalRow, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + col = writeDecimalCell(row, col, vo.getTotalWeight(), vo.getTotalWeightCompareFlag(), + totalRow ? totalDecimalStyle : decimalStyle, compareMode && !totalRow, workbook, + redArrowFont, greenArrowFont, blueArrowFont, styleCache); + col = writeTextCell(row, col, vo.getSalesmen(), totalRow ? totalTextStyle : textStyle); + } List groups = transportLayout ? TRANSPORT_GROUPS : COUNTRY_GROUPS; for (MetricGroup group : groups) { @@ -174,7 +258,8 @@ public class MonthlyShipmentStatExcelUtil { } } - private static void createHeader(Sheet sheet, String[] baseHeaders, List groups, CellStyle headerStyle) { + private static void createHeader(Sheet sheet, String[] baseHeaders, int[] baseWidths, + List groups, CellStyle headerStyle) { Row topRow = sheet.createRow(0); Row subRow = sheet.createRow(1); topRow.setHeightInPoints(22); @@ -186,7 +271,7 @@ public class MonthlyShipmentStatExcelUtil { cell.setCellValue(baseHeaders[i]); cell.setCellStyle(headerStyle); sheet.addMergedRegion(new CellRangeAddress(0, 1, col, col)); - sheet.setColumnWidth(col, BASE_WIDTHS[i] * 256); + sheet.setColumnWidth(col, baseWidths[i] * 256); col++; } @@ -400,9 +485,12 @@ public class MonthlyShipmentStatExcelUtil { total.setCustomerName("合计"); total.setFirstSigningDay(""); total.setSalesmen(""); + total.setSendMonth(""); + total.setBlCompliance(""); total.setTotalTickets(sumInt(source, MonthlyCustomerShipmentStatVO::getTotalTickets)); total.setTotalWeight(sumDecimal(source, MonthlyCustomerShipmentStatVO::getTotalWeight)); + total.setTotalBillFee(sumInt(source, MonthlyCustomerShipmentStatVO::getTotalBillFee)); total.setExpressTickets(sumInt(source, MonthlyCustomerShipmentStatVO::getExpressTickets)); total.setExpressWeight(sumDecimal(source, MonthlyCustomerShipmentStatVO::getExpressWeight)); diff --git a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisCustomerUserServiceImpl.java b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisCustomerUserServiceImpl.java index a593ff905..eca969e16 100644 --- a/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisCustomerUserServiceImpl.java +++ b/emis-biz/src/main/java/com/xdadan/erp/emis/service/impl/EmisCustomerUserServiceImpl.java @@ -11,7 +11,15 @@ package com.xdadan.erp.emis.service.impl; import java.util.*; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.stream.Collectors; +import com.github.pagehelper.PageHelper; +import com.xdadan.erp.common.core.page.PageDomain; +import com.xdadan.erp.common.core.page.TableSupport; +import com.xdadan.erp.common.utils.DateUtils; import com.xdadan.erp.common.utils.SecurityUtils; import com.xdadan.erp.emis.domain.exception.EmisBizError; import com.xdadan.erp.emis.domain.enumtype.EmisBizErrorType; @@ -175,14 +183,119 @@ public class EmisCustomerUserServiceImpl extends EmisBaseService implements IEmi } else if ("4".equals(emisWaybill.getParams().get("statType"))) { // 按目的国家统计,增加与上一个时间段的票数、重量对比标记(根据客户类型自动选择 key) result = buildShipmentStatWithCompare(emisWaybill, false); + } else if ("5".equals(emisWaybill.getParams().get("statType"))) { + // 月结客户达标统计 + // 校验:当complianceStatType=3/4/5/6时,寄件时间段需大于等于3个月 + checkDateForComplianceStat(emisWaybill); + if(Objects.isNull(emisWaybill.getParams().get("beginSendDate"))){ + emisWaybill.getParams().put("beginSendDate","2024-01-01 00:00:00"); + } + if(Objects.isNull(emisWaybill.getParams().get("endSendDate"))){ + emisWaybill.getParams().put("endSendDate", DateUtils.getDate("yyyy-MM-dd HH:mm:ss")); + } + + Object complianceStatTypeObj = emisWaybill.getParams().get("complianceStatType"); + String complianceStatType = complianceStatTypeObj != null ? String.valueOf(complianceStatTypeObj) : null; + + // 统一使用应用层过滤:先清除 PageHelper 分页,查询所有数据 + PageHelper.clearPage(); + List allResults = emisCustomerUserMapper.selectMonthlyCustomerShipmentStatIsCompliance(emisWaybill); + + // 先根据 totalTickets / totalBillFee 在代码中计算 blCompliance(1=达标,2=未达标) + if (allResults != null) { + for (MonthlyCustomerShipmentStatVO vo : allResults) { + if (vo == null) { + continue; + } + Integer tickets = vo.getTotalTickets(); + Integer fee = vo.getTotalBillFee(); + int safeTickets = tickets == null ? 0 : tickets; + int safeFee = fee == null ? 0 : fee; + // 规则:票数>=5 或 总运费>=3000 视为达标 + vo.setBlCompliance((safeTickets >= 5 || safeFee >= 3000) ? "1" : "2"); + } + } + + // 按 complianceStatType 在应用层过滤(1~6 全走代码逻辑) + if (complianceStatType != null && !complianceStatType.trim().isEmpty()) { + result = filterComplianceStat(allResults, complianceStatType.trim()); + } else { + result = allResults; + } + + // 保存过滤后的总数到 params 中,供 Controller 使用 + if (emisWaybill.getParams() == null) { + emisWaybill.setParams(new HashMap<>()); + } + emisWaybill.getParams().put("_filteredTotal", result == null ? 0L : (long) result.size()); + + // 手动分页 + if (result == null) { + result = Collections.emptyList(); + } + PageDomain pageDomain = TableSupport.buildPageRequest(); + Integer pageNum = pageDomain.getPageNum(); + Integer pageSize = pageDomain.getPageSize(); + if (pageNum != null && pageSize != null && pageNum > 0 && pageSize > 0) { + int start = (pageNum - 1) * pageSize; + int end = Math.min(start + pageSize, result.size()); + if (start < result.size()) { + result = result.subList(start, end); + } else { + result = Collections.emptyList(); + } + } } else { result = Collections.emptyList(); } - sortShipmentStat(result); + if(!"5".equals(emisWaybill.getParams().get("statType"))){ + sortShipmentStat(result); + } return result; } + private void checkDateForComplianceStat(EmisWaybill emisWaybill) throws EmisBizError { + Object complianceStatTypeObj = emisWaybill.getParams().get("complianceStatType"); + if (complianceStatTypeObj != null) { + String complianceStatType = String.valueOf(complianceStatTypeObj); + if ("3".equals(complianceStatType) || "4".equals(complianceStatType) + || "5".equals(complianceStatType) || "6".equals(complianceStatType)) { + // 验证时间段必须大于等于3个月 + Object beginSendObj = emisWaybill.getParams().get("beginSendDate"); + Object endSendObj = emisWaybill.getParams().get("endSendDate"); + + if (beginSendObj == null || endSendObj == null) { + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "请选择寄件日期"); + } + + try { + String beginSendDate = String.valueOf(beginSendObj).trim(); + String endSendDate = String.valueOf(endSendObj).trim(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDate beginDate = LocalDate.parse(beginSendDate, formatter); + LocalDate endDate = LocalDate.parse(endSendDate, formatter); + + long monthsBetween = ChronoUnit.MONTHS.between( + beginDate.withDayOfMonth(1), + endDate.withDayOfMonth(1) + ); + + if (monthsBetween < 3) { + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, + "当达标统计类型为" + getComplianceStatTypeName(complianceStatType) + "时,寄件时间段需大于等于3个月"); + } + } catch (Exception e) { + if (e instanceof EmisBizError) { + throw e; + } + throw new EmisBizError(EmisBizErrorType.PARAM_ERROR, "日期格式错误,请使用yyyy-MM-dd HH:mm:ss格式"); + } + } + } + } + /** * 查询现金客户出货统计 * @@ -429,6 +542,184 @@ public class EmisCustomerUserServiceImpl extends EmisBaseService implements IEmi return v == null ? 0 : v; } + /** + * 获取达标统计类型名称 + */ + private String getComplianceStatTypeName(String complianceStatType) { + switch (complianceStatType) { + case "3": return "连续3个月未出货"; + case "4": return "累计3个月未出货"; + case "5": return "连续3个月出货未达标"; + case "6": return "累计3个月出货未达标"; + default: return complianceStatType; + } + } + + /** + * 应用层过滤:根据 complianceStatType 过滤统计结果 + * 优化:将复杂的 SQL EXISTS 子查询移到应用层处理,提升查询性能 + * + * @param allResults 所有查询结果(已按客户+月份分组) + * @param complianceStatType 达标统计类型:3-连续3个月未出货,4-累计3个月未出货,5-连续3个月未达标,6-累计3个月未达标 + * @return 过滤后的结果列表 + */ + private List filterComplianceStat( + List allResults, String complianceStatType) { + if (allResults == null || allResults.isEmpty()) { + return Collections.emptyList(); + } + + // 1/2:简单按 blCompliance 过滤(1=已达标,2=未达标) + if ("1".equals(complianceStatType)) { + return allResults.stream() + .filter(m -> "1".equals(m.getBlCompliance())) + .collect(Collectors.toList()); + } + if ("2".equals(complianceStatType)) { + return allResults.stream() + .filter(m -> "2".equals(m.getBlCompliance())) + .collect(Collectors.toList()); + } + + // 按客户分组,便于后续判断连续/累计 + Map> customerMap = allResults.stream() + .collect(Collectors.groupingBy( + item -> item.getCustNo() != null ? item.getCustNo() : "", + LinkedHashMap::new, + Collectors.toList() + )); + + List filteredResults = new ArrayList<>(); + + for (Map.Entry> entry : customerMap.entrySet()) { + List customerMonths = entry.getValue(); + // 按月份排序(升序) + customerMonths.sort(Comparator.comparing(MonthlyCustomerShipmentStatVO::getSendMonth)); + + switch (complianceStatType) { + case "3": + // 连续3个月以上出货为0 + filteredResults.addAll(filterConsecutiveZeroTickets(customerMonths)); + break; + case "4": + // 累计超过3个月出货为0 + filteredResults.addAll(filterAccumulatedZeroTickets(customerMonths, 3)); + break; + case "5": + // 连续3个月以上出货未达标 + filteredResults.addAll(filterConsecutiveNonCompliance(customerMonths)); + break; + case "6": + // 累计3个月以上出货未达标 + filteredResults.addAll(filterAccumulatedNonCompliance(customerMonths, 3)); + break; + default: + filteredResults.addAll(customerMonths); + break; + } + } + + return filteredResults; + } + + /** + * 过滤连续3个月以上出货为0的月份 + */ + private List filterConsecutiveZeroTickets( + List customerMonths) { + List result = new ArrayList<>(); + for (int i = 0; i < customerMonths.size(); i++) { + MonthlyCustomerShipmentStatVO current = customerMonths.get(i); + if (current.getTotalTickets() == null || current.getTotalTickets() == 0) { + // 检查前两个月是否也为0 + boolean prev1Zero = (i >= 1 && (customerMonths.get(i - 1).getTotalTickets() == null + || customerMonths.get(i - 1).getTotalTickets() == 0)); + boolean prev2Zero = (i >= 2 && (customerMonths.get(i - 2).getTotalTickets() == null + || customerMonths.get(i - 2).getTotalTickets() == 0)); + // 检查后两个月是否也为0 + boolean next1Zero = (i < customerMonths.size() - 1 + && (customerMonths.get(i + 1).getTotalTickets() == null + || customerMonths.get(i + 1).getTotalTickets() == 0)); + boolean next2Zero = (i < customerMonths.size() - 2 + && (customerMonths.get(i + 2).getTotalTickets() == null + || customerMonths.get(i + 2).getTotalTickets() == 0)); + + // 连续口径:某月在连续>=3的窗口内即可返回(包含窗口的前两个月或后两个月) + if ((prev1Zero && prev2Zero) || (prev1Zero && next1Zero) || (next1Zero && next2Zero)) { + result.add(current); + } + } + } + return result; + } + + /** + * 过滤累计超过指定月数出货为0的月份 + */ + private List filterAccumulatedZeroTickets( + List customerMonths, int minMonths) { + // 统计该客户出货为0的月份总数 + long zeroTicketMonths = customerMonths.stream() + .filter(m -> m.getTotalTickets() == null || m.getTotalTickets() == 0) + .count(); + + if (zeroTicketMonths >= minMonths) { + // 返回所有出货为0的月份 + return customerMonths.stream() + .filter(m -> m.getTotalTickets() == null || m.getTotalTickets() == 0) + .collect(Collectors.toList()); + } + return Collections.emptyList(); + } + + /** + * 过滤连续3个月以上出货未达标的月份 + */ + private List filterConsecutiveNonCompliance( + List customerMonths) { + List result = new ArrayList<>(); + for (int i = 0; i < customerMonths.size(); i++) { + MonthlyCustomerShipmentStatVO current = customerMonths.get(i); + if ("2".equals(current.getBlCompliance())) { + // 检查前两个月是否也未达标 + boolean prev1NonCompliance = (i >= 1 && "2".equals(customerMonths.get(i - 1).getBlCompliance())); + boolean prev2NonCompliance = (i >= 2 && "2".equals(customerMonths.get(i - 2).getBlCompliance())); + // 检查后两个月是否也未达标 + boolean next1NonCompliance = (i < customerMonths.size() - 1 + && "2".equals(customerMonths.get(i + 1).getBlCompliance())); + boolean next2NonCompliance = (i < customerMonths.size() - 2 + && "2".equals(customerMonths.get(i + 2).getBlCompliance())); + + // 连续口径:某月在连续>=3的窗口内即可返回 + if ((prev1NonCompliance && prev2NonCompliance) + || (prev1NonCompliance && next1NonCompliance) + || (next1NonCompliance && next2NonCompliance)) { + result.add(current); + } + } + } + return result; + } + + /** + * 过滤累计超过指定月数出货未达标的月份 + */ + private List filterAccumulatedNonCompliance( + List customerMonths, int minMonths) { + // 统计该客户未达标的月份总数 + long nonComplianceMonths = customerMonths.stream() + .filter(m -> "2".equals(m.getBlCompliance())) + .count(); + + if (nonComplianceMonths >= minMonths) { + // 返回所有未达标的月份 + return customerMonths.stream() + .filter(m -> "2".equals(m.getBlCompliance())) + .collect(Collectors.toList()); + } + return Collections.emptyList(); + } + /** * 查询月结客户出货明细 * diff --git a/emis-biz/src/main/resources/mapper/EmisCustomerUserMapper.xml b/emis-biz/src/main/resources/mapper/EmisCustomerUserMapper.xml index 75e145e5f..318b3fe1d 100644 --- a/emis-biz/src/main/resources/mapper/EmisCustomerUserMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisCustomerUserMapper.xml @@ -674,4 +674,160 @@ AND del_flag = '0' + + + + diff --git a/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml b/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml index d154230cb..29b2ba73f 100644 --- a/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml +++ b/emis-biz/src/main/resources/mapper/EmisWaybillMapper.xml @@ -3183,6 +3183,9 @@ or a.take_piece_employee_code=#{params.privEmpCode} ) + + and DATE_FORMAT(a.send_date,'%Y%m')= #{params.billMonth} + @@ -5083,6 +5086,9 @@ ) + + and DATE_FORMAT(a.send_date,'%Y-%m')= #{params.sendMonth} + AND EXISTS (