puzhibing
2026-09-04 8492398378af25d7aa9598c79ea7aeb737d91d76
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TVinChargingOrderServiceImpl.java
@@ -1,17 +1,26 @@
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;
@@ -19,6 +28,11 @@
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;
@@ -36,9 +50,15 @@
    @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;
@@ -58,6 +78,81 @@
    }
    @Override
    public PageInfo<MyVinChargingOrderList> 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<MyVinChargingOrderList> 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<List<Long>> vinIdResponse = vinManagementClient.getVinIdsByAppUserId(appUserId);
        List<Long> 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<MyVinChargingOrderList> records = total == 0 ? Collections.emptyList()
                : baseMapper.pageAppletOrders(vinIds, (long) (current - 1) * size, size);
        fillAppletExtra(records);
        page.setRecords(records);
        return page;
    }
    @Override
    public Map<String, Object> appletDetail(Long chargingOrderId) {
        TVinChargingOrder order = getAuthorizedAppletOrder(chargingOrderId);
        if (order == null) {
            return Collections.emptyMap();
        }
        Map<String, Object> 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<VinChargingStatusVO> getChargingVinStatus(List<Long> vinIds) {
        if (vinIds == null || vinIds.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> distinctVinIds = vinIds.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        return distinctVinIds.isEmpty() ? Collections.emptyList() : baseMapper.getChargingVinStatus(distinctVinIds);
    }
    @Override
    public List<ChargingOrderVO> exportList(VinChargingOrderQuery query) {
        setAuthSiteIds(query);
        long total = baseMapper.count(query);
@@ -70,6 +165,7 @@
            result.addAll(batch);
        }
        fillExtra(result);
        fillRealtimeData(result);
        return result;
    }
@@ -87,9 +183,9 @@
            return Collections.emptyMap();
        }
        Map<String, Object> result = new HashMap<>();
        result.put("id", order.getId());
        result.put("id", order.getId() == null ? null : String.valueOf(order.getId()));
        result.put("code", order.getCode());
        result.put("vin", order.getVin());
        result.put("vin", order.getActualVin());
        result.put("actualVin", order.getActualVin());
        result.put("expectedVin", order.getExpectedVin());
        result.put("plateNum", order.getPlateNum());
@@ -104,10 +200,72 @@
        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<Site> 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<TChargingGun> 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<UploadRealTimeMonitoringData> monitoring = monitoringDataService.getDataByOrderCodeAsc(order.getCode());
        result.put("list", monitoring == null ? Collections.emptyList() : monitoring);
        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
@@ -148,9 +306,118 @@
                .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<List<Long>> response = vinManagementClient.getVinIdsByAppUserId(
                tokenService.getLoginUserApplet().getUserId());
        List<Long> 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<List<Site>> response = siteClient.getSiteByIds(Collections.singletonList(siteId));
        List<Site> 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<TChargingGun> response = chargingGunClient.getChargingGunById(gunId);
        return response == null ? null : response.getData();
    }
    private void fillAppletMonitoring(Map<String, Object> result, String orderCode) {
        List<UploadRealTimeMonitoringData> 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<String, UploadRealTimeMonitoringData> 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<Map<String, Object>> currentAndVoltage = new ArrayList<>();
        List<Map<String, Object>> power = new ArrayList<>();
        for (Map.Entry<String, UploadRealTimeMonitoringData> entry : minuteData.entrySet()) {
            UploadRealTimeMonitoringData data = entry.getValue();
            Map<String, Object> currentItem = new HashMap<>();
            currentItem.put("time", entry.getKey());
            currentItem.put("electricity", data.getOutput_current());
            currentItem.put("voltage", data.getOutput_voltage());
            currentAndVoltage.add(currentItem);
            Map<String, Object> 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<MyVinChargingOrderList> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        List<Integer> siteIds = list.stream().map(MyVinChargingOrderList::getSiteId)
                .filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<Integer> gunIds = list.stream().map(MyVinChargingOrderList::getChargingGunId)
                .filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<Integer, Site> 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<Integer, TChargingGun> 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<ChargingOrderVO> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        List<Long> orderIds = list.stream().map(ChargingOrderVO::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<Long, Integer> periodCounts = new HashMap<>();
        if (!orderIds.isEmpty()) {
            for (Map<String, Object> 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<Integer> siteIds = list.stream().map(ChargingOrderVO::getSiteId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<Integer> gunIds = list.stream().map(ChargingOrderVO::getChargingGunId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
@@ -168,14 +435,29 @@
            if (item.getStartTime() != null && item.getEndTime() != null) {
                item.setChargingSecond(ChronoUnit.SECONDS.between(item.getStartTime(), item.getEndTime()));
            }
            UploadRealTimeMonitoringData data = monitoringDataService.getLastDataById(item.getCode());
            if (data != null) {
                item.setChargeCurrent(data.getOutput_current());
                item.setChargeVoltage(data.getOutput_voltage());
                item.setChargePower(data.getPower());
            }
            item.setCount(periodCounts.getOrDefault(item.getId(), 0));
            item.setPlatformIncome(BigDecimal.ZERO);
            item.setPartnerIncome(BigDecimal.ZERO);
        }
    }
    private void fillRealtimeData(List<ChargingOrderVO> 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);
        }
    }
}