| | |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.MonthlySettle; |
| | | import com.zy.asrs.entity.MonthlySettleDetail; |
| | | import com.zy.asrs.entity.result.MaterialInOutRawDTO; |
| | | import com.zy.asrs.entity.result.MaterialInOutStatDTO; |
| | | import com.zy.asrs.entity.result.MonthlySettleResultVO; |
| | | import com.zy.asrs.entity.result.MonthlySettleStatisticsVO; |
| | |
| | | throw new CoolException("月结时间范围内存在未完成的订单,无法进行月结"); |
| | | } |
| | | |
| | | // 统计物料出入库数量(合并入库和出库) |
| | | // 统计物料出入库数量(分别查询两个表,在Java代码中合并) |
| | | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); |
| | | SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | String startDateStr = dateFormat.format(startDate); |
| | | String endDateStr = dateTimeFormat.format(endDate); |
| | | List<MaterialInOutStatDTO> materialStats = this.baseMapper.statisticsMaterialInOut(startDateStr, endDateStr); |
| | | |
| | | // 分别查询入库表和出库表 |
| | | List<MaterialInOutRawDTO> pakinDataList = this.baseMapper.statisticsMaterialInOutFromPakin(startDateStr, endDateStr); |
| | | List<MaterialInOutRawDTO> pakoutDataList = this.baseMapper.statisticsMaterialInOutFromPakout(startDateStr, endDateStr); |
| | | |
| | | // 合并两个表的数据 |
| | | List<MaterialInOutRawDTO> rawDataList = new java.util.ArrayList<>(); |
| | | if (pakinDataList != null && !pakinDataList.isEmpty()) { |
| | | rawDataList.addAll(pakinDataList); |
| | | } |
| | | if (pakoutDataList != null && !pakoutDataList.isEmpty()) { |
| | | rawDataList.addAll(pakoutDataList); |
| | | } |
| | | |
| | | // 检查是否有出入库历史订单 |
| | | if (materialStats == null || materialStats.isEmpty()) { |
| | | if (rawDataList == null || rawDataList.isEmpty()) { |
| | | throw new CoolException("月结时间范围内没有出入库历史订单,无法进行月结"); |
| | | } |
| | | |
| | | // 在Java代码中处理分类统计逻辑 |
| | | // 1. 处理NULL值(batch、brand、maktx) |
| | | // 2. 根据物料编码、批次、品牌分组 |
| | | // 3. 根据 pakin_pakout_status 区分入库和出库 |
| | | Map<String, MaterialInOutStatDTO> materialStatsMap = new HashMap<>(); |
| | | Map<String, String> maktxMap = new HashMap<>(); // 存储物料名称(取第一个非空值) |
| | | |
| | | for (MaterialInOutRawDTO raw : rawDataList) { |
| | | // 处理NULL值 |
| | | String matnr = raw.getMatnr(); |
| | | String batch = raw.getBatch() != null ? raw.getBatch() : ""; |
| | | String brand = raw.getBrand() != null ? raw.getBrand() : ""; |
| | | String maktx = raw.getMaktx() != null ? raw.getMaktx() : ""; |
| | | String key = matnr + "_" + batch + "_" + brand; |
| | | |
| | | // 保存物料名称(取第一个非空值) |
| | | if (maktx != null && !maktx.isEmpty() && !maktxMap.containsKey(key)) { |
| | | maktxMap.put(key, maktx); |
| | | } |
| | | |
| | | MaterialInOutStatDTO stat = materialStatsMap.get(key); |
| | | if (stat == null) { |
| | | stat = new MaterialInOutStatDTO(); |
| | | stat.setMatnr(matnr); |
| | | stat.setMaktx(maktxMap.getOrDefault(key, "")); |
| | | stat.setBatch(batch); |
| | | stat.setBrand(brand); |
| | | stat.setInQty(BigDecimal.ZERO); |
| | | stat.setOutQty(BigDecimal.ZERO); |
| | | materialStatsMap.put(key, stat); |
| | | } |
| | | |
| | | // 根据 pakin_pakout_status 分类统计 |
| | | // 1 = 入库,2 = 出库,0 = 未知(已在SQL中过滤) |
| | | BigDecimal qty = raw.getQty() != null ? raw.getQty() : BigDecimal.ZERO; |
| | | Integer status = raw.getPakinPakoutStatus(); |
| | | if (status != null && qty.compareTo(BigDecimal.ZERO) > 0) { |
| | | if (status == 1) { |
| | | // 入库 |
| | | stat.setInQty(stat.getInQty().add(qty)); |
| | | } else if (status == 2) { |
| | | // 出库 |
| | | stat.setOutQty(stat.getOutQty().add(qty)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 转换为List |
| | | List<MaterialInOutStatDTO> materialStats = new java.util.ArrayList<>(materialStatsMap.values()); |
| | | |
| | | // 获取上一个月结记录(用于计算期初库存) |
| | | MonthlySettle previousSettle = getLatestSettle(); |
| | | // 获取上一个月结记录(用于计算期初库存和承接上一期的物料) |
| | | MonthlySettle previousSettle = getLatestSettle(); |
| | | Map<String, BigDecimal> previousEndingQtyMap = new HashMap<>(); |
| | | Map<String, PreviousSettleEndingQtyDTO> previousDetailMap = new HashMap<>(); // 存储上一期的完整明细信息 |
| | | if (previousSettle != null) { |
| | | List<PreviousSettleEndingQtyDTO> previousDetails = this.baseMapper.getPreviousSettleEndingQty(previousSettle.getId()); |
| | | for (PreviousSettleEndingQtyDTO detail : previousDetails) { |
| | |
| | | (detail.getBrand() != null ? detail.getBrand() : ""); |
| | | BigDecimal endingQty = detail.getEndingQty() != null ? detail.getEndingQty() : BigDecimal.ZERO; |
| | | previousEndingQtyMap.put(key, endingQty); |
| | | previousDetailMap.put(key, detail); // 保存完整信息,用于后续创建明细 |
| | | } |
| | | } |
| | | |
| | |
| | | BigDecimal totalOutQty = BigDecimal.ZERO; |
| | | int materialCount = 0; |
| | | |
| | | // 创建月结明细 |
| | | // 创建 Map 存储本期有出入库的物料(用于判断是否需要从上一期继承) |
| | | Map<String, MaterialInOutStatDTO> currentMaterialMap = new HashMap<>(); |
| | | for (MaterialInOutStatDTO stat : materialStats) { |
| | | String matnr = stat.getMatnr(); |
| | | String batch = stat.getBatch() != null ? stat.getBatch() : ""; |
| | | String brand = stat.getBrand() != null ? stat.getBrand() : ""; |
| | | String key = matnr + "_" + batch + "_" + brand; |
| | | currentMaterialMap.put(key, stat); |
| | | } |
| | | |
| | | // 1. 处理本期有出入库的物料 |
| | | for (MaterialInOutStatDTO stat : materialStats) { |
| | | // 1. 提取基础信息 |
| | | String matnr = stat.getMatnr(); |
| | |
| | | materialCount++; |
| | | } |
| | | |
| | | // 2. 处理上一期存在但本期没有出入库的物料(需要承接显示) |
| | | if (previousSettle != null && !previousDetailMap.isEmpty()) { |
| | | for (Map.Entry<String, PreviousSettleEndingQtyDTO> entry : previousDetailMap.entrySet()) { |
| | | String key = entry.getKey(); |
| | | // 如果本期没有出入库,但上一期有期末库存(且不为0),则需要创建一条记录 |
| | | if (!currentMaterialMap.containsKey(key)) { |
| | | PreviousSettleEndingQtyDTO previousDetail = entry.getValue(); |
| | | BigDecimal previousEndingQty = previousDetail.getEndingQty() != null ? previousDetail.getEndingQty() : BigDecimal.ZERO; |
| | | |
| | | // 如果上一期的期末库存不为0,或者即使为0也要显示(用于对比) |
| | | // 这里我们总是创建记录,即使上一期期末库存为0,因为用户要求"如果上一期存在过,本期库存归零也要显示一条为0的记录" |
| | | String matnr = previousDetail.getMatnr(); |
| | | String batch = previousDetail.getBatch() != null ? previousDetail.getBatch() : ""; |
| | | String brand = previousDetail.getBrand() != null ? previousDetail.getBrand() : ""; |
| | | String maktx = previousDetail.getMaktx() != null ? previousDetail.getMaktx() : ""; |
| | | |
| | | // 本期没有出入库,所以入库和出库数量都为0 |
| | | BigDecimal inQty = BigDecimal.ZERO; |
| | | BigDecimal outQty = BigDecimal.ZERO; |
| | | |
| | | // 期初库存 = 上一期的期末库存 |
| | | BigDecimal beginningQty = previousEndingQty; |
| | | // 期末库存 = 期初 + 入库 - 出库 = 期初(因为本期没有出入库) |
| | | BigDecimal endingQty = beginningQty; |
| | | // 获取当前实际库存 |
| | | BigDecimal stockQtyDecimal = getCurrentStockQty(matnr, batch); |
| | | // 计算差异 |
| | | 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); |
| | | |
| | | // 累计统计(虽然入库和出库为0,但也要计入物料种类数) |
| | | materialCount++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新月结主记录 |
| | | monthlySettle.setTotalInQty(totalInQty); |
| | | monthlySettle.setTotalOutQty(totalOutQty); |