| src/main/java/com/zy/asrs/mapper/ManLocDetlMapper.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/mapper/MonthlySettleMapper.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/ManLocDetlService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/MonthlySettleService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/impl/ManLocDetlServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/impl/MonthlySettleServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/ManLocDetlMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/MonthlySettleMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/zy/asrs/mapper/ManLocDetlMapper.java
@@ -57,6 +57,12 @@ Double queryStockAnfme(String matnr, String batch); /** * 批量查询库存数量 * @param matnrBatchList 物料编码和批次的组合列表,格式:matnr_batch */ List<com.zy.asrs.entity.result.StockQtyDTO> queryStockAnfmeBatch(@Param("matnrBatchList") List<String> matnrBatchList); List<StockVo> queryStockTotal(); src/main/java/com/zy/asrs/mapper/MonthlySettleMapper.java
@@ -20,14 +20,14 @@ MonthlySettle selectLatestSettle(); /** * 统计月结时间范围内的订单数量 * 统计月结时间范围内未完成的入库订单数量 */ int countOrdersInRange(@Param("startDate") String startDate, @Param("endDate") String endDate); int countUnfinishedOrdersInRangePakin(@Param("startDate") String startDate, @Param("endDate") String endDate); /** * 统计月结时间范围内未完成的订单数量(入库和出库) * 统计月结时间范围内未完成的出库订单数量 */ int countUnfinishedOrdersInRange(@Param("startDate") String startDate, @Param("endDate") String endDate); int countUnfinishedOrdersInRangePakout(@Param("startDate") String startDate, @Param("endDate") String endDate); /** * 统计月结时间范围内的物料出入库数量(从入库表查询) src/main/java/com/zy/asrs/service/ManLocDetlService.java
@@ -47,6 +47,12 @@ Double queryStockAnfme(String matnr, String batch); /** * 批量查询库存数量 * @param matnrBatchList 物料编码和批次的组合列表,格式:matnr_batch */ List<com.zy.asrs.entity.result.StockQtyDTO> queryStockAnfmeBatch(List<String> matnrBatchList); List<StockVo> queryStockTotal(); src/main/java/com/zy/asrs/service/MonthlySettleService.java
@@ -49,6 +49,13 @@ * 删除月结记录 */ void deleteSettle(Long settleId); /** * 检查指定日期是否在任何已月结的区间内 * @param orderTime 订单业务时间(字符串格式:yyyy-MM-dd HH:mm:ss) * @return 如果日期在任何已月结区间内,返回true;否则返回false */ boolean isOrderTimeInSettledRange(String orderTime); } src/main/java/com/zy/asrs/service/impl/ManLocDetlServiceImpl.java
@@ -105,6 +105,14 @@ } @Override public List<com.zy.asrs.entity.result.StockQtyDTO> queryStockAnfmeBatch(List<String> matnrBatchList) { if (matnrBatchList == null || matnrBatchList.isEmpty()) { return new java.util.ArrayList<>(); } return this.baseMapper.queryStockAnfmeBatch(matnrBatchList); } @Override public List<StockVo> queryStockTotal() { return this.baseMapper.queryStockTotal(); } src/main/java/com/zy/asrs/service/impl/MonthlySettleServiceImpl.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.core.common.Cools; import com.core.common.SnowflakeIdWorker; import com.core.exception.CoolException; import com.zy.asrs.entity.MonthlySettle; @@ -91,12 +92,21 @@ cal.set(Calendar.MILLISECOND, 999); endDate = cal.getTime(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 注意:order_time 是 varchar 类型,需要格式化为完整的日期时间字符串进行比较 SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String startDateStr = dateFormat.format(startDate); // 起始日期设置为当天的 00:00:00 Calendar startCal = Calendar.getInstance(); startCal.setTime(startDate); startCal.set(Calendar.HOUR_OF_DAY, 0); startCal.set(Calendar.MINUTE, 0); startCal.set(Calendar.SECOND, 0); startCal.set(Calendar.MILLISECOND, 0); String startDateStr = dateTimeFormat.format(startCal.getTime()); String endDateStr = dateTimeFormat.format(endDate); int count = this.baseMapper.countUnfinishedOrdersInRange(startDateStr, endDateStr); return count > 0; // 分两次查询:入库和出库 int pakinCount = this.baseMapper.countUnfinishedOrdersInRangePakin(startDateStr, endDateStr); int pakoutCount = this.baseMapper.countUnfinishedOrdersInRangePakout(startDateStr, endDateStr); return (pakinCount + pakoutCount) > 0; } @Override @@ -141,9 +151,16 @@ } // 统计物料出入库数量(分别查询两个表,在Java代码中合并) SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 注意:order_time 是 varchar 类型,需要格式化为完整的日期时间字符串进行比较 SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String startDateStr = dateFormat.format(startDate); // 起始日期设置为当天的 00:00:00 Calendar startCal = Calendar.getInstance(); startCal.setTime(startDate); startCal.set(Calendar.HOUR_OF_DAY, 0); startCal.set(Calendar.MINUTE, 0); startCal.set(Calendar.SECOND, 0); startCal.set(Calendar.MILLISECOND, 0); String startDateStr = dateTimeFormat.format(startCal.getTime()); String endDateStr = dateTimeFormat.format(endDate); // 分别查询入库表和出库表 @@ -259,6 +276,42 @@ currentMaterialMap.put(key, stat); } // 收集所有需要查询库存的物料(本期有出入库的 + 上一期存在但本期没有出入库的) List<String> matnrBatchList = new java.util.ArrayList<>(); for (MaterialInOutStatDTO stat : materialStats) { String matnr = stat.getMatnr(); String batch = stat.getBatch() != null ? stat.getBatch() : ""; matnrBatchList.add(matnr + "_" + batch); } if (previousSettle != null && !previousDetailMap.isEmpty()) { for (Map.Entry<String, PreviousSettleEndingQtyDTO> entry : previousDetailMap.entrySet()) { String key = entry.getKey(); if (!currentMaterialMap.containsKey(key)) { PreviousSettleEndingQtyDTO previousDetail = entry.getValue(); String matnr = previousDetail.getMatnr(); String batch = previousDetail.getBatch() != null ? previousDetail.getBatch() : ""; String matnrBatchKey = matnr + "_" + batch; if (!matnrBatchList.contains(matnrBatchKey)) { matnrBatchList.add(matnrBatchKey); } } } } // 批量查询库存 Map<String, BigDecimal> stockQtyMap = new HashMap<>(); if (!matnrBatchList.isEmpty()) { List<com.zy.asrs.entity.result.StockQtyDTO> stockQtyList = manLocDetlService.queryStockAnfmeBatch(matnrBatchList); if (stockQtyList != null) { for (com.zy.asrs.entity.result.StockQtyDTO stockQtyDTO : stockQtyList) { String key = stockQtyDTO.getMatnr() + "_" + (stockQtyDTO.getBatch() != null ? stockQtyDTO.getBatch() : ""); stockQtyMap.put(key, stockQtyDTO.getStockQty() != null ? stockQtyDTO.getStockQty() : BigDecimal.ZERO); } } } // 收集所有明细记录,用于批量插入 List<MonthlySettleDetail> detailList = new java.util.ArrayList<>(); // 1. 处理本期有出入库的物料 for (MaterialInOutStatDTO stat : materialStats) { // 1. 提取基础信息 @@ -274,16 +327,18 @@ // 3. 计算库存相关数量 BigDecimal beginningQty = getBeginningQty(matnr, batch, brand, previousEndingQtyMap); BigDecimal endingQty = calculateEndingQty(beginningQty, inQty, outQty); BigDecimal stockQtyDecimal = getCurrentStockQty(matnr, batch); // 从批量查询的Map中获取库存 String stockKey = matnr + "_" + batch; BigDecimal stockQtyDecimal = stockQtyMap.getOrDefault(stockKey, BigDecimal.ZERO); BigDecimal diffQty = calculateDiffQty(stockQtyDecimal, endingQty); // 4. 创建并保存明细记录 // 4. 创建明细记录(暂不插入) MonthlySettleDetail detail = buildMonthlySettleDetail( monthlySettle.getId(), settleNo, matnr, batch, maktx, brand, beginningQty, inQty, outQty, endingQty, stockQtyDecimal, diffQty ); detail.setIsDeleted(0); // 未删除 monthlySettleDetailMapper.insert(detail); detailList.add(detail); // 5. 累计统计 totalInQty = totalInQty.add(inQty); @@ -315,21 +370,36 @@ BigDecimal beginningQty = previousEndingQty; // 期末库存 = 期初 + 入库 - 出库 = 期初(因为本期没有出入库) BigDecimal endingQty = beginningQty; // 获取当前实际库存 BigDecimal stockQtyDecimal = getCurrentStockQty(matnr, batch); // 从批量查询的Map中获取库存 String stockKey = matnr + "_" + batch; BigDecimal stockQtyDecimal = stockQtyMap.getOrDefault(stockKey, BigDecimal.ZERO); // 计算差异 BigDecimal diffQty = calculateDiffQty(stockQtyDecimal, endingQty); // 创建并保存明细记录 // 创建明细记录(暂不插入) MonthlySettleDetail detail = buildMonthlySettleDetail( monthlySettle.getId(), settleNo, matnr, batch, maktx, brand, beginningQty, inQty, outQty, endingQty, stockQtyDecimal, diffQty ); detail.setIsDeleted(0); // 未删除 monthlySettleDetailMapper.insert(detail); detailList.add(detail); // 累计统计(虽然入库和出库为0,但也要计入物料种类数) materialCount++; } } } // 分批插入,每批1000条,避免一次性插入过多数据 if (!detailList.isEmpty()) { int batchSize = 1000; for (int i = 0; i < detailList.size(); i += batchSize) { int end = Math.min(i + batchSize, detailList.size()); List<MonthlySettleDetail> batch = detailList.subList(i, end); for (MonthlySettleDetail detail : batch) { if (monthlySettleDetailMapper.insert(detail) <= 0) { throw new CoolException("插入月结明细失败"); } } } } @@ -429,8 +499,10 @@ } /** * 获取当前实际库存数量 * 获取当前实际库存数量(已废弃,改用批量查询) * @deprecated 使用批量查询方法替代,避免N+1查询问题 */ @Deprecated private BigDecimal getCurrentStockQty(String matnr, String batch) { Double stockQty = manLocDetlService.queryStockAnfme(matnr, batch); return stockQty != null ? BigDecimal.valueOf(stockQty) : BigDecimal.ZERO; @@ -499,5 +571,59 @@ settle.setUpdateTime(new Date()); this.updateById(settle); } @Override public boolean isOrderTimeInSettledRange(String orderTime) { if (Cools.isEmpty(orderTime)) { return false; } try { // 解析订单业务时间 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date orderDate = sdf.parse(orderTime); // 查询所有已月结的记录(status=1且未删除) EntityWrapper<MonthlySettle> wrapper = new EntityWrapper<>(); wrapper.eq("status", 1); wrapper.eq("is_deleted", 0); List<MonthlySettle> settledList = this.selectList(wrapper); if (settledList == null || settledList.isEmpty()) { return false; } // 检查订单时间是否在任何已月结的区间内 for (MonthlySettle settle : settledList) { Date startDate = settle.getStartDate(); Date endDate = settle.getEndDate(); // 确保startDate是当天的00:00:00 Calendar startCal = Calendar.getInstance(); startCal.setTime(startDate); startCal.set(Calendar.HOUR_OF_DAY, 0); startCal.set(Calendar.MINUTE, 0); startCal.set(Calendar.SECOND, 0); startCal.set(Calendar.MILLISECOND, 0); // 确保endDate是当天的23:59:59.999 Calendar endCal = Calendar.getInstance(); endCal.setTime(endDate); endCal.set(Calendar.HOUR_OF_DAY, 23); endCal.set(Calendar.MINUTE, 59); endCal.set(Calendar.SECOND, 59); endCal.set(Calendar.MILLISECOND, 999); // 判断订单时间是否在区间内:[startDate的00:00:00, endDate的23:59:59.999] if (!orderDate.before(startCal.getTime()) && !orderDate.after(endCal.getTime())) { return true; } } return false; } catch (Exception e) { log.error("检查订单时间是否在已月结区间内失败", e); return false; } } } src/main/resources/mapper/ManLocDetlMapper.xml
@@ -313,4 +313,22 @@ where node_id = #{nodeId} ; </update> <!-- 批量查询库存数量 --> <select id="queryStockAnfmeBatch" resultType="com.zy.asrs.entity.result.StockQtyDTO"> SELECT matnr, ISNULL(batch, '') as batch, SUM(anfme) as stockQty FROM man_loc_detl WHERE 1=1 <if test="matnrBatchList != null and matnrBatchList.size > 0"> AND ( <foreach collection="matnrBatchList" item="item" separator=" OR "> (matnr + '_' + ISNULL(batch, '') = #{item}) </foreach> ) </if> GROUP BY matnr, ISNULL(batch, '') </select> </mapper> src/main/resources/mapper/MonthlySettleMapper.xml
@@ -27,75 +27,74 @@ ORDER BY end_date DESC </select> <!-- 统计月结时间范围内的订单数量 --> <select id="countOrdersInRange" resultType="int"> SELECT COUNT(*) FROM man_order WHERE status = 1 AND order_time >= #{startDate} AND order_time <= #{endDate} <!-- 统计月结时间范围内未完成的入库订单数量 --> <select id="countUnfinishedOrdersInRangePakin" resultType="int"> SELECT COUNT(1) FROM man_order_log_pakin molpi WHERE molpi.status = 1 AND molpi.order_time >= #{startDate} AND molpi.order_time <= #{endDate} AND (molpi.settle IS NULL OR molpi.settle != 6) AND (molpi.monthly_settle_id IS NULL OR molpi.monthly_settle_id = 0) AND EXISTS ( SELECT 1 FROM man_order_detl_log_pakin modlpi WHERE modlpi.order_id = molpi.id AND (modlpi.anfme > modlpi.qty OR modlpi.qty IS NULL) ) </select> <!-- 统计月结时间范围内未完成的订单数量(入库和出库) --> <select id="countUnfinishedOrdersInRange" resultType="int"> SELECT COUNT(*) FROM ( SELECT DISTINCT o.id FROM man_order_log_pakin o INNER JOIN man_order_detl_log_pakin od ON o.id = od.order_id WHERE o.status = 1 AND CONVERT(date, o.order_time) >= #{startDate} AND o.order_time <= #{endDate} AND o.move_status != 2 AND (od.anfme > od.qty OR od.qty IS NULL) AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0) UNION SELECT DISTINCT o.id FROM man_order_log_pakout o INNER JOIN man_order_detl_log_pakout od ON o.id = od.order_id WHERE o.status = 1 AND CONVERT(date, o.order_time) >= #{startDate} AND o.order_time <= #{endDate} AND o.move_status != 2 AND (od.anfme > od.qty OR od.qty IS NULL) AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0) ) t <!-- 统计月结时间范围内未完成的出库订单数量 --> <select id="countUnfinishedOrdersInRangePakout" resultType="int"> SELECT COUNT(1) FROM man_order_log_pakout molpo WHERE molpo.status = 1 AND molpo.order_time >= #{startDate} AND molpo.order_time <= #{endDate} AND (molpo.settle IS NULL OR molpo.settle != 6) AND (molpo.monthly_settle_id IS NULL OR molpo.monthly_settle_id = 0) AND EXISTS ( SELECT 1 FROM man_order_detl_log_pakout modlpo WHERE modlpo.order_id = molpo.id AND (modlpo.anfme > modlpo.qty OR modlpo.qty IS NULL) ) </select> <!-- 统计月结时间范围内的物料出入库数量(从入库表查询) --> <select id="statisticsMaterialInOutFromPakin" resultType="com.zy.asrs.entity.result.MaterialInOutRawDTO"> SELECT od.matnr, od.maktx, od.batch, od.brand, SUM(od.qty) as qty, COALESCE(od.pakin_pakout_status, o.pakin_pakout_status) as pakinPakoutStatus FROM man_order_log_pakin o INNER JOIN man_order_detl_log_pakin od ON o.id = od.order_id WHERE o.status = 1 AND CONVERT(date, o.order_time) >= #{startDate} AND o.order_time <= #{endDate} AND o.move_status = 2 AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0) AND COALESCE(od.pakin_pakout_status, o.pakin_pakout_status) IN (1, 2) GROUP BY od.matnr, od.maktx, od.batch, od.brand, COALESCE(od.pakin_pakout_status, o.pakin_pakout_status) modlpi.matnr, modlpi.maktx, modlpi.batch, modlpi.brand, SUM(modlpi.qty) as qty, COALESCE(modlpi.pakin_pakout_status, molpi.pakin_pakout_status) as pakinPakoutStatus FROM man_order_log_pakin molpi INNER JOIN man_order_detl_log_pakin modlpi ON molpi.id = modlpi.order_id WHERE molpi.status = 1 AND molpi.order_time >= #{startDate} AND molpi.order_time <= #{endDate} AND molpi.settle = 6 AND (molpi.monthly_settle_id IS NULL OR molpi.monthly_settle_id = 0) AND COALESCE(modlpi.pakin_pakout_status, molpi.pakin_pakout_status) IN (1, 2) GROUP BY modlpi.matnr, modlpi.maktx, modlpi.batch, modlpi.brand, COALESCE(modlpi.pakin_pakout_status, molpi.pakin_pakout_status) </select> <!-- 统计月结时间范围内的物料出入库数量(从出库表查询) --> <select id="statisticsMaterialInOutFromPakout" resultType="com.zy.asrs.entity.result.MaterialInOutRawDTO"> SELECT od.matnr, od.maktx, od.batch, od.brand, SUM(od.qty) as qty, COALESCE(od.pakin_pakout_status, o.pakin_pakout_status) as pakinPakoutStatus FROM man_order_log_pakout o INNER JOIN man_order_detl_log_pakout od ON o.id = od.order_id WHERE o.status = 1 AND CONVERT(date, o.order_time) >= #{startDate} AND o.order_time <= #{endDate} AND o.move_status = 2 AND (o.monthly_settle_id IS NULL OR o.monthly_settle_id = 0) AND COALESCE(od.pakin_pakout_status, o.pakin_pakout_status) IN (1, 2) GROUP BY od.matnr, od.maktx, od.batch, od.brand, COALESCE(od.pakin_pakout_status, o.pakin_pakout_status) modlpo.matnr, modlpo.maktx, modlpo.batch, modlpo.brand, SUM(modlpo.qty) as qty, COALESCE(modlpo.pakin_pakout_status, molpo.pakin_pakout_status) as pakinPakoutStatus FROM man_order_log_pakout molpo INNER JOIN man_order_detl_log_pakout modlpo ON molpo.id = modlpo.order_id WHERE molpo.status = 1 AND molpo.order_time >= #{startDate} AND molpo.order_time <= #{endDate} AND molpo.settle = 6 AND (molpo.monthly_settle_id IS NULL OR molpo.monthly_settle_id = 0) AND COALESCE(modlpo.pakin_pakout_status, molpo.pakin_pakout_status) IN (1, 2) GROUP BY modlpo.matnr, modlpo.maktx, modlpo.batch, modlpo.brand, COALESCE(modlpo.pakin_pakout_status, molpo.pakin_pakout_status) </select> <!-- 获取上一个月结的物料期末库存 --> @@ -117,9 +116,9 @@ SET monthly_settle_id = #{settleId}, monthly_settle_no = #{settleNo} WHERE status = 1 AND CONVERT(date, order_time) >= #{startDate} AND order_time >= #{startDate} AND order_time <= #{endDate} AND move_status = 2 AND settle = 6 AND (monthly_settle_id IS NULL OR monthly_settle_id = 0) </update> @@ -129,9 +128,9 @@ SET monthly_settle_id = #{settleId}, monthly_settle_no = #{settleNo} WHERE status = 1 AND CONVERT(date, order_time) >= #{startDate} AND order_time >= #{startDate} AND order_time <= #{endDate} AND move_status = 2 AND settle = 6 AND (monthly_settle_id IS NULL OR monthly_settle_id = 0) </update>