Browse Source

feat(shop): 优化订单处理逻辑并添加新功能

- 新增 DateTimeUtil 工具类,用于统一处理日期时间格式化- 移除 ShopCouponController 中的 PreAuthorize 注解
-重构 ShopOrderServiceImpl 中的支付成功后业务逻辑处理
  - 添加处理支付成功后业务逻辑的 handlePaymentSuccess 方法
  - 新增标记优惠券为已使用的 markCouponAsUsed 方法
  - 新增累计商品销量的 updateGoodsSales 和 updateSingleGoodsSales 方法
- 更新测试账号配置和生产环境配置
dev
科技小王子 2 days ago
parent
commit
2a8d87a4d1
  1. 93
      src/main/java/com/gxwebsoft/common/core/utils/DateTimeUtil.java
  2. 3
      src/main/java/com/gxwebsoft/shop/controller/ShopCouponController.java
  3. 95
      src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java
  4. 6
      src/main/resources/application-prod.yml
  5. 4
      src/main/resources/application.yml

93
src/main/java/com/gxwebsoft/common/core/utils/DateTimeUtil.java

@ -0,0 +1,93 @@
package com.gxwebsoft.common.core.utils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 时间格式化工具类
* 用于统一处理LocalDateTime的格式化
*
* @author WebSoft
* @since 2025-08-23
*/
public class DateTimeUtil {
/**
* 默认的日期时间格式
*/
public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 默认的日期格式
*/
public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
/**
* 默认的时间格式
*/
public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";
/**
* 默认的日期时间格式化器
*/
private static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER =
DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN);
/**
* 格式化LocalDateTime为字符串
* 使用默认格式yyyy-MM-dd HH:mm:ss
*
* @param dateTime 要格式化的时间
* @return 格式化后的字符串如果输入为null则返回null
*/
public static String formatDateTime(LocalDateTime dateTime) {
if (dateTime == null) {
return null;
}
return dateTime.format(DEFAULT_DATETIME_FORMATTER);
}
/**
* 格式化LocalDateTime为字符串
* 使用指定格式
*
* @param dateTime 要格式化的时间
* @param pattern 格式模式
* @return 格式化后的字符串如果输入为null则返回null
*/
public static String formatDateTime(LocalDateTime dateTime, String pattern) {
if (dateTime == null) {
return null;
}
return dateTime.format(DateTimeFormatter.ofPattern(pattern));
}
/**
* 解析字符串为LocalDateTime
* 使用默认格式yyyy-MM-dd HH:mm:ss
*
* @param dateTimeStr 时间字符串
* @return LocalDateTime对象如果输入为null或空字符串则返回null
*/
public static LocalDateTime parseDateTime(String dateTimeStr) {
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
return null;
}
return LocalDateTime.parse(dateTimeStr, DEFAULT_DATETIME_FORMATTER);
}
/**
* 解析字符串为LocalDateTime
* 使用指定格式
*
* @param dateTimeStr 时间字符串
* @param pattern 格式模式
* @return LocalDateTime对象如果输入为null或空字符串则返回null
*/
public static LocalDateTime parseDateTime(String dateTimeStr, String pattern) {
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
return null;
}
return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern));
}
}

3
src/main/java/com/gxwebsoft/shop/controller/ShopCouponController.java

@ -92,7 +92,6 @@ public class ShopCouponController extends BaseController {
}
@PreAuthorize("hasAuthority('shop:shopCoupon:list')")
@Operation(summary = "分页查询优惠券")
@GetMapping("/page")
public ApiResult<PageResult<ShopCoupon>> page(ShopCouponParam param) {
@ -100,7 +99,6 @@ public class ShopCouponController extends BaseController {
return success(shopCouponService.pageRel(param));
}
@PreAuthorize("hasAuthority('shop:shopCoupon:list')")
@Operation(summary = "查询全部优惠券")
@GetMapping()
public ApiResult<List<ShopCoupon>> list(ShopCouponParam param) {
@ -108,7 +106,6 @@ public class ShopCouponController extends BaseController {
return success(shopCouponService.listRel(param));
}
@PreAuthorize("hasAuthority('shop:shopCoupon:list')")
@Operation(summary = "根据id查询优惠券")
@GetMapping("/{id}")
public ApiResult<ShopCoupon> get(@PathVariable("id") Integer id) {

95
src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java

@ -298,8 +298,40 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
@Override
public void updateByOutTradeNo(ShopOrder order) {
baseMapper.updateByOutTradeNo(order);
// 使用优惠券 - 使用新的状态管理服务
if (order.getCouponId() != null && order.getCouponId() > 0) {
// 处理支付成功后的业务逻辑
handlePaymentSuccess(order);
if (order.getTenantId().equals(10550)) {
shopOrderUpdate10550Service.update(order);
}
}
/**
* 处理支付成功后的业务逻辑
*/
private void handlePaymentSuccess(ShopOrder order) {
try {
// 1. 使用优惠券
if (order.getCouponId() != null && order.getCouponId() > 0) {
markCouponAsUsed(order);
}
// 2. 累计商品销量
updateGoodsSales(order);
log.info("支付成功后业务逻辑处理完成 - 订单号:{}", order.getOrderNo());
} catch (Exception e) {
log.error("处理支付成功后业务逻辑失败 - 订单号:{}", order.getOrderNo(), e);
// 不抛出异常,避免影响支付回调的成功响应
}
}
/**
* 标记优惠券为已使用
*/
private void markCouponAsUsed(ShopOrder order) {
try {
// 注入 CouponStatusService 并使用其 useCoupon 方法
// couponStatusService.useCoupon(order.getCouponId().longValue(), order.getOrderId(), order.getOrderNo());
@ -308,10 +340,65 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
if (coupon != null) {
coupon.markAsUsed(order.getOrderId(), order.getOrderNo());
shopUserCouponService.updateById(coupon);
log.info("优惠券标记为已使用 - 优惠券ID:{},订单号:{}", order.getCouponId(), order.getOrderNo());
}
} catch (Exception e) {
log.error("标记优惠券为已使用失败 - 优惠券ID:{},订单号:{}", order.getCouponId(), order.getOrderNo(), e);
}
if (order.getTenantId().equals(10550)) {
shopOrderUpdate10550Service.update(order);
}
/**
* 累计商品销量
*/
private void updateGoodsSales(ShopOrder order) {
try {
// 获取订单商品列表
List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.list(
new LambdaQueryWrapper<ShopOrderGoods>()
.eq(ShopOrderGoods::getOrderId, order.getOrderId())
);
if (orderGoodsList.isEmpty()) {
log.warn("订单商品列表为空 - 订单号:{}", order.getOrderNo());
return;
}
// 累计每个商品的销量
for (ShopOrderGoods orderGoods : orderGoodsList) {
updateSingleGoodsSales(orderGoods);
}
log.info("商品销量累计完成 - 订单号:{},商品数量:{}", order.getOrderNo(), orderGoodsList.size());
} catch (Exception e) {
log.error("累计商品销量失败 - 订单号:{}", order.getOrderNo(), e);
}
}
/**
* 累计单个商品的销量
*/
private void updateSingleGoodsSales(ShopOrderGoods orderGoods) {
try {
ShopGoods goods = shopGoodsService.getById(orderGoods.getGoodsId());
if (goods != null) {
// 累计商品销量
Integer currentSales = goods.getSales() != null ? goods.getSales() : 0;
Integer newSales = currentSales + orderGoods.getTotalNum();
goods.setSales(newSales);
boolean updated = shopGoodsService.updateById(goods);
if (updated) {
log.info("商品销量累计成功 - 商品ID:{},商品名称:{},购买数量:{},累计销量:{} -> {}",
orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum(), currentSales, newSales);
} else {
log.warn("商品销量更新失败 - 商品ID:{}", orderGoods.getGoodsId());
}
} else {
log.warn("商品不存在,无法累计销量 - 商品ID:{}", orderGoods.getGoodsId());
}
} catch (Exception e) {
log.error("累计单个商品销量失败 - 商品ID:{},商品名称:{}",
orderGoods.getGoodsId(), orderGoods.getGoodsName(), e);
}
}

6
src/main/resources/application-prod.yml

@ -3,7 +3,7 @@
# 数据源配置
spring:
datasource:
url: jdbc:mysql://8.134.169.209:13306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
url: jdbc:mysql://1Panel-mysql-Bqdt:3306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: modules
password: 8YdLnk7KsPAyDXGA
driver-class-name: com.mysql.cj.jdbc.Driver
@ -14,8 +14,8 @@ spring:
# redis
redis:
database: 0
host: 8.134.169.209
port: 16379
host: 1Panel-redis-Q1LE
port: 6379
password: redis_WSDb88
# 日志配置

4
src/main/resources/application.yml

@ -119,9 +119,9 @@ shop:
order:
# 测试账号配置
test-account:
enabled: false # 禁用测试账号功能
enabled: true # 禁用测试账号功能
phone-numbers:
- "13800000000" # 改为其他测试手机号
- "13737128880" # 改为其他测试手机号
test-pay-amount: 0.01
# 租户特殊规则配置

Loading…
Cancel
Save