Merge branch '2.2' of http://120.76.84.145:10101/gitblit/r/java/mx_charging_pile into 2.2
| | |
| | | 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) { |
| | |
| | | } |
| | | 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) { |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @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) |
| | |
| | | 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 { |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | 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()); |
| | |
| | | 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()) |
| New file |
| | |
| | | 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()); |
| | | } |
| | | } |
| | |
| | | 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)) |
| | |
| | | |
| | | 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; |
| | |
| | | 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); |
| | |
| | | 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()); |
| | |
| | | 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(); |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | 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 "-"; |
| | |
| | | |
| | | @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; |
| | | } |
| | |
| | | 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, |
| | |
| | | 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 != ''"> |
| New file |
| | |
| | | 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)); |
| | | } |
| | | } |
| | |
| | | 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; |
| | | |
| | |
| | | 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"); |
| | |
| | | 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; |