ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java
@@ -64,6 +64,9 @@ @ApiModelProperty(value = "是否命中白名单") private Boolean whitelistMatched = false; @ApiModelProperty(value = "白名单账户可用余额(企业账户充电显示,共享模式=公司可用余额,分配模式=白名单用户余额)") private BigDecimal whitelistBalance; @ApiModelProperty(value = "白名单权益:1=全部免费,2=免电费,3=免服务费") private Integer whitelistBenefitType; ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java
@@ -31,7 +31,7 @@ @TableId(value = "id", type = IdType.NONE) private Long id; @ApiModelProperty(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)") @ApiModelProperty(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)") @TableField("order_type") private Integer orderType; ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java
@@ -179,6 +179,10 @@ } AppUserWhitelistMatchVO whitelist = whitelistService.matchWhitelist(tokenService.getLoginUserApplet().getUserId(), chargingGun.getSiteId()); data.setWhitelistMatched(Boolean.TRUE.equals(whitelist.getMatched())); if (Boolean.TRUE.equals(whitelist.getMatched())) { // 充电页余额显示:按白名单所属公司账户模式下发账户可用余额(共享=公司余额,分配=白名单余额) data.setWhitelistBalance(whitelistService.resolveWhitelistAccountBalance(whitelist)); } // 白名单权益已下线(充电完全按企业优惠结算),不再下发权益类型与名称,仅保留命中标识 data.setWhitelistBenefitType(null); data.setWhitelistBenefitName(null); ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java
@@ -50,6 +50,13 @@ AppUserWhitelistMatchVO matchWhitelist(Long appUserId, Integer siteId); /** * 解析白名单账户可用余额(小程序充电页余额显示):按所属公司账户模式, * 共享模式=公司可用余额,分配模式=白名单用户余额,账户模式未知按共享处理; * 公司信息查询失败时降级返回 null(由调用方保持原余额显示) */ BigDecimal resolveWhitelistAccountBalance(AppUserWhitelistMatchVO match); /** * 按公司查询未删除的白名单用户列表(公司详情-充电用户信息聚合使用) */ List<TAppUserWhitelist> listByCompany(Integer companyId); ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java
@@ -457,6 +457,26 @@ } @Override public BigDecimal resolveWhitelistAccountBalance(AppUserWhitelistMatchVO match) { if (match == null || !Boolean.TRUE.equals(match.getMatched()) || match.getCompanyId() == null) { return null; } try { TGroupCompany company = loadCompany(match.getCompanyId()); Integer accountMode = company == null ? null : company.getAccountMode(); if (accountMode == null) { // 历史数据账户模式为空,按共享模式处理 accountMode = ACCOUNT_MODE_SHARED; } return resolveAvailableBalance(accountMode, match.getBalance(), company == null ? null : company.getAvailableBalance()); } catch (Exception ex) { log.warn("解析白名单账户可用余额失败,companyId={}", match.getCompanyId(), ex); return null; } } @Override public List<TAppUserWhitelist> listByCompany(Integer companyId) { if (companyId == null) { return Collections.emptyList(); ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml
@@ -4,6 +4,9 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.account.mapper.TCompanyAllocateRecordMapper"> <!-- 分配记录弹窗只统计「给子账号(VIN码/刷卡/白名单)分配余额」的流水: change_type = 1 仅取分配类(1=分配;排除 2=充电结算消费流水,其 after_balance 可为负数); user_type != 4 排除账户模式切换时企业账户自身的回退留痕(不属于子账号分配) --> <select id="selectRecordPage" resultType="com.ruoyi.account.api.model.TCompanyAllocateRecord"> SELECT id, company_id, @@ -21,6 +24,8 @@ create_time FROM t_company_allocate_record WHERE company_id = #{query.companyId} AND change_type = 1 AND user_type != 4 ORDER BY operate_time DESC, id DESC </select> </mapper> ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
@@ -50,6 +50,7 @@ import java.util.concurrent.atomic.AtomicLong; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -259,6 +260,83 @@ assertEquals(null, result.getFleetId()); } // ---------------- 白名单账户可用余额解析(充电页余额显示) ---------------- @Test void resolveWhitelistAccountBalanceReturnsCompanyBalanceForSharedMode() { TGroupCompany company = new TGroupCompany(); company.setAccountMode(1); company.setAvailableBalance(new BigDecimal("500.50")); when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company)); AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO(); match.setMatched(true); match.setCompanyId(12); match.setBalance(new BigDecimal("100.00")); BigDecimal result = service.resolveWhitelistAccountBalance(match); assertEquals(new BigDecimal("500.50"), result); } @Test void resolveWhitelistAccountBalanceReturnsWhitelistBalanceForAllocationMode() { TGroupCompany company = new TGroupCompany(); company.setAccountMode(2); company.setAvailableBalance(new BigDecimal("500.50")); when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company)); AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO(); match.setMatched(true); match.setCompanyId(12); match.setBalance(new BigDecimal("100.00")); BigDecimal result = service.resolveWhitelistAccountBalance(match); assertEquals(new BigDecimal("100.00"), result); } @Test void resolveWhitelistAccountBalanceTreatsNullAccountModeAsShared() { TGroupCompany company = new TGroupCompany(); company.setAccountMode(null); company.setAvailableBalance(new BigDecimal("500.50")); when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company)); AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO(); match.setMatched(true); match.setCompanyId(12); match.setBalance(new BigDecimal("100.00")); BigDecimal result = service.resolveWhitelistAccountBalance(match); assertEquals(new BigDecimal("500.50"), result); } @Test void resolveWhitelistAccountBalanceReturnsNullWhenCompanyQueryFails() { when(groupCompanyClient.getCompanyById(12)).thenReturn(R.fail("公司信息查询失败")); AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO(); match.setMatched(true); match.setCompanyId(12); match.setBalance(new BigDecimal("100.00")); BigDecimal result = service.resolveWhitelistAccountBalance(match); assertNull(result); } @Test void resolveWhitelistAccountBalanceReturnsNullWhenNotMatched() { AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO(); match.setMatched(false); BigDecimal result = service.resolveWhitelistAccountBalance(match); assertNull(result); } // ---------------- 额度分配 ---------------- @Test ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java
@@ -183,7 +183,7 @@ @ApiOperation(value = "获取订单评价详情", tags = {"小程序-充电记录"}) @ApiImplicitParams({ @ApiImplicitParam(value = "订单id", name = "orderId", required = true), @ApiImplicitParam(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)", name = "orderType", required = true), @ApiImplicitParam(value = "订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)", name = "orderType", required = true), }) public AjaxResult<OrderEvaluateVo> getOrderEvaluate(String orderId, Integer orderType){ OrderEvaluateVo orderEvaluate = orderEvaluateService.getOrderEvaluate(orderId, orderType); ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java
@@ -36,7 +36,7 @@ private BigDecimal chargedDegrees; @ApiModelProperty("已充电时间") private String chargedTime; @ApiModelProperty("充电费用") @ApiModelProperty("已使用费用(设备上报已充金额,缺失时回退订单已使用金额)") private BigDecimal chargingCost; @ApiModelProperty("充电状态(0=未知,1=等待中,2=启动中,3=充电中,4=停止中,5=已结束)") private Integer status; ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -2796,7 +2796,8 @@ boolean reservationPending = ReservationOrderSupport.isPending( one.getStatus(), one.getReservationTime(), LocalDateTime.now()); chargingDetails.setStatus(reservationPending ? 1 : one.getStatus()); chargingDetails.setChargingCost(one.getResidualAmount()); // 已使用费用:默认取订单已使用金额,存在实时监测数据时以设备上报已充金额(电费+服务费)为准 chargingDetails.setChargingCost(money(one.getResidualAmount())); UploadRealTimeMonitoringData data = uploadRealTimeMonitoringDataService.getLastDataById(one.getCode()); if (null != data) { chargingDetails.setChargeCurrent(data.getOutput_current()); @@ -2809,6 +2810,10 @@ Integer h = Integer.valueOf(data.getCumulative_charging_time() / 60); Integer m = Integer.valueOf(data.getCumulative_charging_time() % 60); chargingDetails.setChargedTime(String.format("%02d", h) + ":" + String.format("%02d", m)); // 设备上报已充金额非空时覆盖,上报缺失则沿用订单已使用金额 if (null != data.getPaid_amount()) { chargingDetails.setChargingCost(money(data.getPaid_amount())); } if (null != one.getAppUserCarId()) { TAppUserCar appUserCar = appUserCarClient.getCarById(one.getAppUserCarId().toString()).getData(); // 续航 = 续航里程 * soc ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java
@@ -24,6 +24,7 @@ import com.ruoyi.order.api.model.TEvaluationAutoReply; import com.ruoyi.order.api.model.TOrderEvaluate; import com.ruoyi.order.api.model.TOrderEvaluateTag; import com.ruoyi.order.api.model.TVinChargingOrder; import com.ruoyi.order.api.query.TOrderEvaluateQuery; import com.ruoyi.order.api.vo.SiteDetailEvaluateVO; import com.ruoyi.order.api.vo.TOrderEvaluateVO; @@ -36,6 +37,7 @@ import com.ruoyi.order.service.TChargingOrderService; import com.ruoyi.order.service.TEvaluationAutoReplyService; import com.ruoyi.order.service.TOrderEvaluateService; import com.ruoyi.order.service.TVinChargingOrderService; import com.ruoyi.order.service.WxSubscribeMessageService; import com.ruoyi.other.api.domain.TEvaluationTag; import com.ruoyi.other.api.domain.TIntegralRule; @@ -90,6 +92,9 @@ @Resource private TChargingOrderService chargingOrderService; @Resource private TVinChargingOrderService vinChargingOrderService; @Resource private IntegralRuleClient integralRuleClient; @@ -345,9 +350,25 @@ BeanUtils.copyProperties(query, orderEvaluate); Long userid = tokenService.getLoginUserApplet().getUserId(); orderEvaluate.setAppUserId(userid); if(query.getOrderType() == 1){ Integer orderType = query.getOrderType(); if(null == orderType){ return AjaxResult.error("订单类型不能为空"); } if(orderType == 1){ TChargingOrder chargingOrder = chargingOrderService.getById(query.getOrderId()); if(null == chargingOrder){ return AjaxResult.error("订单不存在"); } orderEvaluate.setAppUserCarId(chargingOrder.getAppUserCarId()); }else if(orderType == 5){ //VIN码充电订单,仅允许评价本人订单 TVinChargingOrder vinChargingOrder = vinChargingOrderService.getById(query.getOrderId()); if(null == vinChargingOrder || !userid.equals(vinChargingOrder.getAppUserId())){ return AjaxResult.error("订单不存在"); } orderEvaluate.setAppUserCarId(vinChargingOrder.getAppUserCarId()); }else{ return AjaxResult.error("订单类型不支持评价"); } TAppUser appUser = appUserClient.getUserById(userid).getData(); @@ -392,7 +413,6 @@ appUser.setPoints(appUser.getPoints() + num1); appUserClient.updateAppUser(appUser); TChargingOrder chargingOrder = chargingOrderService.getById(orderEvaluate.getOrderId()); //积分变动明细 TAppUserIntegralChange appUserIntegralChange = new TAppUserIntegralChange(); appUserIntegralChange.setAppUserId(appUser.getId()); @@ -400,7 +420,7 @@ appUserIntegralChange.setHistoricalIntegral(points); appUserIntegralChange.setCurrentIntegral(points + num1); appUserIntegralChange.setCreateTime(LocalDateTime.now()); appUserIntegralChange.setOrderCode(chargingOrder.getCode()); appUserIntegralChange.setOrderCode(getOrderCode(orderEvaluate.getOrderType(), orderEvaluate.getOrderId())); appUserIntegralChange.setExtension(orderEvaluate.getOrderId().toString()); appUserIntegralChangeClient.addAppUserIntegralChange(appUserIntegralChange); } @@ -408,6 +428,21 @@ return AjaxResult.success(); } /** * 根据评价的订单类型获取对应的订单编号 * @param orderType 订单类型(1=充电订单,5=VIN码充电订单) * @param orderId 订单id * @return 订单编号 */ private String getOrderCode(Integer orderType, Long orderId) { if(Integer.valueOf(5).equals(orderType)){ TVinChargingOrder vinChargingOrder = vinChargingOrderService.getById(orderId); return null == vinChargingOrder ? null : vinChargingOrder.getCode(); } TChargingOrder chargingOrder = chargingOrderService.getById(orderId); return null == chargingOrder ? null : chargingOrder.getCode(); } private void applyAutoReply(TOrderEvaluate orderEvaluate) { TEvaluationAutoReply rule = evaluationAutoReplyService.matchRule(orderEvaluate.getContent(), orderEvaluate.getMark()); if (rule == null || StringUtils.isEmpty(rule.getReplyContent())) { ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml
@@ -36,7 +36,7 @@ AND o.charging_gun_id = #{query.gunId} </if> <if test="startTime1 != null and startTime1 != '' and startTime2 != null and startTime2 != ''"> AND o.pay_time BETWEEN #{startTime1} AND #{startTime2} AND o.start_time BETWEEN #{startTime1} AND #{startTime2} </if> <if test="endTime1 != null and endTime1 != '' and endTime2 != null and endTime2 != ''"> AND o.end_time BETWEEN #{endTime1} AND #{endTime2} ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml
@@ -60,7 +60,7 @@ o.status, CASE WHEN EXISTS ( SELECT 1 FROM t_order_evaluate e WHERE e.order_id = o.id AND e.order_type = 1 AND e.del_flag = 0 WHERE e.order_id = o.id AND e.order_type = 5 AND e.del_flag = 0 ) THEN 2 ELSE 1 END AS evaluate FROM t_vin_charging_order o WHERE o.del_flag = 0 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
@@ -134,6 +134,46 @@ } @Test void getChargingDetailsUsesPaidAmountAsUsedCostWhenRealTimeDataPresent() { LoginUserApplet loginUser = new LoginUserApplet(); loginUser.setUserId(88L); when(tokenService.getLoginUserApplet()).thenReturn(loginUser); when(mapper.selectOne(any())).thenReturn(null); TVinChargingOrder vinOrder = new TVinChargingOrder(); vinOrder.setId(1001L); vinOrder.setAppUserId(88L); vinOrder.setChargingGunId(5); vinOrder.setStatus(3); vinOrder.setCode("VD20261013001"); vinOrder.setResidualAmount(new BigDecimal("66.60")); when(vinChargingOrderMapper.selectOne(any())).thenReturn(vinOrder); TChargingGun gun = new TChargingGun(); gun.setChargingPileId(7); when(chargingGunClient.getChargingGunById(5)).thenReturn(R.ok(gun)); TChargingPile pile = new TChargingPile(); pile.setName("1号桩"); pile.setSiteId(9); when(chargingPileClient.getChargingPileById(7)).thenReturn(R.ok(pile)); Site site = new Site(); site.setName("城东站"); when(siteClient.getSiteByIds(Arrays.asList(9))).thenReturn(R.ok(Collections.singletonList(site))); UploadRealTimeMonitoringData data = new UploadRealTimeMonitoringData(); data.setOutput_current(new BigDecimal("10")); data.setOutput_voltage(new BigDecimal("220")); data.setSoc(50); data.setTime_remaining(30); data.setCharging_degree(new BigDecimal("5.5")); data.setCumulative_charging_time(75); // 设备上报已充金额为 4 位小数,展示口径统一保留 2 位 data.setPaid_amount(new BigDecimal("12.3456")); when(uploadRealTimeMonitoringDataService.getLastDataById("VD20261013001")).thenReturn(data); ChargingDetails details = service.getChargingDetails(5); assertEquals(0, new BigDecimal("12.35").compareTo(details.getChargingCost())); } @Test void getChargingDetailsReturnsNullWhenNeitherNormalNorVinOrderExists() { LoginUserApplet loginUser = new LoginUserApplet(); loginUser.setUserId(88L); ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java
New file @@ -0,0 +1,165 @@ package com.ruoyi.order.service.impl; import com.ruoyi.account.api.feignClient.AppUserClient; import com.ruoyi.account.api.model.TAppUser; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.api.model.TOrderEvaluate; import com.ruoyi.order.api.model.TVinChargingOrder; import com.ruoyi.order.dto.OrderEvaluateVo; import com.ruoyi.order.mapper.TOrderEvaluateMapper; import com.ruoyi.order.service.TChargingOrderService; import com.ruoyi.order.service.TEvaluationAutoReplyService; import com.ruoyi.order.service.TVinChargingOrderService; import com.ruoyi.system.api.model.LoginUserApplet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * VIN 码充电订单评价(orderType=5)分支测试 * 覆盖:本人 VIN 订单可评价、他人订单/不存在订单被拒、普通充电订单不存在的兜底校验 */ @ExtendWith(MockitoExtension.class) class TOrderEvaluateServiceImplVinTypeTest { @InjectMocks private TOrderEvaluateServiceImpl service; @Mock private TOrderEvaluateMapper orderEvaluateMapper; @Mock private TokenService tokenService; @Mock private TChargingOrderService chargingOrderService; @Mock private TVinChargingOrderService vinChargingOrderService; @Mock private AppUserClient appUserClient; @Mock private TEvaluationAutoReplyService evaluationAutoReplyService; @BeforeEach void setUp() { ReflectionTestUtils.setField(service, "baseMapper", orderEvaluateMapper); ReflectionTestUtils.setField(service, "orderEvaluateMapper", orderEvaluateMapper); LoginUserApplet loginUser = new LoginUserApplet(); loginUser.setUserId(88L); when(tokenService.getLoginUserApplet()).thenReturn(loginUser); } private OrderEvaluateVo buildQuery(Long orderId, Integer orderType) { OrderEvaluateVo query = new OrderEvaluateVo(); query.setOrderId(orderId); query.setOrderType(orderType); query.setMark(5); return query; } @Test void addOrderEvaluateForOwnVinOrderStoresTypeFiveAndOwnerCar() { TVinChargingOrder vinOrder = new TVinChargingOrder(); vinOrder.setId(1001L); vinOrder.setAppUserId(88L); vinOrder.setAppUserCarId(66L); vinOrder.setCode("VD_1001"); when(vinChargingOrderService.getById(1001L)).thenReturn(vinOrder); TAppUser appUser = new TAppUser(); appUser.setId(88L); appUser.setWxOpenid("openid_88"); when(appUserClient.getUserById(88L)).thenReturn(R.ok(appUser)); when(orderEvaluateMapper.insert(any(TOrderEvaluate.class))).thenReturn(1); AjaxResult result = service.addOrderEvaluate(buildQuery(1001L, 5)); assertTrue(result.isSuccess()); ArgumentCaptor<TOrderEvaluate> captor = ArgumentCaptor.forClass(TOrderEvaluate.class); verify(orderEvaluateMapper).insert(captor.capture()); TOrderEvaluate saved = captor.getValue(); assertEquals(Integer.valueOf(5), saved.getOrderType()); assertEquals(Long.valueOf(88L), saved.getAppUserId()); assertEquals(Long.valueOf(66L), saved.getAppUserCarId()); // VIN 订单评价不应再走普通充电订单表 verify(chargingOrderService, never()).getById(anyLong()); } @Test void addOrderEvaluateRejectsVinOrderBelongingToOtherUser() { TVinChargingOrder vinOrder = new TVinChargingOrder(); vinOrder.setId(1001L); vinOrder.setAppUserId(99L); when(vinChargingOrderService.getById(1001L)).thenReturn(vinOrder); AjaxResult result = service.addOrderEvaluate(buildQuery(1001L, 5)); assertFalse(result.isSuccess()); assertEquals("订单不存在", result.get(AjaxResult.MSG_TAG)); verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class)); } @Test void addOrderEvaluateRejectsMissingVinOrder() { AjaxResult result = service.addOrderEvaluate(buildQuery(1001L, 5)); assertFalse(result.isSuccess()); assertEquals("订单不存在", result.get(AjaxResult.MSG_TAG)); verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class)); } @Test void addOrderEvaluateRejectsMissingChargingOrder() { AjaxResult result = service.addOrderEvaluate(buildQuery(2002L, 1)); assertFalse(result.isSuccess()); assertEquals("订单不存在", result.get(AjaxResult.MSG_TAG)); verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class)); } @Test void addOrderEvaluateRejectsUnsupportedOrderType() { AjaxResult result = service.addOrderEvaluate(buildQuery(3003L, 2)); assertFalse(result.isSuccess()); assertEquals("订单类型不支持评价", result.get(AjaxResult.MSG_TAG)); verify(orderEvaluateMapper, never()).insert(any(TOrderEvaluate.class)); } @Test void addOrderEvaluateStillWorksForNormalChargingOrder() { TChargingOrder chargingOrder = new TChargingOrder(); chargingOrder.setId(2002L); chargingOrder.setAppUserCarId(55L); chargingOrder.setCode("CD_2002"); when(chargingOrderService.getById(2002L)).thenReturn(chargingOrder); TAppUser appUser = new TAppUser(); appUser.setId(88L); appUser.setWxOpenid("openid_88"); when(appUserClient.getUserById(88L)).thenReturn(R.ok(appUser)); when(orderEvaluateMapper.insert(any(TOrderEvaluate.class))).thenReturn(1); AjaxResult result = service.addOrderEvaluate(buildQuery(2002L, 1)); assertTrue(result.isSuccess()); ArgumentCaptor<TOrderEvaluate> captor = ArgumentCaptor.forClass(TOrderEvaluate.class); verify(orderEvaluateMapper).insert(captor.capture()); TOrderEvaluate saved = captor.getValue(); assertEquals(Integer.valueOf(1), saved.getOrderType()); assertEquals(Long.valueOf(55L), saved.getAppUserCarId()); verify(vinChargingOrderService, never()).getById(anyLong()); } } sql/20261013_order_evaluate_vin_type.sql
New file @@ -0,0 +1,6 @@ -- VIN码充电订单评价:t_order_evaluate.order_type 新增取值 5=VIN码充电订单 -- 背景:小程序 VIN 码充电订单列表"评价/查看评价"原先按 order_type=1 提交,后端按普通充电订单表查询导致空指针; -- 现改为独立类型 5,与普通充电订单(1)区分,本脚本仅更新字段注释,无表结构调整。 -- 执行环境:测试库已执行,其他环境发版前同步执行 ALTER TABLE `t_order_evaluate` MODIFY COLUMN `order_type` int NULL DEFAULT NULL COMMENT '订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)'; sql/charging_pile_order.sql
@@ -4287,7 +4287,7 @@ DROP TABLE IF EXISTS `t_order_evaluate`; CREATE TABLE `t_order_evaluate` ( `id` bigint NOT NULL COMMENT '主键', `order_type` int NULL DEFAULT NULL COMMENT '订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)', `order_type` int NULL DEFAULT NULL COMMENT '订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单,5=VIN码充电订单)', `order_id` bigint NULL DEFAULT NULL COMMENT '订单id', `app_user_id` bigint NULL DEFAULT NULL COMMENT '用户id', `mark` int NULL DEFAULT NULL COMMENT '评分',