package com.ruoyi.order.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.account.api.feignClient.VinManagementClient; import com.ruoyi.chargingPile.api.dto.GetSiteListDTO; import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient; import com.ruoyi.chargingPile.api.feignClient.ChargingPileClient; import com.ruoyi.chargingPile.api.feignClient.SiteClient; import com.ruoyi.chargingPile.api.model.Site; import com.ruoyi.chargingPile.api.model.TChargingGun; import com.ruoyi.chargingPile.api.model.TChargingPile; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.integration.api.feignClient.SendMessageClient; import com.ruoyi.integration.api.model.PlatformStopCharging; import com.ruoyi.integration.api.model.UploadRealTimeMonitoringData; import com.ruoyi.order.api.model.TVinChargingOrder; import com.ruoyi.order.api.query.VinChargingOrderQuery; import com.ruoyi.order.api.vo.ChargingOrderVO; import com.ruoyi.order.api.vo.VinChargingStatusVO; import com.ruoyi.order.dto.MyVinChargingOrderList; import com.ruoyi.order.mapper.TVinChargingOrderMapper; import com.ruoyi.order.service.TVinChargingOrderService; import com.ruoyi.order.util.mongodb.service.UploadRealTimeMonitoringDataService; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @Service public class TVinChargingOrderServiceImpl extends ServiceImpl implements TVinChargingOrderService { @Resource private TokenService tokenService; @Resource private VinManagementClient vinManagementClient; @Resource private SiteClient siteClient; @Resource private ChargingGunClient chargingGunClient; @Resource private ChargingPileClient chargingPileClient; @Resource private SendMessageClient sendMessageClient; @Resource private UploadRealTimeMonitoringDataService monitoringDataService; @Override public PageInfo pageList(VinChargingOrderQuery query) { int pageCurr = query.getPageCurr() == null || query.getPageCurr() < 1 ? 1 : query.getPageCurr(); int pageSize = query.getPageSize() == null || query.getPageSize() < 1 ? 50 : query.getPageSize(); setAuthSiteIds(query); PageInfo page = new PageInfo<>(pageCurr, pageSize); long total = baseMapper.count(query); page.setTotal(total); List records = total == 0 ? Collections.emptyList() : baseMapper.pageList(query, (long) (pageCurr - 1) * pageSize, pageSize); fillExtra(records); page.setRecords(records); return page; } @Override public PageInfo pageAppletOrders(Integer pageCurr, Integer pageSize) { int current = pageCurr == null || pageCurr < 1 ? 1 : pageCurr; int size = pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 100); PageInfo page = new PageInfo<>(current, size); if (tokenService.getLoginUserApplet() == null || tokenService.getLoginUserApplet().getUserId() == null) { page.setTotal(0); page.setRecords(Collections.emptyList()); return page; } Long appUserId = tokenService.getLoginUserApplet().getUserId(); R> vinIdResponse = vinManagementClient.getVinIdsByAppUserId(appUserId); List vinIds = vinIdResponse == null ? Collections.emptyList() : Optional.ofNullable(vinIdResponse.getData()).orElse(Collections.emptyList()); if (vinIds.isEmpty()) { page.setTotal(0); page.setRecords(Collections.emptyList()); return page; } long total = baseMapper.countAppletOrders(vinIds); page.setTotal(total); List records = total == 0 ? Collections.emptyList() : baseMapper.pageAppletOrders(vinIds, (long) (current - 1) * size, size); fillAppletExtra(records); page.setRecords(records); return page; } @Override public Map appletDetail(Long chargingOrderId) { TVinChargingOrder order = getAuthorizedAppletOrder(chargingOrderId); if (order == null) { return Collections.emptyMap(); } Map result = new HashMap<>(); result.put("id", String.valueOf(order.getId())); result.put("chargingGunId", order.getChargingGunId()); result.put("code", order.getCode()); result.put("createTime", order.getCreateTime() == null ? null : order.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); result.put("status", order.getStatus()); result.put("licensePlate", order.getPlateNum()); result.put("startTime", toEpochMilli(order.getStartTime())); result.put("endTime", toEpochMilli(order.getEndTime())); result.put("orderAmount", order.getOrderAmount()); result.put("paymentAmount", order.getPaymentAmount()); result.put("rechargeAmount", order.getRechargeAmount()); result.put("couponDiscountAmount", order.getCouponDiscountAmount()); result.put("vipDiscountAmount", order.getVipDiscountAmount()); result.put("refundAmount", order.getRefundAmount()); result.put("electricMoney", order.getElectrovalence()); result.put("serviceMoney", order.getServiceCharge()); result.put("totalElectricQuantity", order.getChargingCapacity()); result.put("stageCost", baseMapper.accountingStrategyList(order.getId())); result.put("actionable", 0); result.put("isAppeal", 0); Site site = getSite(order.getSiteId()); result.put("title", site == null ? "未知电站" : site.getName()); TChargingGun gun = getGun(order.getChargingGunId()); result.put("chargeMode", gun == null ? null : gun.getChargeMode()); result.put("name", gun == null ? null : gun.getName()); fillAppletMonitoring(result, order.getCode()); return result; } @Override public List getChargingVinStatus(List vinIds) { if (vinIds == null || vinIds.isEmpty()) { return Collections.emptyList(); } List distinctVinIds = vinIds.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList()); return distinctVinIds.isEmpty() ? Collections.emptyList() : baseMapper.getChargingVinStatus(distinctVinIds); } @Override public List exportList(VinChargingOrderQuery query) { setAuthSiteIds(query); long total = baseMapper.count(query); List result = new ArrayList<>(); for (long offset = 0; offset < total; offset += 5000) { List batch = baseMapper.pageList(query, offset, 5000); if (batch == null || batch.isEmpty()) { break; } result.addAll(batch); } fillExtra(result); fillRealtimeData(result); return result; } @Override public Map summary(VinChargingOrderQuery query) { setAuthSiteIds(query); Map result = baseMapper.summary(query); return result == null ? new HashMap<>() : result; } @Override public Map detail(Long chargingOrderId) { TVinChargingOrder order = getAuthorizedOrder(chargingOrderId); if (order == null) { return Collections.emptyMap(); } Map result = new HashMap<>(); result.put("id", order.getId() == null ? null : String.valueOf(order.getId())); result.put("code", order.getCode()); result.put("vin", order.getActualVin()); result.put("actualVin", order.getActualVin()); result.put("expectedVin", order.getExpectedVin()); result.put("plateNum", order.getPlateNum()); result.put("phone", order.getPhone()); result.put("status", order.getStatus()); result.put("siteId", order.getSiteId()); result.put("chargingPileId", order.getChargingPileId()); result.put("chargingGunId", order.getChargingGunId()); result.put("startTime", order.getStartTime()); result.put("endTime", order.getEndTime()); result.put("chargingCapacity", order.getChargingCapacity()); result.put("paymentAmount", order.getPaymentAmount()); result.put("electrovalence", order.getElectrovalence()); result.put("serviceCharge", order.getServiceCharge()); if (order.getStartTime() != null && order.getEndTime() != null) { result.put("chargingSecond", ChronoUnit.SECONDS.between(order.getStartTime(), order.getEndTime())); } List sites = order.getSiteId() == null ? Collections.emptyList() : Optional.ofNullable(siteClient.getSiteByIds(Collections.singletonList(order.getSiteId())).getData()).orElse(Collections.emptyList()); Site site = sites.stream().findFirst().orElse(null); result.put("siteName", site == null ? null : site.getName()); List guns = order.getChargingGunId() == null ? Collections.emptyList() : Optional.ofNullable(chargingGunClient.getChargingGunByIds(Collections.singletonList(order.getChargingGunId())).getData()).orElse(Collections.emptyList()); TChargingGun gun = guns.stream().findFirst().orElse(null); result.put("terminalName", gun == null ? null : gun.getName()); List monitoring = monitoringDataService.getDataByOrderCodeAsc(order.getCode()); if (monitoring == null) { monitoring = Collections.emptyList(); } for (UploadRealTimeMonitoringData data : monitoring) { if (data.getOutput_current() != null && data.getOutput_voltage() != null) { data.setPower(data.getOutput_voltage().multiply(data.getOutput_current()).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP)); } } UploadRealTimeMonitoringData latestMonitoring = monitoring.isEmpty() ? null : monitoring.get(monitoring.size() - 1); result.put("cdElectronic", latestMonitoring == null ? null : latestMonitoring.getOutput_current()); result.put("cdVoltage", latestMonitoring == null ? null : latestMonitoring.getOutput_voltage()); result.put("totalPower", latestMonitoring == null ? null : latestMonitoring.getPower()); result.put("surplus", latestMonitoring == null ? null : latestMonitoring.getSoc()); result.put("list", monitoring); result.put("list1", baseMapper.accountingStrategyList(order.getId())); return result; } @Override public AjaxResult stopCharging(String chargingOrderId, Integer chargingGunId) { Long orderId; try { orderId = Long.valueOf(chargingOrderId); } catch (NumberFormatException e) { return AjaxResult.error("VIN码充电订单ID无效"); } TVinChargingOrder order = getAuthorizedOrder(orderId); if (order == null) { return AjaxResult.error("VIN码充电订单不存在或无权操作"); } if (order.getChargingGunId() == null || !order.getChargingGunId().equals(chargingGunId)) { return AjaxResult.error("充电枪与订单不匹配"); } Integer status = order.getStatus(); if (status == null || !status.equals(3)) { return AjaxResult.error(status != null && (status.equals(4) || status.equals(5)) ? "不能重复操作" : "还未开始充电"); } TChargingGun chargingGun = chargingGunClient.getChargingGunById(chargingGunId).getData(); TChargingPile chargingPile = order.getChargingPileId() == null ? null : chargingPileClient.getChargingPileById(order.getChargingPileId()).getData(); if (chargingGun == null || chargingPile == null) { return AjaxResult.error("未找到订单对应的充电设备"); } order.setStatus(4); order.setEndMode(1); order.setEndTime(LocalDateTime.now()); if (!updateById(order)) { return AjaxResult.error("更新VIN码充电订单状态失败"); } PlatformStopCharging command = new PlatformStopCharging(); command.setCharging_pile_code(chargingPile.getCode()); command.setCharging_gun_code(chargingGun.getCode()); sendMessageClient.platformStopCharging(command); return AjaxResult.success(); } @Override public List> accountingStrategyList(Long chargingOrderId) { TVinChargingOrder order = getAuthorizedOrder(chargingOrderId); return order == null ? Collections.emptyList() : baseMapper.accountingStrategyList(chargingOrderId); } private void setAuthSiteIds(VinChargingOrderQuery query) { List authorizedSiteIds = getAuthorizedSiteIds(); if (query.getSiteId() != null) { authorizedSiteIds = authorizedSiteIds.contains(query.getSiteId()) ? Collections.singletonList(query.getSiteId()) : Collections.singletonList(-1); } if (authorizedSiteIds.isEmpty()) { authorizedSiteIds = Collections.singletonList(-1); } query.setSiteIds(authorizedSiteIds); } private TVinChargingOrder getAuthorizedOrder(Long chargingOrderId) { if (chargingOrderId == null) { return null; } TVinChargingOrder order = getById(chargingOrderId); if (order == null || order.getSiteId() == null || !getAuthorizedSiteIds().contains(order.getSiteId())) { return null; } return order; } private List getAuthorizedSiteIds() { Long userId = tokenService.getLoginUser().getUserid(); if (userId == null) { return Collections.emptyList(); } return Optional.ofNullable(siteClient.getSiteListByUserId(userId).getData()) .orElse(Collections.emptyList()).stream().map(GetSiteListDTO::getId).collect(Collectors.toList()); } private TVinChargingOrder getAuthorizedAppletOrder(Long chargingOrderId) { if (chargingOrderId == null || tokenService.getLoginUserApplet() == null || tokenService.getLoginUserApplet().getUserId() == null) { return null; } TVinChargingOrder order = getById(chargingOrderId); if (order == null || order.getVinId() == null) { return null; } R> response = vinManagementClient.getVinIdsByAppUserId( tokenService.getLoginUserApplet().getUserId()); List vinIds = response == null ? Collections.emptyList() : Optional.ofNullable(response.getData()).orElse(Collections.emptyList()); return vinIds.contains(order.getVinId()) ? order : null; } private Long toEpochMilli(LocalDateTime time) { return time == null ? null : time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } private Site getSite(Integer siteId) { if (siteId == null) { return null; } R> response = siteClient.getSiteByIds(Collections.singletonList(siteId)); List sites = response == null ? Collections.emptyList() : Optional.ofNullable(response.getData()).orElse(Collections.emptyList()); return sites.stream().findFirst().orElse(null); } private TChargingGun getGun(Integer gunId) { if (gunId == null) { return null; } R response = chargingGunClient.getChargingGunById(gunId); return response == null ? null : response.getData(); } private void fillAppletMonitoring(Map result, String orderCode) { List dataList = orderCode == null ? Collections.emptyList() : monitoringDataService.getDataByOrderCode(orderCode); if (dataList == null || dataList.isEmpty()) { result.put("currentAndVoltage", Collections.emptyList()); result.put("power", Collections.emptyList()); return; } SimpleDateFormat formatter = new SimpleDateFormat("HH:mm"); Map minuteData = new java.util.LinkedHashMap<>(); for (UploadRealTimeMonitoringData data : dataList) { if (data != null && data.getCreate_time() != null) { minuteData.putIfAbsent(formatter.format(data.getCreate_time()), data); } } List> currentAndVoltage = new ArrayList<>(); List> power = new ArrayList<>(); for (Map.Entry entry : minuteData.entrySet()) { UploadRealTimeMonitoringData data = entry.getValue(); Map currentItem = new HashMap<>(); currentItem.put("time", entry.getKey()); currentItem.put("electricity", data.getOutput_current()); currentItem.put("voltage", data.getOutput_voltage()); currentAndVoltage.add(currentItem); Map powerItem = new HashMap<>(); powerItem.put("time", entry.getKey()); powerItem.put("soc", data.getSoc()); BigDecimal outputPower = data.getOutput_current() == null || data.getOutput_voltage() == null ? null : data.getOutput_current().multiply(data.getOutput_voltage()) .divide(new BigDecimal("1000"), 2, RoundingMode.HALF_DOWN); powerItem.put("power", outputPower); power.add(powerItem); } result.put("currentAndVoltage", currentAndVoltage); result.put("power", power); } private void fillAppletExtra(List list) { if (list == null || list.isEmpty()) { return; } List siteIds = list.stream().map(MyVinChargingOrderList::getSiteId) .filter(Objects::nonNull).distinct().collect(Collectors.toList()); List gunIds = list.stream().map(MyVinChargingOrderList::getChargingGunId) .filter(Objects::nonNull).distinct().collect(Collectors.toList()); Map sites = siteIds.isEmpty() ? Collections.emptyMap() : Optional.ofNullable(siteClient.getSiteByIds(siteIds).getData()).orElse(Collections.emptyList()).stream() .collect(Collectors.toMap(Site::getId, item -> item, (a, b) -> a)); Map guns = gunIds.isEmpty() ? Collections.emptyMap() : Optional.ofNullable(chargingGunClient.getChargingGunByIds(gunIds).getData()).orElse(Collections.emptyList()).stream() .collect(Collectors.toMap(TChargingGun::getId, item -> item, (a, b) -> a)); for (MyVinChargingOrderList item : list) { Site site = sites.get(item.getSiteId()); item.setTitle(site == null ? "未知电站" : site.getName()); TChargingGun gun = guns.get(item.getChargingGunId()); item.setName(gun == null ? null : gun.getName()); } } private void fillExtra(List list) { if (list == null || list.isEmpty()) { return; } List orderIds = list.stream().map(ChargingOrderVO::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); Map periodCounts = new HashMap<>(); if (!orderIds.isEmpty()) { for (Map item : baseMapper.countAccountingStrategies(orderIds)) { Number chargingOrderId = (Number) item.get("chargingOrderId"); Number periodCount = (Number) item.get("periodCount"); if (chargingOrderId != null && periodCount != null) { periodCounts.put(chargingOrderId.longValue(), periodCount.intValue()); } } } List siteIds = list.stream().map(ChargingOrderVO::getSiteId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); List gunIds = list.stream().map(ChargingOrderVO::getChargingGunId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); Map sites = siteIds.isEmpty() ? Collections.emptyMap() : Optional.ofNullable(siteClient.getSiteByIds(siteIds).getData()).orElse(Collections.emptyList()).stream() .collect(Collectors.toMap(Site::getId, item -> item, (a, b) -> a)); Map guns = gunIds.isEmpty() ? Collections.emptyMap() : Optional.ofNullable(chargingGunClient.getChargingGunByIds(gunIds).getData()).orElse(Collections.emptyList()).stream() .collect(Collectors.toMap(TChargingGun::getId, item -> item, (a, b) -> a)); for (ChargingOrderVO item : list) { Site site = sites.get(item.getSiteId()); item.setSiteName(site == null ? null : site.getName()); TChargingGun gun = guns.get(item.getChargingGunId()); item.setTerminalName(gun == null ? null : gun.getName()); if (item.getStartTime() != null && item.getEndTime() != null) { item.setChargingSecond(ChronoUnit.SECONDS.between(item.getStartTime(), item.getEndTime())); } item.setCount(periodCounts.getOrDefault(item.getId(), 0)); item.setPlatformIncome(BigDecimal.ZERO); item.setPartnerIncome(BigDecimal.ZERO); } } private void fillRealtimeData(List list) { for (ChargingOrderVO item : list) { if (item.getCode() == null || item.getCode().trim().isEmpty()) { continue; } UploadRealTimeMonitoringData data = monitoringDataService.getLastDataById(item.getCode()); if (data == null) { continue; } item.setChargeCurrent(data.getOutput_current()); item.setChargeVoltage(data.getOutput_voltage()); BigDecimal power = data.getPower(); if (power == null && data.getOutput_current() != null && data.getOutput_voltage() != null) { power = data.getOutput_current().multiply(data.getOutput_voltage()) .divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP); } item.setChargePower(power); } } }