| | |
| | | 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()); |
| | |
| | | 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()); |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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)); |
| | |
| | | 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(取结算车型名); |
| | |
| | | // 订单类型:按骑行记录 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(); |