package com.fzzy.igds.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fzzy.igds.constant.Constant; import com.fzzy.igds.data.SuperInventoryReportData; import com.fzzy.igds.data.SuperInventoryReportParam; import com.fzzy.igds.domain.*; import com.fzzy.igds.mapper.*; import com.fzzy.igds.utils.ContextUtil; import com.fzzy.igds.utils.DateUtil; import com.ruoyi.common.utils.StringUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; /** * 监管库存报表Service * * @author sgj * @date 2025/12/19 */ @Slf4j @Service public class SuperInventoryReportService { @Resource private DepotStoreMapper depotStoreMapper; @Resource private InoutRecordMapper inoutRecordMapper; @Resource private InoutStockChangeMapper inoutStockChangeMapper; @Resource private CoreCompanyMapper coreCompanyMapper; @Resource private InoutLossOverMapper inoutLossOverMapper; @Resource private CoreDeptService coreDeptService; @Resource private DepotService depotService; /** * 查询报表数据 * * @param param * @author sgj * @date 2025/12/19 */ public List listSuperInventoryReportData(SuperInventoryReportParam param) { //1.获取查询得起止时间,如果没有则,默认截止时间为当天,起始时间为30天前 Date end = new Date(); Date start = DateUtil.getNewByDay(end, -30); if (null == param.getStart()) { param.setStart(DateUtil.getCurZero(start)); } if (null == param.getEnd()) { param.setEnd(DateUtil.getCurZero(end)); } //默认组织编码 String companyId = ContextUtil.getCompanyId(); //默认库区编码 String deptId = ContextUtil.subDeptId(null); param.setCompanyId(companyId); //region 查询条件收储公司和所属库区处理 if (StringUtils.isNotEmpty(param.getDeptId()) && StringUtils.isNotEmpty(param.getCustomerId())) { String substring = param.getDeptId().substring(0, (param.getDeptId().length() - 3)); if (!substring.equals(param.getCustomerId())) { return new ArrayList(); } } if (StringUtils.isEmpty(param.getDeptId())) { param.setDeptId(param.getCustomerId()); } //收储公司,所属库区查询均为空,则查询默认库区 if (StringUtils.isEmpty(param.getCustomerId()) && StringUtils.isEmpty(param.getDeptId())) { param.setDeptId(deptId); } //endregion //region 初始化需要范围的数据 Map columsMap = new HashMap<>(); //查询当前用户下属的所有库区 List deptList = coreDeptService.getDeptData(); if (null == deptList || deptList.isEmpty()) { return new ArrayList<>(); } //预加载所有部门下的仓库信息,减少重复查询 Map deptCache = new HashMap<>(); Map> deptDepotsMap = new HashMap<>(); Map companyCache = new HashMap<>(); for (Dept dept : deptList) { deptCache.put(dept.getId(), dept); //获取库区下所有仓库 List depotList = depotService.getData(companyId, dept.getId(), true); if (null == depotList || depotList.isEmpty()) { continue; } deptDepotsMap.put(dept.getId(), depotList); //缓存公司信息 int deptIdLength = dept.getId().length(); String companyCode = dept.getId().substring(0, deptIdLength - 3); if (!companyCache.containsKey(companyCode)) { Company company = coreCompanyMapper.selectById(companyCode); companyCache.put(companyCode, company); } } //构建结果数据映射map for (Map.Entry> entry : deptDepotsMap.entrySet()) { String deptIdKey = entry.getKey(); Company company = companyCache.get(deptIdKey.substring(0, deptIdKey.length() - 3)); Dept dept = deptCache.get(deptIdKey); for (Depot depot : entry.getValue()) { //库区编码+仓库编码组成唯一键 String key = deptIdKey + "_" + depot.getId(); SuperInventoryReportData data = new SuperInventoryReportData(); data.setCustomerId(Optional.ofNullable(company) .map(Company::getId) .orElse("-")); data.setCustomerName(Optional.ofNullable(company) .map(Company::getDwmc) .orElse("-")); data.setDeptId(deptIdKey); data.setDeptName(dept.getKqmc()); data.setDepotId(depot.getId()); data.setDepotName(depot.getName()); columsMap.put(key, data); } } //endregion if (columsMap.isEmpty()) { return new ArrayList<>(); } //2.查询时间范围内的各种数据 List depotStores = queryDepotStores(param); List inoutRecords = queryInoutRecords(param); List inoutStockChanges = queryInoutStockChanges(param); List inoutLossOvers = queryInoutLossOvers(param); //3. 数据分组预处理,提高后续查找效率 Map> storeGroupMap = depotStores.stream() .collect(Collectors.groupingBy(store -> store.getDeptId() + "_" + store.getDepotId())); Map> recordGroupMap = inoutRecords.stream() .collect(Collectors.groupingBy(record -> record.getDeptId() + "_" + record.getDepotId())); //4. 根据库区、仓库为唯一键,组装报表数据 List result = new ArrayList<>(); Date todayZero = DateUtil.getCurZero(new Date()); boolean isEndDateBeforeToday = param.getEnd().before(todayZero); for (SuperInventoryReportData data : columsMap.values()) { String dataKey = data.getDeptId() + "_" + data.getDepotId(); //获取库存数据 List depotStoreList = storeGroupMap.getOrDefault(dataKey, new ArrayList<>()); if (depotStoreList.isEmpty()) { continue; } //排序库存数据 depotStoreList.sort(Comparator.comparing(DepotStore::getCreateTime)); //获取出入库记录 List recordList = recordGroupMap.getOrDefault(dataKey, new ArrayList<>()); Map> recordPartition = recordList.stream() .collect(Collectors.partitioningBy(record -> Constant.TYPE_IN.equals(record.getType()))); List recordInList = recordPartition.get(true); List recordOutList = recordPartition.get(false); //获取倒仓数据 Map> stockChangePartition = inoutStockChanges.stream() .filter(change -> data.getDeptId().equals(change.getDeptId())) .collect(Collectors.partitioningBy(change -> data.getDepotId().equals(change.getDepotIdIn()))); List stockChangeInList = new ArrayList<>(); List stockChangeOutList = new ArrayList<>(); //倒入数据 stockChangeInList.addAll(stockChangePartition.get(true).stream() .filter(change -> data.getDepotId().equals(change.getDepotIdIn())) .collect(Collectors.toList())); //倒出数据 stockChangeOutList.addAll(stockChangePartition.get(false).stream() .filter(change -> data.getDepotId().equals(change.getDepotIdOut())) .collect(Collectors.toList())); //损益数据 List lossOverList = inoutLossOvers.stream() .filter(loss -> data.getDeptId().equals(loss.getDeptId()) && data.getDepotId().equals(loss.getDepotId())) .collect(Collectors.toList()); //计算各项统计数据 double sumRecordIn = recordInList.stream() .mapToDouble(InoutRecord::getRecordWeight) .sum(); double sumRecordOut = recordOutList.stream() .mapToDouble(InoutRecord::getRecordWeight) .sum(); double sumStockChangeIn = stockChangeInList.stream() .mapToDouble(InoutStockChange::getNumber) .sum(); double sumStockChangeOut = stockChangeOutList.stream() .mapToDouble(InoutStockChange::getNumber) .sum(); double sumLossOver = lossOverList.stream() .mapToDouble(lossOver -> Constant.TYPE_LOSS.equals(lossOver.getType()) ? -lossOver.getAmount() : lossOver.getAmount()) .sum(); //计算期初期末重量 Double initialWeight = depotStoreList.get(0).getStorageReal(); Double finalWeight; if (isEndDateBeforeToday) { //如果截止时间为昨天(当天的0点0分0秒0毫秒)及之前,则最后一条数据为期末数量 finalWeight = depotStoreList.get(depotStoreList.size() - 1).getStorageReal(); } else { //如果截止时间为今天及之后,则需要结合入出库记录数据来计算期末数量,规则:期末数量 = 期初数量 + 入库数量 - 出库数量 + 倒入数量 - 倒出数量+ 损益数据 finalWeight = initialWeight + sumRecordIn - sumRecordOut + sumStockChangeIn - sumStockChangeOut + sumLossOver; } //设置数据 data.setInitialWeight(initialWeight); data.setRecordInWeight(sumRecordIn); data.setChangeInWeight(sumStockChangeIn); data.setRecordOutWeight(sumRecordOut); data.setChangeOutWeight(sumStockChangeOut); data.setLossWeight(sumLossOver); data.setFinalWeight(finalWeight); result.add(data); } return result; } /** * 查询库存数据 */ private List queryDepotStores(SuperInventoryReportParam param) { QueryWrapper depotStoreQueryWrapper = new QueryWrapper<>(); depotStoreQueryWrapper.eq("company_id", param.getCompanyId()); if (StringUtils.isNotBlank(param.getDeptId())) { depotStoreQueryWrapper.likeRight("dept_id", param.getDeptId()); } depotStoreQueryWrapper.between("create_time", param.getStart(), param.getEnd()); depotStoreQueryWrapper.orderByAsc("create_time"); return depotStoreMapper.selectList(depotStoreQueryWrapper); } /** * 查询出入库记录数据 */ private List queryInoutRecords(SuperInventoryReportParam param) { QueryWrapper inoutRecordQueryWrapper = new QueryWrapper<>(); inoutRecordQueryWrapper.eq("company_id", param.getCompanyId()); if (StringUtils.isNotBlank(param.getDeptId())) { inoutRecordQueryWrapper.likeRight("dept_id", param.getDeptId()); } inoutRecordQueryWrapper.between("create_time", param.getStart(), param.getEnd()); inoutRecordQueryWrapper.orderByAsc("create_time"); return inoutRecordMapper.selectList(inoutRecordQueryWrapper); } /** * 查询倒仓数据 */ private List queryInoutStockChanges(SuperInventoryReportParam param) { QueryWrapper inoutStockChangeQueryWrapper = new QueryWrapper<>(); inoutStockChangeQueryWrapper.eq("company_id", param.getCompanyId()); if (StringUtils.isNotBlank(param.getDeptId())) { inoutStockChangeQueryWrapper.likeRight("dept_id", param.getDeptId()); } inoutStockChangeQueryWrapper.between("create_time", param.getStart(), param.getEnd()); inoutStockChangeQueryWrapper.orderByAsc("create_time"); return inoutStockChangeMapper.selectList(inoutStockChangeQueryWrapper); } /** * 查询损益数据 */ private List queryInoutLossOvers(SuperInventoryReportParam param) { QueryWrapper inoutLossOverQueryWrapper = new QueryWrapper<>(); inoutLossOverQueryWrapper.eq("company_id", param.getCompanyId()); if (StringUtils.isNotBlank(param.getDeptId())) { inoutLossOverQueryWrapper.likeRight("dept_id", param.getDeptId()); } inoutLossOverQueryWrapper.between("create_time", param.getStart(), param.getEnd()); inoutLossOverQueryWrapper.orderByAsc("create_time"); return inoutLossOverMapper.selectList(inoutLossOverQueryWrapper); } }