rk
11 小时以前 4f4538356403d620b9bd510fd45729a251291942
server/services/src/main/java/com/doumee/service/business/impl/ReportServiceImpl.java
@@ -155,7 +155,23 @@
            incomeByParam.merge(o.getParamId(), amount, BigDecimal::add);
        }
        // 5. 组装结果:车型名 + 大类 + 收入(分→元,2位),按收入降序
        // 5. 按 paramId 统计每类车型的车辆数量(bikes 表未删除),一次分组查询避免 N 次 count
        Map<String, Long> bikeCountByParam;
        if (incomeByParam.isEmpty()) {
            // 无有收入的车型时跳过查询:空集合传给 in() 会生成 "IN ()",PostgreSQL 语法错误
            bikeCountByParam = Collections.emptyMap();
        } else {
            bikeCountByParam = bikesMapper.selectList(
                    new QueryWrapper<Bikes>().lambda()
                            .select(Bikes::getParamId)
                            .eq(Bikes::getIsdeleted, Constants.ZERO)
                            .in(Bikes::getParamId, incomeByParam.keySet()))
                    .stream()
                    .filter(b -> b.getParamId() != null)
                    .collect(Collectors.groupingBy(Bikes::getParamId, Collectors.counting()));
        }
        // 6. 组装结果:车型名 + 大类 + 收入(分→元,2位)+ 车辆数,按收入降序
        List<BikeIncomeStatVO> result = new ArrayList<>();
        for (Map.Entry<String, BigDecimal> e : incomeByParam.entrySet()) {
            BaseParam param = paramMap.get(e.getKey());
@@ -164,6 +180,7 @@
            vo.setParamName(param == null ? "未知车型" : param.getName());
            vo.setCategory(param == null ? "未知" : categoryOf(param.getType()));
            vo.setIncome(e.getValue().divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP));
            vo.setBikeCount(bikeCountByParam.getOrDefault(e.getKey(), 0L));
            result.add(vo);
        }
        result.sort(Comparator.comparing(BikeIncomeStatVO::getIncome).reversed());
@@ -262,7 +279,7 @@
        BigDecimal totalCents = BigDecimal.ZERO;
        for (Goodsorder o : orders) {
            BigDecimal amount = o.getCloseMoney() == null ? BigDecimal.ZERO : o.getCloseMoney();
            sumByDay.merge(DateUtil.getShortDateStr(o.getPayDate()), amount, BigDecimal::add);
            sumByDay.merge(DateUtil.getDateLong(o.getPayDate()), amount, BigDecimal::add);
            totalCents = totalCents.add(amount);
        }
@@ -272,7 +289,7 @@
        List<IncomeDailyVO> dailyList = new ArrayList<>();
        for (Date d : DateUtil.getDateList(DateUtil.getStartOfDay(start), DateUtil.getStartOfDay(end))) {
            IncomeDailyVO vo = new IncomeDailyVO();
            vo.setDate(DateUtil.getShortDateStr(d));
            vo.setDate(DateUtil.getDateLong(d));
            BigDecimal daySum = sumByDay.getOrDefault(vo.getDate(), BigDecimal.ZERO);
            // 分→元,2位小数
            vo.setIncome(daySum.divide(CENT_PER_YUAN, 2, BigDecimal.ROUND_HALF_UP));
@@ -416,6 +433,8 @@
        IPage<OperationOrderVO> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        OperationOrderQueryDTO model = pageWrap.getModel() == null
                ? new OperationOrderQueryDTO() : pageWrap.getModel();
        // 租用中(status=1):需过滤掉无骑行记录的订单(已支付但用户从未开锁骑行)
        boolean queryInProgress = Objects.nonNull(model.getStatus()) && model.getStatus().equals(Constants.ONE);
        // ── 步骤1:分页主查询 ──
        // 主表 goodsorder left join member(取手机号)+ left join base_param(取结算车型名);
@@ -442,6 +461,9 @@
                // 订单类型:按骑行记录 member_rides.type 筛选(可选)
                .inSql(Objects.nonNull(model.getBikeType()), Goodsorder::getId,
                        "select ordre_id from member_rides where isdeleted = 0 and type = " + model.getBikeType())
                // 租用中(status=1):仅保留存在骑行记录的订单,过滤掉已支付但无骑行记录的数据
                .inSql(queryInProgress, Goodsorder::getId,
                        "select ordre_id from member_rides where isdeleted = 0")
                .orderByDesc(Goodsorder::getPayDate);
        IPage<OperationOrderVO> result = goodsorderMapper.selectJoinPage(page, OperationOrderVO.class, wrapper);
        List<OperationOrderVO> records = result.getRecords();