From 9af2c277033957c095d1090c8e6f77e54b86172f Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期四, 02 七月 2026 16:58:59 +0800
Subject: [PATCH] 新增企业用户充电分析功能页(包含充电明细);新增系统用户管理中的重置操作密码功能;在角色管理中增加独立合作商角色;角色管理中的添加角色操作新增数据驾驶舱和视频监控入口(需在角色管理员有按钮权限控制)。
---
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 57 +++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java | 11
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java | 124 +++++++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisQuery.java | 66 ++++
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysRole.java | 22 +
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RoleInfoVo.java | 6
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java | 93 +++++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisVO.java | 45 +++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java | 5
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml | 180 +++++++++++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingDetailVO.java | 73 ++++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/export/EnterpriseChargingDetailExport.java | 62 ++++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java | 99 ++++++
13 files changed, 831 insertions(+), 12 deletions(-)
diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysRole.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysRole.java
index a1ef53b..c419530 100644
--- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysRole.java
+++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysRole.java
@@ -73,6 +73,12 @@
@TableField(exist = false)
private Long number;
+
+ @TableField(exist = false)
+ private Boolean systemRole;
+
+ @TableField(exist = false)
+ private Boolean partnerRole;
public SysRole()
@@ -214,6 +220,22 @@
public void setNumber(Long number) {
this.number = number;
}
+
+ public Boolean getSystemRole() {
+ return systemRole;
+ }
+
+ public void setSystemRole(Boolean systemRole) {
+ this.systemRole = systemRole;
+ }
+
+ public Boolean getPartnerRole() {
+ return partnerRole;
+ }
+
+ public void setPartnerRole(Boolean partnerRole) {
+ this.partnerRole = partnerRole;
+ }
@Override
public String toString() {
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java
index a73f98b..c82449f 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java
@@ -3,7 +3,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.management.relation.Role;
@@ -61,6 +63,11 @@
@RequestMapping("/role")
@Api(tags = "角色模块")
public class SysRoleController extends BaseController {
+ private static final String INDEPENDENT_PARTNER_ROLE_NAME = "独立合作商";
+ private static final String INDEPENDENT_PARTNER_ROLE_KEY = "independent_partner";
+ private static final String OWN_SITE_NAME = "自有电站";
+ private static final String SYSTEM_ROLE_REMARK = "系统内置角色";
+
@Resource
private ISysRoleService roleService;
@@ -84,6 +91,88 @@
@Resource
private SiteClient siteClient;
+ private void ensureIndependentPartnerRole() {
+ SysRole role = roleService.getOne(new LambdaQueryWrapper<SysRole>()
+ .eq(SysRole::getRoleKey, INDEPENDENT_PARTNER_ROLE_KEY)
+ .eq(SysRole::getDelFlag, 0)
+ .last("LIMIT 1"));
+ if (role == null) {
+ role = roleService.getOne(new LambdaQueryWrapper<SysRole>()
+ .eq(SysRole::getRoleName, INDEPENDENT_PARTNER_ROLE_NAME)
+ .eq(SysRole::getDelFlag, 0)
+ .last("LIMIT 1"));
+ }
+ if (role != null) {
+ return;
+ }
+
+ SysRole newRole = new SysRole();
+ newRole.setRoleName(INDEPENDENT_PARTNER_ROLE_NAME);
+ newRole.setRoleKey(INDEPENDENT_PARTNER_ROLE_KEY);
+ newRole.setDataScope("5");
+ newRole.setStatus("0");
+ newRole.setDelFlag("0");
+ newRole.setRemark(SYSTEM_ROLE_REMARK);
+ newRole.setCreateBy(SecurityUtils.getUsername());
+ newRole.setCreateTime(new Date());
+ Set<Long> menuIds = getIndependentPartnerMenuIds();
+ newRole.setMenuIds(menuIds.toArray(new Long[0]));
+ roleService.insertRole(newRole);
+ }
+
+ private Set<Long> getIndependentPartnerMenuIds() {
+ List<SysMenus> menus = menuMapper.getAll();
+ Set<Long> menuIds = new HashSet<>();
+ Set<Long> rootIds = new HashSet<>();
+ for (SysMenus menu : menus) {
+ String path = menu.getPath() == null ? "" : menu.getPath();
+ String menuName = menu.getMenuName() == null ? "" : menu.getMenuName();
+ if ("standingPile".equals(path) || "order".equals(path)
+ || menuName.contains("站桩管理") || menuName.contains("订单管理")) {
+ rootIds.add(menu.getMenuId());
+ }
+ }
+ for (Long rootId : rootIds) {
+ collectMenuTreeIds(rootId, menus, menuIds);
+ }
+ return menuIds;
+ }
+
+ private void collectMenuTreeIds(Long menuId, List<SysMenus> menus, Set<Long> menuIds) {
+ if (menuId == null || menuIds.contains(menuId)) {
+ return;
+ }
+ menuIds.add(menuId);
+ for (SysMenus menu : menus) {
+ if (menuId.equals(menu.getParentId())) {
+ collectMenuTreeIds(menu.getMenuId(), menus, menuIds);
+ }
+ }
+ }
+
+ private boolean isIndependentPartnerRole(SysRole role) {
+ return role != null && (INDEPENDENT_PARTNER_ROLE_KEY.equals(role.getRoleKey())
+ || INDEPENDENT_PARTNER_ROLE_NAME.equals(role.getRoleName()));
+ }
+
+ private boolean isSystemBuiltinRole(SysRole role) {
+ return role != null && (role.isAdmin() || isIndependentPartnerRole(role));
+ }
+
+ private void fillRoleV2Info(SysRole role) {
+ if (role == null) {
+ return;
+ }
+ boolean partnerRole = isIndependentPartnerRole(role);
+ role.setPartnerRole(partnerRole);
+ role.setSystemRole(isSystemBuiltinRole(role));
+ if (partnerRole) {
+ role.setSiteNames(Arrays.asList(OWN_SITE_NAME));
+ if (StringUtils.isEmpty(role.getRemark())) {
+ role.setRemark(SYSTEM_ROLE_REMARK);
+ }
+ }
+ }
@@ -102,6 +191,7 @@
@GetMapping("/listPage")
@ApiOperation(value = "获取角色列表", tags = {"管理后台-角色管理"})
public AjaxResult listPage(String name, BasePage basePage) {
+ ensureIndependentPartnerRole();
PageInfo<SysRole> pageInfo = new PageInfo<>(basePage.getPageCurr(), basePage.getPageSize());
LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<SysRole>().eq(SysRole::getStatus, 0).eq(SysRole::getDelFlag, 0);
if (StringUtils.isNotEmpty(name)) {
@@ -118,6 +208,7 @@
}
long count = sysUserRoleService.count(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, record.getRoleId()));
record.setNumber(count);
+ fillRoleV2Info(record);
}
return AjaxResult.success(page);
}
@@ -169,6 +260,9 @@
RoleInfoVo roleInfoVo = new RoleInfoVo();
roleInfoVo.setRoleId(role.getRoleId());
roleInfoVo.setRoleName(role.getRoleName());
+ roleInfoVo.setRoleKey(role.getRoleKey());
+ roleInfoVo.setPartnerRole(isIndependentPartnerRole(role));
+ roleInfoVo.setSystemRole(isSystemBuiltinRole(role));
// 获取当前角色的菜单id
List<Long> menusId = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, id)).stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
if (menusId.size() == 0) {
@@ -194,12 +288,20 @@
}
roleInfoVo.setMenus(menusId);
roleInfoVo.setRemark(role.getRemark());
- List<Integer> siteIds = roleSiteClient.getSiteIds(role.getRoleId()).getData();
- if (null != siteIds && siteIds.size() > 0) {
- List<Site> sites = siteClient.getSiteByIds(siteIds).getData();
- List<String> siteNames = sites.stream().map(Site::getName).collect(Collectors.toList());
- roleInfoVo.setSiteNames(siteNames);
- roleInfoVo.setSiteIds(siteIds);
+ if (isIndependentPartnerRole(role)) {
+ roleInfoVo.setSiteNames(Arrays.asList(OWN_SITE_NAME));
+ roleInfoVo.setSiteIds(new ArrayList<>());
+ if (StringUtils.isEmpty(roleInfoVo.getRemark())) {
+ roleInfoVo.setRemark(SYSTEM_ROLE_REMARK);
+ }
+ } else {
+ List<Integer> siteIds = roleSiteClient.getSiteIds(role.getRoleId()).getData();
+ if (null != siteIds && siteIds.size() > 0) {
+ List<Site> sites = siteClient.getSiteByIds(siteIds).getData();
+ List<String> siteNames = sites.stream().map(Site::getName).collect(Collectors.toList());
+ roleInfoVo.setSiteNames(siteNames);
+ roleInfoVo.setSiteIds(siteIds);
+ }
}
return AjaxResult.success(roleInfoVo);
}
@@ -209,6 +311,10 @@
@PostMapping("/roleUpdate")
@ApiOperation(value = "编辑角色", tags = {"管理后台-角色管理"})
public AjaxResult roleUpdate(@Validated @RequestBody RoleUpdateDto dto) {
+ SysRole oldRole = roleService.selectRoleById(dto.getRoleId());
+ if (isSystemBuiltinRole(oldRole)) {
+ return AjaxResult.error("系统内置角色不可编辑");
+ }
SysRole role = new SysRole();
role.setRoleName(dto.getRoleName());
SysRole one = roleService.getOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleName, dto.getRoleName()));
@@ -269,6 +375,12 @@
@DeleteMapping("/{roleIds}")
@ApiOperation(value = "删除角色", tags = {"管理后台-角色管理"})
public AjaxResult remove(@PathVariable Long[] roleIds) {
+ for (Long roleId : roleIds) {
+ SysRole role = roleService.selectRoleById(roleId);
+ if (isSystemBuiltinRole(role)) {
+ return AjaxResult.error("系统内置角色不可删除");
+ }
+ }
return toAjax(roleService.deleteRoleByIds(roleIds));
}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
index 849327f..d94a6e6 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.controller;
import java.util.*;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Resource;
@@ -8,8 +9,12 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.chargingPile.api.feignClient.SiteClient;
import com.ruoyi.chargingPile.api.model.Site;
+import com.ruoyi.common.core.constant.MsgConstants;
+import com.ruoyi.common.core.utils.HttpUtils;
+import com.ruoyi.common.core.utils.MsgUtil;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.annotation.Logical;
import com.ruoyi.other.api.domain.TUserSite;
@@ -48,6 +53,9 @@
@RequestMapping("/user")
@Api(tags = "用户信息")
public class SysUserController extends BaseController {
+ private static final String RESET_PWD_CODE_KEY = "system:user:resetPwd:code:";
+ private static final String RESET_PWD_LIMIT_KEY = "system:user:resetPwd:limit:";
+
@Resource
private ISysUserService userService;
@@ -80,6 +88,9 @@
@Resource
private SiteClient siteClient;
+
+ @Resource
+ private RedisService redisService;
@@ -541,18 +552,92 @@
/**
+ * 发送重置密码验证码
+ */
+ @RequiresPermissions(value = {"/systemUserManagement/reset_passwords"}, logical = Logical.OR)
+ @PostMapping("/resetPwd/sendCode")
+ @ApiOperation(value = "发送重置密码验证码", tags = {"管理后台-系统用户管理"})
+ public AjaxResult sendResetPwdCode(@RequestBody Map<String, Object> params) {
+ Long userId = parseLong(params.get("userId"));
+ if (userId == null) {
+ return AjaxResult.error("用户不存在");
+ }
+ SysUser user = userService.selectUserById(userId);
+ if (user == null) {
+ return AjaxResult.error("用户不存在");
+ }
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(userId);
+ if (StringUtils.isEmpty(user.getPhonenumber())) {
+ return AjaxResult.error("当前用户未维护手机号");
+ }
+
+ String limitKey = RESET_PWD_LIMIT_KEY + userId;
+ if (Boolean.TRUE.equals(redisService.hasKey(limitKey))) {
+ return AjaxResult.error("验证码发送过于频繁,请30秒后再试");
+ }
+
+ String code = MsgUtil.createCode();
+ String reqStr = MsgUtil.codeMsg(user.getPhonenumber(), code);
+ HttpUtils.post(MsgConstants.SEND_URL, reqStr);
+
+ redisService.setCacheObject(RESET_PWD_CODE_KEY + userId, code, 5L, TimeUnit.MINUTES);
+ redisService.setCacheObject(limitKey, "1", 30L, TimeUnit.SECONDS);
+ return AjaxResult.success("验证码已发送");
+ }
+
+ /**
* 重置密码
*/
@RequiresPermissions(value = {"/systemUserManagement/reset_passwords"}, logical = Logical.OR)
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd")
@ApiOperation(value = "重置密码", tags = {"管理后台-系统用户管理"})
- public AjaxResult resetPwd(@RequestBody SysUser user) {
+ public AjaxResult resetPwd(@RequestBody Map<String, Object> params) {
+ Long userId = parseLong(params.get("userId"));
+ String password = parseString(params.get("password"));
+ String code = parseString(params.get("code"));
+ if (userId == null) {
+ return AjaxResult.error("用户不存在");
+ }
+ if (StringUtils.isEmpty(password)) {
+ return AjaxResult.error("请输入新密码");
+ }
+ if (StringUtils.isEmpty(code)) {
+ return AjaxResult.error("请输入验证码");
+ }
+
+ SysUser user = userService.selectUserById(userId);
+ if (user == null) {
+ return AjaxResult.error("用户不存在");
+ }
userService.checkUserAllowed(user);
- userService.checkUserDataScope(user.getUserId());
- user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+ userService.checkUserDataScope(userId);
+
+ String cacheCode = redisService.getCacheObject(RESET_PWD_CODE_KEY + userId);
+ if (StringUtils.isEmpty(cacheCode)) {
+ return AjaxResult.error("验证码已过期,请重新获取验证码");
+ }
+ if (!code.equals(cacheCode)) {
+ return AjaxResult.error("验证码错误");
+ }
+
+ user.setPassword(SecurityUtils.encryptPassword(password));
user.setUpdateBy(SecurityUtils.getUsername());
- return toAjax(userService.resetPwd(user));
+ int result = userService.resetPwd(user);
+ redisService.deleteObject(RESET_PWD_CODE_KEY + userId);
+ return toAjax(result);
+ }
+
+ private Long parseLong(Object value) {
+ if (value == null || StringUtils.isEmpty(String.valueOf(value))) {
+ return null;
+ }
+ return Long.valueOf(String.valueOf(value));
+ }
+
+ private String parseString(Object value) {
+ return value == null ? null : String.valueOf(value);
}
/**
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RoleInfoVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RoleInfoVo.java
index a935fd0..c621eeb 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RoleInfoVo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RoleInfoVo.java
@@ -13,6 +13,12 @@
private String roleName;
+ private String roleKey;
+
+ private Boolean systemRole;
+
+ private Boolean partnerRole;
+
@ApiModelProperty("菜单id")
private List<Long> menus;
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
index fd39ada..3a23f90 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -53,6 +53,7 @@
import com.ruoyi.order.dto.OrderEvaluateVo;
import com.ruoyi.order.dto.*;
import com.ruoyi.order.export.PayOrderExport;
+import com.ruoyi.order.export.EnterpriseChargingDetailExport;
import com.ruoyi.order.service.*;
import com.ruoyi.order.util.PreviousSixMonths;
import com.ruoyi.order.util.mongodb.service.UploadRealTimeMonitoringDataService;
@@ -217,6 +218,104 @@
}
+ @RequiresPermissions(value = {"/chargingUserAnalysis"}, logical = Logical.OR)
+ @ResponseBody
+ @PostMapping(value = "/enterprise/charging/analysis")
+ @ApiOperation(value = "企业用户充电分析", tags = {"管理后台-数据分析-企业用户充电分析"})
+ public R<PageInfo<EnterpriseChargingAnalysisVO>> enterpriseChargingAnalysis(@RequestBody EnterpriseChargingAnalysisQuery query) {
+ return chargingOrderService.enterpriseChargingAnalysis(query);
+ }
+
+ @RequiresPermissions(value = {"/chargingUserAnalysis"}, logical = Logical.OR)
+ @ResponseBody
+ @PostMapping(value = "/enterprise/charging/detail")
+ @ApiOperation(value = "企业用户充电明细", tags = {"管理后台-数据分析-企业用户充电分析"})
+ public R<PageInfo<EnterpriseChargingDetailVO>> enterpriseChargingDetail(@RequestBody EnterpriseChargingAnalysisQuery query) {
+ return chargingOrderService.enterpriseChargingDetail(query);
+ }
+
+ @RequiresPermissions(value = {"/chargingUserAnalysis"}, logical = Logical.OR)
+ @ResponseBody
+ @PutMapping(value = "/enterprise/charging/detail/export")
+ @ApiOperation(value = "企业用户充电明细导出", tags = {"管理后台-数据分析-企业用户充电分析"})
+ public void exportEnterpriseChargingDetail(@RequestBody EnterpriseChargingAnalysisQuery query) {
+ List<EnterpriseChargingDetailVO> records = chargingOrderService.enterpriseChargingDetailExport(query);
+ List<EnterpriseChargingDetailExport> exports = records.stream().map(this::buildEnterpriseChargingDetailExport).collect(Collectors.toList());
+ Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), EnterpriseChargingDetailExport.class, exports);
+ HttpServletResponse response = WebUtils.response();
+ response.setContentType("application/vnd.ms-excel;charset=UTF-8");
+ response.setCharacterEncoding("utf-8");
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-Control", "no-cache");
+ try {
+ response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("企业用户充电明细.xls", "utf-8"));
+ try (ServletOutputStream outputStream = response.getOutputStream()) {
+ workbook.write(outputStream);
+ }
+ workbook.close();
+ } catch (IOException e) {
+ log.error("导出企业用户充电明细失败", e);
+ }
+ }
+
+ private EnterpriseChargingDetailExport buildEnterpriseChargingDetailExport(EnterpriseChargingDetailVO dto) {
+ EnterpriseChargingDetailExport export = new EnterpriseChargingDetailExport();
+ export.setCode(dto.getCode());
+ export.setOrderType(formatEnterpriseOrderType(dto.getOrderType()));
+ export.setOrderClassification(formatOrderClassification(dto.getOrderClassification()));
+ export.setSiteName(dto.getSiteName());
+ export.setTerminalName(dto.getTerminalName());
+ export.setStatus(formatPayOrderStatus(1, dto.getStatus()));
+ export.setChargingSecond(dto.getChargingSecond());
+ export.setTotalAmount(dto.getTotalAmount());
+ export.setCouponDiscountAmount(dto.getCouponDiscountAmount());
+ export.setVipDiscountAmount(dto.getVipDiscountAmount());
+ export.setPaymentAmount(dto.getPaymentAmount());
+ export.setRefundAmount(dto.getRefundAmount());
+ export.setPartnerName(dto.getPartnerName());
+ export.setPhone(dto.getPhone());
+ 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()));
+ return export;
+ }
+
+ private String formatEnterpriseOrderType(Integer type) {
+ if (type == null) {
+ return "-";
+ }
+ if (type == 1) {
+ return "充电订单(小程序)";
+ }
+ if (type == 2) {
+ return "充电订单(刷卡)";
+ }
+ return "充电订单";
+ }
+
+ private String formatOrderClassification(Integer type) {
+ if (type == null) {
+ return "-";
+ }
+ return type == 1 ? "线上订单" : "线下订单";
+ }
+
+ private String formatOrderSource(Integer source) {
+ if (source == null) {
+ return "-";
+ }
+ if (source == 0) {
+ return "自有平台";
+ }
+ if (source == 1) {
+ return "第三方平台";
+ }
+ if (source == 2) {
+ return "引流平台";
+ }
+ return "其他";
+ }
+
@RequiresPermissions(value = {"/invoiceManagement/select_order", "/paymentOrder/order"}, logical = Logical.OR)
@ResponseBody
@PostMapping(value = "/pay/order/list")
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisQuery.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisQuery.java
new file mode 100644
index 0000000..5da2b90
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisQuery.java
@@ -0,0 +1,66 @@
+package com.ruoyi.order.dto;
+
+import com.ruoyi.common.core.web.page.BasePage;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@ApiModel("Enterprise charging analysis query")
+public class EnterpriseChargingAnalysisQuery extends BasePage {
+
+ @ApiModelProperty("Company name")
+ private String companyName;
+
+ @ApiModelProperty("Social credit code")
+ private String socialCreditCode;
+
+ @ApiModelProperty("Exact company name")
+ private String exactCompanyName;
+
+ @ApiModelProperty("Site type")
+ private Integer siteType;
+
+ @ApiModelProperty("Partner id")
+ private Integer partnerId;
+
+ @ApiModelProperty("Site id")
+ private Integer siteId;
+
+ @ApiModelProperty("Order create start time")
+ private LocalDateTime createTime1;
+
+ @ApiModelProperty("Order create end time")
+ private LocalDateTime createTime2;
+ @ApiModelProperty("Order code")
+ private String code;
+
+ @ApiModelProperty("Charging order type")
+ private Integer orderType;
+
+ @ApiModelProperty("User phone")
+ private String phone;
+
+ @ApiModelProperty("Order status")
+ private Integer status;
+
+ @ApiModelProperty("Partner or service provider name")
+ private String partnerName;
+
+ @ApiModelProperty("Order source")
+ private Integer orderSource;
+
+ @ApiModelProperty("Charging start time begin")
+ private LocalDateTime startTime1;
+
+ @ApiModelProperty("Charging start time end")
+ private LocalDateTime startTime2;
+
+ @ApiModelProperty("Charging end time begin")
+ private LocalDateTime endTime1;
+
+ @ApiModelProperty("Charging end time end")
+ private LocalDateTime endTime2;
+}
\ No newline at end of file
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisVO.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisVO.java
new file mode 100644
index 0000000..bca19c4
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingAnalysisVO.java
@@ -0,0 +1,45 @@
+package com.ruoyi.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@ApiModel("Enterprise charging analysis view")
+public class EnterpriseChargingAnalysisVO {
+
+ @ApiModelProperty("Company name")
+ private String companyName;
+
+ @ApiModelProperty("Social credit code")
+ private String socialCreditCode;
+
+ @ApiModelProperty("Company address")
+ private String companyAddress;
+
+ @ApiModelProperty("Company phone")
+ private String companyPhone;
+
+ @ApiModelProperty("Charging count")
+ private Long chargingCount;
+
+ @ApiModelProperty("Invoice count")
+ private Long invoiceCount;
+
+ @ApiModelProperty("Invoice amount")
+ private BigDecimal invoiceAmount;
+
+ @ApiModelProperty("Top site names")
+ private String topSiteNames;
+
+ @ApiModelProperty("Latest charging time")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime latestChargingTime;
+
+ @ApiModelProperty("Average charging interval hours")
+ private BigDecimal averageChargingInterval;
+}
\ No newline at end of file
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingDetailVO.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingDetailVO.java
new file mode 100644
index 0000000..5a89bbf
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/EnterpriseChargingDetailVO.java
@@ -0,0 +1,73 @@
+package com.ruoyi.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@ApiModel("Enterprise charging detail view")
+public class EnterpriseChargingDetailVO {
+
+ private Long id;
+
+ @ApiModelProperty("Order code")
+ private String code;
+
+ @ApiModelProperty("Charging order type")
+ private Integer orderType;
+
+ @ApiModelProperty("Order classification")
+ private Integer orderClassification;
+
+ @ApiModelProperty("Site name")
+ private String siteName;
+
+ @ApiModelProperty("Terminal name")
+ private String terminalName;
+
+ @ApiModelProperty("Status")
+ private Integer status;
+
+ @ApiModelProperty("Charging seconds")
+ private Long chargingSecond;
+
+ @ApiModelProperty("Total amount")
+ private BigDecimal totalAmount;
+
+ @ApiModelProperty("Coupon discount amount")
+ private BigDecimal couponDiscountAmount;
+
+ @ApiModelProperty("Vip discount amount")
+ private BigDecimal vipDiscountAmount;
+
+ @ApiModelProperty("Actual payment amount")
+ private BigDecimal paymentAmount;
+
+ @ApiModelProperty("Refund amount")
+ private BigDecimal refundAmount;
+
+ @ApiModelProperty("Order source")
+ private Integer orderSource;
+
+ @ApiModelProperty("Partner name")
+ private String partnerName;
+
+ @ApiModelProperty("Phone")
+ private String phone;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime createTime;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime startTime;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime endTime;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private LocalDateTime payTime;
+}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/export/EnterpriseChargingDetailExport.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/export/EnterpriseChargingDetailExport.java
new file mode 100644
index 0000000..bcac15b
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/export/EnterpriseChargingDetailExport.java
@@ -0,0 +1,62 @@
+package com.ruoyi.order.export;
+
+import cn.afterturn.easypoi.excel.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class EnterpriseChargingDetailExport implements Serializable {
+
+ @Excel(name = "订单编号", width = 30)
+ private String code;
+
+ @Excel(name = "订单类型", width = 20)
+ private String orderType;
+
+ @Excel(name = "订单分类", width = 20)
+ private String orderClassification;
+
+ @Excel(name = "站点名称", width = 30)
+ private String siteName;
+
+ @Excel(name = "充电终端名称", width = 30)
+ private String terminalName;
+
+ @Excel(name = "状态", width = 20)
+ private String status;
+
+ @Excel(name = "充电时长(秒)", width = 20)
+ private Long chargingSecond;
+
+ @Excel(name = "总金额", width = 20)
+ private BigDecimal totalAmount;
+
+ @Excel(name = "优惠券抵扣", width = 20)
+ private BigDecimal couponDiscountAmount;
+
+ @Excel(name = "会员抵扣", width = 20)
+ private BigDecimal vipDiscountAmount;
+
+ @Excel(name = "实付金额", width = 20)
+ private BigDecimal paymentAmount;
+
+ @Excel(name = "退款金额", width = 20)
+ private BigDecimal refundAmount;
+
+ @Excel(name = "归属合作商/服务商", width = 30)
+ private String partnerName;
+
+ @Excel(name = "手机号", width = 20)
+ private String phone;
+
+ @Excel(name = "订单来源", width = 20)
+ private String orderSource;
+
+ @Excel(name = "开始时间", width = 30)
+ private String startTime;
+
+ @Excel(name = "最后时间", width = 30)
+ private String endTime;
+}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
index b72e2a1..3ca1971 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
@@ -67,6 +67,17 @@
List<ChargingOrderBalanceIncomeDetailVO> exchangeCodeBalanceIncomeDetail(@Param("orderIds") List<Long> orderIds);
List<PayOrderDto> payOrderQuery(@Param("pageInfo")PageInfo<PayOrderDto> pageInfo,@Param("data") PayOrderQueryDto payOrderQueryDto);
+ List<EnterpriseChargingAnalysisVO> enterpriseChargingAnalysis(@Param("pageInfo") PageInfo<EnterpriseChargingAnalysisVO> pageInfo,
+ @Param("data") EnterpriseChargingAnalysisQuery query);
+
+ List<Map<String, Object>> enterpriseTopSites(@Param("data") EnterpriseChargingAnalysisQuery query);
+
+ List<LocalDateTime> enterpriseChargingTimes(@Param("data") EnterpriseChargingAnalysisQuery query);
+
+ List<EnterpriseChargingDetailVO> enterpriseChargingDetail(@Param("pageInfo") PageInfo<EnterpriseChargingDetailVO> pageInfo,
+ @Param("data") EnterpriseChargingAnalysisQuery query);
+
+ List<EnterpriseChargingDetailVO> enterpriseChargingDetailExport(@Param("data") EnterpriseChargingAnalysisQuery query);
List<TChargingOrderRefund> getRefundList(@Param("pageInfo")PageInfo<TChargingOrderRefund> pageInfo,@Param("data") ChargingRefundDto chargingRefundDto);
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java
index b80ced4..2eeade7 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java
@@ -147,6 +147,11 @@
List<ChargingOrderBalanceIncomeDetailVO> balanceIncomeDetail(ChargingOrderQuery dto);
R<PageInfo<PayOrderDto>> payOrderQuery(PayOrderQueryDto payOrderQueryDto);
+ R<PageInfo<EnterpriseChargingAnalysisVO>> enterpriseChargingAnalysis(EnterpriseChargingAnalysisQuery query);
+
+ R<PageInfo<EnterpriseChargingDetailVO>> enterpriseChargingDetail(EnterpriseChargingAnalysisQuery query);
+
+ List<EnterpriseChargingDetailVO> enterpriseChargingDetailExport(EnterpriseChargingAnalysisQuery query);
R<PageInfo<TChargingOrderRefund>> getRefundList(ChargingRefundDto chargingRefundDto);
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 dfd718e..85f821c 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
@@ -2228,7 +2228,62 @@
pageInfo.setRecords(list);
return R.ok(pageInfo);
}
-
+ @Override
+ public R<PageInfo<EnterpriseChargingAnalysisVO>> enterpriseChargingAnalysis(EnterpriseChargingAnalysisQuery query) {
+ PageInfo<EnterpriseChargingAnalysisVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize());
+ List<EnterpriseChargingAnalysisVO> list = this.baseMapper.enterpriseChargingAnalysis(pageInfo, query);
+ for (EnterpriseChargingAnalysisVO row : list) {
+ EnterpriseChargingAnalysisQuery rowQuery = buildEnterpriseRowQuery(query, row);
+ List<Map<String, Object>> topSites = this.baseMapper.enterpriseTopSites(rowQuery);
+ String topSiteNames = topSites.stream()
+ .map(item -> Objects.toString(item.get("siteName"), ""))
+ .filter(org.springframework.util.StringUtils::hasText)
+ .collect(Collectors.joining("、"));
+ row.setTopSiteNames(topSiteNames);
+ row.setAverageChargingInterval(calculateAverageChargingInterval(this.baseMapper.enterpriseChargingTimes(rowQuery)));
+ }
+ pageInfo.setRecords(list);
+ return R.ok(pageInfo);
+ }
+
+ @Override
+ public R<PageInfo<EnterpriseChargingDetailVO>> enterpriseChargingDetail(EnterpriseChargingAnalysisQuery query) {
+ PageInfo<EnterpriseChargingDetailVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize());
+ List<EnterpriseChargingDetailVO> list = this.baseMapper.enterpriseChargingDetail(pageInfo, query);
+ pageInfo.setRecords(list);
+ return R.ok(pageInfo);
+ }
+
+ @Override
+ public List<EnterpriseChargingDetailVO> enterpriseChargingDetailExport(EnterpriseChargingAnalysisQuery query) {
+ return this.baseMapper.enterpriseChargingDetailExport(query);
+ }
+
+ private EnterpriseChargingAnalysisQuery buildEnterpriseRowQuery(EnterpriseChargingAnalysisQuery source, EnterpriseChargingAnalysisVO row) {
+ EnterpriseChargingAnalysisQuery rowQuery = new EnterpriseChargingAnalysisQuery();
+ BeanUtils.copyProperties(source, rowQuery);
+ rowQuery.setCompanyName(null);
+ rowQuery.setExactCompanyName(row.getCompanyName());
+ rowQuery.setSocialCreditCode(row.getSocialCreditCode());
+ return rowQuery;
+ }
+
+ private BigDecimal calculateAverageChargingInterval(List<LocalDateTime> times) {
+ if (times == null || times.size() < 2) {
+ return BigDecimal.ZERO;
+ }
+ long totalMinutes = 0L;
+ for (int i = 1; i < times.size(); i++) {
+ long minutes = ChronoUnit.MINUTES.between(times.get(i - 1), times.get(i));
+ if (minutes > 0) {
+ totalMinutes += minutes;
+ }
+ }
+ return BigDecimal.valueOf(totalMinutes)
+ .divide(BigDecimal.valueOf(times.size() - 1L), 4, RoundingMode.HALF_UP)
+ .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);
+ }
+
@Override
public R<PageInfo<TChargingOrderRefund>> getRefundList(ChargingRefundDto chargingRefundDto) {
PageInfo<TChargingOrderRefund> pageInfo = new PageInfo<>(chargingRefundDto.getPageCurr(), chargingRefundDto.getPageSize());
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
index 9eaf884..7dbaa6e 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.order.mapper.TChargingOrderMapper">
@@ -2454,4 +2454,182 @@
group by orderId,recharge_payment_type,site_id,recharge_amount,refund_amount,platformFee
) as aa group by aa.site_id,aa.recharge_payment_type order by aa.site_id
</select>
+
+ <sql id="enterpriseChargingBaseWhere">
+ toi.invoicing_object_type = 2
+ AND toi.status IN (2, 3)
+ AND tod.order_type = 1
+ AND co.del_flag = 0
+ AND co.recharge_payment_status = 2
+ <if test="data.exactCompanyName != null and data.exactCompanyName != ''">
+ AND toi.name = #{data.exactCompanyName}
+ </if>
+ <if test="(data.exactCompanyName == null or data.exactCompanyName == '') and data.companyName != null and data.companyName != ''">
+ AND toi.name LIKE CONCAT('%', #{data.companyName}, '%')
+ </if>
+ <if test="data.socialCreditCode != null and data.socialCreditCode != ''">
+ AND IFNULL(toi.tax_identification_number, '') = #{data.socialCreditCode}
+ </if>
+ <if test="data.siteType != null">
+ AND s.site_type = #{data.siteType}
+ </if>
+ <if test="data.partnerId != null">
+ AND s.partner_id = #{data.partnerId}
+ </if>
+ <if test="data.siteId != null">
+ AND co.site_id = #{data.siteId}
+ </if>
+ <if test="data.createTime1 != null">
+ AND co.create_time >= #{data.createTime1}
+ </if>
+ <if test="data.createTime2 != null">
+ AND co.create_time <= #{data.createTime2}
+ </if>
+ </sql>
+
+ <select id="enterpriseChargingAnalysis" resultType="com.ruoyi.order.dto.EnterpriseChargingAnalysisVO">
+ SELECT
+ b.companyName,
+ b.socialCreditCode,
+ MAX(b.companyAddress) AS companyAddress,
+ MAX(b.companyPhone) AS companyPhone,
+ SUM(b.orderCount) AS chargingCount,
+ COUNT(1) AS invoiceCount,
+ SUM(CASE WHEN b.detailInvoiceAmount > 0 THEN b.detailInvoiceAmount ELSE b.totalAmount END) AS invoiceAmount,
+ MAX(b.latestChargingTime) AS latestChargingTime
+ FROM (
+ SELECT
+ toi.id AS invoiceId,
+ toi.name AS companyName,
+ IFNULL(toi.tax_identification_number, '') AS socialCreditCode,
+ MAX(toi.company_address) AS companyAddress,
+ MAX(toi.company_phone) AS companyPhone,
+ MAX(IFNULL(toi.total_amount, 0)) AS totalAmount,
+ SUM(IFNULL(tod.invoice_amount, 0)) AS detailInvoiceAmount,
+ COUNT(DISTINCT co.id) AS orderCount,
+ MAX(co.end_time) AS latestChargingTime
+ FROM t_order_invoice toi
+ INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id
+ INNER JOIN t_charging_order co ON co.id = tod.order_id
+ LEFT JOIN charging_pile_service.t_site s ON s.id = co.site_id
+ <where>
+ <include refid="enterpriseChargingBaseWhere" />
+ </where>
+ GROUP BY toi.id, toi.name, toi.tax_identification_number
+ ) b
+ GROUP BY b.companyName, b.socialCreditCode
+ ORDER BY chargingCount DESC
+ </select>
+
+ <select id="enterpriseTopSites" resultType="map">
+ SELECT
+ s.name AS siteName,
+ COUNT(DISTINCT co.id) AS counts
+ FROM t_order_invoice toi
+ INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id
+ INNER JOIN t_charging_order co ON co.id = tod.order_id
+ LEFT JOIN charging_pile_service.t_site s ON s.id = co.site_id
+ <where>
+ <include refid="enterpriseChargingBaseWhere" />
+ AND s.name IS NOT NULL
+ </where>
+ GROUP BY s.id, s.name
+ ORDER BY counts DESC
+ LIMIT 3
+ </select>
+
+ <select id="enterpriseChargingTimes" resultType="java.time.LocalDateTime">
+ SELECT DISTINCT co.start_time
+ FROM t_order_invoice toi
+ INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id
+ INNER JOIN t_charging_order co ON co.id = tod.order_id
+ LEFT JOIN charging_pile_service.t_site s ON s.id = co.site_id
+ <where>
+ <include refid="enterpriseChargingBaseWhere" />
+ AND co.start_time IS NOT NULL
+ </where>
+ ORDER BY co.start_time ASC
+ </select>
+
+ <sql id="enterpriseChargingDetailWhere">
+ <include refid="enterpriseChargingBaseWhere" />
+ <if test="data.code != null and data.code != ''">
+ AND co.code LIKE CONCAT('%', #{data.code}, '%')
+ </if>
+ <if test="data.orderType != null">
+ AND co.order_type = #{data.orderType}
+ </if>
+ <if test="data.phone != null and data.phone != ''">
+ AND au.phone LIKE CONCAT('%', #{data.phone}, '%')
+ </if>
+ <if test="data.status != null">
+ AND co.status = #{data.status}
+ </if>
+ <if test="data.partnerName != null and data.partnerName != ''">
+ AND p.name LIKE CONCAT('%', #{data.partnerName}, '%')
+ </if>
+ <if test="data.orderSource != null">
+ AND co.order_source = #{data.orderSource}
+ </if>
+ <if test="data.startTime1 != null">
+ AND co.start_time >= #{data.startTime1}
+ </if>
+ <if test="data.startTime2 != null">
+ AND co.start_time <= #{data.startTime2}
+ </if>
+ <if test="data.endTime1 != null">
+ AND co.end_time >= #{data.endTime1}
+ </if>
+ <if test="data.endTime2 != null">
+ AND co.end_time <= #{data.endTime2}
+ </if>
+ </sql>
+
+ <sql id="enterpriseChargingDetailSelect">
+ SELECT DISTINCT
+ co.id,
+ co.code,
+ co.order_type AS orderType,
+ co.order_classification AS orderClassification,
+ s.name AS siteName,
+ CONCAT(IFNULL(cp.name, ''), IFNULL(cg.name, '')) AS terminalName,
+ co.status,
+ (UNIX_TIMESTAMP(co.end_time) - UNIX_TIMESTAMP(co.start_time)) AS chargingSecond,
+ co.recharge_amount AS totalAmount,
+ IFNULL(co.coupon_discount_amount, 0) AS couponDiscountAmount,
+ IFNULL(co.vip_discount_amount, 0) AS vipDiscountAmount,
+ co.payment_amount AS paymentAmount,
+ IFNULL(co.refund_amount, 0) AS refundAmount,
+ co.order_source AS orderSource,
+ p.name AS partnerName,
+ au.phone AS phone,
+ co.create_time AS createTime,
+ co.start_time AS startTime,
+ co.end_time AS endTime,
+ co.pay_time AS payTime
+ FROM t_order_invoice toi
+ INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id
+ INNER JOIN t_charging_order co ON co.id = tod.order_id
+ LEFT JOIN charging_pile_service.t_site s ON s.id = co.site_id
+ LEFT JOIN charging_pile_service.t_partner p ON p.id = s.partner_id
+ LEFT JOIN charging_pile_service.t_charging_pile cp ON cp.id = co.charging_pile_id
+ LEFT JOIN charging_pile_service.t_charging_gun cg ON cg.id = co.charging_gun_id
+ LEFT JOIN charging_pile_account.t_app_user au ON au.id = co.app_user_id
+ </sql>
+
+ <select id="enterpriseChargingDetail" resultType="com.ruoyi.order.dto.EnterpriseChargingDetailVO">
+ <include refid="enterpriseChargingDetailSelect" />
+ <where>
+ <include refid="enterpriseChargingDetailWhere" />
+ </where>
+ ORDER BY co.create_time DESC
+ </select>
+
+ <select id="enterpriseChargingDetailExport" resultType="com.ruoyi.order.dto.EnterpriseChargingDetailVO">
+ <include refid="enterpriseChargingDetailSelect" />
+ <where>
+ <include refid="enterpriseChargingDetailWhere" />
+ </where>
+ ORDER BY co.create_time DESC
+ </select>
</mapper>
--
Gitblit v1.7.1