| | |
| | | public R<Map<String, Object>> franchiseeOperation(@RequestBody(required = false) Map<String, Object> params) { |
| | | Map<String, Object> result = new LinkedHashMap<>(); |
| | | List<Integer> siteIds = franchiseeSiteIds(params); |
| | | List<TChargingPile> piles = Collections.emptyList(); |
| | | if (!siteIds.isEmpty()) { R<List<TChargingPile>> pileResult = chargingPileClient.getChargingPileBySiteIds(siteIds); if (pileResult != null && pileResult.getData() != null) piles = pileResult.getData(); } |
| | | List<TChargingGun> guns = Collections.emptyList(); |
| | | List<Integer> pileIds = piles.stream().map(TChargingPile::getId).filter(Objects::nonNull).collect(Collectors.toList()); |
| | | if (!pileIds.isEmpty()) { |
| | | GetChargingGunByChargingPileIdsVo query = new GetChargingGunByChargingPileIdsVo(); query.setChargingPileIds(pileIds); |
| | | R<List<TChargingGun>> gunResult = chargingGunClient.getChargingGunByChargingPileIds(query); |
| | | if (gunResult != null && gunResult.getData() != null) guns = gunResult.getData(); |
| | | } |
| | | BigDecimal total = BigDecimal.valueOf(guns.size()); |
| | | BigDecimal available = BigDecimal.valueOf(guns.stream().filter(this::isAvailableGun).count()); |
| | | BigDecimal fault = countGuns(guns, 7), offline = countGuns(guns, 1); |
| | | LocalDateTime[] range = franchiseeRange(params); |
| | | List<FranchiseeDayStat> operationStats = franchiseeDayStats(siteIds, range); |
| | | BigDecimal powerSatisfaction = demandPowerSatisfaction(operationStats); |
| | | Map<Integer, FranchiseeGunSat> gunSatMap = Collections.emptyMap(); |
| | | if (!siteIds.isEmpty() && range[0] != null && range[1] != null) { |
| | | gunSatMap = chargingOrderMapper.franchiseeGunSatisfaction(siteIds, range[0], range[1]).stream() |
| | | .filter(sat -> sat != null && sat.getChargingGunId() != null) |
| | | .collect(Collectors.toMap(FranchiseeGunSat::getChargingGunId, sat -> sat, (left, right) -> left)); |
| | | } |
| | | Map<String, Object> summary = new LinkedHashMap<>(); summary.put("availableRate", rate(available, total)); summary.put("faultRate", rate(fault, total)); summary.put("offlineRate", rate(offline, total)); summary.put("powerSatisfactionRate", powerSatisfaction); |
| | | result.put("summary", summary); result.put("dcCharts", operationCharts(guns, gunSatMap, true)); result.put("acCharts", operationCharts(guns, gunSatMap, false)); |
| | | ChargingStatisticsQueryDto query = new ChargingStatisticsQueryDto(); |
| | | query.setDayType(5); |
| | | query.setStartTime(range[0].toLocalDate()); |
| | | query.setEndTime(range[1].toLocalDate().minusDays(1)); |
| | | |
| | | List<Map<String, Object>> dcAvailable = safeList(chargingOrderService.equipmentUserType1(siteIds, query)); |
| | | List<Map<String, Object>> acAvailable = safeList(chargingOrderService.equipmentUserType2(siteIds, query)); |
| | | List<Map<String, Object>> dcFault = safeList(chargingOrderService.equipmentMapbroke1(siteIds, query)); |
| | | List<Map<String, Object>> acFault = safeList(chargingOrderService.equipmentMapbroke2(siteIds, query)); |
| | | List<Map<String, Object>> dcOffline = safeList(chargingOrderService.equipmentMapOut1(siteIds, query)); |
| | | List<Map<String, Object>> acOffline = safeList(chargingOrderService.equipmentMapOut2(siteIds, query)); |
| | | List<Map<String, Object>> dcSatisfaction = safeList(chargingOrderService.needElec(siteIds, query)); |
| | | List<Map<String, Object>> acSatisfaction = safeList(chargingOrderService.needElec1(siteIds, query)); |
| | | normalizeOperationPercents(dcAvailable); |
| | | normalizeOperationPercents(acAvailable); |
| | | normalizeOperationPercents(dcFault); |
| | | normalizeOperationPercents(acFault); |
| | | normalizeOperationPercents(dcOffline); |
| | | normalizeOperationPercents(acOffline); |
| | | normalizeOperationPercents(dcSatisfaction); |
| | | normalizeOperationPercents(acSatisfaction); |
| | | |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("availableRate", calculateAveragePercent(dcAvailable, acAvailable)); |
| | | summary.put("faultRate", calculateAveragePercent(dcFault, acFault)); |
| | | summary.put("offlineRate", calculateAveragePercent(dcOffline, acOffline)); |
| | | summary.put("powerSatisfactionRate", calculateAveragePercent(dcSatisfaction, acSatisfaction)); |
| | | result.put("summary", summary); |
| | | result.put("dcCharts", Arrays.asList( |
| | | operationChart(dcAvailable, "可用率"), |
| | | operationChart(dcFault, "故障率"), |
| | | operationChart(dcOffline, "离网率"), |
| | | operationChart(dcSatisfaction, "需求电流满足率"))); |
| | | result.put("acCharts", Arrays.asList( |
| | | operationChart(acAvailable, "可用率"), |
| | | operationChart(acFault, "故障率"), |
| | | operationChart(acOffline, "离网率"), |
| | | operationChart(acSatisfaction, "需求电流满足率"))); |
| | | return R.ok(result); |
| | | } |
| | | |
| | | private Map<String, Object> operationChart(List<Map<String, Object>> rows, String name) { |
| | | List<String> categories = rows.stream().map(row -> { |
| | | String siteName = row.get("siteName") == null ? "" : String.valueOf(row.get("siteName")); |
| | | String gunName = row.get("name") == null ? "" : String.valueOf(row.get("name")); |
| | | return siteName + gunName; |
| | | }).collect(Collectors.toList()); |
| | | List<Object> values = rows.stream().map(row -> row.getOrDefault("percent", "0")).collect(Collectors.toList()); |
| | | Map<String, Object> chart = new LinkedHashMap<>(); |
| | | chart.put("categories", categories); |
| | | Map<String, Object> series = new LinkedHashMap<>(); |
| | | series.put("name", name); |
| | | series.put("data", values); |
| | | chart.put("series", Collections.singletonList(series)); |
| | | return chart; |
| | | } |
| | | |
| | | private void normalizeOperationPercents(List<Map<String, Object>> rows) { |
| | | for (Map<String, Object> row : rows) { |
| | | Object raw = row.get("percent"); |
| | | try { |
| | | BigDecimal percent = raw == null ? BigDecimal.ZERO : new BigDecimal(String.valueOf(raw)); |
| | | row.put("percent", percent.abs().toPlainString()); |
| | | } catch (NumberFormatException ignored) { |
| | | row.put("percent", "0"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** 加盟商看板按日聚合(siteIds 为空直接返回空,避免空 IN)。 */ |
| | | private List<FranchiseeDayStat> franchiseeDayStats(List<Integer> siteIds, LocalDateTime[] range) { |
| | | if (siteIds == null || siteIds.isEmpty() || range == null || range[0] == null || range[1] == null) { |