From 88580dae55106dcf4a8f80693b90638e07af02fa Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 14 十月 2026 09:20:23 +0800
Subject: [PATCH] 修改bug
---
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 7
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml | 2
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java | 7 +
ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java | 78 +++++++++++
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml | 2
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java | 165 +++++++++++++++++++++++
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml | 5
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java | 2
sql/20261013_order_evaluate_vin_type.sql | 6
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java | 2
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java | 41 +++++
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java | 20 ++
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java | 4
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java | 40 +++++
sql/charging_pile_order.sql | 2
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java | 3
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java | 2
17 files changed, 378 insertions(+), 10 deletions(-)
diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java
index 3b4a479..fd40572 100644
--- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java
+++ b/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;
diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java
index 4ebe265..f6fa736 100644
--- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderEvaluate.java
+++ b/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;
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java
index bd3b4eb..177c3df 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java
+++ b/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);
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java
index 1b6b29a..44e0d03 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/TAppUserWhitelistService.java
+++ b/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);
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java
index 5a88272..c9d1af4 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImpl.java
+++ b/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();
diff --git a/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml b/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml
index 9c72703..a56d9cd 100644
--- a/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TCompanyAllocateRecordMapper.xml
+++ b/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>
diff --git a/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java b/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
index 6621aa1..e763e60 100644
--- a/ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
+++ b/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
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java
index 27c1c87..315f7b5 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderEvaluateController.java
+++ b/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);
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java
index 5b248cc..a8f136d 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java
+++ b/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;
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
index 8d08113..d9d4d96 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
+++ b/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
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java
index ab0bcc4..4ab6514 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImpl.java
+++ b/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())) {
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml
index 8df7f35..1f743b8 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml
+++ b/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}
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml
index 93ffe57..3813b89 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TVinChargingOrderMapper.xml
+++ b/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
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
index dda4567..090cb4a 100644
--- a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TChargingOrderServiceImplVinFallbackTest.java
+++ b/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);
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java
new file mode 100644
index 0000000..8d29ef8
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/TOrderEvaluateServiceImplVinTypeTest.java
@@ -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());
+ }
+}
diff --git a/sql/20261013_order_evaluate_vin_type.sql b/sql/20261013_order_evaluate_vin_type.sql
new file mode 100644
index 0000000..a312407
--- /dev/null
+++ b/sql/20261013_order_evaluate_vin_type.sql
@@ -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码充电订单)';
diff --git a/sql/charging_pile_order.sql b/sql/charging_pile_order.sql
index 92a2216..4e37e5d 100644
--- a/sql/charging_pile_order.sql
+++ b/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 '评分',
--
Gitblit v1.7.1