liujie
2026-07-22 e2ab44b7724f8c9283b9d3a333b6f850702fd171
Merge branch '2.2' of http://120.76.84.145:10101/gitblit/r/java/mx_charging_pile into 2.2
2个文件已添加
12个文件已修改
240 ■■■■■ 已修改文件
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TFaultMessageController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/dto/SiteExcelDTO.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/PartnerServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/controller/TFaultMessageControllerTest.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/dto/SiteExcelDTOTest.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/PartnerServiceImplTest.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/FinancialSettlementController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/export/EnterpriseChargingDetailExport.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/FinancialSettlementControllerTest.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/TChargingOrderControllerTest.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/mapper/PayOrderQueryPerformanceMapperTest.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -548,11 +548,13 @@
                data1.addAll(data);
            }
            Set<Integer> siteIds = new HashSet<>(data1);
            List<Site> data = siteClient.getSiteByIds(siteIds.stream().collect(Collectors.toList())).getData();
            if (null != data) {
                List<String> siteNames = data.stream().map(Site::getName).collect(Collectors.toList());
                sysUser.setSiteNames(siteNames);
                sysUser.setSiteIds(data.stream().map(Site::getId).collect(Collectors.toList()));
            if (!applyAllSitePermission(sysUser, siteIds)) {
                List<Site> data = siteClient.getSiteByIds(new ArrayList<>(siteIds)).getData();
                if (null != data) {
                    List<String> siteNames = data.stream().map(Site::getName).collect(Collectors.toList());
                    sysUser.setSiteNames(siteNames);
                    sysUser.setSiteIds(data.stream().map(Site::getId).collect(Collectors.toList()));
                }
            }
            List<String> roleNames = new ArrayList<>();
            for (SysUserRole sysUserRole : list1) {
@@ -565,6 +567,15 @@
        }
        return pageInfo.setRecords(list);
    }
    static boolean applyAllSitePermission(SysUser sysUser, Set<Integer> siteIds) {
        if (!siteIds.contains(0)) {
            return false;
        }
        sysUser.setSiteNames(Collections.singletonList("全部"));
        sysUser.setSiteIds(Collections.singletonList(0));
        return true;
    }
    
    @Override
    public PageInfo<SysUser> getAllList(PageInfo<SysUser> pageInfo, List<Integer> collect) {
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TFaultMessageController.java
@@ -26,6 +26,7 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
/**
@@ -89,9 +90,17 @@
    @ApiOperation(value = "添加故障信息", tags = {"管理后台-设备监控"})
    @Log(title = "【设备监控】添加故障信息", businessType = BusinessType.INSERT,operatorType = OperatorType.MANAGE)
    public AjaxResult addFaultMessage(@RequestBody TFaultMessage faultMessage){
        prepareManualFaultMessage(faultMessage);
        faultMessageService.save(faultMessage);
        return AjaxResult.success();
    }
    static void prepareManualFaultMessage(TFaultMessage faultMessage) {
        faultMessage.setDelFlag(false);
        if (faultMessage.getCreateTime() == null) {
            faultMessage.setCreateTime(LocalDateTime.now());
        }
    }
    
    
    @RequiresPermissions(value = {"/faultInformationList/del"}, logical = Logical.OR)
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/dto/SiteExcelDTO.java
@@ -6,7 +6,12 @@
import org.springframework.beans.BeanUtils;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
@Data
public class SiteExcelDTO {
@@ -138,6 +143,30 @@
        if (site.getEstablishmentTime() != null) {
            dto.setEstablishmentTime(site.getEstablishmentTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }
        dto.setOfficialRunTime(formatDateOnly(site.getOfficialRunTime()));
        return dto;
    }
    static String formatDateOnly(String value) {
        if (value == null || value.trim().isEmpty()) {
            return value;
        }
        String text = value.trim();
        try {
            return LocalDate.parse(text, DateTimeFormatter.ISO_LOCAL_DATE).toString();
        } catch (DateTimeParseException ignored) {
            // Continue with timestamp formats used by historical site data.
        }
        try {
            return OffsetDateTime.parse(text, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
                    .atZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDate().toString();
        } catch (DateTimeParseException ignored) {
            // Some records use an instant with millisecond precision and a trailing Z.
        }
        try {
            return Instant.parse(text).atZone(ZoneId.of("Asia/Shanghai")).toLocalDate().toString();
        } catch (DateTimeParseException ignored) {
            return text;
        }
    }
}
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/PartnerServiceImpl.java
@@ -235,15 +235,7 @@
                throw new RuntimeException(r.getMsg());
            }
        }else{
            user.setPhonenumber(partner.getPhoneOne());
            user.setUserName(partner.getAccount());
            user.setNickName(partner.getName());
            user.setAvatar(partner.getLogoUrl());
            if(StringUtils.isNotEmpty(partner.getPassword())){
                user.setPassword(partner.getPassword());
                user.setPassWordUpdate(new Date());
            }
            user.setRoleId(partner.getRoleId().longValue());
            prepareExistingUserForUpdate(user, partner);
            R r = sysUserClient.updateSysUser(user);
            if(200 != r.getCode()){
                throw new RuntimeException(r.getMsg());
@@ -256,6 +248,14 @@
        return AjaxResult.success();
    }
    void prepareExistingUserForUpdate(SysUser user, Partner partner) {
        user.setPhonenumber(partner.getPhoneOne());
        user.setUserName(partner.getAccount());
        user.setNickName(partner.getName());
        user.setAvatar(partner.getLogoUrl());
        user.setRoleId(partner.getRoleId().longValue());
    }
    void updateShareRatios(Partner partner) {
        this.update(new UpdateWrapper<Partner>()
                .eq("id", partner.getId())
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/controller/TFaultMessageControllerTest.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.chargingPile.controller;
import com.ruoyi.chargingPile.api.model.TFaultMessage;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class TFaultMessageControllerTest {
    @Test
    void manualFaultIsVisibleToActiveListQuery() {
        TFaultMessage faultMessage = new TFaultMessage();
        TFaultMessageController.prepareManualFaultMessage(faultMessage);
        assertEquals(Boolean.FALSE, faultMessage.getDelFlag());
        assertNotNull(faultMessage.getCreateTime());
    }
}
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/dto/SiteExcelDTOTest.java
@@ -14,6 +14,13 @@
class SiteExcelDTOTest {
    @Test
    void formatsOfficialRunTimeAsLocalDate() {
        assertEquals("2024-12-31", SiteExcelDTO.formatDateOnly("2024-12-30T16:00:00.000Z"));
        assertEquals("2025-05-31", SiteExcelDTO.formatDateOnly("2025-05-30T16:02:14.900Z"));
        assertEquals("2026-07-21", SiteExcelDTO.formatDateOnly("2026-07-21"));
    }
    @Test
    void columnsFollowSitePrototypeOrder() {
        List<String> actual = Arrays.stream(SiteExcelDTO.class.getDeclaredFields())
                .map(field -> field.getAnnotation(Excel.class))
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/PartnerServiceImplTest.java
@@ -2,6 +2,7 @@
import com.ruoyi.chargingPile.api.model.Partner;
import com.ruoyi.chargingPile.mapper.PartnerMapper;
import com.ruoyi.system.api.domain.SysUser;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.jupiter.api.Test;
@@ -21,6 +22,25 @@
class PartnerServiceImplTest {
    @Test
    void editingPartnerDoesNotReplaceExistingLoginPasswordHash() {
        PartnerServiceImpl service = new PartnerServiceImpl();
        Partner partner = new Partner();
        partner.setAccount("partner-user");
        partner.setName("合作商A");
        partner.setPhoneOne("13800000000");
        partner.setLogoUrl("logo.jpg");
        partner.setRoleId(9);
        SysUser user = new SysUser();
        user.setPassword("$2a$10$existing-bcrypt-hash");
        service.prepareExistingUserForUpdate(user, partner);
        assertEquals("$2a$10$existing-bcrypt-hash", user.getPassword());
        assertEquals("partner-user", user.getUserName());
        assertEquals(Long.valueOf(9), user.getRoleId());
    }
    @Test
    void acceptsShareRatioWithoutIcbcSubMerchantConfiguration() {
        Partner partner = new Partner();
        partner.setId(1);
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/FinancialSettlementController.java
@@ -220,7 +220,7 @@
            tChargingOrderExport.setElectrovalencePrice("");
            tChargingOrderExport.setServiceChargePrice("");
            tChargingOrderExport.setServiceChargePriceLook("");
            tChargingOrderExport.setCumulativeChargingTime(chargingOrderListVO.getChargingSecond() + "");
            tChargingOrderExport.setCumulativeChargingTime(formatChargingDurationMinutes(chargingOrderListVO.getChargingSecond()));
            tChargingOrderExport.setRefundAmount(null != chargingOrderListVO.getRefundAmount() ? chargingOrderListVO.getRefundAmount().toString() : "");
            tChargingOrderExport.setStartSoc(chargingOrderListVO.getStartSoc());
            tChargingOrderExport.setEndtSoc(chargingOrderListVO.getEndSoc());
@@ -338,6 +338,16 @@
    private String formatMoney(BigDecimal amount) {
        return nullToZero(amount).setScale(2, RoundingMode.HALF_UP).toPlainString();
    }
    static String formatChargingDurationMinutes(Long chargingSeconds) {
        if (chargingSeconds == null) {
            return "";
        }
        return BigDecimal.valueOf(chargingSeconds)
                .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP)
                .stripTrailingZeros()
                .toPlainString();
    }
    
    
    
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -282,9 +282,33 @@
        export.setOrderSource(formatOrderSource(dto.getOrderSource()));
        export.setStartTime(dto.getStartTime() == null ? null : DateUtils.localDateTimeToString(dto.getStartTime()));
        export.setEndTime(dto.getEndTime() == null ? null : DateUtils.localDateTimeToString(dto.getEndTime()));
        export.setLicensePlate(dto.getLicensePlate());
        export.setChargingCapacity(dto.getChargingCapacity());
        export.setElectrovalence(dto.getElectrovalence());
        export.setServiceCharge(dto.getServiceCharge());
        export.setEndMode(formatChargingEndMode(dto.getEndMode()));
        export.setPeriodCount(dto.getPeriodCount());
        return export;
    }
    private String formatChargingEndMode(Integer endMode) {
        if (endMode == null) {
            return "-";
        }
        switch (endMode) {
            case 0:
                return "异常终止";
            case 1:
                return "主动终止";
            case 2:
                return "满电终止";
            case 3:
                return "费用不足终止";
            default:
                return "-";
        }
    }
    private String formatEnterpriseOrderType(Integer type) {
        if (type == null) {
            return "-";
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/export/EnterpriseChargingDetailExport.java
@@ -59,4 +59,22 @@
    @Excel(name = "最后时间", width = 30)
    private String endTime;
    @Excel(name = "车牌号", width = 20)
    private String licensePlate;
    @Excel(name = "累计充电量", width = 20, numFormat = "0.0000")
    private BigDecimal chargingCapacity;
    @Excel(name = "累计电费", width = 20, numFormat = "0.0000")
    private BigDecimal electrovalence;
    @Excel(name = "累计服务费", width = 20, numFormat = "0.0000")
    private BigDecimal serviceCharge;
    @Excel(name = "结束原因", width = 20)
    private String endMode;
    @Excel(name = "时段数", width = 15)
    private Integer periodCount;
}
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
@@ -305,6 +305,10 @@
        1 as type
        FROM t_charging_order_refund re
        LEFT JOIN t_charging_order co ON re.charging_order_id = co.id
        <if test="data.specialRefund != null and data.specialRefund">
            WHERE re.refund_title = '特殊退款处理'
        </if>
        <if test="data.specialRefund == null or !data.specialRefund">
        UNION ALL
        SELECT
        re.id,
@@ -355,6 +359,7 @@
        3 as type
        FROM t_vip_order_refund vr
        LEFT JOIN t_vip_order vo on vr.vip_order_id = vo.id
        </if>
        ) o
        <where>
            <if test="data.code != null and data.code != ''">
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/FinancialSettlementControllerTest.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.order.controller;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class FinancialSettlementControllerTest {
    @Test
    void shouldFormatChargingDurationInMinutes() {
        assertEquals("377.5", FinancialSettlementController.formatChargingDurationMinutes(22650L));
        assertEquals("34.6", FinancialSettlementController.formatChargingDurationMinutes(2076L));
        assertEquals("", FinancialSettlementController.formatChargingDurationMinutes(null));
    }
}
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/TChargingOrderControllerTest.java
@@ -4,11 +4,14 @@
import com.ruoyi.order.api.query.ChargingOrderQuery;
import com.ruoyi.order.api.vo.TCharingOrderVO;
import com.ruoyi.order.dto.SixChargingDto;
import com.ruoyi.order.dto.EnterpriseChargingDetailVO;
import com.ruoyi.order.export.EnterpriseChargingDetailExport;
import com.ruoyi.order.service.TChargingOrderService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.time.LocalDate;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
@@ -23,6 +26,27 @@
class TChargingOrderControllerTest {
    @Test
    void enterpriseChargingDetailExportContainsVisibleDetailColumns() {
        EnterpriseChargingDetailVO detail = new EnterpriseChargingDetailVO();
        detail.setLicensePlate("川JD20960");
        detail.setChargingCapacity(new BigDecimal("40.693"));
        detail.setElectrovalence(new BigDecimal("43.0857"));
        detail.setServiceCharge(new BigDecimal("16.2772"));
        detail.setEndMode(0);
        detail.setPeriodCount(1);
        EnterpriseChargingDetailExport export = ReflectionTestUtils.invokeMethod(
                new TChargingOrderController(), "buildEnterpriseChargingDetailExport", detail);
        assertEquals("川JD20960", export.getLicensePlate());
        assertEquals(new BigDecimal("40.693"), export.getChargingCapacity());
        assertEquals(new BigDecimal("43.0857"), export.getElectrovalence());
        assertEquals(new BigDecimal("16.2772"), export.getServiceCharge());
        assertEquals("异常终止", export.getEndMode());
        assertEquals(1, export.getPeriodCount());
    }
    @Test
    void latestAdjacentMonthDataMovesTheSixMonthWindowForward() {
        SixChargingDto june = new SixChargingDto();
        june.setMonth("06");
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/mapper/PayOrderQueryPerformanceMapperTest.java
@@ -55,6 +55,24 @@
        assertEquals(3, countOccurrences(refundQuery, "as site_id"));
    }
    @Test
    void specialRefundListSkipsUnrelatedOrderUnions() throws IOException {
        InputStream input = getClass().getClassLoader()
                .getResourceAsStream("mapper/order/TChargingOrderMapper.xml");
        assertNotNull(input);
        String mapper;
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
            mapper = reader.lines().collect(Collectors.joining("\n"));
        }
        String refundQuery = mapper.substring(
                mapper.indexOf("<select id=\"getRefundList\""),
                mapper.indexOf("<select id=\"chargingOrderGroup\""));
        assertTrue(refundQuery.contains("WHERE re.refund_title = '特殊退款处理'"));
        assertTrue(refundQuery.contains("<if test=\"data.specialRefund == null or !data.specialRefund\">"));
    }
    private int countOccurrences(String text, String target) {
        int count = 0;
        int index = 0;