nameMap = companyIds.isEmpty() ? Collections.emptyMap()
: groupCompanyService.listByIds(companyIds).stream()
.collect(Collectors.toMap(TGroupCompany::getId, TGroupCompany::getName, (a, b) -> a));
// 复用与列表相同的聚合逻辑填充5列
fillAggregates(fleets);
return fleets.stream().map(item -> {
FleetExportDTO dto = new FleetExportDTO();
dto.setFleetName(item.getFleetName());
dto.setCompanyName(nameMap.get(item.getCompanyId()));
dto.setVinCount(item.getVinCount() == null ? null : String.valueOf(item.getVinCount()));
dto.setStationCount(item.getStationCount() == null ? null : String.valueOf(item.getStationCount()));
dto.setCumulativeCharge(item.getCumulativeCharge() == null ? null : item.getCumulativeCharge().toPlainString());
dto.setCumulativeElectrovalence(item.getCumulativeElectrovalence() == null ? null : item.getCumulativeElectrovalence().toPlainString());
dto.setCumulativeServiceCharge(item.getCumulativeServiceCharge() == null ? null : item.getCumulativeServiceCharge().toPlainString());
dto.setStatus(item.getStatus() == null ? null : String.valueOf(item.getStatus()));
return dto;
}).collect(Collectors.toList());
}
/**
* 填充车队5列聚合(VIN车辆数、可充电站数、累计充电量/电费/服务费)
* VIN/订单聚合通过远程调用(feign fallback 已兜底返回 0/空),可充电站数本地查询 t_charge_authorization.site_ids 去重计数(过滤 del_flag=0);
* t_site.status 过滤需跨库(charging_pile_service)暂不实施(保持本服务自治);任一远程调用异常不会影响整体加载。
*/
public void fillAggregates(List fleets) {
if (fleets == null || fleets.isEmpty()) {
return;
}
// 1. 可充电站数:按 companyId 聚合 t_charge_authorization.site_ids 去重计数
Set companyIds = fleets.stream()
.map(TFleet::getCompanyId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map stationCountMap = companyIds.isEmpty()
? Collections.emptyMap()
: chargeAuthorizationMapper.selectList(Wrappers.lambdaQuery()
.in(TChargeAuthorization::getCompanyId, companyIds)
.eq(TChargeAuthorization::getDelFlag, 0))
.stream()
.collect(Collectors.toMap(
TChargeAuthorization::getCompanyId,
auth -> countSiteIds(auth.getSiteIds()),
(a, b) -> a));
// 2. 遍历填充
for (TFleet fleet : fleets) {
if (fleet.getId() == null) {
continue;
}
// VIN车辆数(远程调用,软失败 fallback 已处理)
try {
R response = vinManagementClient.countByFleet(fleet.getId());
fleet.setVinCount(response == null || !R.isSuccess(response) ? 0L : response.getData());
} catch (Exception ex) {
fleet.setVinCount(0L);
}
// 可充电站数(本地查询)
fleet.setStationCount(fleet.getCompanyId() == null ? 0L : stationCountMap.getOrDefault(fleet.getCompanyId(), 0L));
// 累计三列(远程调用,软失败 fallback 已处理返回 0)
try {
R response = fleetOrderAggregateClient.aggregateByFleet(fleet.getId());
FleetOrderAggregateVO data = response == null || !R.isSuccess(response) ? null : response.getData();
fleet.setCumulativeCharge(data == null || data.getCumulativeCharge() == null ? BigDecimal.ZERO : data.getCumulativeCharge());
fleet.setCumulativeElectrovalence(data == null || data.getCumulativeElectrovalence() == null ? BigDecimal.ZERO : data.getCumulativeElectrovalence());
fleet.setCumulativeServiceCharge(data == null || data.getCumulativeServiceCharge() == null ? BigDecimal.ZERO : data.getCumulativeServiceCharge());
} catch (Exception ex) {
fleet.setCumulativeCharge(BigDecimal.ZERO);
fleet.setCumulativeElectrovalence(BigDecimal.ZERO);
fleet.setCumulativeServiceCharge(BigDecimal.ZERO);
}
}
}
/**
* 统计授权 site_ids 逗号字符串的去重 ID 数(容错:null/空/末尾逗号/连续逗号)
*/
private long countSiteIds(String siteIds) {
if (!StringUtils.hasText(siteIds)) {
return 0L;
}
Set set = new LinkedHashSet<>();
for (String token : siteIds.split(",")) {
String trimmed = token == null ? "" : token.trim();
if (!trimmed.isEmpty()) {
set.add(trimmed);
}
}
return set.size();
}
private String trim(String value) {
return value == null ? null : value.trim();
}
private Integer parseStatus(String value, int row) {
if (!StringUtils.hasText(value) || "1".equals(value.trim()) || "启用".equals(value.trim())) {
return ENABLED;
}
if ("0".equals(value.trim()) || "停用".equals(value.trim())) {
return DISABLED;
}
throw new ServiceException((row > 0 ? "第" + row + "行" : "") + "启用状态错误");
}
@Override
public boolean deleteFleets(List ids) {
if (ids == null || ids.isEmpty()) {
throw new ServiceException("请选择需要删除的车队");
}
List distinct = ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
if (distinct.isEmpty()) {
throw new ServiceException("请选择需要删除的车队");
}
if (listByIds(distinct).size() != distinct.size()) {
throw new ServiceException("部分车队不存在或已删除");
}
// 先解绑该车队下的 VIN码/充电卡/白名单(跨服务无分布式事务:解绑失败即中止删除,两侧数据保持一致;
// 解绑成功后删除失败仅剩车队未删,可重试删除,不会产生已删车队挂靠的脏引用)
try {
R response = fleetUnbindClient.unbindByFleetIds(distinct);
if (response == null || !R.isSuccess(response)) {
throw new ServiceException("车队关联数据解绑失败:" + (response == null ? "服务无响应" : response.getMsg()));
}
} catch (ServiceException ex) {
throw ex;
} catch (Exception ex) {
throw new ServiceException("车队关联数据解绑失败,请稍后重试");
}
return removeByIds(distinct);
}
}