202507051753
This commit is contained in:
parent
faf16add2c
commit
1a8a62321a
1
pom.xml
1
pom.xml
|
|
@ -16,6 +16,7 @@
|
||||||
<ruoyi.version>3.8.9</ruoyi.version>
|
<ruoyi.version>3.8.9</ruoyi.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
<spring-boot.version>2.5.15</spring-boot.version>
|
<spring-boot.version>2.5.15</spring-boot.version>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ ruoyi:
|
||||||
# 验证码类型 math 数字计算 char 字符验证
|
# 验证码类型 math 数字计算 char 字符验证
|
||||||
captchaType: math
|
captchaType: math
|
||||||
wechat:
|
wechat:
|
||||||
appid: wx1234567890123456
|
appid: wx73d0202b3c8a6d68
|
||||||
mchid: 1672571923
|
mchid: 1672571923
|
||||||
apikey: sssssssssssssssssssssssssssssssS
|
apikey: sssssssssssssssssssssssssssssssS
|
||||||
certpath: wechat/apiclient_cert.p12
|
certpath: wechat/apiclient_cert.p12
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,461 @@
|
||||||
|
package com.ruoyi.system.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.ControllerUtil.AppletControllerUtil;
|
||||||
|
import com.ruoyi.system.ControllerUtil.AppletLoginUtil;
|
||||||
|
import com.ruoyi.system.ControllerUtil.InvoiceUtil;
|
||||||
|
import com.ruoyi.system.domain.Users;
|
||||||
|
import com.ruoyi.system.service.IUsersService;
|
||||||
|
import com.ruoyi.system.service.IUsersInvoiceInfoService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发票管理控制器
|
||||||
|
*
|
||||||
|
* 提供发票相关的API接口,包括:
|
||||||
|
* 1. 发票中心数据获取
|
||||||
|
* 2. 待开票订单查询
|
||||||
|
* 3. 已开票记录查询
|
||||||
|
* 4. 批量开票功能
|
||||||
|
* 5. 发票信息管理
|
||||||
|
* 6. 发票统计数据
|
||||||
|
*
|
||||||
|
* @author Mr. Zhang Pan
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2025-01-26
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/user/invoice")
|
||||||
|
public class AppleInvoiceController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUsersService usersService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUsersInvoiceInfoService usersInvoiceInfoService;
|
||||||
|
|
||||||
|
private ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户发票中心数据
|
||||||
|
*
|
||||||
|
* @param params 请求参数
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 发票中心数据
|
||||||
|
*/
|
||||||
|
@PostMapping("/center")
|
||||||
|
public AjaxResult getUserInvoiceCenter(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取分页参数
|
||||||
|
int page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
|
||||||
|
int limit = params.get("limit") != null ? Integer.parseInt(params.get("limit").toString()) : 10;
|
||||||
|
|
||||||
|
// 4. 获取发票中心数据
|
||||||
|
Map<String, Object> invoiceCenterData = InvoiceUtil.getUserInvoiceCenter(user.getId(), page, limit);
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(invoiceCenterData);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取发票中心数据失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待开票订单列表
|
||||||
|
*
|
||||||
|
* @param params 请求参数
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 待开票订单列表
|
||||||
|
*/
|
||||||
|
@PostMapping("/pending")
|
||||||
|
public AjaxResult getPendingInvoiceOrders(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取分页参数
|
||||||
|
int page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
|
||||||
|
int limit = params.get("limit") != null ? Integer.parseInt(params.get("limit").toString()) : 10;
|
||||||
|
|
||||||
|
// 4. 获取待开票订单列表
|
||||||
|
List<Map<String, Object>> pendingOrders = InvoiceUtil.getPendingInvoiceOrders(user.getId(), page, limit);
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(pendingOrders);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取待开票订单列表失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已开票列表
|
||||||
|
*
|
||||||
|
* @param params 请求参数
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 已开票列表
|
||||||
|
*/
|
||||||
|
@PostMapping("/completed")
|
||||||
|
public AjaxResult getCompletedInvoices(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取分页参数
|
||||||
|
int page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
|
||||||
|
int limit = params.get("limit") != null ? Integer.parseInt(params.get("limit").toString()) : 10;
|
||||||
|
|
||||||
|
// 4. 获取已开票列表
|
||||||
|
List<Map<String, Object>> completedInvoices = InvoiceUtil.getCompletedInvoices(user.getId(), page, limit);
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(completedInvoices);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取已开票列表失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开具发票接口(支持批量开票)
|
||||||
|
*
|
||||||
|
* @param params 发票参数
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 开票结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/create")
|
||||||
|
public AjaxResult createInvoice(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 调试日志:输出接收到的原始参数
|
||||||
|
System.out.println("接收到的原始参数: " + params);
|
||||||
|
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证必要参数
|
||||||
|
List<String> orderIds = new ArrayList<>();
|
||||||
|
|
||||||
|
// 支持多种参数格式:orderIds数组、orderIds字符串数组、单个orderId
|
||||||
|
if (params.get("orderIds") != null) {
|
||||||
|
Object orderIdsObj = params.get("orderIds");
|
||||||
|
|
||||||
|
if (orderIdsObj instanceof List) {
|
||||||
|
// 批量开票:orderIds数组
|
||||||
|
List<?> orderIdList = (List<?>) orderIdsObj;
|
||||||
|
for (Object orderIdObj : orderIdList) {
|
||||||
|
if (orderIdObj != null) {
|
||||||
|
orderIds.add(orderIdObj.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (orderIdsObj instanceof String) {
|
||||||
|
// 处理字符串格式的数组,如 "['B1750646653464697','B1750413502322711']"
|
||||||
|
String orderIdsStr = orderIdsObj.toString();
|
||||||
|
|
||||||
|
// 去掉外层的方括号和引号
|
||||||
|
orderIdsStr = orderIdsStr.trim();
|
||||||
|
if (orderIdsStr.startsWith("[") && orderIdsStr.endsWith("]")) {
|
||||||
|
orderIdsStr = orderIdsStr.substring(1, orderIdsStr.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按逗号分割并清理每个订单ID
|
||||||
|
String[] orderIdArray = orderIdsStr.split(",");
|
||||||
|
for (String orderId : orderIdArray) {
|
||||||
|
orderId = orderId.trim();
|
||||||
|
// 去掉单引号或双引号
|
||||||
|
if ((orderId.startsWith("'") && orderId.endsWith("'")) ||
|
||||||
|
(orderId.startsWith("\"") && orderId.endsWith("\""))) {
|
||||||
|
orderId = orderId.substring(1, orderId.length() - 1);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(orderId)) {
|
||||||
|
orderIds.add(orderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (params.get("orderId") != null) {
|
||||||
|
// 单个开票:orderId字符串(兼容旧版本)
|
||||||
|
orderIds.add(params.get("orderId").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderIds.isEmpty()) {
|
||||||
|
return AppletControllerUtil.appletWarning("请选择要开票的订单");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试日志:输出解析后的订单ID列表
|
||||||
|
System.out.println("解析后的订单ID列表: " + orderIds);
|
||||||
|
|
||||||
|
// 4. 调用批量开票方法
|
||||||
|
return InvoiceUtil.createBatchInvoice(user.getId(), orderIds, params);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("开具发票失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户已保存的发票信息
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 发票信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/saved")
|
||||||
|
public AjaxResult getUserSavedInvoiceInfo(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取用户发票信息列表
|
||||||
|
List<Map<String, Object>> invoiceInfoList = InvoiceUtil.getUserInvoiceInfoList(user.getId());
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(invoiceInfoList);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取发票信息失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取发票统计数据
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 统计数据
|
||||||
|
*/
|
||||||
|
@GetMapping("/statistics")
|
||||||
|
public AjaxResult getInvoiceStatistics(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取统计数据
|
||||||
|
Map<String, Object> statistics = InvoiceUtil.getInvoiceStatistics(user.getId());
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(statistics);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取发票统计数据失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存或更新用户发票信息
|
||||||
|
*
|
||||||
|
* @param params 发票信息参数
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 保存结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/info")
|
||||||
|
public AjaxResult saveOrUpdateUserInvoiceInfo(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证必要参数
|
||||||
|
if (params.get("invoiceTitle") == null || StringUtils.isEmpty(params.get("invoiceTitle").toString())) {
|
||||||
|
return AppletControllerUtil.appletWarning("发票抬头不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.get("category") == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("发票类别不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer category = Integer.valueOf(params.get("category").toString());
|
||||||
|
String invoiceTitle = params.get("invoiceTitle").toString();
|
||||||
|
|
||||||
|
// 4. 根据类别验证参数
|
||||||
|
if (category == 0) {
|
||||||
|
// 个人发票验证
|
||||||
|
if (invoiceTitle.length() > 50) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票抬头长度不能超过50个字符");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否填写了企业字段
|
||||||
|
if (StringUtils.isNotEmpty((String) params.get("taxNumber"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票不能填写纳税人识别号");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) params.get("address"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票不能填写单位地址");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) params.get("phone"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票不能填写联系电话");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) params.get("bankName"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票不能填写开户银行");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) params.get("bankAccount"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票不能填写银行账号");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) params.get("wechat"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("个人发票不能填写微信号");
|
||||||
|
}
|
||||||
|
} else if (category == 1) {
|
||||||
|
// 企业发票验证
|
||||||
|
if (StringUtils.isEmpty((String) params.get("taxNumber"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("企业发票必须填写纳税人识别号");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty((String) params.get("address"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("企业发票必须填写单位地址");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty((String) params.get("phone"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("企业发票必须填写联系电话");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty((String) params.get("bankName"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("企业发票必须填写开户银行");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty((String) params.get("bankAccount"))) {
|
||||||
|
return AppletControllerUtil.appletWarning("企业发票必须填写银行账号");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return AppletControllerUtil.appletWarning("发票类别参数错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 保存发票信息(简化实现)
|
||||||
|
return AppletControllerUtil.appletSuccess("发票信息保存成功");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("保存发票信息失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户发票信息列表
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 发票信息列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public AjaxResult getUserInvoiceInfoList(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取用户发票信息列表
|
||||||
|
List<Map<String, Object>> invoiceInfoList = InvoiceUtil.getUserInvoiceInfoList(user.getId());
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(invoiceInfoList);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取发票信息列表失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户发票信息
|
||||||
|
*
|
||||||
|
* @param id 发票信息ID
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 删除结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/info/{id}")
|
||||||
|
public AjaxResult deleteUserInvoiceInfo(@PathVariable("id") Integer id, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 删除发票信息(简化实现)
|
||||||
|
return AppletControllerUtil.appletSuccess("发票信息删除成功");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("删除发票信息失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,848 @@
|
||||||
|
package com.ruoyi.system.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.system.ControllerUtil.*;
|
||||||
|
import com.ruoyi.system.domain.*;
|
||||||
|
import com.ruoyi.system.service.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员管理控制器
|
||||||
|
*
|
||||||
|
* 提供会员相关的API接口,包括:
|
||||||
|
* 1. 会员充值功能
|
||||||
|
* 2. 充值记录管理
|
||||||
|
* 3. 消费记录管理
|
||||||
|
* 4. 会员权益管理
|
||||||
|
* 5. 订单评价功能
|
||||||
|
* 6. 师傅报价功能
|
||||||
|
* 7. 拼团支付功能
|
||||||
|
* 8. 次卡管理功能
|
||||||
|
* 9. 余额支付功能
|
||||||
|
*
|
||||||
|
* @author Mr. Zhang Pan
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2025-01-26
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
|
public class AppleMemberController extends BaseController {
|
||||||
|
|
||||||
|
// ==================== 依赖注入 ====================
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUsersService usersService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserMemberRechargeLogService userMemberRechargeLogService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserMemberRechargeProgramService userMemberRechargeProgramService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISiteConfigService siteConfigService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserMemnerConsumptionLogService userMemnerConsumptionLogService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IOrderService orderService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IOrderCommentService orderCommentService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IOrderLogService orderLogService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IServiceCateService serviceCateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserSecondaryCardService userSecondaryCardService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IServiceGoodsService serviceGoodsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserDemandQuotationService userDemandQuotationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserGroupBuyingService userGroupBuyingService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserBenefitPointsService userBenefitPointsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WechatPayUtil wechatPayUtil;
|
||||||
|
|
||||||
|
// ==================== 会员充值相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员充值支付接口
|
||||||
|
*
|
||||||
|
* 支持两种充值方式:
|
||||||
|
* 1. 通过充值套餐ID充值(优先级更高)
|
||||||
|
* 2. 通过自定义金额充值
|
||||||
|
*
|
||||||
|
* 业务逻辑:
|
||||||
|
* - 如果id和money都有值,优先使用id充值套餐
|
||||||
|
* - 如果只有money有值,使用自定义金额充值
|
||||||
|
* - 支持充值优惠配置(从系统配置中读取)
|
||||||
|
* - 生成充值记录并调用微信支付
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 支付结果,包含prepayId等微信支付参数
|
||||||
|
*/
|
||||||
|
@PostMapping("/member/recharge/pay")
|
||||||
|
public AjaxResult memberRechargePay(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("money", 300); // 测试用固定金额,实际应从请求参数获取
|
||||||
|
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户未登录或token无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 参数验证逻辑:id和money必须有一个有值,如果都有值则优先使用id
|
||||||
|
Object idObj = params.get("id");
|
||||||
|
Object moneyObj = params.get("money");
|
||||||
|
boolean idEmpty = (idObj == null || idObj.toString().trim().isEmpty());
|
||||||
|
boolean moneyEmpty = (moneyObj == null || moneyObj.toString().trim().isEmpty());
|
||||||
|
|
||||||
|
if (idEmpty && moneyEmpty) {
|
||||||
|
return AppletControllerUtil.appletWarning("参数不能为空,类目和金额必须有一个有值");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果id和money都有值,优先走id逻辑,money置空
|
||||||
|
if (!idEmpty && !moneyEmpty) {
|
||||||
|
moneyObj = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 创建充值记录
|
||||||
|
String money = "";
|
||||||
|
UserMemberRechargeLog userMemberRechargeLog = new UserMemberRechargeLog();
|
||||||
|
userMemberRechargeLog.setUid(Math.toIntExact(user.getId()));
|
||||||
|
userMemberRechargeLog.setOrderid(GenerateCustomCode.generCreateOrder("DYZ"));
|
||||||
|
userMemberRechargeLog.setPaytype(0); // 0=微信支付
|
||||||
|
userMemberRechargeLog.setPaytime(new Date());
|
||||||
|
|
||||||
|
if (!idEmpty) {
|
||||||
|
// 5a. 通过充值套餐ID充值
|
||||||
|
UserMemberRechargeProgram userMemberRechargeProgram = userMemberRechargeProgramService
|
||||||
|
.selectUserMemberRechargeProgramById(Integer.valueOf(idObj.toString()));
|
||||||
|
|
||||||
|
if (userMemberRechargeProgram != null) {
|
||||||
|
userMemberRechargeLog.setInmoney(userMemberRechargeProgram.getMoney()); // 应付金额
|
||||||
|
userMemberRechargeLog.setComemoney(userMemberRechargeProgram.getDiscount()); // 实际到账金额
|
||||||
|
userMemberRechargeLog.setReamk("购买" + userMemberRechargeProgram.getRechargename()
|
||||||
|
+ "应付" + userMemberRechargeProgram.getMoney() + "元,应到"
|
||||||
|
+ userMemberRechargeProgram.getDiscount() + "元");
|
||||||
|
userMemberRechargeLog.setProid(userMemberRechargeProgram.getId());
|
||||||
|
money = userMemberRechargeProgram.getMoney().toString();
|
||||||
|
|
||||||
|
// type大于0表示会员包年充值,需要特殊处理
|
||||||
|
if (userMemberRechargeProgram.getType() > 0) {
|
||||||
|
userMemberRechargeLog.setIsmember(1); // 会员充值
|
||||||
|
} else {
|
||||||
|
userMemberRechargeLog.setIsmember(2); // 普通充值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!moneyEmpty) {
|
||||||
|
// 5b. 通过自定义金额充值
|
||||||
|
money = moneyObj.toString();
|
||||||
|
BigDecimal rechargeAmount = new BigDecimal(money);
|
||||||
|
BigDecimal actualAmount = rechargeAmount; // 默认实际到账金额等于充值金额
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 查询充值优惠配置
|
||||||
|
SiteConfig siteConfig = siteConfigService.selectSiteConfigByName("config_one");
|
||||||
|
if (siteConfig != null && siteConfig.getValue() != null) {
|
||||||
|
JSONObject configJson = JSONObject.parseObject(siteConfig.getValue());
|
||||||
|
if (configJson.containsKey("recharge_discount")) {
|
||||||
|
// 获取充值优惠率(百分比)
|
||||||
|
BigDecimal discountRate = configJson.getBigDecimal("recharge_discount");
|
||||||
|
if (discountRate != null && discountRate.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
// 计算实际到账金额:充值金额 * (1 + 优惠率/100)
|
||||||
|
BigDecimal discountMultiplier = BigDecimal.ONE.add(
|
||||||
|
discountRate.divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));
|
||||||
|
actualAmount = rechargeAmount.multiply(discountMultiplier)
|
||||||
|
.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("获取充值优惠配置失败:" + e.getMessage());
|
||||||
|
// 配置获取失败时,使用原金额,不影响充值流程
|
||||||
|
}
|
||||||
|
|
||||||
|
userMemberRechargeLog.setInmoney(rechargeAmount); // 应付金额
|
||||||
|
userMemberRechargeLog.setComemoney(actualAmount); // 实际到账金额
|
||||||
|
userMemberRechargeLog.setIsmember(2); // 普通充值
|
||||||
|
|
||||||
|
// 更新备注信息,显示优惠详情
|
||||||
|
if (actualAmount.compareTo(rechargeAmount) > 0) {
|
||||||
|
BigDecimal bonusAmount = actualAmount.subtract(rechargeAmount);
|
||||||
|
userMemberRechargeLog.setReamk("会员现金充值" + money + "元,实际到账" + actualAmount
|
||||||
|
+ "元(含优惠" + bonusAmount + "元)");
|
||||||
|
} else {
|
||||||
|
userMemberRechargeLog.setReamk("会员现金充值" + money + "元");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 保存充值记录并调用微信支付
|
||||||
|
if (userMemberRechargeLogService.insertUserMemberRechargeLog(userMemberRechargeLog) > 0) {
|
||||||
|
// 调用微信支付(测试环境使用0.01元)
|
||||||
|
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
|
||||||
|
user.getOpenid(),
|
||||||
|
userMemberRechargeLog.getId().toString(),
|
||||||
|
new BigDecimal("0.01"), // 测试金额
|
||||||
|
1,
|
||||||
|
wechatPayUtil.PAY_FH + "api/recharge/pay/notify");
|
||||||
|
|
||||||
|
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
|
||||||
|
// 构建支付响应数据
|
||||||
|
Map<String, Object> responseData = new HashMap<>();
|
||||||
|
responseData.put("mainOrderId", userMemberRechargeLog.getId().toString());
|
||||||
|
responseData.put("totalAmount", money);
|
||||||
|
responseData.put("prepayId", payResult.get("prepayId"));
|
||||||
|
// 合并所有支付参数
|
||||||
|
responseData.putAll(payResult);
|
||||||
|
return AppletControllerUtil.appletSuccess(responseData);
|
||||||
|
} else {
|
||||||
|
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
|
||||||
|
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletWarning("支付失败");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("会员充值支付异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("充值支付失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取充值类目列表
|
||||||
|
*
|
||||||
|
* 查询状态为0(启用)且类型为0(普通充值)的充值套餐
|
||||||
|
* 用于用户选择充值项目
|
||||||
|
*
|
||||||
|
* @return 充值类目列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/member/recharge/catalogue")
|
||||||
|
public AjaxResult getRechargeCatalogue() {
|
||||||
|
try {
|
||||||
|
UserMemberRechargeProgram query = new UserMemberRechargeProgram();
|
||||||
|
query.setStatus(0); // 0=启用状态
|
||||||
|
query.setType(0); // 0=普通充值类型
|
||||||
|
|
||||||
|
List<UserMemberRechargeProgram> list = userMemberRechargeProgramService
|
||||||
|
.selectUserMemberRechargeProgramList(query);
|
||||||
|
return AppletControllerUtil.appletSuccess(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取充值类目失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取包年充值项目列表
|
||||||
|
*
|
||||||
|
* 根据类型ID查询对应的包年充值项目
|
||||||
|
* 用于会员包年充值功能
|
||||||
|
*
|
||||||
|
* @param id 充值类型ID
|
||||||
|
* @return 包年充值项目列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/member/recharge/catal/{id}")
|
||||||
|
public AjaxResult getRechargeCatalyear(@PathVariable("id") int id) {
|
||||||
|
try {
|
||||||
|
UserMemberRechargeProgram query = new UserMemberRechargeProgram();
|
||||||
|
query.setStatus(0); // 0=启用状态
|
||||||
|
query.setType(id); // 指定类型
|
||||||
|
|
||||||
|
List<UserMemberRechargeProgram> list = userMemberRechargeProgramService
|
||||||
|
.selectUserMemberRechargeProgramList(query);
|
||||||
|
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
return AppletControllerUtil.appletSuccess(list);
|
||||||
|
} else {
|
||||||
|
return AppletControllerUtil.appletWarning("暂无数据");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取充值类目失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 余额支付相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额支付测试接口
|
||||||
|
*
|
||||||
|
* 测试用户余额支付功能
|
||||||
|
* 模拟购买99.99元商品的余额支付流程
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 支付结果
|
||||||
|
*/
|
||||||
|
@GetMapping("/balance/payment")
|
||||||
|
public AjaxResult apibalancepayment(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户未登录或token无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 调用余额支付工具类
|
||||||
|
Map<String, Object> rmap = BalancePayUtil.processBalancePayment(
|
||||||
|
user.getId(),
|
||||||
|
new BigDecimal("99.99"),
|
||||||
|
"购买一般商品单价99.99");
|
||||||
|
return AppletControllerUtil.appletSuccess(rmap.get("message"));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("余额支付异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("余额支付失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 记录查询相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户充值记录列表
|
||||||
|
*
|
||||||
|
* 查询当前用户的所有充值记录
|
||||||
|
* 按时间倒序排列
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 用户充值记录列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/member/recharge/log")
|
||||||
|
public AjaxResult getRechargelog(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户未登录或token无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询充值记录
|
||||||
|
UserMemberRechargeLog query = new UserMemberRechargeLog();
|
||||||
|
query.setUid(Math.toIntExact(user.getId()));
|
||||||
|
|
||||||
|
List<UserMemberRechargeLog> list = userMemberRechargeLogService
|
||||||
|
.selectUserMemberRechargeLogList(query);
|
||||||
|
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
return AppletControllerUtil.appletSuccess(list);
|
||||||
|
} else {
|
||||||
|
return AppletControllerUtil.appletWarning("暂无数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取数据失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户消费记录
|
||||||
|
*
|
||||||
|
* 查询当前用户的消费记录
|
||||||
|
* 注意:这里只返回第一条记录(可能是设计问题,建议返回完整列表)
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 用户消费记录
|
||||||
|
*/
|
||||||
|
@GetMapping("/member/consumption/log")
|
||||||
|
public AjaxResult getconsumptionlog(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户未登录或token无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询消费记录
|
||||||
|
UserMemnerConsumptionLog query = new UserMemnerConsumptionLog();
|
||||||
|
query.setUid(Math.toIntExact(user.getId()));
|
||||||
|
|
||||||
|
List<UserMemnerConsumptionLog> list = userMemnerConsumptionLogService
|
||||||
|
.selectUserMemnerConsumptionLogList(query);
|
||||||
|
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
// 注意:这里只返回第一条记录,可能需要根据业务需求调整
|
||||||
|
return AppletControllerUtil.appletSuccess(list.getFirst());
|
||||||
|
} else {
|
||||||
|
return AppletControllerUtil.appletWarning("暂无数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AppletControllerUtil.appletError("获取消费记录失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 订单评价相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务订单评价接口
|
||||||
|
*
|
||||||
|
* 用户对已完成的服务订单进行评价
|
||||||
|
* 包括评分、评价内容、图片、标签等
|
||||||
|
*
|
||||||
|
* 业务逻辑:
|
||||||
|
* 1. 验证用户登录状态
|
||||||
|
* 2. 检查订单是否存在且属于当前用户
|
||||||
|
* 3. 检查是否已经评价过(防止重复评价)
|
||||||
|
* 4. 保存评价信息
|
||||||
|
* 5. 添加订单日志
|
||||||
|
* 6. 更新订单状态为已完成
|
||||||
|
*
|
||||||
|
* @param params 评价参数(order_id, content, num, images, labels)
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 评价结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/service/order/comment")
|
||||||
|
public AjaxResult serviceOrderComment(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户未登录或token无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 参数验证
|
||||||
|
if (!params.containsKey("order_id") || !params.containsKey("content") || !params.containsKey("num")) {
|
||||||
|
return AppletControllerUtil.appletWarning("参数错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
String orderId = params.get("order_id").toString();
|
||||||
|
String content = params.get("content").toString();
|
||||||
|
Integer num = Integer.parseInt(params.get("num").toString());
|
||||||
|
|
||||||
|
// 4. 获取订单信息并验证
|
||||||
|
Order order = orderService.selectOrderByOrderId(orderId);
|
||||||
|
if (order == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("订单不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 检查是否已经评价过
|
||||||
|
int count = orderCommentService.selectCountOrderCommentByOid(order.getId());
|
||||||
|
if (count > 0) {
|
||||||
|
return AppletControllerUtil.appletWarning("请勿重复提交");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 计算评分类型
|
||||||
|
Integer numType;
|
||||||
|
if (num == 1) {
|
||||||
|
numType = 3; // 差评
|
||||||
|
} else if (num == 2 || num == 3) {
|
||||||
|
numType = 2; // 中评
|
||||||
|
} else {
|
||||||
|
numType = 1; // 好评
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 构建评价数据
|
||||||
|
OrderComment comment = new OrderComment();
|
||||||
|
comment.setOid(order.getId());
|
||||||
|
comment.setOrderId(orderId);
|
||||||
|
comment.setProductId(order.getProductId());
|
||||||
|
comment.setContent(content);
|
||||||
|
comment.setNum(Long.valueOf(num));
|
||||||
|
comment.setNumType(Long.valueOf(numType));
|
||||||
|
comment.setUid(user.getId());
|
||||||
|
comment.setWorkerId(order.getWorkerId());
|
||||||
|
|
||||||
|
// 8. 处理图片附件
|
||||||
|
if (params.containsKey("images") && params.get("images") != null) {
|
||||||
|
String images = JSON.toJSONString(params.get("images"));
|
||||||
|
comment.setImages(images);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 处理评价标签
|
||||||
|
if (params.containsKey("labels") && params.get("labels") != null) {
|
||||||
|
String labels = JSON.toJSONString(params.get("labels"));
|
||||||
|
comment.setLabels(labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. 保存评价并更新订单状态
|
||||||
|
// 保存评价
|
||||||
|
orderCommentService.insertOrderComment(comment);
|
||||||
|
|
||||||
|
// 添加订单日志
|
||||||
|
OrderLog orderLog = new OrderLog();
|
||||||
|
orderLog.setOid(order.getId());
|
||||||
|
orderLog.setOrderId(orderId);
|
||||||
|
orderLog.setTitle("订单评价");
|
||||||
|
orderLog.setType(BigDecimal.valueOf(8)); // 8=评价类型
|
||||||
|
|
||||||
|
Map<String, Object> logContent = new HashMap<>();
|
||||||
|
logContent.put("text", content);
|
||||||
|
logContent.put("image", params.get("images"));
|
||||||
|
logContent.put("num", num);
|
||||||
|
orderLog.setContent(JSON.toJSONString(logContent));
|
||||||
|
|
||||||
|
orderLogService.insertOrderLog(orderLog);
|
||||||
|
|
||||||
|
// 更新订单状态
|
||||||
|
order.setStatus(4L); // 4=完成状态
|
||||||
|
order.setIsComment(1); // 1=已评价
|
||||||
|
orderService.updateOrder(order);
|
||||||
|
|
||||||
|
return AjaxResult.success("评价提交成功");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("服务订单评价异常:" + e.getMessage());
|
||||||
|
return AjaxResult.error("评价提交失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 用户验证相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户是否使用默认头像和昵称
|
||||||
|
*
|
||||||
|
* 验证用户是否还在使用系统默认的头像和昵称
|
||||||
|
* 如果是默认的,提示用户修改
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 验证结果
|
||||||
|
*/
|
||||||
|
@GetMapping("/user/check/default")
|
||||||
|
public AjaxResult checkUserDefault(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证图像和昵称是否为系统默认
|
||||||
|
String defaultAvatar = "https://img.huafurenjia.cn/default/user_avatar.jpeg";
|
||||||
|
String defaultName = "微信用户";
|
||||||
|
|
||||||
|
if (defaultAvatar.equals(user.getAvatar()) && defaultName.equals(user.getName())) {
|
||||||
|
return AppletControllerUtil.appletWarning("请修改您的图像和昵称");
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess("校验通过");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("验证用户图像和昵称异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("验证失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 分类和次卡相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取二级分类列表
|
||||||
|
*
|
||||||
|
* 查询所有的服务分类信息
|
||||||
|
* 用于前端分类展示
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 分类列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/secondary/classification")
|
||||||
|
public AjaxResult classification(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
List<ServiceCate> list = serviceCateService.selectServiceCateCiKaList();
|
||||||
|
return AppletControllerUtil.appletSuccess(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("获取二级分类异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("获取分类失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取次卡列表(支持分页)
|
||||||
|
*
|
||||||
|
* 查询用户次卡列表,支持按类型筛选和分页
|
||||||
|
* 每个次卡会包含对应的服务商品详情
|
||||||
|
*
|
||||||
|
* @param params 查询参数(page, limit, type)
|
||||||
|
* @param request HTTP请求对象
|
||||||
|
* @return 次卡列表(分页格式)
|
||||||
|
*/
|
||||||
|
@PostMapping("/secondary/card/list")
|
||||||
|
public AjaxResult getSecondaryCardList(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 获取并验证分页参数
|
||||||
|
int page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
|
||||||
|
int limit = params.get("limit") != null ? Integer.parseInt(params.get("limit").toString()) : 15;
|
||||||
|
|
||||||
|
Map<String, Object> pageValidation = PageUtil.validatePageParams(page, limit);
|
||||||
|
if (!(Boolean) pageValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning((String) pageValidation.get("message"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取type参数
|
||||||
|
Long type = params.get("type") != null ? Long.parseLong(params.get("type").toString()) : null;
|
||||||
|
|
||||||
|
// 3. 创建查询对象
|
||||||
|
UserSecondaryCard queryParams = new UserSecondaryCard();
|
||||||
|
queryParams.setStatus(1L); // 只查询状态为1的数据
|
||||||
|
if (type != null) {
|
||||||
|
queryParams.setType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 设置分页参数
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
|
||||||
|
// 5. 执行查询
|
||||||
|
List<UserSecondaryCard> list = userSecondaryCardService.selectUserSecondaryCardList(queryParams);
|
||||||
|
|
||||||
|
// 6. 为每个次卡填充服务商品详情
|
||||||
|
for (UserSecondaryCard card : list) {
|
||||||
|
List<String> idsList = com.alibaba.fastjson2.JSONArray.parseArray(card.getGoodsids(), String.class);
|
||||||
|
card.setServiceDetail(serviceGoodsService.selectServiceGoodsfrocikaList(idsList));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 获取分页信息并构建响应
|
||||||
|
TableDataInfo tableDataInfo = getDataTable(list);
|
||||||
|
Map<String, Object> pageData = PageUtil.buildPageResponse(tableDataInfo, page, limit);
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(pageData);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("查询次卡列表异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("获取次卡列表失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 师傅报价相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 师傅报价接口
|
||||||
|
*
|
||||||
|
* 师傅对用户发布的需求订单进行报价
|
||||||
|
* 支持新增报价和更新已有报价
|
||||||
|
*
|
||||||
|
* 业务逻辑:
|
||||||
|
* 1. 验证师傅登录状态
|
||||||
|
* 2. 验证订单是否存在
|
||||||
|
* 3. 检查是否已经报过价
|
||||||
|
* 4. 如果已报价则更新,否则新增报价记录
|
||||||
|
*
|
||||||
|
* @param params 报价参数(orderid, money)
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 报价结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/worker/quote/price")
|
||||||
|
public AjaxResult workerQuotePrice(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户未登录或token无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证必要参数
|
||||||
|
if (params == null || params.get("orderid") == null || params.get("money") == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("订单ID和报价金额不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 获取参数
|
||||||
|
String orderId = params.get("orderid").toString();
|
||||||
|
BigDecimal quoteMoney = new BigDecimal(params.get("money").toString());
|
||||||
|
|
||||||
|
// 5. 查询订单是否存在
|
||||||
|
Order order = orderService.selectOrderByOrderId(orderId);
|
||||||
|
if (order == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("订单不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 查询用户是否已对该订单报过价
|
||||||
|
UserDemandQuotation queryParams = new UserDemandQuotation();
|
||||||
|
queryParams.setWorkerid(user.getId());
|
||||||
|
queryParams.setOrderid(orderId);
|
||||||
|
List<UserDemandQuotation> existingQuotes = userDemandQuotationService
|
||||||
|
.selectUserDemandQuotationList(queryParams);
|
||||||
|
|
||||||
|
// 7. 处理报价
|
||||||
|
UserDemandQuotation quoteRecord;
|
||||||
|
if (existingQuotes != null && !existingQuotes.isEmpty()) {
|
||||||
|
// 已有报价,更新
|
||||||
|
quoteRecord = existingQuotes.getFirst();
|
||||||
|
quoteRecord.setMoney(quoteMoney);
|
||||||
|
quoteRecord.setQuotationTime(new Date());
|
||||||
|
quoteRecord.setUpdateTime(new Date());
|
||||||
|
userDemandQuotationService.updateUserDemandQuotation(quoteRecord);
|
||||||
|
} else {
|
||||||
|
// 新增报价
|
||||||
|
quoteRecord = new UserDemandQuotation();
|
||||||
|
quoteRecord.setWorkerid(user.getId());
|
||||||
|
quoteRecord.setOrderid(orderId);
|
||||||
|
quoteRecord.setMoney(quoteMoney);
|
||||||
|
quoteRecord.setQuotationTime(new Date());
|
||||||
|
quoteRecord.setStatus(1L); // 设置状态为有效
|
||||||
|
quoteRecord.setWorkername(user.getName());
|
||||||
|
quoteRecord.setWorkerimage(user.getAvatar());
|
||||||
|
quoteRecord.setCreateTime(new Date());
|
||||||
|
userDemandQuotationService.insertUserDemandQuotation(quoteRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess("报价成功");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("师傅报价异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("报价失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 拼团支付相关接口 ====================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== 用户权益相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户服务金/消费金日志(支持分页)
|
||||||
|
*
|
||||||
|
* 查询用户的服务金或消费金变动日志
|
||||||
|
* 支持分页查询,按时间倒序排列
|
||||||
|
*
|
||||||
|
* @param type 日志类型(1=服务金,2=消费金)
|
||||||
|
* @param limit 每页条数(默认10)
|
||||||
|
* @param page 页码(默认1)
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @return 权益日志列表(分页格式)
|
||||||
|
*/
|
||||||
|
@GetMapping("/user/benefit/log")
|
||||||
|
public AjaxResult getUserBenefitLog(
|
||||||
|
@RequestParam(value = "type") Integer type,
|
||||||
|
@RequestParam(value = "limit", defaultValue = "10") int limit,
|
||||||
|
@RequestParam(value = "page", defaultValue = "1") int page,
|
||||||
|
HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
// 1. 验证分页参数
|
||||||
|
Map<String, Object> pageValidation = PageUtil.validatePageParams(page, limit);
|
||||||
|
if (!(Boolean) pageValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletWarning((String) pageValidation.get("message"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证用户登录状态
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
||||||
|
if (!(Boolean) userValidation.get("valid")) {
|
||||||
|
return AppletControllerUtil.appletUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取用户信息
|
||||||
|
Users user = (Users) userValidation.get("user");
|
||||||
|
if (user == null) {
|
||||||
|
return AppletControllerUtil.appletWarning("用户信息获取失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 设置分页参数
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
|
||||||
|
// 5. 查询服务金/消费金日志
|
||||||
|
UserBenefitPoints query = new UserBenefitPoints();
|
||||||
|
query.setUid(user.getId());
|
||||||
|
query.setType(Long.valueOf(type));
|
||||||
|
List<UserBenefitPoints> logList = userBenefitPointsService.selectUserBenefitPointsList(query);
|
||||||
|
|
||||||
|
// 6. 获取分页信息并构建响应
|
||||||
|
TableDataInfo tableDataInfo = getDataTable(logList);
|
||||||
|
Map<String, Object> pageData = PageUtil.buildPageResponse(tableDataInfo, page, limit);
|
||||||
|
|
||||||
|
return AppletControllerUtil.appletSuccess(pageData);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("查询用户服务金/消费金日志异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("查询服务金/消费金日志失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序用户余额日志查询接口
|
||||||
|
*
|
||||||
|
* 查询用户的余额变动日志
|
||||||
|
* 调用工具类方法统一处理
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象(需要包含token)
|
||||||
|
* @param params 查询参数
|
||||||
|
* @return 余额日志列表
|
||||||
|
*/
|
||||||
|
@PostMapping("/user/balance/logs")
|
||||||
|
public AjaxResult getBalanceLogList(HttpServletRequest request, @RequestBody Map<String, Object> params) {
|
||||||
|
try {
|
||||||
|
// 从请求头获取token
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
|
||||||
|
// 调用工具类方法统一处理
|
||||||
|
return AppletControllerUtil.getUserBalanceLogList(params, token, usersService, userMemnerConsumptionLogService);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("查询用户余额日志异常:" + e.getMessage());
|
||||||
|
return AppletControllerUtil.appletError("查询余额日志失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,164 +0,0 @@
|
||||||
package com.ruoyi.system.controller;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
|
||||||
import com.ruoyi.system.ControllerUtil.*;
|
|
||||||
import com.ruoyi.system.domain.*;
|
|
||||||
import com.ruoyi.system.service.*;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 游标工具控制器
|
|
||||||
*
|
|
||||||
* @author Mr. Zhang Pan
|
|
||||||
* @version 1.0
|
|
||||||
* @date 2025-01-10
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class CursorUtil extends BaseController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IServiceGoodsService serviceGoodsService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IGoodsOrderCursorService goodsOrderCursorService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IUsersService usersService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IUserAddressService userAddressService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IGoodsOrderService goodsOrderService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WechatPayUtil wechatPayUtil;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IOrderService orderService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IOrderLogService orderLogService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IOrderCommentService orderCommentService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IUsersInvoiceInfoService usersInvoiceInfoService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序接口:维护用户发票信息(新增/修改)
|
|
||||||
* POST /api/user/invoice/info
|
|
||||||
* @param params 发票信息参数
|
|
||||||
* @param request 请求对象
|
|
||||||
* @return AjaxResult
|
|
||||||
*/
|
|
||||||
@PostMapping("/api/user/invoicedata/info")
|
|
||||||
public AjaxResult saveOrUpdateInvoiceInfo(@RequestBody Map<String, Object> params, HttpServletRequest request) {
|
|
||||||
// 1. 校验用户登录
|
|
||||||
String token = request.getHeader("token");
|
|
||||||
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
|
||||||
if (!(Boolean) userValidation.get("valid")) {
|
|
||||||
return AjaxResult.error("用户未登录或token无效");
|
|
||||||
}
|
|
||||||
Users user = (Users) userValidation.get("user");
|
|
||||||
if (user == null) {
|
|
||||||
return AjaxResult.error("用户信息获取失败");
|
|
||||||
}
|
|
||||||
// 2. 构建发票对象
|
|
||||||
UsersInvoiceInfo invoiceInfo = new UsersInvoiceInfo();
|
|
||||||
invoiceInfo.setId(params.get("id") != null ? Integer.valueOf(params.get("id").toString()) : null);
|
|
||||||
invoiceInfo.setUid(user.getId() != null ? user.getId().intValue() : null);
|
|
||||||
invoiceInfo.setInvoiceTitle((String) params.get("invoiceTitle"));
|
|
||||||
invoiceInfo.setTaxNumber((String) params.get("taxNumber"));
|
|
||||||
invoiceInfo.setBankName((String) params.get("bankName"));
|
|
||||||
invoiceInfo.setBankAccount((String) params.get("bankAccount"));
|
|
||||||
invoiceInfo.setAddress((String) params.get("address"));
|
|
||||||
invoiceInfo.setPhone((String) params.get("phone"));
|
|
||||||
invoiceInfo.setEmail((String) params.get("email"));
|
|
||||||
invoiceInfo.setWechat((String) params.get("wechat"));
|
|
||||||
invoiceInfo.setType(params.get("type") != null ? Integer.valueOf(params.get("type").toString()) : 1);
|
|
||||||
invoiceInfo.setCategory(params.get("category") != null ? Integer.valueOf(params.get("category").toString()) : 1);
|
|
||||||
// 3. 保存或更新
|
|
||||||
try {
|
|
||||||
if (invoiceInfo.getId() != null) {
|
|
||||||
usersInvoiceInfoService.updateUsersInvoiceInfo(invoiceInfo);
|
|
||||||
} else {
|
|
||||||
usersInvoiceInfoService.insertUsersInvoiceInfo(invoiceInfo);
|
|
||||||
}
|
|
||||||
return AjaxResult.success("发票信息保存成功");
|
|
||||||
} catch (Exception e) {
|
|
||||||
return AjaxResult.error("发票信息保存失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序接口:查询当前用户所有发票信息
|
|
||||||
* GET /api/user/invoice/list
|
|
||||||
* @param request 请求对象
|
|
||||||
* @return AjaxResult
|
|
||||||
*/
|
|
||||||
@GetMapping("/api/user/invoicedata/list")
|
|
||||||
public AjaxResult getInvoicelist(HttpServletRequest request) {
|
|
||||||
// 1. 校验用户登录
|
|
||||||
String token = request.getHeader("token");
|
|
||||||
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
|
||||||
if (!(Boolean) userValidation.get("valid")) {
|
|
||||||
return AjaxResult.error("用户未登录或token无效");
|
|
||||||
}
|
|
||||||
Users user = (Users) userValidation.get("user");
|
|
||||||
if (user == null) {
|
|
||||||
return AjaxResult.error("用户信息获取失败");
|
|
||||||
}
|
|
||||||
UsersInvoiceInfo invoiceInfo = new UsersInvoiceInfo();
|
|
||||||
invoiceInfo.setUid(user.getId() != null ? user.getId().intValue() : null);
|
|
||||||
// 2. 查询所有发票信息
|
|
||||||
List<UsersInvoiceInfo> list = usersInvoiceInfoService.selectUsersInvoiceInfoList(invoiceInfo);
|
|
||||||
return AjaxResult.success(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序接口:删除用户单个发票信息
|
|
||||||
* DELETE /api/user/invoice/delete/{id}
|
|
||||||
* @param id 发票ID
|
|
||||||
* @param request 请求对象
|
|
||||||
* @return AjaxResult
|
|
||||||
*/
|
|
||||||
@DeleteMapping("/api/user/invoicedata/delete/{id}")
|
|
||||||
public AjaxResult deleteInvoiceInfo(@PathVariable Integer id, HttpServletRequest request) {
|
|
||||||
// 1. 校验用户登录
|
|
||||||
String token = request.getHeader("token");
|
|
||||||
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
|
|
||||||
if (!(Boolean) userValidation.get("valid")) {
|
|
||||||
return AjaxResult.error("用户未登录或token无效");
|
|
||||||
}
|
|
||||||
Users user = (Users) userValidation.get("user");
|
|
||||||
if (user == null) {
|
|
||||||
return AjaxResult.error("用户信息获取失败");
|
|
||||||
}
|
|
||||||
// 2. 删除发票(需校验归属)
|
|
||||||
try {
|
|
||||||
int result = usersInvoiceInfoService.deleteUsersInvoiceInfoById(id);
|
|
||||||
if (result > 0) {
|
|
||||||
return AjaxResult.success("删除成功");
|
|
||||||
} else {
|
|
||||||
return AjaxResult.error("删除失败或无权限");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return AjaxResult.error("删除异常: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -300,6 +300,18 @@ public class PayNotifyController extends BaseController {
|
||||||
userMemberRechargeLog.setPaytype(1);
|
userMemberRechargeLog.setPaytype(1);
|
||||||
userMemberRechargeLog.setTransactionId(transactionId);
|
userMemberRechargeLog.setTransactionId(transactionId);
|
||||||
userMemberRechargeLogService.updateUserMemberRechargeLog(userMemberRechargeLog);
|
userMemberRechargeLogService.updateUserMemberRechargeLog(userMemberRechargeLog);
|
||||||
|
//成功之后就要给大哥加流水,确保大哥的账户流水里面有这条充值的记录,如果购买了会员下一步扣除就可以
|
||||||
|
UserMemnerConsumptionLog newuserMemnerConsumptionLog = new UserMemnerConsumptionLog();
|
||||||
|
newuserMemnerConsumptionLog.setUid(Math.toIntExact(users.getId()));
|
||||||
|
newuserMemnerConsumptionLog.setConsumptiontype(3);
|
||||||
|
newuserMemnerConsumptionLog.setConsumptiontime(new Date());
|
||||||
|
newuserMemnerConsumptionLog.setConsumptionmoney(userMemberRechargeLog.getComemoney());
|
||||||
|
newuserMemnerConsumptionLog.setReamk("用户充值"+userMemberRechargeLog.getInmoney()+"实际到账"+userMemberRechargeLog.getComemoney());
|
||||||
|
newuserMemnerConsumptionLog.setBeformoney(users.getBalance());
|
||||||
|
newuserMemnerConsumptionLog.setAftermoney(users.getBalance().add(userMemberRechargeLog.getComemoney()));
|
||||||
|
newuserMemnerConsumptionLog.setNowmoney(users.getBalance().add(userMemberRechargeLog.getComemoney()));
|
||||||
|
newuserMemnerConsumptionLog.setType(1);
|
||||||
|
userMemnerConsumptionLogService.insertUserMemnerConsumptionLog(newuserMemnerConsumptionLog);
|
||||||
users.setBalance(users.getBalance().add(userMemberRechargeLog.getComemoney()));
|
users.setBalance(users.getBalance().add(userMemberRechargeLog.getComemoney()));
|
||||||
usersService.updateUsers(users);
|
usersService.updateUsers(users);
|
||||||
WXsendMsgUtil.sendUserPayMoney(users.getOpenid(),"充值成功",totalFee,"1","充值成功");
|
WXsendMsgUtil.sendUserPayMoney(users.getOpenid(),"充值成功",totalFee,"1","充值成功");
|
||||||
|
|
@ -310,10 +322,11 @@ public class PayNotifyController extends BaseController {
|
||||||
userMemnerConsumptionLog.setConsumptiontype(2);
|
userMemnerConsumptionLog.setConsumptiontype(2);
|
||||||
userMemnerConsumptionLog.setConsumptiontime(new Date());
|
userMemnerConsumptionLog.setConsumptiontime(new Date());
|
||||||
userMemnerConsumptionLog.setConsumptionmoney(userMemberRechargeLog.getComemoney());
|
userMemnerConsumptionLog.setConsumptionmoney(userMemberRechargeLog.getComemoney());
|
||||||
userMemnerConsumptionLog.setReamk("会员包年充值");
|
userMemnerConsumptionLog.setReamk("会员包年扣减");
|
||||||
userMemnerConsumptionLog.setBeformoney(users.getBalance());
|
userMemnerConsumptionLog.setBeformoney(users.getBalance());
|
||||||
userMemnerConsumptionLog.setAftermoney(users.getBalance().subtract(userMemberRechargeLog.getComemoney()));
|
userMemnerConsumptionLog.setAftermoney(users.getBalance().subtract(userMemberRechargeLog.getComemoney()));
|
||||||
userMemnerConsumptionLog.setNowmoney(users.getBalance().subtract(userMemberRechargeLog.getComemoney()));
|
userMemnerConsumptionLog.setNowmoney(users.getBalance().subtract(userMemberRechargeLog.getComemoney()));
|
||||||
|
userMemnerConsumptionLog.setType(2);
|
||||||
userMemnerConsumptionLogService.insertUserMemnerConsumptionLog(userMemnerConsumptionLog);
|
userMemnerConsumptionLogService.insertUserMemnerConsumptionLog(userMemnerConsumptionLog);
|
||||||
users.setBalance(users.getBalance().subtract(userMemberRechargeLog.getComemoney()));
|
users.setBalance(users.getBalance().subtract(userMemberRechargeLog.getComemoney()));
|
||||||
users.setIsmember(1);
|
users.setIsmember(1);
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,30 @@ import com.ruoyi.system.domain.Users;
|
||||||
import com.ruoyi.system.domain.UserMemnerConsumptionLog;
|
import com.ruoyi.system.domain.UserMemnerConsumptionLog;
|
||||||
import com.ruoyi.system.service.IUserMemnerConsumptionLogService;
|
import com.ruoyi.system.service.IUserMemnerConsumptionLogService;
|
||||||
import com.ruoyi.system.service.IUsersService;
|
import com.ruoyi.system.service.IUsersService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 余额支付工具类
|
* 余额支付工具类
|
||||||
*
|
*
|
||||||
* @author
|
* @author ruoyi
|
||||||
|
* @date 2025-01-26
|
||||||
*/
|
*/
|
||||||
public class BalancePayUtil {
|
public class BalancePayUtil {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(BalancePayUtil.class);
|
||||||
|
|
||||||
private static final IUserMemnerConsumptionLogService userMemnerConsumptionLogService = SpringUtils.getBean(IUserMemnerConsumptionLogService.class);
|
private static final IUserMemnerConsumptionLogService userMemnerConsumptionLogService = SpringUtils.getBean(IUserMemnerConsumptionLogService.class);
|
||||||
|
|
||||||
private static final IUsersService usersService = SpringUtils.getBean(IUsersService.class);
|
private static final IUsersService usersService = SpringUtils.getBean(IUsersService.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户余额支付
|
* 用户余额支付(原有方法保持不变)
|
||||||
* @param user 用户对象
|
* @param user 用户对象
|
||||||
* @param amount 支付金额
|
* @param amount 支付金额
|
||||||
* @return AjaxResult 支付结果
|
* @return AjaxResult 支付结果
|
||||||
|
|
@ -57,14 +65,212 @@ public class BalancePayUtil {
|
||||||
log.setBeformoney(beforeBalance);
|
log.setBeformoney(beforeBalance);
|
||||||
log.setAftermoney(user.getBalance());
|
log.setAftermoney(user.getBalance());
|
||||||
log.setNowmoney(user.getBalance());
|
log.setNowmoney(user.getBalance());
|
||||||
|
log.setType(2); // 2=支出
|
||||||
userMemnerConsumptionLogService.insertUserMemnerConsumptionLog(log);
|
userMemnerConsumptionLogService.insertUserMemnerConsumptionLog(log);
|
||||||
// 推送支付成功消息
|
// 推送支付成功消息
|
||||||
try {
|
try {
|
||||||
WXsendMsgUtil.sendUserPayMoney(user.getOpenid(), "余额支付成功", amount.toString(), "1", "余额支付成功");
|
WXsendMsgUtil.sendUserPayMoney(user.getOpenid(), "余额支付成功", amount.toString(), "1", "余额支付成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 推送失败不影响主流程
|
// 推送失败不影响主流程
|
||||||
System.err.println("余额支付消息推送失败: " + e.getMessage());
|
logger.warn("余额支付消息推送失败: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
return AjaxResult.success("余额支付成功");
|
return AjaxResult.success("余额支付成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户余额支付(增强版)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param money 支付金额
|
||||||
|
* @param remark 支付备注
|
||||||
|
* @return Map<String, Object> 支付结果
|
||||||
|
*
|
||||||
|
* 返回结果说明:
|
||||||
|
* - success: true/false 支付是否成功
|
||||||
|
* - message: 结果消息
|
||||||
|
* - insufficientAmount: 余额不足时,还差多少钱(仅在余额不足时返回)
|
||||||
|
* - beforeBalance: 支付前余额
|
||||||
|
* - afterBalance: 支付后余额
|
||||||
|
* - consumptionLogId: 消费记录ID
|
||||||
|
*/
|
||||||
|
public static Map<String, Object> processBalancePayment(Long userId, BigDecimal money, String remark) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 参数验证
|
||||||
|
if (userId == null || userId <= 0) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "用户ID无效");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (money == null || money.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "支付金额必须大于0");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remark == null || remark.trim().isEmpty()) {
|
||||||
|
remark = "余额支付";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = usersService.selectUsersById(userId);
|
||||||
|
if (user == null) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "用户不存在");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 检查用户余额
|
||||||
|
BigDecimal currentBalance = user.getBalance();
|
||||||
|
if (currentBalance == null) {
|
||||||
|
currentBalance = BigDecimal.ZERO;
|
||||||
|
user.setBalance(currentBalance);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("beforeBalance", currentBalance);
|
||||||
|
|
||||||
|
// 4. 判断余额是否足够
|
||||||
|
if (currentBalance.compareTo(money) < 0) {
|
||||||
|
// 余额不足,计算还差多少钱
|
||||||
|
BigDecimal insufficientAmount = money.subtract(currentBalance);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "余额不足");
|
||||||
|
result.put("insufficientAmount", insufficientAmount);
|
||||||
|
result.put("currentBalance", currentBalance);
|
||||||
|
result.put("requiredAmount", money);
|
||||||
|
|
||||||
|
logger.info("用户{}余额支付失败,余额不足。当前余额:{},需要支付:{},还差:{}",
|
||||||
|
userId, currentBalance, money, insufficientAmount);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 执行余额扣减
|
||||||
|
BigDecimal afterBalance = currentBalance.subtract(money);
|
||||||
|
user.setBalance(afterBalance);
|
||||||
|
|
||||||
|
int updateResult = usersService.updateUsers(user);
|
||||||
|
if (updateResult <= 0) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "余额扣减失败,请重试");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 记录消费流水
|
||||||
|
UserMemnerConsumptionLog consumptionLog = new UserMemnerConsumptionLog();
|
||||||
|
consumptionLog.setUid(Math.toIntExact(userId));
|
||||||
|
consumptionLog.setConsumptiontype(1); // 1=余额支付消费
|
||||||
|
consumptionLog.setConsumptiontime(new Date());
|
||||||
|
consumptionLog.setConsumptionmoney(money);
|
||||||
|
consumptionLog.setReamk(remark);
|
||||||
|
consumptionLog.setBeformoney(currentBalance);
|
||||||
|
consumptionLog.setAftermoney(afterBalance);
|
||||||
|
consumptionLog.setNowmoney(afterBalance);
|
||||||
|
consumptionLog.setType(2); // 2=支出
|
||||||
|
|
||||||
|
int logResult = userMemnerConsumptionLogService.insertUserMemnerConsumptionLog(consumptionLog);
|
||||||
|
|
||||||
|
// 7. 构建成功结果
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "余额支付成功");
|
||||||
|
result.put("afterBalance", afterBalance);
|
||||||
|
result.put("paymentAmount", money);
|
||||||
|
result.put("remark", remark);
|
||||||
|
|
||||||
|
if (logResult > 0) {
|
||||||
|
result.put("consumptionLogId", consumptionLog.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 发送支付成功通知(可选)
|
||||||
|
try {
|
||||||
|
if (user.getOpenid() != null && !user.getOpenid().trim().isEmpty()) {
|
||||||
|
WXsendMsgUtil.sendUserPayMoney(user.getOpenid(), "余额支付成功",
|
||||||
|
money.toString(), "1", remark);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("余额支付成功通知发送失败,用户ID:{},错误:{}", userId, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("用户{}余额支付成功,支付金额:{},支付前余额:{},支付后余额:{},备注:{}",
|
||||||
|
userId, money, currentBalance, afterBalance, remark);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("余额支付处理异常,用户ID:{},支付金额:{},备注:{}", userId, money, remark, e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "余额支付处理异常:" + e.getMessage());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户余额是否足够
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param requiredAmount 需要的金额
|
||||||
|
* @return Map<String, Object> 检查结果
|
||||||
|
*
|
||||||
|
* 返回结果说明:
|
||||||
|
* - sufficient: true/false 余额是否足够
|
||||||
|
* - currentBalance: 当前余额
|
||||||
|
* - requiredAmount: 需要的金额
|
||||||
|
* - insufficientAmount: 不足的金额(仅在余额不足时返回)
|
||||||
|
*/
|
||||||
|
public static Map<String, Object> checkBalanceSufficiency(Long userId, BigDecimal requiredAmount) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 参数验证
|
||||||
|
if (userId == null || userId <= 0) {
|
||||||
|
result.put("sufficient", false);
|
||||||
|
result.put("message", "用户ID无效");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredAmount == null || requiredAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
result.put("sufficient", false);
|
||||||
|
result.put("message", "检查金额必须大于0");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取用户信息
|
||||||
|
Users user = usersService.selectUsersById(userId);
|
||||||
|
if (user == null) {
|
||||||
|
result.put("sufficient", false);
|
||||||
|
result.put("message", "用户不存在");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 检查余额
|
||||||
|
BigDecimal currentBalance = user.getBalance();
|
||||||
|
if (currentBalance == null) {
|
||||||
|
currentBalance = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("currentBalance", currentBalance);
|
||||||
|
result.put("requiredAmount", requiredAmount);
|
||||||
|
|
||||||
|
if (currentBalance.compareTo(requiredAmount) >= 0) {
|
||||||
|
// 余额足够
|
||||||
|
result.put("sufficient", true);
|
||||||
|
result.put("message", "余额充足");
|
||||||
|
} else {
|
||||||
|
// 余额不足
|
||||||
|
BigDecimal insufficientAmount = requiredAmount.subtract(currentBalance);
|
||||||
|
result.put("sufficient", false);
|
||||||
|
result.put("message", "余额不足");
|
||||||
|
result.put("insufficientAmount", insufficientAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("检查余额充足性异常,用户ID:{},需要金额:{}", userId, requiredAmount, e);
|
||||||
|
result.put("sufficient", false);
|
||||||
|
result.put("message", "检查余额异常:" + e.getMessage());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,615 @@
|
||||||
|
package com.ruoyi.system.ControllerUtil;
|
||||||
|
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import com.ruoyi.system.domain.*;
|
||||||
|
import com.ruoyi.system.service.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发票工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2025-01-26
|
||||||
|
*/
|
||||||
|
public class InvoiceUtil {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(InvoiceUtil.class);
|
||||||
|
|
||||||
|
private static final IUsersInvoiceInfoService usersInvoiceInfoService = SpringUtils.getBean(IUsersInvoiceInfoService.class);
|
||||||
|
private static final IOrderService orderService = SpringUtils.getBean(IOrderService.class);
|
||||||
|
private static final IGoodsOrderService goodsOrderService = SpringUtils.getBean(IGoodsOrderService.class);
|
||||||
|
private static final IUserMemberRechargeLogService userMemberRechargeLogService = SpringUtils.getBean(IUserMemberRechargeLogService.class);
|
||||||
|
private static final IUsersService usersService = SpringUtils.getBean(IUsersService.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户发票中心数据
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param page 页码
|
||||||
|
* @param limit 每页数量
|
||||||
|
* @return 发票中心数据
|
||||||
|
*/
|
||||||
|
public static Map<String, Object> getUserInvoiceCenter(Long userId, int page, int limit) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
// 1. 获取待开票订单列表
|
||||||
|
List<Map<String, Object>> pendingInvoices = getPendingInvoiceOrders(userId, page, limit);
|
||||||
|
|
||||||
|
// 2. 获取已开票列表
|
||||||
|
List<Map<String, Object>> completedInvoices = getCompletedInvoices(userId, page, limit);
|
||||||
|
|
||||||
|
// 3. 统计数据
|
||||||
|
Map<String, Object> statistics = getInvoiceStatistics(userId);
|
||||||
|
|
||||||
|
result.put("pendingInvoices", pendingInvoices);
|
||||||
|
result.put("completedInvoices", completedInvoices);
|
||||||
|
result.put("statistics", statistics);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取用户发票中心数据失败", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待开票订单列表
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param page 页码
|
||||||
|
* @param limit 每页数量
|
||||||
|
* @return 待开票订单列表
|
||||||
|
*/
|
||||||
|
public static List<Map<String, Object>> getPendingInvoiceOrders(Long userId, int page, int limit) {
|
||||||
|
try {
|
||||||
|
List<Map<String, Object>> pendingOrders = new ArrayList<>();
|
||||||
|
|
||||||
|
// 设置分页
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
|
||||||
|
// 1. 查询服务订单(已完成且未开票)
|
||||||
|
Order orderQuery = new Order();
|
||||||
|
orderQuery.setUid(userId);
|
||||||
|
orderQuery.setStatus(4L); // 已完成状态
|
||||||
|
List<Order> serviceOrders = orderService.selectOrderList(orderQuery);
|
||||||
|
|
||||||
|
for (Order order : serviceOrders) {
|
||||||
|
// 检查是否已开票
|
||||||
|
if (!isOrderInvoiced(order.getOrderId())) {
|
||||||
|
Map<String, Object> orderMap = new HashMap<>();
|
||||||
|
orderMap.put("orderId", order.getOrderId());
|
||||||
|
orderMap.put("orderType", "service"); // 服务订单
|
||||||
|
orderMap.put("orderTypeText", "服务订单");
|
||||||
|
orderMap.put("amount", order.getTotalPrice());
|
||||||
|
orderMap.put("title", order.getOrderId()+ "服务订单");
|
||||||
|
orderMap.put("createTime", order.getCreateTime());
|
||||||
|
orderMap.put("canInvoice", true);
|
||||||
|
pendingOrders.add(orderMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查询商品订单(已完成且未开票)
|
||||||
|
GoodsOrder goodsOrderQuery = new GoodsOrder();
|
||||||
|
goodsOrderQuery.setUid(userId);
|
||||||
|
goodsOrderQuery.setStatus(4L); // 已完成状态
|
||||||
|
List<GoodsOrder> goodsOrders = goodsOrderService.selectGoodsOrderList(goodsOrderQuery);
|
||||||
|
|
||||||
|
for (GoodsOrder goodsOrder : goodsOrders) {
|
||||||
|
// 检查是否已开票
|
||||||
|
if (!isOrderInvoiced(goodsOrder.getOrderId())) {
|
||||||
|
Map<String, Object> orderMap = new HashMap<>();
|
||||||
|
orderMap.put("orderId", goodsOrder.getOrderId());
|
||||||
|
orderMap.put("orderType", "goods"); // 商品订单
|
||||||
|
orderMap.put("orderTypeText", "商品订单");
|
||||||
|
orderMap.put("amount", goodsOrder.getTotalPrice());
|
||||||
|
orderMap.put("title", "商品订单");
|
||||||
|
orderMap.put("createTime", goodsOrder.getCreateTime());
|
||||||
|
orderMap.put("canInvoice", true);
|
||||||
|
pendingOrders.add(orderMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询充值订单(已完成且未开票)
|
||||||
|
UserMemberRechargeLog rechargeQuery = new UserMemberRechargeLog();
|
||||||
|
rechargeQuery.setUid(Math.toIntExact(userId));
|
||||||
|
rechargeQuery.setPaytype(1); // 已完成状态
|
||||||
|
List<UserMemberRechargeLog> rechargeOrders = userMemberRechargeLogService.selectUserMemberRechargeLogList(rechargeQuery);
|
||||||
|
|
||||||
|
for (UserMemberRechargeLog recharge : rechargeOrders) {
|
||||||
|
// 检查是否已开票
|
||||||
|
if (!isOrderInvoiced(recharge.getOrderid())) {
|
||||||
|
Map<String, Object> orderMap = new HashMap<>();
|
||||||
|
orderMap.put("orderId", recharge.getOrderid());
|
||||||
|
orderMap.put("orderType", "recharge"); // 充值订单
|
||||||
|
orderMap.put("orderTypeText", "充值订单");
|
||||||
|
orderMap.put("amount", recharge.getInmoney());
|
||||||
|
orderMap.put("title", recharge.getReamk() != null ? recharge.getReamk() : "会员充值");
|
||||||
|
orderMap.put("createTime", recharge.getCreatedAt());
|
||||||
|
orderMap.put("canInvoice", true);
|
||||||
|
pendingOrders.add(orderMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 按创建时间倒序排列
|
||||||
|
// pendingOrders.sort((a, b) -> {
|
||||||
|
// Date timeA = (Date) a.get("createTime");
|
||||||
|
// Date timeB = (Date) b.get("createTime");
|
||||||
|
// return timeB.compareTo(timeA);
|
||||||
|
// });
|
||||||
|
|
||||||
|
return pendingOrders;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取待开票订单列表失败", e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已开票列表
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param page 页码
|
||||||
|
* @param limit 每页数量
|
||||||
|
* @return 已开票列表
|
||||||
|
*/
|
||||||
|
public static List<Map<String, Object>> getCompletedInvoices(Long userId, int page, int limit) {
|
||||||
|
try {
|
||||||
|
// 设置分页
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
|
||||||
|
UsersInvoiceInfo query = new UsersInvoiceInfo();
|
||||||
|
query.setUid(userId.intValue());
|
||||||
|
List<UsersInvoiceInfo> invoiceList = usersInvoiceInfoService.selectUsersInvoiceInfoList(query);
|
||||||
|
|
||||||
|
List<Map<String, Object>> completedInvoices = new ArrayList<>();
|
||||||
|
for (UsersInvoiceInfo invoice : invoiceList) {
|
||||||
|
Map<String, Object> invoiceMap = new HashMap<>();
|
||||||
|
invoiceMap.put("id", invoice.getId());
|
||||||
|
invoiceMap.put("orderId", invoice.getOrderid());
|
||||||
|
invoiceMap.put("invoiceTitle", invoice.getInvoiceTitle());
|
||||||
|
invoiceMap.put("amount", invoice.getInvoicemoney());
|
||||||
|
invoiceMap.put("invoiceText", invoice.getInvoicetext());
|
||||||
|
invoiceMap.put("status", invoice.getStatus());
|
||||||
|
invoiceMap.put("statusText", getInvoiceStatusText(invoice.getStatus()));
|
||||||
|
invoiceMap.put("type", invoice.getType());
|
||||||
|
invoiceMap.put("typeText", getInvoiceTypeText(invoice.getType()));
|
||||||
|
invoiceMap.put("category", invoice.getCategory());
|
||||||
|
invoiceMap.put("categoryText", invoice.getCategory() == 0 ? "个人" : "企业");
|
||||||
|
invoiceMap.put("createTime", invoice.getCreatedAt());
|
||||||
|
invoiceMap.put("hasFile", StringUtils.isNotEmpty(invoice.getFiledata()));
|
||||||
|
invoiceMap.put("fileUrl", invoice.getFiledata());
|
||||||
|
completedInvoices.add(invoiceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return completedInvoices;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取已开票列表失败", e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取发票统计数据
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 统计数据
|
||||||
|
*/
|
||||||
|
public static Map<String, Object> getInvoiceStatistics(Long userId) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> statistics = new HashMap<>();
|
||||||
|
|
||||||
|
// 待开票数量
|
||||||
|
List<Map<String, Object>> pendingOrders = getPendingInvoiceOrders(userId, 1, 1000);
|
||||||
|
int pendingCount = pendingOrders.size();
|
||||||
|
|
||||||
|
// 已开票数量
|
||||||
|
UsersInvoiceInfo query = new UsersInvoiceInfo();
|
||||||
|
query.setUid(userId.intValue());
|
||||||
|
List<UsersInvoiceInfo> invoiceList = usersInvoiceInfoService.selectUsersInvoiceInfoList(query);
|
||||||
|
int completedCount = invoiceList.size();
|
||||||
|
|
||||||
|
// 已开票总金额
|
||||||
|
BigDecimal totalAmount = invoiceList.stream()
|
||||||
|
.filter(invoice -> invoice.getInvoicemoney() != null)
|
||||||
|
.map(UsersInvoiceInfo::getInvoicemoney)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
|
statistics.put("pendingCount", pendingCount);
|
||||||
|
statistics.put("completedCount", completedCount);
|
||||||
|
statistics.put("totalAmount", totalAmount);
|
||||||
|
|
||||||
|
return statistics;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取发票统计数据失败", e);
|
||||||
|
Map<String, Object> statistics = new HashMap<>();
|
||||||
|
statistics.put("pendingCount", 0);
|
||||||
|
statistics.put("completedCount", 0);
|
||||||
|
statistics.put("totalAmount", BigDecimal.ZERO);
|
||||||
|
return statistics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量开具发票
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param orderIds 订单ID数组
|
||||||
|
* @param invoiceData 发票数据
|
||||||
|
* @return 开票结果
|
||||||
|
*/
|
||||||
|
public static AjaxResult createBatchInvoice(Long userId, List<String> orderIds, Map<String, Object> invoiceData) {
|
||||||
|
try {
|
||||||
|
// 1. 参数验证
|
||||||
|
if (orderIds == null || orderIds.isEmpty()) {
|
||||||
|
return AppletControllerUtil.appletWarning("请选择要开票的订单");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证发票数据
|
||||||
|
String validateResult = validateInvoiceData(invoiceData);
|
||||||
|
if (StringUtils.isNotEmpty(validateResult)) {
|
||||||
|
return AppletControllerUtil.appletWarning(validateResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> successOrders = new ArrayList<>();
|
||||||
|
List<String> failedOrders = new ArrayList<>();
|
||||||
|
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||||
|
List<String> invoiceTexts = new ArrayList<>();
|
||||||
|
|
||||||
|
// 3. 逐个处理订单
|
||||||
|
for (String orderId : orderIds) {
|
||||||
|
try {
|
||||||
|
// 验证订单是否存在且属于当前用户
|
||||||
|
Map<String, Object> orderInfo = getOrderInfo(orderId, userId);
|
||||||
|
if (orderInfo == null) {
|
||||||
|
failedOrders.add(orderId + "(订单不存在或不属于当前用户)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已开票
|
||||||
|
if (isOrderInvoiced(orderId)) {
|
||||||
|
failedOrders.add(orderId + "(已开过发票)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 累计金额和开票内容
|
||||||
|
BigDecimal orderAmount = (BigDecimal) orderInfo.get("amount");
|
||||||
|
if (orderAmount != null) {
|
||||||
|
totalAmount = totalAmount.add(orderAmount);
|
||||||
|
}
|
||||||
|
invoiceTexts.add((String) orderInfo.get("title"));
|
||||||
|
successOrders.add(orderId);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
failedOrders.add(orderId + "(处理异常: " + e.getMessage() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 如果没有可开票的订单
|
||||||
|
if (successOrders.isEmpty()) {
|
||||||
|
return AppletControllerUtil.appletWarning("没有可开票的订单:" + String.join(", ", failedOrders));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 创建发票记录
|
||||||
|
UsersInvoiceInfo invoice = new UsersInvoiceInfo();
|
||||||
|
invoice.setUid(userId.intValue());
|
||||||
|
invoice.setOrderid(String.join(",", successOrders)); // 多个订单ID用逗号分隔
|
||||||
|
invoice.setInvoiceTitle((String) invoiceData.get("invoiceTitle"));
|
||||||
|
invoice.setType((Integer) invoiceData.get("type"));
|
||||||
|
invoice.setCategory((Integer) invoiceData.get("category"));
|
||||||
|
invoice.setInvoicemoney(totalAmount); // 总金额
|
||||||
|
invoice.setInvoicetext(String.join("、", invoiceTexts)); // 开票内容合并
|
||||||
|
invoice.setStatus(1); // 待开票
|
||||||
|
invoice.setCreatedAt(new Date());
|
||||||
|
|
||||||
|
// 根据发票类别设置不同字段
|
||||||
|
if ((Integer) invoiceData.get("category") == 0) {
|
||||||
|
// 个人发票
|
||||||
|
invoice.setEmail((String) invoiceData.get("email"));
|
||||||
|
// 清空企业字段
|
||||||
|
invoice.setTaxNumber(null);
|
||||||
|
invoice.setBankName(null);
|
||||||
|
invoice.setBankAccount(null);
|
||||||
|
invoice.setAddress(null);
|
||||||
|
invoice.setPhone(null);
|
||||||
|
invoice.setWechat(null);
|
||||||
|
} else {
|
||||||
|
// 企业发票
|
||||||
|
invoice.setTaxNumber((String) invoiceData.get("taxNumber"));
|
||||||
|
invoice.setAddress((String) invoiceData.get("address"));
|
||||||
|
invoice.setPhone((String) invoiceData.get("phone"));
|
||||||
|
invoice.setBankName((String) invoiceData.get("bankName"));
|
||||||
|
invoice.setBankAccount((String) invoiceData.get("bankAccount"));
|
||||||
|
invoice.setEmail((String) invoiceData.get("email"));
|
||||||
|
invoice.setWechat((String) invoiceData.get("wechat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 保存发票信息
|
||||||
|
int result = usersInvoiceInfoService.insertUsersInvoiceInfo(invoice);
|
||||||
|
if (result > 0) {
|
||||||
|
Map<String, Object> resultData = new HashMap<>();
|
||||||
|
resultData.put("successCount", successOrders.size());
|
||||||
|
resultData.put("successOrders", successOrders);
|
||||||
|
resultData.put("totalAmount", totalAmount);
|
||||||
|
resultData.put("invoiceId", invoice.getId());
|
||||||
|
|
||||||
|
if (!failedOrders.isEmpty()) {
|
||||||
|
resultData.put("failedCount", failedOrders.size());
|
||||||
|
resultData.put("failedOrders", failedOrders);
|
||||||
|
resultData.put("message", "发票申请提交成功,成功开票 " + successOrders.size() + " 个订单,失败 " + failedOrders.size() + " 个订单");
|
||||||
|
return AppletControllerUtil.appletSuccess(resultData);
|
||||||
|
} else {
|
||||||
|
resultData.put("message", "发票申请提交成功,共开票 " + successOrders.size() + " 个订单");
|
||||||
|
return AppletControllerUtil.appletSuccess(resultData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return AppletControllerUtil.appletWarning("发票申请提交失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("批量开具发票失败", e);
|
||||||
|
return AppletControllerUtil.appletError("批量开具发票失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开具发票(单个订单,兼容旧接口)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param orderId 订单ID
|
||||||
|
* @param invoiceData 发票数据
|
||||||
|
* @return 开票结果
|
||||||
|
*/
|
||||||
|
public static AjaxResult createInvoice(Long userId, String orderId, Map<String, Object> invoiceData) {
|
||||||
|
List<String> orderIds = new ArrayList<>();
|
||||||
|
orderIds.add(orderId);
|
||||||
|
return createBatchInvoice(userId, orderIds, invoiceData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取订单信息
|
||||||
|
*
|
||||||
|
* @param orderId 订单ID
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 订单信息
|
||||||
|
*/
|
||||||
|
private static Map<String, Object> getOrderInfo(String orderId, Long userId) {
|
||||||
|
try {
|
||||||
|
// 1. 查询服务订单
|
||||||
|
Order serviceOrder = orderService.selectOrderByOrderId(orderId);
|
||||||
|
if (serviceOrder != null && serviceOrder.getUid().equals(userId)) {
|
||||||
|
Map<String, Object> orderInfo = new HashMap<>();
|
||||||
|
orderInfo.put("orderId", serviceOrder.getOrderId());
|
||||||
|
orderInfo.put("amount", serviceOrder.getTotalPrice());
|
||||||
|
orderInfo.put("title", serviceOrder.getOrderId()+ "服务订单");
|
||||||
|
orderInfo.put("type", "service");
|
||||||
|
return orderInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查询商品订单
|
||||||
|
GoodsOrder goodsOrder = goodsOrderService.selectGoodsOrderByorderId(orderId);
|
||||||
|
if (goodsOrder != null && goodsOrder.getUid().equals(userId)) {
|
||||||
|
Map<String, Object> orderInfo = new HashMap<>();
|
||||||
|
orderInfo.put("orderId", goodsOrder.getOrderId());
|
||||||
|
orderInfo.put("amount", goodsOrder.getTotalPrice());
|
||||||
|
orderInfo.put("title", "商品订单");
|
||||||
|
orderInfo.put("type", "goods");
|
||||||
|
return orderInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询充值订单
|
||||||
|
UserMemberRechargeLog rechargeOrder = userMemberRechargeLogService.selectUserMemberRechargeLogByorderid(orderId);
|
||||||
|
if (rechargeOrder != null && rechargeOrder.getUid().equals(userId)) {
|
||||||
|
Map<String, Object> orderInfo = new HashMap<>();
|
||||||
|
orderInfo.put("orderId", rechargeOrder.getOrderid());
|
||||||
|
orderInfo.put("amount", rechargeOrder.getInmoney());
|
||||||
|
orderInfo.put("title", rechargeOrder.getReamk() != null ? rechargeOrder.getReamk() : "会员充值");
|
||||||
|
orderInfo.put("type", "recharge");
|
||||||
|
return orderInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取订单信息失败", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查订单是否已开票
|
||||||
|
*
|
||||||
|
* @param orderId 订单ID
|
||||||
|
* @return 是否已开票
|
||||||
|
*/
|
||||||
|
private static boolean isOrderInvoiced(String orderId) {
|
||||||
|
try {
|
||||||
|
// 查询所有发票记录
|
||||||
|
UsersInvoiceInfo query = new UsersInvoiceInfo();
|
||||||
|
List<UsersInvoiceInfo> invoiceList = usersInvoiceInfoService.selectUsersInvoiceInfoList(query);
|
||||||
|
|
||||||
|
// 检查订单ID是否在任何发票记录中
|
||||||
|
for (UsersInvoiceInfo invoice : invoiceList) {
|
||||||
|
if (invoice.getOrderid() != null) {
|
||||||
|
// 支持单个订单ID或多个订单ID(逗号分隔)
|
||||||
|
String[] orderIds = invoice.getOrderid().split(",");
|
||||||
|
for (String id : orderIds) {
|
||||||
|
if (id.trim().equals(orderId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("检查订单开票状态失败", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证发票数据
|
||||||
|
*
|
||||||
|
* @param invoiceData 发票数据
|
||||||
|
* @return 验证结果,为空表示验证通过
|
||||||
|
*/
|
||||||
|
private static String validateInvoiceData(Map<String, Object> invoiceData) {
|
||||||
|
// 基础字段验证
|
||||||
|
if (invoiceData.get("invoiceTitle") == null || StringUtils.isEmpty(invoiceData.get("invoiceTitle").toString())) {
|
||||||
|
return "发票抬头不能为空";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invoiceData.get("type") == null) {
|
||||||
|
return "发票类型不能为空";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invoiceData.get("category") == null) {
|
||||||
|
return "发票类别不能为空";
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer category = (Integer) invoiceData.get("category");
|
||||||
|
String invoiceTitle = invoiceData.get("invoiceTitle").toString();
|
||||||
|
|
||||||
|
// 个人发票验证
|
||||||
|
if (category == 0) {
|
||||||
|
if (invoiceTitle.length() > 50) {
|
||||||
|
return "个人发票抬头长度不能超过50个字符";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否填写了企业字段
|
||||||
|
if (StringUtils.isNotEmpty((String) invoiceData.get("taxNumber"))) {
|
||||||
|
return "个人发票不能填写纳税人识别号";
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) invoiceData.get("address"))) {
|
||||||
|
return "个人发票不能填写单位地址";
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) invoiceData.get("phone"))) {
|
||||||
|
return "个人发票不能填写联系电话";
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty((String) invoiceData.get("wechat"))) {
|
||||||
|
return "个人发票不能填写微信号";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 企业发票验证
|
||||||
|
else if (category == 1) {
|
||||||
|
if (invoiceTitle.length() > 100) {
|
||||||
|
return "企业发票抬头长度不能超过100个字符";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 必填字段验证
|
||||||
|
if (StringUtils.isEmpty((String) invoiceData.get("taxNumber"))) {
|
||||||
|
return "企业发票的纳税人识别号不能为空";
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty((String) invoiceData.get("address"))) {
|
||||||
|
return "企业发票的单位地址不能为空";
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty((String) invoiceData.get("phone"))) {
|
||||||
|
return "企业发票的联系电话不能为空";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式验证
|
||||||
|
String taxNumber = (String) invoiceData.get("taxNumber");
|
||||||
|
if (!taxNumber.matches("^[A-Z0-9]{15,20}$")) {
|
||||||
|
return "纳税人识别号格式不正确";
|
||||||
|
}
|
||||||
|
|
||||||
|
String phone = (String) invoiceData.get("phone");
|
||||||
|
if (!phone.matches("^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$|^400-?\\d{3}-?\\d{4}$")) {
|
||||||
|
return "联系电话格式不正确";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // 验证通过
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取发票状态文本
|
||||||
|
*
|
||||||
|
* @param status 状态值
|
||||||
|
* @return 状态文本
|
||||||
|
*/
|
||||||
|
private static String getInvoiceStatusText(Integer status) {
|
||||||
|
if (status == null) return "未知";
|
||||||
|
switch (status) {
|
||||||
|
case 1: return "待开票";
|
||||||
|
case 2: return "已开票";
|
||||||
|
case 3: return "已完成";
|
||||||
|
default: return "未知";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取发票类型文本
|
||||||
|
*
|
||||||
|
* @param type 类型值
|
||||||
|
* @return 类型文本
|
||||||
|
*/
|
||||||
|
private static String getInvoiceTypeText(Integer type) {
|
||||||
|
if (type == null) return "未知";
|
||||||
|
switch (type) {
|
||||||
|
case 1: return "增值税专用发票";
|
||||||
|
case 2: return "增值税普通发票";
|
||||||
|
case 3: return "电子发票";
|
||||||
|
default: return "未知";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户发票信息列表(用于选择已保存的发票信息)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 发票信息列表
|
||||||
|
*/
|
||||||
|
public static List<Map<String, Object>> getUserInvoiceInfoList(Long userId) {
|
||||||
|
try {
|
||||||
|
UsersInvoiceInfo query = new UsersInvoiceInfo();
|
||||||
|
query.setUid(userId.intValue());
|
||||||
|
List<UsersInvoiceInfo> invoiceList = usersInvoiceInfoService.selectUsersInvoiceInfoList(query);
|
||||||
|
|
||||||
|
// 去重,只保留不同的发票抬头
|
||||||
|
Map<String, UsersInvoiceInfo> uniqueInvoices = new HashMap<>();
|
||||||
|
for (UsersInvoiceInfo invoice : invoiceList) {
|
||||||
|
String key = invoice.getCategory() + "_" + invoice.getInvoiceTitle();
|
||||||
|
if (!uniqueInvoices.containsKey(key)) {
|
||||||
|
uniqueInvoices.put(key, invoice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, Object>> result = new ArrayList<>();
|
||||||
|
for (UsersInvoiceInfo invoice : uniqueInvoices.values()) {
|
||||||
|
Map<String, Object> invoiceMap = new HashMap<>();
|
||||||
|
invoiceMap.put("id", invoice.getId());
|
||||||
|
invoiceMap.put("invoiceTitle", invoice.getInvoiceTitle());
|
||||||
|
invoiceMap.put("category", invoice.getCategory());
|
||||||
|
invoiceMap.put("categoryText", invoice.getCategory() == 0 ? "个人" : "企业");
|
||||||
|
invoiceMap.put("taxNumber", invoice.getTaxNumber());
|
||||||
|
invoiceMap.put("address", invoice.getAddress());
|
||||||
|
invoiceMap.put("phone", invoice.getPhone());
|
||||||
|
invoiceMap.put("bankName", invoice.getBankName());
|
||||||
|
invoiceMap.put("bankAccount", invoice.getBankAccount());
|
||||||
|
invoiceMap.put("email", invoice.getEmail());
|
||||||
|
invoiceMap.put("wechat", invoice.getWechat());
|
||||||
|
result.add(invoiceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取用户发票信息列表失败", e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.system.config.QiniuConfig;
|
import com.ruoyi.system.config.QiniuConfig;
|
||||||
import com.ruoyi.system.config.WechatConfig;
|
import com.ruoyi.system.config.WechatConfig;
|
||||||
|
import org.apache.xmlbeans.impl.xb.xsdschema.Public;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
@ -79,6 +80,8 @@ public class WechatPayUtil {
|
||||||
private static final String WECHAT_REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
|
private static final String WECHAT_REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
|
||||||
private static final String WECHAT_TRANSFER_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; // 企业付款
|
private static final String WECHAT_TRANSFER_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; // 企业付款
|
||||||
|
|
||||||
|
|
||||||
|
public static final String PAY_FH = "https://4b29b18c.r3.cpolar.top/";
|
||||||
/**
|
/**
|
||||||
* 其他配置常量
|
* 其他配置常量
|
||||||
*/
|
*/
|
||||||
|
|
@ -138,7 +141,7 @@ public class WechatPayUtil {
|
||||||
if (notifyUrl == null || notifyUrl.trim().isEmpty()) {
|
if (notifyUrl == null || notifyUrl.trim().isEmpty()) {
|
||||||
return failResult("回调通知地址不能为空");
|
return failResult("回调通知地址不能为空");
|
||||||
}
|
}
|
||||||
|
System.out.println("wechatConfig().getAppid():"+wechatConfig().getAppid());
|
||||||
// 2. 构建参数
|
// 2. 构建参数
|
||||||
Map<String, String> params = new HashMap<>();
|
Map<String, String> params = new HashMap<>();
|
||||||
params.put("appid", wechatConfig().getAppid());
|
params.put("appid", wechatConfig().getAppid());
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,8 @@ public class GoodsOrder extends BaseEntity
|
||||||
@Excel(name = "优惠券id")
|
@Excel(name = "优惠券id")
|
||||||
private Long couponId;
|
private Long couponId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 抵扣金额 */
|
/** 抵扣金额 */
|
||||||
@Excel(name = "抵扣金额")
|
@Excel(name = "抵扣金额")
|
||||||
private BigDecimal deduction;
|
private BigDecimal deduction;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ public interface GoodsOrderMapper
|
||||||
public GoodsOrder selectGoodsOrderById(Long id);
|
public GoodsOrder selectGoodsOrderById(Long id);
|
||||||
|
|
||||||
|
|
||||||
|
public GoodsOrder selectGoodsOrderByorderId(String orderId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public int selectCountGoodsOrderByUid(@Param("uid") Long uid, @Param("status") Long status);
|
public int selectCountGoodsOrderByUid(@Param("uid") Long uid, @Param("status") Long status);
|
||||||
|
|
||||||
public int selectAllCountGoodsOrderByUid(Long uid);
|
public int selectAllCountGoodsOrderByUid(Long uid);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ public interface UserMemberRechargeLogMapper
|
||||||
*/
|
*/
|
||||||
public UserMemberRechargeLog selectUserMemberRechargeLogById(Integer id);
|
public UserMemberRechargeLog selectUserMemberRechargeLogById(Integer id);
|
||||||
|
|
||||||
|
|
||||||
|
public UserMemberRechargeLog selectUserMemberRechargeLogByorderid(String orderid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户充值记录列表
|
* 查询用户充值记录列表
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public interface IGoodsOrderService
|
||||||
*/
|
*/
|
||||||
public List<GoodsOrder> selectGoodsOrderList(GoodsOrder goodsOrder);
|
public List<GoodsOrder> selectGoodsOrderList(GoodsOrder goodsOrder);
|
||||||
|
|
||||||
|
public GoodsOrder selectGoodsOrderByorderId(String orderId);
|
||||||
|
|
||||||
public int selectCountGoodsOrderByUid(Long uid,Long status);
|
public int selectCountGoodsOrderByUid(Long uid,Long status);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ public interface IUserMemberRechargeLogService
|
||||||
*/
|
*/
|
||||||
public UserMemberRechargeLog selectUserMemberRechargeLogById(Integer id);
|
public UserMemberRechargeLog selectUserMemberRechargeLogById(Integer id);
|
||||||
|
|
||||||
|
|
||||||
|
public UserMemberRechargeLog selectUserMemberRechargeLogByorderid(String orderid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户充值记录列表
|
* 查询用户充值记录列表
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ public class GoodsOrderServiceImpl implements IGoodsOrderService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public GoodsOrder selectGoodsOrderByorderId(String orderId){
|
||||||
|
return goodsOrderMapper.selectGoodsOrderByorderId(orderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public int selectCountGoodsOrderByUid(Long uid,Long status) {
|
public int selectCountGoodsOrderByUid(Long uid,Long status) {
|
||||||
return goodsOrderMapper.selectCountGoodsOrderByUid(uid,status);
|
return goodsOrderMapper.selectCountGoodsOrderByUid(uid,status);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,12 @@ public class UserMemberRechargeLogServiceImpl implements IUserMemberRechargeLogS
|
||||||
return userMemberRechargeLogMapper.selectUserMemberRechargeLogById(id);
|
return userMemberRechargeLogMapper.selectUserMemberRechargeLogById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public UserMemberRechargeLog selectUserMemberRechargeLogByorderid(String orderid){
|
||||||
|
return userMemberRechargeLogMapper.selectUserMemberRechargeLogByorderid(orderid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户充值记录列表
|
* 查询用户充值记录列表
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
order by id desc
|
order by id desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectGoodsOrderByorderId" parameterType="String" resultMap="GoodsOrderResult">
|
||||||
|
<include refid="selectGoodsOrderVo"/>
|
||||||
|
where order_id = #{orderId} limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectGoodsOrderById" parameterType="Long" resultMap="GoodsOrderResult">
|
<select id="selectGoodsOrderById" parameterType="Long" resultMap="GoodsOrderResult">
|
||||||
<include refid="selectGoodsOrderVo"/>
|
<include refid="selectGoodsOrderVo"/>
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
<where>
|
<where>
|
||||||
<if test="uid != null "> and uid = #{uid}</if>
|
<if test="uid != null "> and uid = #{uid}</if>
|
||||||
</where>
|
</where>
|
||||||
order by updated_at desc
|
order by id desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectUserMemberRechargeLogById" parameterType="Integer" resultMap="UserMemberRechargeLogResult">
|
<select id="selectUserMemberRechargeLogById" parameterType="Integer" resultMap="UserMemberRechargeLogResult">
|
||||||
|
|
@ -41,6 +41,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<select id="selectUserMemberRechargeLogByorderid" parameterType="String" resultMap="UserMemberRechargeLogResult">
|
||||||
|
<include refid="selectUserMemberRechargeLogVo"/>
|
||||||
|
where orderid = #{orderid} limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<insert id="insertUserMemberRechargeLog" parameterType="UserMemberRechargeLog" useGeneratedKeys="true" keyProperty="id">
|
<insert id="insertUserMemberRechargeLog" parameterType="UserMemberRechargeLog" useGeneratedKeys="true" keyProperty="id">
|
||||||
insert into user_member_recharge_log
|
insert into user_member_recharge_log
|
||||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
<if test="uid != null "> and uid = #{uid}</if>
|
<if test="uid != null "> and uid = #{uid}</if>
|
||||||
<if test="del != null "> and del = #{del}</if>
|
<if test="del != null "> and del = #{del}</if>
|
||||||
</where>
|
</where>
|
||||||
order by updated_at desc
|
order by id desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectUserMemnerConsumptionLogById" parameterType="Integer" resultMap="UserMemnerConsumptionLogResult">
|
<select id="selectUserMemnerConsumptionLogById" parameterType="Integer" resultMap="UserMemnerConsumptionLogResult">
|
||||||
|
|
|
||||||
|
|
@ -248,9 +248,9 @@
|
||||||
<!-- 日志记录弹窗 -->
|
<!-- 日志记录弹窗 -->
|
||||||
<el-dialog :title="logTitle" :visible.sync="logVisible" width="1000px" append-to-body>
|
<el-dialog :title="logTitle" :visible.sync="logVisible" width="1000px" append-to-body>
|
||||||
<!-- 统计信息卡片 -->
|
<!-- 统计信息卡片 -->
|
||||||
<el-row :gutter="16" class="mb8">
|
<el-row :gutter="12" class="mb8">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover" class="summary-card income-card">
|
<div class="summary-card income-card">
|
||||||
<div class="summary-content">
|
<div class="summary-content">
|
||||||
<div class="summary-icon">
|
<div class="summary-icon">
|
||||||
<i class="el-icon-plus"></i>
|
<i class="el-icon-plus"></i>
|
||||||
|
|
@ -260,10 +260,10 @@
|
||||||
<div class="summary-value">¥{{ formatMoney(totalIncome) }}</div>
|
<div class="summary-value">¥{{ formatMoney(totalIncome) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover" class="summary-card expense-card">
|
<div class="summary-card expense-card">
|
||||||
<div class="summary-content">
|
<div class="summary-content">
|
||||||
<div class="summary-icon">
|
<div class="summary-icon">
|
||||||
<i class="el-icon-minus"></i>
|
<i class="el-icon-minus"></i>
|
||||||
|
|
@ -273,10 +273,10 @@
|
||||||
<div class="summary-value">¥{{ formatMoney(totalExpense) }}</div>
|
<div class="summary-value">¥{{ formatMoney(totalExpense) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover" class="summary-card net-card">
|
<div class="summary-card net-card">
|
||||||
<div class="summary-content">
|
<div class="summary-content">
|
||||||
<div class="summary-icon">
|
<div class="summary-icon">
|
||||||
<i class="el-icon-d-arrow-right"></i>
|
<i class="el-icon-d-arrow-right"></i>
|
||||||
|
|
@ -288,7 +288,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
|
@ -301,14 +301,7 @@
|
||||||
<el-option label="支出" value="2"></el-option>
|
<el-option label="支出" value="2"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6" v-if="currentType === null">
|
|
||||||
<el-select v-model="logFilter.consumptionType" placeholder="消费类别" clearable @change="filterLogs">
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="商城消费" value="0"></el-option>
|
|
||||||
<el-option label="服务类消费" value="1"></el-option>
|
|
||||||
<el-option label="其他消费" value="2"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="logFilter.dateRange"
|
v-model="logFilter.dateRange"
|
||||||
|
|
@ -337,7 +330,7 @@
|
||||||
>
|
>
|
||||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
|
||||||
<el-table-column label="变动类型" align="center" width="80">
|
<el-table-column label="变动类型" align="center" width="130">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag
|
<el-tag
|
||||||
:type="getChangeTypeTag(scope.row)"
|
:type="getChangeTypeTag(scope.row)"
|
||||||
|
|
@ -395,16 +388,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="消费类别" align="center" width="100" v-if="currentType === null">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-tag
|
|
||||||
:type="getConsumptionTypeTag(scope.row.consumptiontype)"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
{{ getConsumptionTypeText(scope.row.consumptiontype) }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column label="变动说明" align="center" prop="reamk" min-width="200" :show-overflow-tooltip="true">
|
<el-table-column label="变动说明" align="center" prop="reamk" min-width="200" :show-overflow-tooltip="true">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
|
|
@ -415,7 +399,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="变动时间" align="center" width="160">
|
<el-table-column label="变动时间" align="center" width="180">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div class="time-content">
|
<div class="time-content">
|
||||||
<i class="el-icon-time"></i>
|
<i class="el-icon-time"></i>
|
||||||
|
|
@ -486,11 +470,7 @@
|
||||||
<el-descriptions-item label="订单金额" v-if="logDetail.ordermoney">
|
<el-descriptions-item label="订单金额" v-if="logDetail.ordermoney">
|
||||||
¥{{ parseFloat(logDetail.ordermoney).toFixed(2) }}
|
¥{{ parseFloat(logDetail.ordermoney).toFixed(2) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="消费类别" v-if="logDetail.consumptiontype !== undefined">
|
|
||||||
<el-tag :type="getConsumptionTypeTag(logDetail.consumptiontype)" size="small">
|
|
||||||
{{ getConsumptionTypeText(logDetail.consumptiontype) }}
|
|
||||||
</el-tag>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="变动时间" :span="2">
|
<el-descriptions-item label="变动时间" :span="2">
|
||||||
{{ formatDateTime(logDetail) }}
|
{{ formatDateTime(logDetail) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
@ -590,7 +570,6 @@ export default {
|
||||||
// 筛选条件
|
// 筛选条件
|
||||||
logFilter: {
|
logFilter: {
|
||||||
type: '',
|
type: '',
|
||||||
consumptionType: '',
|
|
||||||
dateRange: []
|
dateRange: []
|
||||||
},
|
},
|
||||||
// 统计数据
|
// 统计数据
|
||||||
|
|
@ -825,12 +804,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按消费类别筛选(仅余额变动)
|
|
||||||
if (this.logFilter.consumptionType && this.currentType === null) {
|
|
||||||
filtered = filtered.filter(item => {
|
|
||||||
return item.consumptiontype === parseInt(this.logFilter.consumptionType);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按日期范围筛选
|
// 按日期范围筛选
|
||||||
if (this.logFilter.dateRange && this.logFilter.dateRange.length === 2) {
|
if (this.logFilter.dateRange && this.logFilter.dateRange.length === 2) {
|
||||||
|
|
@ -873,7 +847,8 @@ export default {
|
||||||
// 获取变动类型标签
|
// 获取变动类型标签
|
||||||
getChangeTypeTag(row) {
|
getChangeTypeTag(row) {
|
||||||
if (this.currentType === null) {
|
if (this.currentType === null) {
|
||||||
return 'info'; // 余额变动
|
// 余额变动:type=1收入(绿色),type=2支出(红色)
|
||||||
|
return row.type === 1 ? 'success' : 'danger';
|
||||||
}
|
}
|
||||||
if (row.type === 1) { // 服务金变动
|
if (row.type === 1) { // 服务金变动
|
||||||
return 'success';
|
return 'success';
|
||||||
|
|
@ -884,6 +859,12 @@ export default {
|
||||||
// 获取变动类型文本
|
// 获取变动类型文本
|
||||||
getChangeTypeText(row) {
|
getChangeTypeText(row) {
|
||||||
if (this.currentType === null) {
|
if (this.currentType === null) {
|
||||||
|
// 余额变动:根据type判断增加或减少
|
||||||
|
if (row.type === 1) {
|
||||||
|
return '余额变动--增加';
|
||||||
|
} else if (row.type === 2) {
|
||||||
|
return '余额变动--减少';
|
||||||
|
}
|
||||||
return '余额变动';
|
return '余额变动';
|
||||||
}
|
}
|
||||||
if (row.type === 1) {
|
if (row.type === 1) {
|
||||||
|
|
@ -895,9 +876,9 @@ export default {
|
||||||
// 获取变动金额
|
// 获取变动金额
|
||||||
getAmountValue(row) {
|
getAmountValue(row) {
|
||||||
if (this.currentType === null) {
|
if (this.currentType === null) {
|
||||||
// 余额变动
|
// 余额变动:type=1收入(正数),type=2支出(负数)
|
||||||
if (row.consumptionmoney) {
|
if (row.consumptionmoney) {
|
||||||
return row.type === 1 ? row.consumptionmoney : -row.consumptionmoney;
|
return row.type === 1 ? parseFloat(row.consumptionmoney) : -parseFloat(row.consumptionmoney);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -925,30 +906,31 @@ export default {
|
||||||
// 服务金/消费金变动
|
// 服务金/消费金变动
|
||||||
return parseFloat(row.aftremoney || 0).toFixed(2);
|
return parseFloat(row.aftremoney || 0).toFixed(2);
|
||||||
},
|
},
|
||||||
// 获取消费类别标签
|
|
||||||
getConsumptionTypeTag(type) {
|
|
||||||
if (type === 0) {
|
|
||||||
return 'info'; // 商城消费
|
|
||||||
} else if (type === 1) {
|
|
||||||
return 'success'; // 服务类消费
|
|
||||||
} else {
|
|
||||||
return 'warning'; // 其他消费
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 获取消费类别文本
|
|
||||||
getConsumptionTypeText(type) {
|
|
||||||
if (type === 0) {
|
|
||||||
return '商城消费';
|
|
||||||
} else if (type === 1) {
|
|
||||||
return '服务类消费';
|
|
||||||
} else {
|
|
||||||
return '其他消费';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 格式化日期时间
|
// 格式化日期时间
|
||||||
formatDateTime(row) {
|
formatDateTime(row) {
|
||||||
const dateTime = row.createTime || row.createdAt || row.dotime || row.consumptiontime;
|
const dateTime = row.createTime || row.createdAt || row.dotime || row.consumptiontime;
|
||||||
return this.parseTime(dateTime, '{y}-{m}-{d} {h}:{i}:{s}');
|
if (!dateTime) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试解析时间,如果包含时分秒信息则显示完整时间,否则只显示日期
|
||||||
|
const date = new Date(dateTime);
|
||||||
|
if (isNaN(date.getTime())) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查原始时间字符串是否包含时分秒信息
|
||||||
|
const timeStr = dateTime.toString();
|
||||||
|
const hasTimeInfo = timeStr.includes(':') || timeStr.includes('T') || timeStr.length > 10;
|
||||||
|
|
||||||
|
if (hasTimeInfo) {
|
||||||
|
// 如果有时分秒信息,显示完整的日期时间(精确到秒)
|
||||||
|
return this.parseTime(dateTime, '{y}-{m}-{d} {h}:{i}:{s}');
|
||||||
|
} else {
|
||||||
|
// 如果只有日期信息,只显示日期
|
||||||
|
return this.parseTime(dateTime, '{y}-{m}-{d}');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 显示余额变动记录 */
|
/** 显示余额变动记录 */
|
||||||
showBalanceLogs(userId) {
|
showBalanceLogs(userId) {
|
||||||
|
|
@ -963,7 +945,6 @@ export default {
|
||||||
resetLogFilters() {
|
resetLogFilters() {
|
||||||
this.logFilter = {
|
this.logFilter = {
|
||||||
type: '',
|
type: '',
|
||||||
consumptionType: '',
|
|
||||||
dateRange: []
|
dateRange: []
|
||||||
};
|
};
|
||||||
this.logQuery.pageNum = 1;
|
this.logQuery.pageNum = 1;
|
||||||
|
|
@ -1048,10 +1029,18 @@ export default {
|
||||||
.summary-card {
|
.summary-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 8px 12px;
|
padding: 6px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.06);
|
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.08);
|
||||||
min-height: 60px;
|
min-height: 45px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card:hover {
|
||||||
|
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
border-color: #e6f7ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-content {
|
.summary-content {
|
||||||
|
|
@ -1060,8 +1049,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-icon {
|
.summary-icon {
|
||||||
font-size: 18px;
|
font-size: 16px;
|
||||||
margin-right: 8px;
|
margin-right: 6px;
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1071,13 +1060,13 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-title {
|
.summary-title {
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
color: #606266;
|
color: #606266;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-value {
|
.summary-value {
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,8 @@
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="发票类别" prop="category">
|
<el-form-item label="发票类别" prop="category">
|
||||||
<el-select v-model="queryParams.category" placeholder="请选择发票类别" clearable>
|
<el-select v-model="queryParams.category" placeholder="请选择发票类别" clearable>
|
||||||
<el-option label="个人" :value="1" />
|
<el-option label="个人" :value="0" />
|
||||||
<el-option label="企业" :value="2" />
|
<el-option label="企业" :value="1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -162,8 +162,8 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="发票类别" align="center" width="100">
|
<el-table-column label="发票类别" align="center" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="scope.row.category === 1 ? 'info' : 'warning'" size="small">
|
<el-tag :type="scope.row.category === 0 ? 'info' : 'warning'" size="small">
|
||||||
{{ scope.row.category === 1 ? '个人' : '企业' }}
|
{{ scope.row.category === 0 ? '个人' : '企业' }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
@ -294,8 +294,8 @@
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="发票类别" prop="category">
|
<el-form-item label="发票类别" prop="category">
|
||||||
<el-select v-model="form.category" placeholder="请选择发票类别">
|
<el-select v-model="form.category" placeholder="请选择发票类别">
|
||||||
<el-option label="个人" :value="1" />
|
<el-option label="个人" :value="0" />
|
||||||
<el-option label="企业" :value="2" />
|
<el-option label="企业" :value="1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -317,7 +317,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 企业信息 -->
|
<!-- 企业信息 -->
|
||||||
<div v-if="form.category === 2">
|
<div v-if="form.category === 1">
|
||||||
<el-divider content-position="left">企业税务信息</el-divider>
|
<el-divider content-position="left">企业税务信息</el-divider>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
|
|
@ -439,8 +439,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<label>发票类别:</label>
|
<label>发票类别:</label>
|
||||||
<el-tag :type="detailForm.category === 1 ? 'info' : 'warning'" size="small">
|
<el-tag :type="detailForm.category === 0 ? 'info' : 'warning'" size="small">
|
||||||
{{ detailForm.category === 1 ? '个人' : '企业' }}
|
{{ detailForm.category === 0 ? '个人' : '企业' }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
|
|
@ -475,7 +475,7 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<div v-if="detailForm.category === 2" class="detail-section">
|
<div v-if="detailForm.category === 1" class="detail-section">
|
||||||
<h4>企业税务信息</h4>
|
<h4>企业税务信息</h4>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue