| | |
| | | */ |
| | | @RequestMapping("/platform") |
| | | public String index(Model model) { |
| | | Object o = type1(null); |
| | | model.addAttribute("data",o); |
| | | // type1 保留课程/门票/订场扇形图所需的图表明细;金额卡片再以营收接口覆盖, |
| | | // 避免图表数据丢失,也避免收入类型与净收入的统计口径不一致。 |
| | | Map<String, Object> typeData = (Map<String, Object>) type1(null); |
| | | Map<String, Object> incomeData = (Map<String, Object>) getIncomeData(null, null, null); |
| | | Map<Integer, BigDecimal> incomeTypeNet = (Map<Integer, BigDecimal>) incomeData.get("incomeTypeNet"); |
| | | typeData.put("fee1", incomeTypeNet.getOrDefault(1, BigDecimal.ZERO)); |
| | | typeData.put("fee2", incomeTypeNet.getOrDefault(2, BigDecimal.ZERO)); |
| | | typeData.put("fee3", incomeTypeNet.getOrDefault(3, BigDecimal.ZERO)); |
| | | typeData.put("fee4", incomeTypeNet.getOrDefault(4, BigDecimal.ZERO)); |
| | | typeData.put("fee5", incomeTypeNet.getOrDefault(5, BigDecimal.ZERO)); |
| | | typeData.put("fee7", incomeTypeNet.getOrDefault(6, BigDecimal.ZERO)); |
| | | model.addAttribute("data", typeData); |
| | | // 教学统计 |
| | | HashMap<String, Object> map = appUserClient.queryUserAge(); |
| | | model.addAttribute("stuData",map); |
| | |
| | | */ |
| | | @RequestMapping(value = "/getIncomeData") |
| | | @ResponseBody |
| | | public Object getIncomeData(Integer operatorId,Integer storeId) { |
| | | // operatorId = resolveOperatorId(operatorId); |
| | | // storeId = resolveStoreId(operatorId); |
| | | public Object getIncomeData(Integer operatorId,Integer storeId, String time) { |
| | | Integer roleType = UserExt.getUser().getObjectType(); |
| | | Integer objectId = UserExt.getUser().getObjectId(); |
| | | List<Integer> cityManagerId= new ArrayList<>(); |
| | | if(objectId>0){ |
| | | operatorId=objectId; |
| | | if(storeId==null){ |
| | | cityManagerId= storeService.list(new QueryWrapper<TStore>().eq("cityManagerId", objectId).ne("state", 3)).stream().map(TStore::getId).collect(Collectors.toList()); |
| | | }else { |
| | | cityManagerId.add(storeId); |
| | | } |
| | | |
| | | // 同一接口由平台、运营商、门店三个统计页面复用: |
| | | // 平台角色不应因自身 objectId 被错误收窄为某个运营商;运营商和门店只能查看各自范围。 |
| | | if (Integer.valueOf(3).equals(roleType)) { |
| | | operatorId = null; |
| | | storeId = objectId; |
| | | } else if (Integer.valueOf(2).equals(roleType)) { |
| | | operatorId = objectId; |
| | | storeId = resolveStoreId(storeId); |
| | | } |
| | | |
| | | // 参数代表当前统计目标,而非当前登录人的角色;平台账号查看运营商/门店页时, |
| | | // 会员、充值也必须跟随被查看的运营商/门店归属。 |
| | | Integer statisticsScopeType = Integer.valueOf(3).equals(roleType) || storeId != null ? 3 |
| | | : (Integer.valueOf(2).equals(roleType) || operatorId != null ? 2 : 1); |
| | | Integer statisticsScopeObjectId = statisticsScopeType == 3 ? storeId |
| | | : (statisticsScopeType == 2 ? operatorId : null); |
| | | |
| | | List<Integer> cityManagerId= new ArrayList<>(); |
| | | if (Integer.valueOf(2).equals(statisticsScopeType) && statisticsScopeObjectId != null) { |
| | | cityManagerId = storeService.list(new QueryWrapper<TStore>() |
| | | .eq("cityManagerId", statisticsScopeObjectId).ne("state", 3)) |
| | | .stream().map(TStore::getId).collect(Collectors.toList()); |
| | | } else if (Integer.valueOf(3).equals(statisticsScopeType) && statisticsScopeObjectId != null) { |
| | | cityManagerId.add(statisticsScopeObjectId); |
| | | } |
| | | // 报名课程查询query |
| | | RegisterOrderQuery query = new RegisterOrderQuery(); |
| | |
| | | siteBookingQuery.setStoreIds(list); |
| | | competitionQuery.setStoreId(storeId); |
| | | } |
| | | |
| | | |
| | | Integer roleType = UserExt.getUser().getObjectType(); |
| | | rechargeRecordsQuery.setInsertType(roleType); |
| | | query.setInsertType(roleType); |
| | | competitionQuery.setInsertType(roleType); |
| | | incomeQuery.setInsertType(roleType); |
| | | rechargeRecordsQuery.setObjectId(UserExt.getUser().getObjectId()); |
| | | // 会员、充值按当前统计目标的用户创建来源归属。平台全量统计仅按 insertType=1, |
| | | // 不能叠加当前平台账号的 addUserId 条件。 |
| | | rechargeRecordsQuery.setInsertType(statisticsScopeType); |
| | | query.setInsertType(statisticsScopeType); |
| | | competitionQuery.setInsertType(statisticsScopeType); |
| | | incomeQuery.setInsertType(statisticsScopeType); |
| | | rechargeRecordsQuery.setTime(time); |
| | | query.setRegisterTime(time); |
| | | competitionQuery.setTime(time); |
| | | incomeQuery.setTime(time); |
| | | siteBookingQuery.setTime(time); |
| | | if (!Integer.valueOf(1).equals(statisticsScopeType)) { |
| | | rechargeRecordsQuery.setObjectId(statisticsScopeObjectId); |
| | | } |
| | | List<IncomeVO> incomeVOS = new ArrayList<>(); |
| | | Set<Long> usedCouponIds = new HashSet<>(); |
| | | // 会员支付记录 |
| | |
| | | for (VipPayment vipPayment : vipPayments) { |
| | | if (vipPayment.getPayStatus() == 3 && vipPayment.getAmount() != null) { |
| | | IncomeVO payment = new IncomeVO(); |
| | | payment.setIncomeType(1); |
| | | payment.setInsertTime(vipPayment.getPayTime() == null ? vipPayment.getInsertTime() : vipPayment.getPayTime()); |
| | | payment.setAmount(BigDecimal.valueOf(vipPayment.getAmount())); |
| | | incomeVOS.add(payment); |
| | | IncomeVO refund = new IncomeVO(); |
| | | refund.setIncomeType(1); |
| | | refund.setInsertTime(vipPayment.getRefundTime() == null ? vipPayment.getInsertTime() : vipPayment.getRefundTime()); |
| | | refund.setRefundAmount(BigDecimal.valueOf(vipPayment.getAmount())); |
| | | incomeVOS.add(refund); |
| | | continue; |
| | | } |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(1); |
| | | if (vipPayment.getState()!=3){ |
| | | temp.setInsertTime(vipPayment.getPayTime()); |
| | | incomeVOS.add(temp); |
| | |
| | | List<RechargeRecordsVO> rechargeRecordsVOS = financeClient.rechargeList(rechargeRecordsQuery); |
| | | for (RechargeRecordsVO rechargeRecordsVO : rechargeRecordsVOS) { |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(2); |
| | | temp.setInsertTime(rechargeRecordsVO.getPayTime()); |
| | | if (rechargeRecordsVO.getAmount() != null) { |
| | | temp.setAmount(rechargeRecordsVO.getAmount()); |
| | |
| | | continue; |
| | | } |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(3); |
| | | temp.setInsertTime(registerOrderVO.getInsertTime()); |
| | | if (registerOrderVO.getMoney() != null) { |
| | | temp.setAmount(registerOrderVO.getMoney()); |
| | |
| | | } |
| | | if (competition.getPayStatus() == 3 && competition.getAmount() != null) { |
| | | IncomeVO payment = new IncomeVO(); |
| | | payment.setIncomeType(4); |
| | | payment.setInsertTime(competition.getPayTime() == null |
| | | ? competition.getInsertTime() : competition.getPayTime()); |
| | | payment.setAmount(BigDecimal.valueOf(competition.getAmount())); |
| | | incomeVOS.add(payment); |
| | | IncomeVO refund = new IncomeVO(); |
| | | refund.setIncomeType(4); |
| | | refund.setInsertTime(competition.getRefundTime() == null |
| | | ? competition.getInsertTime() : competition.getRefundTime()); |
| | | refund.setRefundAmount(BigDecimal.valueOf(competition.getAmount())); |
| | |
| | | continue; |
| | | } |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(4); |
| | | temp.setInsertTime(competition.getPayTime()); |
| | | if (competition.getAmount() != null) { |
| | | temp.setAmount(new BigDecimal(competition.getAmount().toString())); |
| | |
| | | List<SiteBooking> siteBookings = siteClient.listAll(siteBookingQuery); |
| | | for (SiteBooking siteBooking : siteBookings) { |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(5); |
| | | if (siteBooking.getStatus() == 5) { |
| | | if (siteBooking.getPayMoney() != null) { |
| | | IncomeVO payment = new IncomeVO(); |
| | | payment.setIncomeType(5); |
| | | payment.setInsertTime(siteBooking.getPayTime() == null |
| | | ? siteBooking.getInsertTime() : siteBooking.getPayTime()); |
| | | payment.setAmount(BigDecimal.valueOf(siteBooking.getPayMoney())); |
| | | incomeVOS.add(payment); |
| | | IncomeVO refund = new IncomeVO(); |
| | | refund.setIncomeType(5); |
| | | refund.setInsertTime(siteBooking.getCancelTime() == null |
| | | ? siteBooking.getInsertTime() : siteBooking.getCancelTime()); |
| | | refund.setRefundAmount(BigDecimal.valueOf(siteBooking.getPayMoney())); |
| | |
| | | } |
| | | } |
| | | |
| | | Map<Long, BigDecimal> couponDeductionAmounts = getCouponDeductionAmounts(usedCouponIds); |
| | | applyCouponDeductions(incomeVOS, couponDeductionAmounts); |
| | | |
| | | // 惠民卡和优惠券购买不归属到单一课程/场地门店,当前仅在平台或运营商汇总中计入。 |
| | | if (storeId == null) { |
| | | appendHuiminIncome(incomeVOS, operatorId); |
| | | appendHuiminIncome(incomeVOS, operatorId, usedCouponIds); |
| | | if (operatorId == null) { |
| | | appendCouponPurchaseIncome(incomeVOS); |
| | | } |
| | |
| | | List<PointMerchandiseIncomeVo> amount = pointMercharsClient.getAmount(cityManagerId); |
| | | for (PointMerchandiseIncomeVo pointMerchandiseIncomeVo : amount) { |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(6); |
| | | if (pointMerchandiseIncomeVo==null) continue; |
| | | temp.setInsertTime(pointMerchandiseIncomeVo.getInsertTime()); |
| | | if (pointMerchandiseIncomeVo.getCash()!=null){ |
| | | temp.setAmount(pointMerchandiseIncomeVo.getCash()); |
| | | if (pointMerchandiseIncomeVo.getUserCouponId() != null) { |
| | | usedCouponIds.add(pointMerchandiseIncomeVo.getUserCouponId()); |
| | | temp.setId(pointMerchandiseIncomeVo.getUserCouponId().toString()); |
| | | } |
| | | incomeVOS.add(temp); |
| | | } |
| | | } |
| | | Map<Long, BigDecimal> couponDeductionAmounts = getCouponDeductionAmounts(usedCouponIds); |
| | | applyCouponDeductions(incomeVOS, couponDeductionAmounts); |
| | | // 平台智慧球场 |
| | | if (storeId==null&&operatorId==null){ |
| | | gameDataQuery.setObjectId(0); |
| | | List<TGameRecord> data = ballClient.getData(gameDataQuery); |
| | | for (TGameRecord datum : data) { |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(5); |
| | | temp.setAmount(datum.getMoney()); |
| | | temp.setInsertTime(datum.getTime()); |
| | | incomeVOS.add(temp); |
| | |
| | | List<TGameRecord> data = ballClient.getData(gameDataQuery); |
| | | for (TGameRecord datum : data) { |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(5); |
| | | temp.setAmount(datum.getMoney()); |
| | | temp.setInsertTime(datum.getTime()); |
| | | incomeVOS.add(temp); |
| | |
| | | List<TGameRecord> data = ballClient.getData(gameDataQuery); |
| | | for (TGameRecord datum : data) { |
| | | IncomeVO temp = new IncomeVO(); |
| | | temp.setIncomeType(5); |
| | | temp.setAmount(datum.getMoney()); |
| | | temp.setInsertTime(datum.getTime()); |
| | | incomeVOS.add(temp); |
| | | } |
| | | } |
| | | Map<String, Object> monthlyData = buildIncomeStatistics(incomeVOS); |
| | | // 部分跨服务查询不支持日期参数,统一在收入明细层按支付/退款时间过滤, |
| | | // 确保总营收、净收入和收入类型统计使用完全相同的数据集。 |
| | | List<IncomeVO> statisticsIncomeVOS = filterIncomeRecordsByTime(incomeVOS, time); |
| | | Map<String, Object> monthlyData = buildIncomeStatistics(statisticsIncomeVOS); |
| | | monthlyData.put("incomeTypeNet", buildIncomeTypeNet(statisticsIncomeVOS, null)); |
| | | // 门票饼图需要日/月/季/年卡拆分;此前该数据只在 type1 内部返回, |
| | | // 现随统一营收接口返回,供平台页直接使用。 |
| | | monthlyData.put("ticketIncome", getTicketIncome(time, operatorId, storeId)); |
| | | return monthlyData; |
| | | } |
| | | |
| | | private Map<String, Object> getTicketIncome(String time, Integer operatorId, Integer storeId) { |
| | | List<Integer> userIds; |
| | | if (storeId != null) { |
| | | userIds = appUserClient.getUserStore(storeId); |
| | | } else if (operatorId != null) { |
| | | userIds = appUserClient.getUserYYs(operatorId); |
| | | } else { |
| | | List<Integer> platformUserIds = sysUserService.list(new LambdaQueryWrapper<User>() |
| | | .eq(User::getObjectType, 1)) |
| | | .stream().map(User::getId).collect(Collectors.toList()); |
| | | userIds = appUserClient.getUserPt(platformUserIds); |
| | | } |
| | | if (userIds == null) { |
| | | userIds = new ArrayList<>(); |
| | | } |
| | | // 活动服务对空集合会补充 -1,传入可变副本以兼容该历史实现。 |
| | | return pointMercharsClient.queryFee(new QueryDataFee(time, new ArrayList<>(userIds))); |
| | | } |
| | | |
| | | /** 惠民卡采用支付、退款两条事实流水,赠送卡不计营收。 */ |
| | | private void appendHuiminIncome(List<IncomeVO> incomeRecords, Integer operatorId) { |
| | | private void appendHuiminIncome(List<IncomeVO> incomeRecords, Integer operatorId, Set<Long> usedCouponIds) { |
| | | HuiminPayQuery query = new HuiminPayQuery(); |
| | | query.setGiftPaymentType(3); |
| | | if (operatorId != null) { |
| | |
| | | continue; |
| | | } |
| | | IncomeVO payment = new IncomeVO(); |
| | | payment.setIncomeType(6); |
| | | payment.setInsertTime(record.getPaymentTime()); |
| | | payment.setAmount(record.getSalesMoney()); |
| | | if (record.getUserCouponId() != null) { |
| | | usedCouponIds.add(record.getUserCouponId()); |
| | | payment.setId(record.getUserCouponId().toString()); |
| | | } |
| | | incomeRecords.add(payment); |
| | | if (Integer.valueOf(3).equals(record.getStatus()) |
| | | || Integer.valueOf(2).equals(record.getRefundStatus()) |
| | | || Integer.valueOf(3).equals(record.getRefundStatus())) { |
| | | IncomeVO refund = new IncomeVO(); |
| | | refund.setIncomeType(6); |
| | | refund.setInsertTime(record.getRefundTime() == null ? record.getPaymentTime() : record.getRefundTime()); |
| | | refund.setRefundAmount(record.getSalesMoney()); |
| | | incomeRecords.add(refund); |
| | |
| | | continue; |
| | | } |
| | | IncomeVO payment = new IncomeVO(); |
| | | payment.setIncomeType(6); |
| | | payment.setInsertTime(record.getPaymentTime()); |
| | | payment.setAmount(BigDecimal.valueOf(record.getCash())); |
| | | incomeRecords.add(payment); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 收入类型统计与净收入共用同一份收入明细。 |
| | | * 类型 1-5 对应会员、充值、课程、赛事、订场;6 为商品及其他平台收入。 |
| | | */ |
| | | private Map<Integer, BigDecimal> buildIncomeTypeNet(List<IncomeVO> incomeRecords, String time) { |
| | | Map<Integer, BigDecimal> result = new HashMap<>(); |
| | | for (int type = 1; type <= 6; type++) { |
| | | result.put(type, BigDecimal.ZERO); |
| | | } |
| | | Date startTime = null; |
| | | Date endTime = null; |
| | | if (ToolUtil.isNotEmpty(time)) { |
| | | try { |
| | | startTime = DateUtil.parse(time.split(" - ")[0] + " 00:00:00"); |
| | | endTime = DateUtil.parse(time.split(" - ")[1] + " 23:59:59"); |
| | | } catch (Exception ignored) { |
| | | // 页面日期格式异常时与原接口一致,不额外按日期过滤。 |
| | | } |
| | | } |
| | | for (IncomeVO record : incomeRecords) { |
| | | if (record.getIncomeType() == null || record.getInsertTime() == null) { |
| | | continue; |
| | | } |
| | | if (startTime != null && (record.getInsertTime().before(startTime) |
| | | || record.getInsertTime().after(endTime))) { |
| | | continue; |
| | | } |
| | | BigDecimal netAmount = getZeroIfNull(record.getAmount()) |
| | | .subtract(getZeroIfNull(record.getRefundAmount())); |
| | | result.put(record.getIncomeType(), result.getOrDefault(record.getIncomeType(), BigDecimal.ZERO) |
| | | .add(netAmount)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private List<IncomeVO> filterIncomeRecordsByTime(List<IncomeVO> incomeRecords, String time) { |
| | | if (ToolUtil.isEmpty(time)) { |
| | | return incomeRecords; |
| | | } |
| | | try { |
| | | Date startTime = DateUtil.parse(time.split(" - ")[0] + " 00:00:00"); |
| | | Date endTime = DateUtil.parse(time.split(" - ")[1] + " 23:59:59"); |
| | | return incomeRecords.stream() |
| | | .filter(record -> record.getInsertTime() != null |
| | | && !record.getInsertTime().before(startTime) |
| | | && !record.getInsertTime().after(endTime)) |
| | | .collect(Collectors.toList()); |
| | | } catch (Exception ignored) { |
| | | // 兼容旧页面的日期格式:解析失败时保留原有全量统计行为。 |
| | | return incomeRecords; |
| | | } |
| | | } |
| | | |
| | |
| | | map.put("quarterone",quarter); |
| | | map.put("yearone",year); |
| | | |
| | | // 数值卡片复用营收数据的同一批收入明细和退款口径。图表数据仍沿用原查询, |
| | | // 但收入类型净额之和始终与“营收数据-净收入”一致。 |
| | | Map<String, Object> incomeData = (Map<String, Object>) getIncomeData(null, null, time); |
| | | Map<Integer, BigDecimal> incomeTypeNet = (Map<Integer, BigDecimal>) incomeData.get("incomeTypeNet"); |
| | | map.put("fee1", incomeTypeNet.getOrDefault(1, BigDecimal.ZERO)); |
| | | map.put("fee2", incomeTypeNet.getOrDefault(2, BigDecimal.ZERO)); |
| | | map.put("fee3", incomeTypeNet.getOrDefault(3, BigDecimal.ZERO)); |
| | | map.put("fee4", incomeTypeNet.getOrDefault(4, BigDecimal.ZERO)); |
| | | map.put("fee5", incomeTypeNet.getOrDefault(5, BigDecimal.ZERO)); |
| | | map.put("fee7", incomeTypeNet.getOrDefault(6, BigDecimal.ZERO)); |
| | | |
| | | return map; |
| | | } |
| | | |
| | |
| | | List<Integer> ids = list.stream().map(User::getId).collect(Collectors.toList()); |
| | | List<Integer> userIds = appUserClient.getUserPt(ids); |
| | | QueryDataFee queryDataFee = new QueryDataFee(time, userIds); |
| | | // 课程和赛事接口的 ids 参数表示门店 ID;不能把平台用户 ID 传入。 |
| | | List<Integer> platformStoreIds = storeService.list(new LambdaQueryWrapper<TStore>() |
| | | .eq(TStore::getState, 1)) |
| | | .stream().map(TStore::getId).collect(Collectors.toList()); |
| | | QueryDataFee storeFeeQuery = new QueryDataFee(time, platformStoreIds); |
| | | // 会员费 |
| | | HashMap<String, Object> map1 = appUserClient.queryFee(queryDataFee); |
| | | Object fee1 = map1.get("fee1"); |
| | |
| | | Object fee2 = map1.get("fee2"); |
| | | map.put("fee2",fee2); |
| | | // 课程收入 |
| | | HashMap<String, Object> map3 = courseClient.queryFee(queryDataFee); |
| | | HashMap<String, Object> map3 = courseClient.queryFee(storeFeeQuery); |
| | | map.put("fee3",map3.get("fee")); |
| | | Object data = map3.get("data"); |
| | | map.put("courseData",data); |
| | | // 赛事收入 |
| | | Double aDouble1 = competitionClient.queryFee(queryDataFee); |
| | | Double aDouble1 = competitionClient.queryFee(storeFeeQuery); |
| | | map.put("fee4",aDouble1); |
| | | // 订场 |
| | | if(ids.size()==0){ |
| | | ids.add(-1); |
| | | } |
| | | LambdaQueryWrapper<SiteBooking> vipPaymentLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | if(ToolUtil.isNotEmpty(time)){ |
| | | String stime = time.split(" - ")[0]+" 00:00:00"; |
| | | String etime = time.split(" - ")[1]+" 23:59:59"; |
| | | vipPaymentLambdaQueryWrapper.between(SiteBooking::getInsertTime,stime,etime); |
| | | vipPaymentLambdaQueryWrapper.between(SiteBooking::getPayTime,stime,etime); |
| | | } |
| | | if(userIds.size()==0){ |
| | | userIds.add(-1); |
| | | } |
| | | vipPaymentLambdaQueryWrapper.eq(SiteBooking::getState, 1); |
| | | vipPaymentLambdaQueryWrapper.ne(SiteBooking::getStatus,0); |
| | | vipPaymentLambdaQueryWrapper.ne(SiteBooking::getStatus,5); |
| | | ArrayList<Integer> objects = new ArrayList<>(); |
| | | objects.add(1); |
| | | objects.add(2); |
| | | vipPaymentLambdaQueryWrapper.in(SiteBooking::getPayType,objects); |
| | | List<SiteBooking> list1 = siteBookingService.list(new QueryWrapper<SiteBooking>() |
| | | .ne("status",0) |
| | | .ne("status",5) |
| | | .ne("payType",3) |
| | | .ne("payType",4)); |
| | | List<SiteBooking> list1 = siteBookingService.list(vipPaymentLambdaQueryWrapper); |
| | | double sum = list1.stream().mapToDouble(SiteBooking::getPayMoney).sum(); |
| | | // 智慧球场查询query |
| | | GameDataQuery gameDataQuery = new GameDataQuery(); |
| | | gameDataQuery.setObjectId(0); |
| | | if (ToolUtil.isNotEmpty(time)) { |
| | | gameDataQuery.setStartTime(time.split(" - ")[0] + " 00:00:00"); |
| | | gameDataQuery.setEndTime(time.split(" - ")[1] + " 23:59:59"); |
| | | } |
| | | // 平台智慧球场 |
| | | List<TGameRecord> data1 = ballClient.getData(gameDataQuery); |
| | | double sum1 = data1.stream() |