Pu Zhibing
2025-11-27 414a3acae0686fd39f9296aec3dad512ac2e2f74
新增加成都监管对接代码
1个文件已删除
14 文件已重命名
11个文件已添加
2个文件已修改
1768 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ChengDuJianGuanClientFallbackFactory.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ChengDuJianGuanClient.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/vo/NotificationStationFeeVo.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/ChengDuJianGuanUtil.java 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/ChengDuJianGuanController.java 303 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/ChengDuJianGuanUtil.java 517 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/ConnectorTypeEnum.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/ConstructionEnum.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/EquipmentTypeEnum.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/InterfaceUrlEnum.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/StationStatusEnum.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/StationTypeEnum.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/CDEquipmentInfo.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/CDOrderInfo.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/CDStationInfo.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/ChargeFeeDetail.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/ConnectorChargeStatusInfo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/EDIMessagePack.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/NotificationStationFee.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Cryptos.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Digests.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Encodes.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Exceptions.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/GBSignUtils.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/HttpRequestUtil.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/SignUtils.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ChengDuJianGuanClientFallbackFactory.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.integration.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.integration.api.feignClient.ChengDuJianGuanClient;
import com.ruoyi.integration.api.vo.NotificationStationFeeVo;
import org.springframework.cloud.openfeign.FallbackFactory;
public class ChengDuJianGuanClientFallbackFactory implements FallbackFactory<ChengDuJianGuanClient> {
    @Override
    public ChengDuJianGuanClient create(Throwable cause) {
        return new ChengDuJianGuanClient() {
            @Override
            public R notificationStationInfo(Integer siteId) {
                return R.fail("充电站信息变化推送失败:" + cause.getMessage());
            }
            @Override
            public R notificationStationFee(NotificationStationFeeVo vo) {
                return R.fail("站点费率变化推送失败:" + cause.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ChengDuJianGuanClient.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.integration.api.feignClient;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.integration.api.factory.ChengDuJianGuanClientFallbackFactory;
import com.ruoyi.integration.api.vo.NotificationStationFeeVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(contextId = "ChengDuJianGuanClient", value = ServiceNameConstants.JIANGUAN_SERVICE, fallbackFactory = ChengDuJianGuanClientFallbackFactory.class)
public interface ChengDuJianGuanClient {
    /**
     * 充电站信息变化推送
     * @param siteId
     * @return
     */
    @PostMapping("/chengdu/jianguan/notificationStationInfo")
    R notificationStationInfo(@RequestParam("siteId") Integer siteId);
    /**
     * 站点费率变化推送
     * @param vo
     * @return
     */
    @PostMapping("/chengdu/jianguan/notificationStationFee")
    R notificationStationFee(@RequestBody NotificationStationFeeVo vo);
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/vo/NotificationStationFeeVo.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.integration.api.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class NotificationStationFeeVo {
    /**
     * 站点code
     */
    private String siteCode;
    /**
     * 设备类型
     * 1:直流设备
     * 2:交流设备
     * 3:交直流一体设备
     */
    private Integer equipmentType;
    /**
     * 充电桩code
     */
    private String chargingPileCode;
}
ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,2 +1,3 @@
com.ruoyi.integration.api.factory.ChargingMessageClientFallbackFactory
com.ruoyi.integration.api.factory.ELuTongClientFallbackFactory
com.ruoyi.integration.api.factory.ELuTongClientFallbackFactory
com.ruoyi.integration.api.factory.ChengDuJianGuanClientFallbackFactory
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/ChengDuJianGuanUtil.java
File was deleted
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/ChengDuJianGuanController.java
New file
@@ -0,0 +1,303 @@
package com.ruoyi.jianguan.chengdujianguan;
import com.ruoyi.chargingPile.api.feignClient.AccountingStrategyDetailClient;
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.TAccountingStrategyDetail;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.chargingPile.api.model.TChargingPile;
import com.ruoyi.chargingPile.api.vo.GetChargingGunByChargingPileIdsVo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.integration.api.vo.NotificationStationFeeVo;
import com.ruoyi.integration.api.vo.SiteVo;
import com.ruoyi.integration.api.vo.TAccountingStrategyDetailVo;
import com.ruoyi.integration.api.vo.TChargingPileVo;
import com.ruoyi.jianguan.chengdujianguan.enu.*;
import com.ruoyi.jianguan.chengdujianguan.model.CDEquipmentInfo;
import com.ruoyi.jianguan.chengdujianguan.model.CDStationInfo;
import com.ruoyi.jianguan.chengdujianguan.model.ChargeFeeDetail;
import com.ruoyi.jianguan.chengdujianguan.model.NotificationStationFee;
import com.ruoyi.jianguan.model.ConnectorInfo;
import com.ruoyi.other.api.feignClient.SystemConfigurationClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/chengdu/jianguan")
public class ChengDuJianGuanController {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private SiteClient siteClient;
    @Resource
    private ChargingPileClient chargingPileClient;
    @Resource
    private ChargingGunClient chargingGunClient;
    @Resource
    private SystemConfigurationClient systemConfigurationClient;
    @Resource
    private AccountingStrategyDetailClient accountingStrategyDetailClient;
    /**
     * 充电站信息变化推送
     * @param siteId
     * @return
     */
    @PostMapping("/notificationStationInfo")
    public R notificationStationInfo(@RequestParam("siteId") Integer siteId){
        Site site = siteClient.getSiteByIds(Arrays.asList(siteId)).getData().get(0);
        ChengDuJianGuanUtil.notificationStationInfo(redisTemplate, buildStationInfo(site));
        return R.ok();
    }
    private CDStationInfo buildStationInfo(Site site){
        String serviceTel = systemConfigurationClient.getServerPhone().getData();
        CDStationInfo stationInfo = new CDStationInfo();
        stationInfo.setStationID(site.getCode());
        stationInfo.setOperatorID("906171535");
        stationInfo.setEquipmentOwnerID("906171535");
        stationInfo.setStationName(site.getName());
        stationInfo.setIsAloneApply(site.getBusinessExpandType());
        stationInfo.setAccountNumber(site.getResidentNo());
        stationInfo.setCapacity(site.getCapacity());
        stationInfo.setCountryCode(StringUtils.isNotEmpty(site.getCountryCode()) ? site.getCountryCode() : "CN");
        stationInfo.setAreaCode(site.getDistrictsCode());
        stationInfo.setAreaCodeCountryside(site.getDistrictsCode() + "000000");
        stationInfo.setAddress(site.getAddress());
        stationInfo.setStationTel(StringUtils.isNotEmpty(serviceTel) ? serviceTel.split(",")[0] : "");
        stationInfo.setServiceTel(StringUtils.isNotEmpty(serviceTel) ? serviceTel.split(",")[0] : "");
        switch (site.getSiteType()){
            case 0:
                stationInfo.setStationType(StationTypeEnum.OTHER.getType());
                break;
            case 1:
                stationInfo.setStationType(StationTypeEnum.PUBLIC.getType());
                break;
            case 2:
                stationInfo.setStationType(StationTypeEnum.PERSONAGE.getType());
                break;
            case 3:
                stationInfo.setStationType(StationTypeEnum.BUS_SPECIFIC.getType());
                break;
            case 4:
                stationInfo.setStationType(StationTypeEnum.SANITATION_SPECIFIC.getType());
                break;
            case 5:
                stationInfo.setStationType(StationTypeEnum.LOGISTICS_SPECIFIC.getType());
                break;
            case 6:
                stationInfo.setStationType(StationTypeEnum.TEXT_SPECIFIC.getType());
                break;
        }
        stationInfo.setIsOpen(1);
        if(site.getStatus() == 1){
            stationInfo.setStationStatus(StationStatusEnum.NORMAL_USE.getStatus());
        }
        if(site.getStatus() == 2){
            stationInfo.setStationStatus(StationStatusEnum.MAINTAIN.getStatus());
        }
        if(site.getStatus() == 3){
            stationInfo.setStationStatus(StationStatusEnum.OFF_LINE.getStatus());
        }
        stationInfo.setParkNums(site.getParkingSpace());
        stationInfo.setStationLng(new BigDecimal(site.getLon()).setScale(6, RoundingMode.HALF_EVEN));
        stationInfo.setStationLat(new BigDecimal(site.getLat()).setScale(6, RoundingMode.HALF_EVEN));
        stationInfo.setSiteGuide(site.getGuide());
        stationInfo.setConstruction(site.getConstructionSite() == 0 ? ConstructionEnum.OTHER.getType() : site.getConstructionSite());
        stationInfo.setPictures(StringUtils.isNotEmpty(site.getImgUrl()) ? Arrays.asList(site.getImgUrl().split(",")) : new ArrayList<>());
        stationInfo.setMatchCars(site.getVehicleDescription());
        stationInfo.setParkInfo("");
        stationInfo.setParkOwner("");
        stationInfo.setParkManager("");
        stationInfo.setOpenAllDay(1);
        stationInfo.setBusinessHours("周一至周日00:00-24:00");
        stationInfo.setElectricityFee(site.getRateDescription());
        stationInfo.setServiceFee(site.getServiceFee());
        stationInfo.setParkFeeType(site.getParkType());
        stationInfo.setParkFee(site.getParkFee());
        stationInfo.setPayment("线上");
        stationInfo.setSupportOrder(site.getSupportOrder());
        stationInfo.setRemark(site.getRemark());
        if(StringUtils.isNotEmpty(site.getSupportingFacilities())){
            List<String> list = Arrays.asList(site.getSupportingFacilities().split(","));
            stationInfo.setToiletFlag(list.contains("1") ? 1 : 0);
            stationInfo.setStoreFlag(list.contains("2") ? 1 : 0);
            stationInfo.setLoungeFlag(list.contains("4") ? 1 : 0);
            stationInfo.setCanopyFlag(list.contains("5") ? 1 : 0);
        }else{
            stationInfo.setToiletFlag(0);
            stationInfo.setStoreFlag(0);
            stationInfo.setLoungeFlag(0);
            stationInfo.setCanopyFlag(0);
        }
        stationInfo.setPrinterFlag(site.getPrinterFlag());
        stationInfo.setBarrierFlag(site.getBarrierFlag());
        stationInfo.setParkingLockFlag(site.getParkingLockFlag());
        stationInfo.setIsDemandResponse(1);
        stationInfo.setIsSupportOrderlyCharging(1);
        stationInfo.setIsEnergyStorage();
        stationInfo.setElectricityType(site.getElectricityType());
        stationInfo.setRatedPower(site.getRatedPower());
        stationInfo.setPeriodFee(site.getPeriodFee());
        stationInfo.setOfficialRunTime(site.getOfficialRunTime());
        stationInfo.setVideoMonitor(site.getVideoMonitor());
        stationInfo.setEquipmentInfos1(buildEquipmentInfo(site.getId()));
        return stationInfo;
    }
    private List<CDEquipmentInfo> buildEquipmentInfo(Integer siteId){
        List<TChargingPile> tChargingPiles = chargingPileClient.getChargingPileBySiteIds(Arrays.asList(siteId)).getData();
        List<Integer> collect1 = tChargingPiles.stream().map(TChargingPile::getId).collect(Collectors.toList());
        GetChargingGunByChargingPileIdsVo vo = new GetChargingGunByChargingPileIdsVo();
        vo.setChargingPileIds(collect1);
        List<TChargingGun> chargingGunList = chargingGunClient.getChargingGunByChargingPileIds(vo).getData();
        List<CDEquipmentInfo> equipmentInfos = new ArrayList<>();
        for (TChargingPile tChargingPile : tChargingPiles) {
            CDEquipmentInfo cdEquipmentInfo = new CDEquipmentInfo();
            cdEquipmentInfo.setEquipmentID(tChargingPile.getCode());
            cdEquipmentInfo.setManufacturerID(tChargingPile.getManufacturerCode());
            cdEquipmentInfo.setManufacturerName(tChargingPile.getManufacturer());
            cdEquipmentInfo.setEquipmentModel(tChargingPile.getEquipmentType());
            cdEquipmentInfo.setEquipmentProductCode();
            cdEquipmentInfo.setEquipmentName(tChargingPile.getName());
            cdEquipmentInfo.setConstructionTime(tChargingPile.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            if(null != tChargingPile.getProductionDate()){
                cdEquipmentInfo.setProductionDate(tChargingPile.getProductionDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            switch (tChargingPile.getType()){
                case 0:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.OTHER.getType());
                    break;
                case 1:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.DIRECT_CURRENT.getType());
                    break;
                case 2:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.ALTERNATING_CURRENT.getType());
                    break;
                case 3:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.ALTERNATING_DIRECT.getType());
                    break;
                case 4:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.WIRELESS_DEVICE.getType());
                    break;
                case 5:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.ORDER.getType());
                    break;
                case 6:
                    cdEquipmentInfo.setEquipmentType(EquipmentTypeEnum.V2G.getType());
                    break;
            }
            switch (tChargingPile.getStatus()){
                case 1:
                    cdEquipmentInfo.setEquipmentStatus(50);
                    break;
                case 2:
                    cdEquipmentInfo.setEquipmentStatus(5);
                    break;
                case 3:
                    cdEquipmentInfo.setEquipmentStatus(5);
                    break;
            }
            cdEquipmentInfo.setEquipmentPurpose();
            cdEquipmentInfo.setEquipmentPower(tChargingPile.getRatedPower());
            cdEquipmentInfo.setNewNationalStandard();
            cdEquipmentInfo.setEquipmentLng(new BigDecimal(tChargingPile.getEquipmentLng()).setScale(6, RoundingMode.HALF_EVEN));
            cdEquipmentInfo.setEquipmentLat(new BigDecimal(tChargingPile.getEquipmentLat()).setScale(6, RoundingMode.HALF_EVEN));
            cdEquipmentInfo.setVinFlag();
            cdEquipmentInfo.setConnectorInfos(buildConnectorInfo(tChargingPile.getId(), chargingGunList));
            equipmentInfos.add(cdEquipmentInfo);
        }
        return equipmentInfos;
    }
    private List<ConnectorInfo> buildConnectorInfo(Integer chargingPileId, List<TChargingGun> chargingGunList){
        List<TChargingGun> tChargingGunList = chargingGunList.stream().filter(s -> s.getChargingPileId().equals(chargingPileId)).collect(Collectors.toList());
        List<ConnectorInfo> connectorInfos = new ArrayList<>();
        for (TChargingGun chargingGun : tChargingGunList) {
            ConnectorInfo connectorInfo = new ConnectorInfo();
            connectorInfo.setConnectorID(chargingGun.getFullNumber());
            connectorInfo.setConnectorName(chargingGun.getName());
            switch (chargingGun.getType()){
                case 0:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.OTHER.getType());
                    break;
                case 1:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.HOUSEHOLD_SOCKET.getType());
                    break;
                case 2:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.AC_SOCKET.getType());
                    break;
                case 3:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.AC_INTERFACE_PLUG.getType());
                    break;
                case 4:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.DC_INTERFACE_GUN_HEAD.getType());
                    break;
                case 5:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.WIRELESS_CHARGING_STAND.getType());
                    break;
            }
            connectorInfo.setVoltageUpperLimits(chargingGun.getUpperRatedVoltage());
            connectorInfo.setVoltageLowerLimits(chargingGun.getLowerLimitOfRatedVoltage());
            connectorInfo.setCurrent(chargingGun.getRatedCurrent().intValue());
            connectorInfo.setPower(chargingGun.getRatedPower());
            connectorInfo.setNationalStandard(Integer.valueOf(chargingGun.getNationalStandard()));
            connectorInfo.setAuxPower(chargingGun.getAuxPower());
            connectorInfo.setOpreateStatus(chargingGun.getParkingStatus());
            connectorInfo.setParkNo("");
            connectorInfo.setOpreateHours(chargingGun.getOpreateHours());
            connectorInfos.add(connectorInfo);
        }
        return connectorInfos;
    }
    /**
     * 站点费率变化推送
     * @param vo
     * @return
     */
    @PostMapping("/notificationStationFee")
    public R notificationStationFee(@RequestBody NotificationStationFeeVo vo){
        NotificationStationFee notificationStationFee = new NotificationStationFee();
        notificationStationFee.setOperatorID("906171535");
        notificationStationFee.setStationID(vo.getSiteCode());
        List<ChargeFeeDetail> chargeFeeDetail = new ArrayList<>();
        List<TAccountingStrategyDetail> strategyDetails = accountingStrategyDetailClient.getDetailListByCode(vo.getChargingPileCode()).getData();
        for (TAccountingStrategyDetail accountingStrategyDetail : strategyDetails) {
            ChargeFeeDetail chargeFeeDetail1 = new ChargeFeeDetail();
            chargeFeeDetail1.setEquipmentType(vo.getEquipmentType());
            chargeFeeDetail1.setStartTime(accountingStrategyDetail.getStartTime());
            chargeFeeDetail1.setEndTime(accountingStrategyDetail.getEndTime());
            chargeFeeDetail1.setElectricityFee(accountingStrategyDetail.getElectrovalence());
            chargeFeeDetail1.setServiceFee(accountingStrategyDetail.getServiceCharge());
            chargeFeeDetail.add(chargeFeeDetail1);
            notificationStationFee.setChargeFeeDetail(chargeFeeDetail);
        }
        ChengDuJianGuanUtil.notificationStationFee(redisTemplate, notificationStationFee);
        return R.ok();
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/ChengDuJianGuanUtil.java
New file
@@ -0,0 +1,517 @@
package com.ruoyi.jianguan.chengdujianguan;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.ruoyi.jianguan.chengdujianguan.model.*;
import com.ruoyi.jianguan.chengdujianguan.util.Cryptos;
import com.ruoyi.jianguan.chengdujianguan.util.Encodes;
import com.ruoyi.jianguan.chengdujianguan.util.GBSignUtils;
import com.ruoyi.jianguan.chengdujianguan.util.HttpRequestUtil;
import com.ruoyi.jianguan.model.ConnectorInfo;
import com.ruoyi.jianguan.model.ConnectorStatusInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
@Slf4j
public class ChengDuJianGuanUtil {
    private static String OperatorID = "906171535";
    private static String OperatorSecret = "amq62RxDSvtqDKYn";    // 运营商秘钥
    private static String SigSecret = "r7UIikKAXCBj3WI9";              // 签名秘钥
    private static String DataSecret = "bQHUTLvEFPFGoGYl";           // 消息密钥
    private static String DataSecretIV = "GBRyCjqbzlPFQjPu";        // 消息密钥初始化向量
    private static String requestUrl = "https://dataex.cdczpt.com:8101/shevcs/v1";
    //测试环境
//    private static String OperatorSecret = "9jG8qysc5RxdbjvnvdmuRYQg6J82FwjL";    // 运营商秘钥
//    private static String SigSecret = "RruzbZxnr74tqxeW";              // 签名秘钥
//    private static String DataSecret = "3QJXn4MSj78zcpWF";           // 消息密钥
//    private static String DataSecretIV = "jhqj64V9gX8NHbuf";        // 消息密钥初始化向量
//    private static String requestUrl = "http://106.14.123.68:8101/shevcs/v1";
//    public static void main(String[] args) {
//        CDStationInfo stationInfo = new CDStationInfo();
//        stationInfo.setStationID("241231001");
//        stationInfo.setOperatorID("906171535");
//        stationInfo.setEquipmentOwnerID("M01234567");
//        stationInfo.setStationName("灵泉大道充电站");
//        stationInfo.setIsAloneApply(1);
//        stationInfo.setAccountNumber("0110042963");
//        stationInfo.setCapacity(new BigDecimal(1250));
//        stationInfo.setCountryCode("CN");
//        stationInfo.setAreaCode("510903");
//        stationInfo.setAreaCodeCountryside("510903000000");
//        stationInfo.setAddress("灵泉大道中国石化僧家沟加油站B区旁边前进150米");
//        stationInfo.setStationTel("18081278695");
//        stationInfo.setServiceTel("18081278695");
//        stationInfo.setStationType(1);
//        stationInfo.setIsOpen(1);
//        stationInfo.setStationStatus(5);
//        stationInfo.setParkNums(10);
//        stationInfo.setStationLng(new BigDecimal(105.616058).setScale(6, RoundingMode.HALF_EVEN));
//        stationInfo.setStationLat(new BigDecimal(30.527943).setScale(6, RoundingMode.HALF_EVEN));
//        stationInfo.setSiteGuide("-----");
//        stationInfo.setConstruction(8);
//        stationInfo.setPictures(Arrays.asList("https://comppad.didistatic.com/static/comp-pad/da2f2f5f52e2af3a.blob",
//                "https://comppad.didistatic.com/static/comp-pad/19b79f9d586f78ed.blob",
//                "https://comppad.didistatic.com/static/comp-pad/fedcbe7d7e342e6c.blob"));
//        stationInfo.setMatchCars("司机乘用车、出租车");
//        stationInfo.setParkInfo("");
//        stationInfo.setParkOwner("");
//        stationInfo.setParkManager("");
//        stationInfo.setOpenAllDay(1);
//        stationInfo.setBusinessHours("全天");
//        stationInfo.setElectricityFee("0.49");
//        stationInfo.setServiceFee("0.52");
//        stationInfo.setParkFeeType(0);
//        stationInfo.setParkFee("入场充电车辆,可享受停车减免2小时,超时按场地实际收费为准,临牌不支持减免");
//        stationInfo.setPayment("线上");
//        stationInfo.setSupportOrder(0);
//        stationInfo.setRemark("");
//        stationInfo.setParkFeeType(3);
//        stationInfo.setToiletFlag(0);
//        stationInfo.setStoreFlag(0);
//        stationInfo.setLoungeFlag(0);
//        stationInfo.setCanopyFlag(0);
//        stationInfo.setPrinterFlag(0);
//        stationInfo.setBarrierFlag(1);
//        stationInfo.setParkingLockFlag(0);
//        stationInfo.setIsDemandResponse(1);
//        stationInfo.setIsSupportOrderlyCharging(1);
//        stationInfo.setIsEnergyStorage(0);
//        stationInfo.setElectricityType(3);
//        stationInfo.setRatedPower(new BigDecimal(600));
//        stationInfo.setPeriodFee(1);
//        stationInfo.setOfficialRunTime("2024-12-31");
//        stationInfo.setVideoMonitor(1);
//        List<CDEquipmentInfo> equipmentInfos1 = new ArrayList<>();
//        CDEquipmentInfo cdEquipmentInfo = new CDEquipmentInfo();
//        cdEquipmentInfo.setEquipmentID("2024123100001001");
//        cdEquipmentInfo.setManufacturerID("123456789");
//        cdEquipmentInfo.setManufacturerName("12345");
//        cdEquipmentInfo.setEquipmentModel("123");
//        cdEquipmentInfo.setEquipmentProductCode("12345");
//        cdEquipmentInfo.setEquipmentName("灵泉大道1号桩");
//        cdEquipmentInfo.setProductionDate("2024-06-31");
//        cdEquipmentInfo.setConstructionTime("2024-12-31");
//        cdEquipmentInfo.setEquipmentType(1);
//        cdEquipmentInfo.setEquipmentStatus(5);
//        cdEquipmentInfo.setEquipmentPurpose(1);
//        cdEquipmentInfo.setEquipmentPower(new BigDecimal(120));
//        cdEquipmentInfo.setNewNationalStandard(1);
//        cdEquipmentInfo.setEquipmentLng(new BigDecimal(105.616058).setScale(6, RoundingMode.HALF_EVEN));
//        cdEquipmentInfo.setEquipmentLat(new BigDecimal(30.527943).setScale(6, RoundingMode.HALF_EVEN));
//        cdEquipmentInfo.setVinFlag(0);
//        List<ConnectorInfo> connectorInfos = new ArrayList<>();
//        ConnectorInfo connectorInfo = new ConnectorInfo();
//        connectorInfo.setConnectorID("202412310000100101");
//        connectorInfo.setConnectorName("1号桩01枪");
//        connectorInfo.setConnectorType(4);
//        connectorInfo.setVoltageUpperLimits(new BigDecimal(380));
//        connectorInfo.setVoltageLowerLimits(new BigDecimal(220));
//        connectorInfo.setCurrent(120);
//        connectorInfo.setPower(new BigDecimal(250));
//        connectorInfo.setNationalStandard(2);
//        connectorInfo.setAuxPower(1);
//        connectorInfo.setOpreateStatus(5);
//        connectorInfo.setParkNo("01");
//        connectorInfos.add(connectorInfo);
//        cdEquipmentInfo.setConnectorInfos(connectorInfos);
//        equipmentInfos1.add(cdEquipmentInfo);
//        stationInfo.setEquipmentInfos1(equipmentInfos1);
//        ChengDuJianGuanUtil.notificationStationInfo(null, stationInfo);
//    }
    public static void main(String[] args) {
        NotificationStationFee notificationStationFee = new NotificationStationFee();
        notificationStationFee.setOperatorID(OperatorID);
        notificationStationFee.setStationID("241231001");
        List<ChargeFeeDetail> chargeFeeDetail = new ArrayList<>();
        ChargeFeeDetail chargeFeeDetail1 = new ChargeFeeDetail();
        chargeFeeDetail1.setEquipmentType(1);
        chargeFeeDetail1.setStartTime("00:00");
        chargeFeeDetail1.setEndTime("23:59");
        chargeFeeDetail1.setElectricityFee(new BigDecimal(0.49));
        chargeFeeDetail1.setServiceFee(new BigDecimal(0.51));
        chargeFeeDetail.add(chargeFeeDetail1);
        notificationStationFee.setChargeFeeDetail(chargeFeeDetail);
        ChengDuJianGuanUtil.notificationStationFee(null, notificationStationFee);
    }
//    public static void main(String[] args) {
//        ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo();
//        connectorStatusInfo.setOperatorID(OperatorID);
//        connectorStatusInfo.setEquipmentOwnerID("M01234567");
//        connectorStatusInfo.setStationID("241231001");
//        connectorStatusInfo.setEquipmentID("2024123100001001");
//        connectorStatusInfo.setEquipmentClassification(1);
//        connectorStatusInfo.setConnectorID("202412310000100101");
//        connectorStatusInfo.setStatus(1);
//        connectorStatusInfo.setParkStatus(0);
//        connectorStatusInfo.setLookStatus(0);
//        ChengDuJianGuanUtil.notificationStationStatus(null, connectorStatusInfo);
//    }
//    public static void main(String[] args) {
//        ConnectorChargeStatusInfo connectorChargeStatusInfo = new ConnectorChargeStatusInfo();
//        connectorChargeStatusInfo.setOperatorID(OperatorID);
//        connectorChargeStatusInfo.setEquipmentOwnerID("M01234567");
//        connectorChargeStatusInfo.setStationID("241231001");
//        connectorChargeStatusInfo.setEquipmentID("2024123100001001");
//        connectorChargeStatusInfo.setStartChargeSeq("0000001");
//        connectorChargeStatusInfo.setConnectorID("202412310000100101");
//        connectorChargeStatusInfo.setConnectorStatus(3);
//        connectorChargeStatusInfo.setOrderStatus(2);
//        connectorChargeStatusInfo.setCurrentA(new BigDecimal(120));
//        connectorChargeStatusInfo.setVoltageA(new BigDecimal(120));
//        connectorChargeStatusInfo.setSoc(new BigDecimal(60));
//        connectorChargeStatusInfo.setStartTime("2025-11-26 13:00:00");
//        connectorChargeStatusInfo.setEndTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//        connectorChargeStatusInfo.setPushTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//        connectorChargeStatusInfo.setLastPushTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//        connectorChargeStatusInfo.setTotalPower(new BigDecimal(20));
//        connectorChargeStatusInfo.setElecMoney(new BigDecimal(22));
//        connectorChargeStatusInfo.setSeviceMoney(new BigDecimal(28));
//        connectorChargeStatusInfo.setTotalMoney(new BigDecimal(50));
//        connectorChargeStatusInfo.setSoc1(new BigDecimal(62));
//        ChengDuJianGuanUtil.notificationConnectorChargeStatus(null, connectorChargeStatusInfo);
//    }
//    public static void main(String[] args) {
//        CDOrderInfo orderInfo = new CDOrderInfo();
//        orderInfo.setOperatorID(OperatorID);
//        orderInfo.setEquipmentOwnerID("M01234567");
//        orderInfo.setStationID("241231001");
//        orderInfo.setEquipmentID("2024123100001001");
//        orderInfo.setConnectorID("202412310000100101");
//        orderInfo.setEquipmentClassification(1);
//        orderInfo.setStartChargeSeq("0000001");
//        orderInfo.setUserChargeType(1);
//        orderInfo.setMoney(new BigDecimal(50));
//        orderInfo.setElectMoney(new BigDecimal(22));
//        orderInfo.setServiceMoney(new BigDecimal(28));
//        orderInfo.setElect(new BigDecimal(20));
//        orderInfo.setStartTime("2025-11-26 13:00:00");
//        orderInfo.setEndTime("2025-11-26 15:50:00");
//        orderInfo.setPaymentAmount(new BigDecimal(50));
//        orderInfo.setPayChannel(2);
//        orderInfo.setStopReason(1);
//        orderInfo.setPower(new BigDecimal(120));
//        orderInfo.setChargeLast(10200);
//        orderInfo.setMeterValueStart(new BigDecimal(0));
//        orderInfo.setMeterValueEnd(new BigDecimal(0));
//        orderInfo.setPushTimeStamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//
//        List<ChargeDetail> chargeDetails = new ArrayList<>();
//        ChargeDetail chargeDetail = new ChargeDetail();
//        chargeDetail.setDetailStartTime("2025-11-26 13:00:00");
//        chargeDetail.setDetailEndTime("2025-11-26 15:50:00");
//        chargeDetail.setElecPrice(new BigDecimal(0.49));
//        chargeDetail.setSevicePrice(new BigDecimal(0.51));
//        chargeDetail.setDetailPower(new BigDecimal(20));
//        chargeDetail.setDetailElecMoney(new BigDecimal(22));
//        chargeDetail.setDetailSeviceMoney(new BigDecimal(28));
//        chargeDetails.add(chargeDetail);
//        orderInfo.setChargeDetails(chargeDetails);
//        ChengDuJianGuanUtil.notificationOrderInfo(null, orderInfo);
//    }
    /**
     * 请求联联,获取token
     */
    public static String getToken(RedisTemplate redisTemplate) {
        try {
//            Object o = redisTemplate.opsForValue().get("LLTOKEN");
//            if(null != o){
//                return o.toString();
//            }
            // 请求data
            Map<String, String> data = new HashMap<>();
            data.put("OperatorID", OperatorID);
            data.put("OperatorSecret", OperatorSecret);
            String dataJson = JacksonUtils.toJson(data);
            // 加密
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            // 生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String tokenRequest = JacksonUtils.toJson(request);
            log.info("【成都监管-获取token】请求参数明文:" + dataJson);
            log.info("【成都监管-获取token】请求参数密文:" + tokenRequest);
            String response = HttpUtil.post(requestUrl + "/query_token", tokenRequest);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            log.info("【成都监管-获取token】响应参数密文:" + response);
            if (result.getRet() == 0) {
                //解密data
                byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64((String) result.getData()),
                        DataSecret.getBytes(), DataSecretIV.getBytes());
                String dataStr = new String(plainText, "UTF-8");
                log.info("【成都监管-获取token】响应参数明文:" + dataStr);
                JSONObject jsonObject = JSON.parseObject(dataStr);
                Map<String, String> resultMap = (Map<String, String>) JSON.parse(dataStr);
                String accessToken = jsonObject.getString("AccessToken");
                Long tokenAvailableTime = jsonObject.getLong("TokenAvailableTime");
//                redisTemplate.opsForValue().set("LLTOKEN", accessToken, Long.valueOf(tokenAvailableTime), TimeUnit.SECONDS);
                return accessToken;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("【成都监管-获取token】获取Token异常", e);
        }
        return null;
    }
    /**
     * 充电站信息变化推送
     * @param redisTemplate
     * @param stationInfo
     */
    public static void notificationStationInfo(RedisTemplate redisTemplate, CDStationInfo stationInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("StationInfo", stationInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-充电站信息变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-充电站信息变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_stationInfo", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-充电站信息变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-充电站信息变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-充电站信息变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-充电站信息变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 站点费率变化推送
     * @param redisTemplate
     * @param notificationStationFee
     */
    public static void notificationStationFee(RedisTemplate redisTemplate, NotificationStationFee notificationStationFee){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("StationFee", notificationStationFee);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-站点费率变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-站点费率变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_stationFee", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-站点费率变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-站点费率变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-站点费率变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 设备状态变化推送
     * @param redisTemplate
     * @param connectorStatusInfo
     */
    public static void notificationStationStatus(RedisTemplate redisTemplate, ConnectorStatusInfo connectorStatusInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ConnectorStatusInfo", connectorStatusInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-设备状态变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-设备状态变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_stationStatus", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-设备状态变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-设备状态变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-设备状态变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 设备充电中状态变化推送
     * @param redisTemplate
     * @param connectorChargeStatusInfo
     */
    public static void notificationConnectorChargeStatus(RedisTemplate redisTemplate, ConnectorChargeStatusInfo connectorChargeStatusInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ConnectorChargeStatusInfo", connectorChargeStatusInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-设备充电中状态变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-设备充电中状态变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_connector_charge_status", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-设备充电中状态变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-设备充电中状态变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-设备充电中状态变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 订单信息推送
     * @param redisTemplate
     * @param orderInfo
     */
    public static void notificationOrderInfo(RedisTemplate redisTemplate, CDOrderInfo orderInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("OrderInfo", orderInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-订单信息推送】请求参数明文:" + dataJson);
            log.info("【成都监管-订单信息推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_orderInfo", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-订单信息推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-订单信息推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-订单信息推送】异常:" + e.getMessage());
        }
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/ConnectorTypeEnum.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.jianguan.chengdujianguan.enu;
/**
 * 充电设备接口类型
 * @author zhibing.pu
 * @Date 2025/1/21 14:14
 */
public enum ConnectorTypeEnum {
    HOUSEHOLD_SOCKET(1, "家用插座"),
    AC_SOCKET(2, "交流接口插座"),
    AC_INTERFACE_PLUG(3, "交流接口插头"),
    DC_INTERFACE_GUN_HEAD(4, "直流接口枪头"),
    WIRELESS_CHARGING_STAND(5, "无线充电座"),
    OTHER(6, "其他")
    ;
    private Integer type;
    private String note;
    ConnectorTypeEnum(Integer type, String note) {
        this.type = type;
        this.note = note;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/ConstructionEnum.java
New file
@@ -0,0 +1,49 @@
package com.ruoyi.jianguan.chengdujianguan.enu;
/**
 * 建设场所
 * @author zhibing.pu
 * @Date 2025/1/21 13:25
 */
public enum ConstructionEnum {
    RESIDENTIAL_AREA(1, "居民区"),
    PUBLIC_INSTITUTION(2, "公共机构"),
    ENTERPRISE(3, "企事业单位"),
    OFFICE_BUILDING(4, "写字楼"),
    INDUSTRIAL_PARK(5, "工业园区"),
    TRANSPORTATION_JUNCTION(6, "交通枢纽"),
    CULTURE_AND_SPORTS(7, "大型文体设施"),
    URBAN_GREEN_SPACE(8, "城市绿地"),
    ANCILLARY_PARKING_LOT(9, "大型建筑配建停车场"),
    OFF_STREET_PARKING_SPACE(10, "路边停车位"),
    HIGH_SPEED_SERVICE_AREA(11, "城际高速服务区"),
    SCENIC_SPOT(12, "风景区"),
    BUS_YARD(13, "公交场站"),
    REFUELING_STATION(14, "加油加气站"),
    TAXI(15, "出租车"),
    OTHER(255, "其他");
    private Integer type;
    private String note;
    ConstructionEnum(Integer type, String note) {
        this.type = type;
        this.note = note;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/EquipmentTypeEnum.java
New file
@@ -0,0 +1,42 @@
package com.ruoyi.jianguan.chengdujianguan.enu;
/**
 * 设备类型
 * @author zhibing.pu
 * @Date 2025/1/21 13:59
 */
public enum EquipmentTypeEnum {
    DIRECT_CURRENT(1, "直流设备"),
    ALTERNATING_CURRENT(2, "交流设备"),
    ALTERNATING_DIRECT(3, "交直流一体设备"),
    WIRELESS_DEVICE(4, "无线设备"),
    OTHER(5, "其他"),
    ORDER(6, "有序"),
    V2G(7, "V2G")
    ;
    private Integer type;
    private String note;
    EquipmentTypeEnum(Integer type, String note) {
        this.type = type;
        this.note = note;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/InterfaceUrlEnum.java
New file
@@ -0,0 +1,43 @@
package com.ruoyi.jianguan.chengdujianguan.enu;
/**
 * 接口地址枚举
 * @author zhibing.pu
 * @Date 2025/1/21 14:38
 */
public enum InterfaceUrlEnum {
    QUERY_TOKEN("/query_token", "获取权限token"),
    NOTIFICATION_STATION_STATUS("/notification_stationStatus", "设备状态变化推送"),
    NOTIFICATION_STATION_CHANGE("/notification_station_change", "站点计费策略变更推送"),
    NOTIFICATION_START_CHARGE_RESULT("/notification_start_charge_result", "推送启动充电结果"),
    NOTIFICATION_EQUIP_CHARGE_STATUS("/notification_equip_charge_status", "推送充电状态"),
    NOTIFICATION_STOP_CHARGE_RESULT("/notification_stop_charge_result", "推送停止充电结果"),
    NOTIFICATION_CHARGE_ORDER_INFO("/notification_charge_order_info", "推送充电订单信息"),
    CHECK_CHARGE_ORDERS("/check_charge_orders", "推送订单对账结果信息"),
    ;
    private String url;
    private String note;
    InterfaceUrlEnum(String url, String note) {
        this.url = url;
        this.note = note;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/StationStatusEnum.java
New file
@@ -0,0 +1,38 @@
package com.ruoyi.jianguan.chengdujianguan.enu;
/**
 * 站点状态
 * @author zhibing.pu
 * @Date 2025/1/21 12:10
 */
public enum StationStatusEnum {
    UNKNOWN(0, "未知"),
    UNDER_CONSTRUCTION(1, "建设中"),
    OFF_LINE(5, "关闭下线"),
    MAINTAIN(6, "维护中"),
    NORMAL_USE(50, "正常使用")
    ;
    private Integer status;
    private String note;
    StationStatusEnum(Integer status, String note) {
        this.status = status;
        this.note = note;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/enu/StationTypeEnum.java
New file
@@ -0,0 +1,45 @@
package com.ruoyi.jianguan.chengdujianguan.enu;
/**
 * 站点类型
 * @author zhibing.pu
 * @Date 2025/1/21 12:00
 */
public enum StationTypeEnum {
    PUBLIC(1, "公共"),
    PERSONAGE(50, "个人"),
    BUS_SPECIFIC(100, "公交(专用)"),
    SANITATION_SPECIFIC(101, "环卫(专用)"),
    LOGISTICS_SPECIFIC(102, "物流(专用)"),
    TEXT_SPECIFIC(103, "出租车(专用)"),
    PERIODIC_LEASE(104, "分时租赁(专用)"),
    CELL_SHARING(105, "小区共享(专用)"),
    DEPARTMENT(106, "单位(专用)"),
    PRIVATE_SHARED_PILE(107, "私人共享桩(专用)"),
    OTHER(255, "其他")
    ;
    private Integer type;
    private String note;
    StationTypeEnum(Integer type, String note) {
        this.type = type;
        this.note = note;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/CDEquipmentInfo.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDEquipmentInfo.java
@@ -1,13 +1,14 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.model.ConnectorInfo;
import com.ruoyi.integration.drainage.model.EquipmentInfo;
import com.ruoyi.jianguan.model.EquipmentInfo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充电设备信息
 */
@Data
public class CDEquipmentInfo extends EquipmentInfo {
    /**
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/CDOrderInfo.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDOrderInfo.java
@@ -1,11 +1,12 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.model.ChargeDetail;
import com.ruoyi.integration.drainage.model.SupChargeOrderInfo;
import com.ruoyi.jianguan.model.ChargeDetail;
import com.ruoyi.jianguan.model.SupChargeOrderInfo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class CDOrderInfo extends SupChargeOrderInfo {
@@ -111,7 +112,7 @@
     * 充电明细信息
     */
    @JsonProperty("ChargeDetails")
    private ChargeDetail chargeDetails;
    private List<ChargeDetail> chargeDetails;
    /**
     * 推送时间
     * yyyy-MM-dd HH:mm:ss
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/CDStationInfo.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDStationInfo.java
@@ -1,15 +1,18 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.model.EquipmentInfo;
import com.ruoyi.integration.drainage.model.StationInfo;
import com.ruoyi.jianguan.model.StationInfo;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import javax.validation.constraints.Null;
import java.util.List;
/**
 * 充电站信息
 */
@Data
public class CDStationInfo extends StationInfo {
    /**
@@ -25,13 +28,35 @@
    @JsonProperty("AccountNumber")
    private String accountNumber;
    /**
     * 小区是否对外开放
     * 0:否,1:是
     */
    @JsonProperty("IsOpen")
    private Integer isOpen;
    /**
     * 停车场产权人
     */
    @JsonProperty("ParkOwner")
    private String parkOwner;
    /**
     * 停车场管理人
     */
    @JsonProperty("ParkManager")
    private String parkManager;
    /**
     * 是否全天开放
     * 0:否,1:是
     */
    @JsonProperty("OpenAllDay")
    private Integer openAllDay;
    /**
     * 听测收费类型
     * 营业时间
     */
    @Null
    @JsonProperty("BusinessHours")
    private String businessHours;
    /**
     * 停车收费类型
     * 0:停车收费
     * 1:停车免费
     * 2:限时免费
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/ChargeFeeDetail.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/ChargeFeeDetail.java
@@ -1,4 +1,4 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/ConnectorChargeStatusInfo.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/ConnectorChargeStatusInfo.java
@@ -1,4 +1,4 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/EDIMessagePack.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/EDIMessagePack.java
@@ -1,9 +1,7 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Map;
/**
 * 返回结果
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/model/NotificationStationFee.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/NotificationStationFee.java
@@ -1,4 +1,4 @@
package com.ruoyi.integration.chengdujianguan.model;
package com.ruoyi.jianguan.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -6,6 +6,9 @@
import java.util.List;
/**
 * 站点费率
 */
@Data
public class NotificationStationFee {
    /**
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Cryptos.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Cryptos.java
@@ -1,6 +1,9 @@
/**
 */
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import com.ruoyi.integration.chengdujianguan.util.Encodes;
import com.ruoyi.integration.chengdujianguan.util.Exceptions;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Digests.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Digests.java
@@ -1,7 +1,8 @@
/**
 */
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import com.ruoyi.integration.chengdujianguan.util.Exceptions;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Encodes.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Encodes.java
@@ -1,7 +1,7 @@
/**
 * Copyright (c) 2005-2012 springside.org.cn
 */
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/Exceptions.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Exceptions.java
@@ -1,4 +1,4 @@
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/GBSignUtils.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/GBSignUtils.java
@@ -1,5 +1,6 @@
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import com.ruoyi.integration.chengdujianguan.util.Encodes;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/HttpRequestUtil.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/HttpRequestUtil.java
@@ -1,4 +1,4 @@
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/chengdujianguan/util/SignUtils.java
File was renamed from ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/SignUtils.java
@@ -1,4 +1,4 @@
package com.ruoyi.integration.chengdujianguan.util;
package com.ruoyi.jianguan.chengdujianguan.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java
@@ -30,6 +30,9 @@
import com.ruoyi.other.api.feignClient.GoodsClient;
import com.ruoyi.other.api.feignClient.InvoiceTypeClient;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
@@ -40,6 +43,7 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -84,11 +88,10 @@
    
    @Resource
    private TChargingOrderAccountingStrategyService chargingOrderAccountingStrategyService;
    @Autowired
    private RedissonClient redissonClient;
    /**
     * 添加开票申请
     * @param addOrderInvoice
@@ -97,57 +100,67 @@
    @Override
    public AjaxResult addOrderInvoice(AddOrderInvoice addOrderInvoice) {
        Long userId = tokenService.getLoginUserApplet().getUserId();
        String orders = addOrderInvoice.getOrders();
        if(StringUtils.isEmpty(orders)){
            return AjaxResult.error("请选择有效的订单");
        }
        JSONArray parse = JSONArray.parse(orders);
        List<Long> orderIds = new ArrayList<>();
        Map<Long, BigDecimal> map = new HashMap<>();
        for (int i = 0; i < parse.size(); i++) {
            JSONObject jsonObject = parse.getJSONObject(i);
            Long id = jsonObject.getLong("id");
            BigDecimal amount = jsonObject.getBigDecimal("amount");
            orderIds.add(id);
            map.put(id, amount);
        }
        long count = orderInvoiceDetailService.count(new LambdaQueryWrapper<TOrderInvoiceDetail>().eq(TOrderInvoiceDetail::getOrderType, addOrderInvoice.getOrderType())
                .in(TOrderInvoiceDetail::getOrderId, orderIds));
        if(count > 0){
            return AjaxResult.error("不能重复申请开票,请刷新数据后重试");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String code = Double.valueOf(Math.random() * 1000).intValue() + sdf.format(new Date());
        //获取开票类型
        TInvoiceType invoiceType = invoiceTypeClient.getInvoiceType(addOrderInvoice.getInvoiceTypeId()).getData();
        addOrderInvoice.setInvoicingCompany(invoiceType.getInvoicingCompany());
        addOrderInvoice.setInvoiceType(invoiceType.getName());
        addOrderInvoice.setInvoiceMaterial(2);
        addOrderInvoice.setInvoicingMethod(invoiceType.getInvoicingMethod());
        addOrderInvoice.setAppUserId(userId);
        addOrderInvoice.setCode(code);
        addOrderInvoice.setStatus(1);
        addOrderInvoice.setCreateTime(LocalDateTime.now());
        this.save(addOrderInvoice);
        for (Long orderId : orderIds) {
            List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>()
                    .eq(TChargingOrderAccountingStrategy::getChargingOrderId, orderId));
            BigDecimal electrovalence = list.stream().map(TChargingOrderAccountingStrategy::getElectrovalence).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal serviceCharge = list.stream().map(TChargingOrderAccountingStrategy::getServiceCharge).reduce(BigDecimal.ZERO, BigDecimal::add);
            TOrderInvoiceDetail orderInvoiceDetail = new TOrderInvoiceDetail();
            orderInvoiceDetail.setOrderInvoiceId(addOrderInvoice.getId());
            orderInvoiceDetail.setInvoiceAmount(map.get(orderId));
            orderInvoiceDetail.setOrderType(addOrderInvoice.getOrderType());
            orderInvoiceDetail.setOrderId(orderId);
            orderInvoiceDetail.setElectricityTariff(invoiceType.getElectricityTariff());
            orderInvoiceDetail.setServiceTariff(invoiceType.getServiceTariff());
            orderInvoiceDetail.setAddedServiceTariff(invoiceType.getAddedServiceTariff());
            orderInvoiceDetail.setElectrovalence(electrovalence);
            orderInvoiceDetail.setServiceCharge(serviceCharge);
            orderInvoiceDetail.setAddedService(serviceCharge.multiply(null == invoiceType.getAddedServiceTariff()
                    ? new BigDecimal(1) : invoiceType.getAddedServiceTariff().divide(new BigDecimal(100))));
            orderInvoiceDetailService.save(orderInvoiceDetail);
        RLock lock = redissonClient.getLock("ADD_ORDER_INVOICE:" + userId);
        try {
            boolean tryLock = lock.tryLock(5, TimeUnit.SECONDS);
            if(tryLock){
                String orders = addOrderInvoice.getOrders();
                if(StringUtils.isEmpty(orders)){
                    return AjaxResult.error("请选择有效的订单");
                }
                JSONArray parse = JSONArray.parse(orders);
                List<Long> orderIds = new ArrayList<>();
                Map<Long, BigDecimal> map = new HashMap<>();
                for (int i = 0; i < parse.size(); i++) {
                    JSONObject jsonObject = parse.getJSONObject(i);
                    Long id = jsonObject.getLong("id");
                    BigDecimal amount = jsonObject.getBigDecimal("amount");
                    orderIds.add(id);
                    map.put(id, amount);
                }
                long count = orderInvoiceDetailService.count(new LambdaQueryWrapper<TOrderInvoiceDetail>().eq(TOrderInvoiceDetail::getOrderType, addOrderInvoice.getOrderType())
                        .in(TOrderInvoiceDetail::getOrderId, orderIds));
                if(count > 0){
                    return AjaxResult.error("不能重复申请开票,请刷新数据后重试");
                }
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                String code = Double.valueOf(Math.random() * 1000).intValue() + sdf.format(new Date());
                //获取开票类型
                TInvoiceType invoiceType = invoiceTypeClient.getInvoiceType(addOrderInvoice.getInvoiceTypeId()).getData();
                addOrderInvoice.setInvoicingCompany(invoiceType.getInvoicingCompany());
                addOrderInvoice.setInvoiceType(invoiceType.getName());
                addOrderInvoice.setInvoiceMaterial(2);
                addOrderInvoice.setInvoicingMethod(invoiceType.getInvoicingMethod());
                addOrderInvoice.setAppUserId(userId);
                addOrderInvoice.setCode(code);
                addOrderInvoice.setStatus(1);
                addOrderInvoice.setCreateTime(LocalDateTime.now());
                this.save(addOrderInvoice);
                for (Long orderId : orderIds) {
                    List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>()
                            .eq(TChargingOrderAccountingStrategy::getChargingOrderId, orderId));
                    BigDecimal electrovalence = list.stream().map(TChargingOrderAccountingStrategy::getElectrovalence).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal serviceCharge = list.stream().map(TChargingOrderAccountingStrategy::getServiceCharge).reduce(BigDecimal.ZERO, BigDecimal::add);
                    TOrderInvoiceDetail orderInvoiceDetail = new TOrderInvoiceDetail();
                    orderInvoiceDetail.setOrderInvoiceId(addOrderInvoice.getId());
                    orderInvoiceDetail.setInvoiceAmount(map.get(orderId));
                    orderInvoiceDetail.setOrderType(addOrderInvoice.getOrderType());
                    orderInvoiceDetail.setOrderId(orderId);
                    orderInvoiceDetail.setElectricityTariff(invoiceType.getElectricityTariff());
                    orderInvoiceDetail.setServiceTariff(invoiceType.getServiceTariff());
                    orderInvoiceDetail.setAddedServiceTariff(invoiceType.getAddedServiceTariff());
                    orderInvoiceDetail.setElectrovalence(electrovalence);
                    orderInvoiceDetail.setServiceCharge(serviceCharge);
                    orderInvoiceDetail.setAddedService(serviceCharge.multiply(null == invoiceType.getAddedServiceTariff()
                            ? new BigDecimal(1) : invoiceType.getAddedServiceTariff().divide(new BigDecimal(100))));
                    orderInvoiceDetailService.save(orderInvoiceDetail);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return AjaxResult.success();
    }