| | |
| | | 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; |
| | |
| | | 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 |
| | |
| | | } |
| | | |
| | | // 统计物料出入库数量(分别查询两个表,在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); |
| | | |
| | | // 分别查询入库表和出库表 |
| | |
| | | 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. 提取基础信息 |
| | |
| | | // 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); |
| | |
| | | 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("插入月结明细失败"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取当前实际库存数量 |
| | | * 获取当前实际库存数量(已废弃,改用批量查询) |
| | | * @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; |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | |