You've already forked FrameTour-BE
feat(order): 新增订单管理功能 V2
- 新增订单创建、查询、备注更新、申请退款等接口 - 添加订单相关实体类和枚举类 - 实现订单事件监听器,处理支付、退款、订单状态变化 - 优化移动端订单创建逻辑,集成订单服务
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.constant.BaseContextHandler;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.pricing.dto.*;
|
||||
@@ -8,6 +9,10 @@ import com.ycwl.basic.service.pc.FaceService;
|
||||
import com.ycwl.basic.service.PriceCacheService;
|
||||
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||
import com.ycwl.basic.dto.MobileOrderRequest;
|
||||
import com.ycwl.basic.order.service.IOrderService;
|
||||
import com.ycwl.basic.order.dto.OrderV2DetailResponse;
|
||||
import com.ycwl.basic.order.dto.OrderV2ListResponse;
|
||||
import com.ycwl.basic.order.dto.OrderV2PageRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -27,6 +32,7 @@ public class AppOrderV2Controller {
|
||||
private final IPriceCalculationService priceCalculationService;
|
||||
private final FaceService faceService;
|
||||
private final PriceCacheService priceCacheService;
|
||||
private final IOrderService orderService;
|
||||
|
||||
/**
|
||||
* 移动端价格计算
|
||||
@@ -157,20 +163,80 @@ public class AppOrderV2Controller {
|
||||
log.info("价格缓存验证通过: userId={}, scenicId={}, finalAmount={}",
|
||||
currentUserId, scenicId, cachedResult.getFinalAmount());
|
||||
|
||||
// TODO: 实现订单创建逻辑
|
||||
// 1. 生成订单号
|
||||
// 2. 创建订单基础信息
|
||||
// 3. 保存订单商品明细
|
||||
// 4. 记录使用的优惠券和券码信息
|
||||
// 5. 更新优惠券和券码状态
|
||||
// 6. 初始化订单状态为待支付
|
||||
// 7. 发送订单创建成功通知
|
||||
|
||||
String orderId = "ORDER_" + System.currentTimeMillis(); // 临时订单号生成逻辑
|
||||
// 创建订单
|
||||
try {
|
||||
Long orderId = orderService.createOrder(request, currentUserId, scenicId, cachedResult);
|
||||
|
||||
log.info("移动端订单创建成功: orderId={}, userId={}, scenicId={}, finalAmount={}",
|
||||
orderId, currentUserId, scenicId, cachedResult.getFinalAmount());
|
||||
|
||||
return ApiResponse.success(orderId);
|
||||
return ApiResponse.success(orderId.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("订单创建失败: userId={}, scenicId={}, error={}", currentUserId, scenicId, e.getMessage(), e);
|
||||
return ApiResponse.fail("订单创建失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
// ====== 新增移动端订单查询功能 ======
|
||||
|
||||
/**
|
||||
* 用户分页查询自己的订单列表
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
public ApiResponse<PageInfo<OrderV2ListResponse>> pageUserOrders(@RequestBody OrderV2PageRequest request) {
|
||||
String currentUserIdStr = BaseContextHandler.getUserId();
|
||||
if (currentUserIdStr == null) {
|
||||
log.warn("用户未登录");
|
||||
return ApiResponse.fail("用户未登录");
|
||||
}
|
||||
|
||||
Long currentUserId = Long.valueOf(currentUserIdStr);
|
||||
request.setMemberId(currentUserId); // 设置当前用户ID,确保只查询自己的订单
|
||||
|
||||
log.info("用户查询订单列表: userId={}, request={}", currentUserId, request);
|
||||
|
||||
try {
|
||||
PageInfo<OrderV2ListResponse> pageInfo = orderService.pageOrdersByUser(request);
|
||||
return ApiResponse.success(pageInfo);
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户订单列表失败: userId={}", currentUserId, e);
|
||||
return ApiResponse.fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户查询自己的订单详情
|
||||
*/
|
||||
@GetMapping("/detail/{orderId}")
|
||||
public ApiResponse<OrderV2DetailResponse> getUserOrderDetail(@PathVariable("orderId") Long orderId) {
|
||||
String currentUserIdStr = BaseContextHandler.getUserId();
|
||||
if (currentUserIdStr == null) {
|
||||
log.warn("用户未登录");
|
||||
return ApiResponse.fail("用户未登录");
|
||||
}
|
||||
|
||||
Long currentUserId = Long.valueOf(currentUserIdStr);
|
||||
|
||||
log.info("用户查询订单详情: userId={}, orderId={}", currentUserId, orderId);
|
||||
|
||||
try {
|
||||
OrderV2DetailResponse detail = orderService.getOrderDetail(orderId);
|
||||
if (detail == null) {
|
||||
return ApiResponse.fail("订单不存在");
|
||||
}
|
||||
|
||||
// 验证订单是否属于当前用户
|
||||
if (!currentUserId.equals(detail.getMemberId())) {
|
||||
log.warn("用户尝试访问他人订单: userId={}, orderId={}, orderOwner={}",
|
||||
currentUserId, orderId, detail.getMemberId());
|
||||
return ApiResponse.fail("无权访问该订单");
|
||||
}
|
||||
|
||||
return ApiResponse.success(detail);
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户订单详情失败: userId={}, orderId={}", currentUserId, orderId, e);
|
||||
return ApiResponse.fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,89 @@
|
||||
package com.ycwl.basic.order.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.order.dto.*;
|
||||
import com.ycwl.basic.order.service.IOrderService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 订单管理控制器V2 - 管理端
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/order/v2")
|
||||
@RequiredArgsConstructor
|
||||
public class OrderV2Controller {
|
||||
|
||||
private final IOrderService orderService;
|
||||
|
||||
/**
|
||||
* 分页查询订单列表
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
public ApiResponse<PageInfo<OrderV2ListResponse>> pageOrders(@RequestBody OrderV2PageRequest request) {
|
||||
log.info("分页查询订单列表: {}", request);
|
||||
try {
|
||||
PageInfo<OrderV2ListResponse> pageInfo = orderService.pageOrders(request);
|
||||
return ApiResponse.success(pageInfo);
|
||||
} catch (Exception e) {
|
||||
log.error("分页查询订单列表失败", e);
|
||||
return ApiResponse.fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单详情
|
||||
*/
|
||||
@GetMapping("/detail/{orderId}")
|
||||
public ApiResponse<OrderV2DetailResponse> getOrderDetail(@PathVariable("orderId") Long orderId) {
|
||||
log.info("查询订单详情: orderId={}", orderId);
|
||||
try {
|
||||
OrderV2DetailResponse detail = orderService.getOrderDetail(orderId);
|
||||
if (detail == null) {
|
||||
return ApiResponse.fail("订单不存在");
|
||||
}
|
||||
return ApiResponse.success(detail);
|
||||
} catch (Exception e) {
|
||||
log.error("查询订单详情失败: orderId={}", orderId, e);
|
||||
return ApiResponse.fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单备注
|
||||
*/
|
||||
@PutMapping("/remark/{orderId}")
|
||||
public ApiResponse<String> updateOrderRemarks(@PathVariable("orderId") Long orderId,
|
||||
@RequestBody OrderRemarkRequest request) {
|
||||
log.info("更新订单备注: orderId={}, remarks={}", orderId, request.getRemarks());
|
||||
try {
|
||||
boolean success = orderService.updateOrderRemarks(orderId, request.getRemarks());
|
||||
if (success) {
|
||||
return ApiResponse.success("备注更新成功");
|
||||
} else {
|
||||
return ApiResponse.fail("备注更新失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("更新订单备注失败: orderId={}", orderId, e);
|
||||
return ApiResponse.fail("更新失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*/
|
||||
@PostMapping("/refund")
|
||||
public ApiResponse<String> createRefund(@RequestBody RefundRequest request) {
|
||||
log.info("申请退款: {}", request);
|
||||
try {
|
||||
Long refundId = orderService.createRefundRecord(request);
|
||||
return ApiResponse.success("退款申请已提交,退款ID:" + refundId);
|
||||
} catch (Exception e) {
|
||||
log.error("申请退款失败: {}", request, e);
|
||||
return ApiResponse.fail("退款申请失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package com.ycwl.basic.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 订单备注修改请求DTO
|
||||
*/
|
||||
@Data
|
||||
public class OrderRemarkRequest {
|
||||
|
||||
/**
|
||||
* 订单备注
|
||||
*/
|
||||
private String remarks;
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
package com.ycwl.basic.order.dto;
|
||||
|
||||
import com.ycwl.basic.order.entity.OrderDiscountV2;
|
||||
import com.ycwl.basic.order.entity.OrderItemV2;
|
||||
import com.ycwl.basic.order.entity.OrderRefundV2;
|
||||
import com.ycwl.basic.order.enums.OrderStatus;
|
||||
import com.ycwl.basic.order.enums.PaymentStatus;
|
||||
import com.ycwl.basic.order.enums.RefundStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单详情响应DTO
|
||||
*/
|
||||
@Data
|
||||
public class OrderV2DetailResponse {
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 会员ID
|
||||
*/
|
||||
private Long memberId;
|
||||
|
||||
/**
|
||||
* 小程序openId
|
||||
*/
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 人脸ID
|
||||
*/
|
||||
private Long faceId;
|
||||
|
||||
/**
|
||||
* 景区ID
|
||||
*/
|
||||
private Long scenicId;
|
||||
|
||||
/**
|
||||
* 原始金额
|
||||
*/
|
||||
private BigDecimal originalAmount;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 最终金额
|
||||
*/
|
||||
private BigDecimal finalAmount;
|
||||
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private OrderStatus orderStatus;
|
||||
|
||||
/**
|
||||
* 订单状态描述
|
||||
*/
|
||||
private String orderStatusDesc;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
*/
|
||||
private PaymentStatus paymentStatus;
|
||||
|
||||
/**
|
||||
* 支付状态描述
|
||||
*/
|
||||
private String paymentStatusDesc;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
private RefundStatus refundStatus;
|
||||
|
||||
/**
|
||||
* 退款状态描述
|
||||
*/
|
||||
private String refundStatusDesc;
|
||||
|
||||
/**
|
||||
* 总退款金额
|
||||
*/
|
||||
private BigDecimal totalRefundAmount;
|
||||
|
||||
/**
|
||||
* 订单备注
|
||||
*/
|
||||
private String remarks;
|
||||
|
||||
/**
|
||||
* 支付时间
|
||||
*/
|
||||
private Date payTime;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
private Date completeTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 订单商品明细列表
|
||||
*/
|
||||
private List<OrderItemV2> orderItems;
|
||||
|
||||
/**
|
||||
* 订单优惠记录列表
|
||||
*/
|
||||
private List<OrderDiscountV2> orderDiscounts;
|
||||
|
||||
/**
|
||||
* 订单退款记录列表
|
||||
*/
|
||||
private List<OrderRefundV2> orderRefunds;
|
||||
}
|
131
src/main/java/com/ycwl/basic/order/dto/OrderV2ListResponse.java
Normal file
131
src/main/java/com/ycwl/basic/order/dto/OrderV2ListResponse.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package com.ycwl.basic.order.dto;
|
||||
|
||||
import com.ycwl.basic.order.enums.OrderStatus;
|
||||
import com.ycwl.basic.order.enums.PaymentStatus;
|
||||
import com.ycwl.basic.order.enums.RefundStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单列表响应DTO
|
||||
*/
|
||||
@Data
|
||||
public class OrderV2ListResponse {
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 会员ID
|
||||
*/
|
||||
private Long memberId;
|
||||
|
||||
/**
|
||||
* 小程序openId
|
||||
*/
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 人脸ID
|
||||
*/
|
||||
private Long faceId;
|
||||
|
||||
/**
|
||||
* 景区ID
|
||||
*/
|
||||
private Long scenicId;
|
||||
|
||||
/**
|
||||
* 原始金额
|
||||
*/
|
||||
private BigDecimal originalAmount;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 最终金额
|
||||
*/
|
||||
private BigDecimal finalAmount;
|
||||
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private OrderStatus orderStatus;
|
||||
|
||||
/**
|
||||
* 订单状态描述
|
||||
*/
|
||||
private String orderStatusDesc;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
*/
|
||||
private PaymentStatus paymentStatus;
|
||||
|
||||
/**
|
||||
* 支付状态描述
|
||||
*/
|
||||
private String paymentStatusDesc;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
private RefundStatus refundStatus;
|
||||
|
||||
/**
|
||||
* 退款状态描述
|
||||
*/
|
||||
private String refundStatusDesc;
|
||||
|
||||
/**
|
||||
* 总退款金额
|
||||
*/
|
||||
private BigDecimal totalRefundAmount;
|
||||
|
||||
/**
|
||||
* 订单备注
|
||||
*/
|
||||
private String remarks;
|
||||
|
||||
/**
|
||||
* 支付时间
|
||||
*/
|
||||
private Date payTime;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
private Date completeTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 商品数量(订单中商品种类数)
|
||||
*/
|
||||
private Integer itemCount;
|
||||
|
||||
/**
|
||||
* 商品总数量(所有商品数量之和)
|
||||
*/
|
||||
private Integer totalQuantity;
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
package com.ycwl.basic.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单分页查询请求DTO
|
||||
*/
|
||||
@Data
|
||||
public class OrderV2PageRequest {
|
||||
|
||||
/**
|
||||
* 页码(从1开始)
|
||||
*/
|
||||
private Integer pageNum = 1;
|
||||
|
||||
/**
|
||||
* 每页大小
|
||||
*/
|
||||
private Integer pageSize = 10;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 用户ID(移动端查询时自动设置)
|
||||
*/
|
||||
private Long memberId;
|
||||
|
||||
/**
|
||||
* 景区ID
|
||||
*/
|
||||
private Long scenicId;
|
||||
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private String orderStatus;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
*/
|
||||
private String paymentStatus;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
private String refundStatus;
|
||||
|
||||
/**
|
||||
* 开始创建时间
|
||||
*/
|
||||
private Date createTimeStart;
|
||||
|
||||
/**
|
||||
* 结束创建时间
|
||||
*/
|
||||
private Date createTimeEnd;
|
||||
|
||||
/**
|
||||
* 开始支付时间
|
||||
*/
|
||||
private Date payTimeStart;
|
||||
|
||||
/**
|
||||
* 结束支付时间
|
||||
*/
|
||||
private Date payTimeEnd;
|
||||
}
|
52
src/main/java/com/ycwl/basic/order/dto/RefundRequest.java
Normal file
52
src/main/java/com/ycwl/basic/order/dto/RefundRequest.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package com.ycwl.basic.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 退款申请请求DTO
|
||||
*/
|
||||
@Data
|
||||
public class RefundRequest {
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 退款类型
|
||||
*/
|
||||
private String refundType;
|
||||
|
||||
/**
|
||||
* 退款金额
|
||||
*/
|
||||
private BigDecimal refundAmount;
|
||||
|
||||
/**
|
||||
* 退款手续费
|
||||
*/
|
||||
private BigDecimal refundFee = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
*/
|
||||
private String refundReason;
|
||||
|
||||
/**
|
||||
* 退款详细说明
|
||||
*/
|
||||
private String refundDescription;
|
||||
|
||||
/**
|
||||
* 操作备注
|
||||
*/
|
||||
private String operatorRemarks;
|
||||
|
||||
/**
|
||||
* 退款渠道
|
||||
*/
|
||||
private String refundChannel = "ORIGINAL";
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
package com.ycwl.basic.order.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ycwl.basic.order.enums.DiscountType;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单优惠记录表实体V2
|
||||
*/
|
||||
@Data
|
||||
@TableName("order_discount_v2")
|
||||
public class OrderDiscountV2 {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
@TableField("order_id")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 优惠类型
|
||||
*/
|
||||
@TableField("discount_type")
|
||||
private DiscountType discountType;
|
||||
|
||||
/**
|
||||
* 优惠名称
|
||||
*/
|
||||
@TableField("discount_name")
|
||||
private String discountName;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
@TableField("discount_amount")
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 优惠比例
|
||||
*/
|
||||
@TableField("discount_rate")
|
||||
private BigDecimal discountRate;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
@TableField("sort_order")
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 优惠券ID
|
||||
*/
|
||||
@TableField("coupon_id")
|
||||
private Long couponId;
|
||||
|
||||
/**
|
||||
* 优惠券码
|
||||
*/
|
||||
@TableField("coupon_code")
|
||||
private String couponCode;
|
||||
|
||||
/**
|
||||
* 券码
|
||||
*/
|
||||
@TableField("voucher_code")
|
||||
private String voucherCode;
|
||||
|
||||
/**
|
||||
* 券码批次ID
|
||||
*/
|
||||
@TableField("voucher_batch_id")
|
||||
private Long voucherBatchId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
}
|
84
src/main/java/com/ycwl/basic/order/entity/OrderItemV2.java
Normal file
84
src/main/java/com/ycwl/basic/order/entity/OrderItemV2.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package com.ycwl.basic.order.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单商品明细表实体V2
|
||||
*/
|
||||
@Data
|
||||
@TableName("order_item_v2")
|
||||
public class OrderItemV2 {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
@TableField("order_id")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 商品类型
|
||||
*/
|
||||
@TableField("product_type")
|
||||
private String productType;
|
||||
|
||||
/**
|
||||
* 商品ID
|
||||
*/
|
||||
@TableField("product_id")
|
||||
private String productId;
|
||||
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
@TableField("product_name")
|
||||
private String productName;
|
||||
|
||||
/**
|
||||
* 商品数量
|
||||
*/
|
||||
@TableField("quantity")
|
||||
private Integer quantity;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
@TableField("unit_price")
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 原始小计
|
||||
*/
|
||||
@TableField("original_amount")
|
||||
private BigDecimal originalAmount;
|
||||
|
||||
/**
|
||||
* 最终小计
|
||||
*/
|
||||
@TableField("final_amount")
|
||||
private BigDecimal finalAmount;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
}
|
146
src/main/java/com/ycwl/basic/order/entity/OrderRefundV2.java
Normal file
146
src/main/java/com/ycwl/basic/order/entity/OrderRefundV2.java
Normal file
@@ -0,0 +1,146 @@
|
||||
package com.ycwl.basic.order.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ycwl.basic.order.enums.RefundStatus;
|
||||
import com.ycwl.basic.order.enums.RefundType;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单退款记录表实体V2
|
||||
*/
|
||||
@Data
|
||||
@TableName("order_refund_v2")
|
||||
public class OrderRefundV2 {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
@TableField("order_id")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 退款单号
|
||||
*/
|
||||
@TableField("refund_no")
|
||||
private String refundNo;
|
||||
|
||||
/**
|
||||
* 退款类型
|
||||
*/
|
||||
@TableField("refund_type")
|
||||
private RefundType refundType;
|
||||
|
||||
/**
|
||||
* 退款金额
|
||||
*/
|
||||
@TableField("refund_amount")
|
||||
private BigDecimal refundAmount;
|
||||
|
||||
/**
|
||||
* 退款手续费
|
||||
*/
|
||||
@TableField("refund_fee")
|
||||
private BigDecimal refundFee;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
@TableField("refund_status")
|
||||
private RefundStatus refundStatus;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
*/
|
||||
@TableField("refund_reason")
|
||||
private String refundReason;
|
||||
|
||||
/**
|
||||
* 退款详细说明
|
||||
*/
|
||||
@TableField("refund_description")
|
||||
private String refundDescription;
|
||||
|
||||
/**
|
||||
* 申请人ID
|
||||
*/
|
||||
@TableField("apply_by")
|
||||
private Long applyBy;
|
||||
|
||||
/**
|
||||
* 审批人ID
|
||||
*/
|
||||
@TableField("approve_by")
|
||||
private Long approveBy;
|
||||
|
||||
/**
|
||||
* 操作备注
|
||||
*/
|
||||
@TableField("operator_remarks")
|
||||
private String operatorRemarks;
|
||||
|
||||
/**
|
||||
* 支付平台退款单号
|
||||
*/
|
||||
@TableField("payment_refund_id")
|
||||
private String paymentRefundId;
|
||||
|
||||
/**
|
||||
* 退款渠道
|
||||
*/
|
||||
@TableField("refund_channel")
|
||||
private String refundChannel;
|
||||
|
||||
/**
|
||||
* 申请时间
|
||||
*/
|
||||
@TableField("apply_time")
|
||||
private Date applyTime;
|
||||
|
||||
/**
|
||||
* 审批时间
|
||||
*/
|
||||
@TableField("approve_time")
|
||||
private Date approveTime;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
@TableField("complete_time")
|
||||
private Date completeTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField("create_by")
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@TableField("update_by")
|
||||
private Long updateBy;
|
||||
}
|
153
src/main/java/com/ycwl/basic/order/entity/OrderV2.java
Normal file
153
src/main/java/com/ycwl/basic/order/entity/OrderV2.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package com.ycwl.basic.order.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ycwl.basic.order.enums.OrderStatus;
|
||||
import com.ycwl.basic.order.enums.PaymentStatus;
|
||||
import com.ycwl.basic.order.enums.RefundStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单主表实体V2
|
||||
*/
|
||||
@Data
|
||||
@TableName("order_v2")
|
||||
public class OrderV2 {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
@TableField("order_no")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 会员ID
|
||||
*/
|
||||
@TableField("member_id")
|
||||
private Long memberId;
|
||||
|
||||
/**
|
||||
* 小程序openId
|
||||
*/
|
||||
@TableField("open_id")
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 人脸ID
|
||||
*/
|
||||
@TableField("face_id")
|
||||
private Long faceId;
|
||||
|
||||
/**
|
||||
* 景区ID
|
||||
*/
|
||||
@TableField("scenic_id")
|
||||
private Long scenicId;
|
||||
|
||||
/**
|
||||
* 原始金额
|
||||
*/
|
||||
@TableField("original_amount")
|
||||
private BigDecimal originalAmount;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
@TableField("discount_amount")
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 最终金额
|
||||
*/
|
||||
@TableField("final_amount")
|
||||
private BigDecimal finalAmount;
|
||||
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
@TableField("order_status")
|
||||
private OrderStatus orderStatus;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
*/
|
||||
@TableField("payment_status")
|
||||
private PaymentStatus paymentStatus;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
@TableField("refund_status")
|
||||
private RefundStatus refundStatus;
|
||||
|
||||
/**
|
||||
* 总退款金额
|
||||
*/
|
||||
@TableField("total_refund_amount")
|
||||
private BigDecimal totalRefundAmount;
|
||||
|
||||
/**
|
||||
* 订单备注
|
||||
*/
|
||||
@TableField("remarks")
|
||||
private String remarks;
|
||||
|
||||
/**
|
||||
* 支付时间
|
||||
*/
|
||||
@TableField("pay_time")
|
||||
private Date payTime;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
@TableField("complete_time")
|
||||
private Date completeTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField("create_by")
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@TableField("update_by")
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
*/
|
||||
@TableField("deleted")
|
||||
private Integer deleted;
|
||||
|
||||
/**
|
||||
* 删除时间
|
||||
*/
|
||||
@TableField("deleted_at")
|
||||
private Date deletedAt;
|
||||
}
|
60
src/main/java/com/ycwl/basic/order/enums/DiscountType.java
Normal file
60
src/main/java/com/ycwl/basic/order/enums/DiscountType.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.ycwl.basic.order.enums;
|
||||
|
||||
/**
|
||||
* 优惠类型枚举
|
||||
*/
|
||||
public enum DiscountType {
|
||||
|
||||
/**
|
||||
* 优惠券
|
||||
*/
|
||||
COUPON("COUPON", "优惠券"),
|
||||
|
||||
/**
|
||||
* 券码
|
||||
*/
|
||||
VOUCHER("VOUCHER", "券码"),
|
||||
|
||||
/**
|
||||
* 限时立减
|
||||
*/
|
||||
FLASH_SALE("FLASH_SALE", "限时立减"),
|
||||
|
||||
/**
|
||||
* 套餐优惠
|
||||
*/
|
||||
BUNDLE("BUNDLE", "套餐优惠"),
|
||||
|
||||
/**
|
||||
* 一口价优惠
|
||||
*/
|
||||
FIXED_PRICE("FIXED_PRICE", "一口价优惠");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
DiscountType(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static DiscountType fromCode(String code) {
|
||||
for (DiscountType type : values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown DiscountType code: " + code);
|
||||
}
|
||||
}
|
70
src/main/java/com/ycwl/basic/order/enums/OrderStatus.java
Normal file
70
src/main/java/com/ycwl/basic/order/enums/OrderStatus.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.ycwl.basic.order.enums;
|
||||
|
||||
/**
|
||||
* 订单状态枚举
|
||||
*/
|
||||
public enum OrderStatus {
|
||||
|
||||
/**
|
||||
* 待支付
|
||||
*/
|
||||
PENDING_PAYMENT("PENDING_PAYMENT", "待支付"),
|
||||
|
||||
/**
|
||||
* 已支付
|
||||
*/
|
||||
PAID("PAID", "已支付"),
|
||||
|
||||
/**
|
||||
* 处理中
|
||||
*/
|
||||
PROCESSING("PROCESSING", "处理中"),
|
||||
|
||||
/**
|
||||
* 已完成
|
||||
*/
|
||||
COMPLETED("COMPLETED", "已完成"),
|
||||
|
||||
/**
|
||||
* 已取消
|
||||
*/
|
||||
CANCELLED("CANCELLED", "已取消"),
|
||||
|
||||
/**
|
||||
* 退款中
|
||||
*/
|
||||
REFUNDING("REFUNDING", "退款中"),
|
||||
|
||||
/**
|
||||
* 已退款
|
||||
*/
|
||||
REFUNDED("REFUNDED", "已退款");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
OrderStatus(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static OrderStatus fromCode(String code) {
|
||||
for (OrderStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown OrderStatus code: " + code);
|
||||
}
|
||||
}
|
50
src/main/java/com/ycwl/basic/order/enums/PaymentStatus.java
Normal file
50
src/main/java/com/ycwl/basic/order/enums/PaymentStatus.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.ycwl.basic.order.enums;
|
||||
|
||||
/**
|
||||
* 支付状态枚举
|
||||
*/
|
||||
public enum PaymentStatus {
|
||||
|
||||
/**
|
||||
* 未支付
|
||||
*/
|
||||
UNPAID("UNPAID", "未支付"),
|
||||
|
||||
/**
|
||||
* 已支付
|
||||
*/
|
||||
PAID("PAID", "已支付"),
|
||||
|
||||
/**
|
||||
* 已退款
|
||||
*/
|
||||
REFUNDED("REFUNDED", "已退款");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
PaymentStatus(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static PaymentStatus fromCode(String code) {
|
||||
for (PaymentStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown PaymentStatus code: " + code);
|
||||
}
|
||||
}
|
55
src/main/java/com/ycwl/basic/order/enums/RefundStatus.java
Normal file
55
src/main/java/com/ycwl/basic/order/enums/RefundStatus.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.ycwl.basic.order.enums;
|
||||
|
||||
/**
|
||||
* 退款状态枚举
|
||||
*/
|
||||
public enum RefundStatus {
|
||||
|
||||
/**
|
||||
* 无退款
|
||||
*/
|
||||
NO_REFUND("NO_REFUND", "无退款"),
|
||||
|
||||
/**
|
||||
* 部分退款
|
||||
*/
|
||||
PARTIAL_REFUND("PARTIAL_REFUND", "部分退款"),
|
||||
|
||||
/**
|
||||
* 全额退款
|
||||
*/
|
||||
FULL_REFUND("FULL_REFUND", "全额退款"),
|
||||
|
||||
/**
|
||||
* 退款处理中
|
||||
*/
|
||||
REFUND_PROCESSING("REFUND_PROCESSING", "退款处理中");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
RefundStatus(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static RefundStatus fromCode(String code) {
|
||||
for (RefundStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown RefundStatus code: " + code);
|
||||
}
|
||||
}
|
50
src/main/java/com/ycwl/basic/order/enums/RefundType.java
Normal file
50
src/main/java/com/ycwl/basic/order/enums/RefundType.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.ycwl.basic.order.enums;
|
||||
|
||||
/**
|
||||
* 退款类型枚举
|
||||
*/
|
||||
public enum RefundType {
|
||||
|
||||
/**
|
||||
* 全额退款
|
||||
*/
|
||||
FULL_REFUND("FULL_REFUND", "全额退款"),
|
||||
|
||||
/**
|
||||
* 部分退款
|
||||
*/
|
||||
PARTIAL_REFUND("PARTIAL_REFUND", "部分退款"),
|
||||
|
||||
/**
|
||||
* 商品退款
|
||||
*/
|
||||
ITEM_REFUND("ITEM_REFUND", "商品退款");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
RefundType(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static RefundType fromCode(String code) {
|
||||
for (RefundType type : values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown RefundType code: " + code);
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package com.ycwl.basic.order.event;
|
||||
|
||||
/**
|
||||
* 订单事件监听器接口
|
||||
*/
|
||||
public interface OrderEventListener {
|
||||
|
||||
/**
|
||||
* 支付状态变更事件
|
||||
*
|
||||
* @param event 支付状态变更事件
|
||||
*/
|
||||
void onPaymentStatusChanged(PaymentStatusChangeEvent event);
|
||||
|
||||
/**
|
||||
* 退款状态变更事件
|
||||
*
|
||||
* @param event 退款状态变更事件
|
||||
*/
|
||||
void onRefundStatusChanged(RefundStatusChangeEvent event);
|
||||
|
||||
/**
|
||||
* 订单状态变更事件
|
||||
*
|
||||
* @param event 订单状态变更事件
|
||||
*/
|
||||
void onOrderStatusChanged(OrderStatusChangeEvent event);
|
||||
}
|
125
src/main/java/com/ycwl/basic/order/event/OrderEventManager.java
Normal file
125
src/main/java/com/ycwl/basic/order/event/OrderEventManager.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package com.ycwl.basic.order.event;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* 订单事件管理器
|
||||
* 管理事件监听器的注册和事件分发
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class OrderEventManager {
|
||||
|
||||
private final List<OrderEventListener> listeners = new ArrayList<>();
|
||||
private final Executor eventExecutor = Executors.newFixedThreadPool(5,
|
||||
r -> new Thread(r, "order-event-thread"));
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.info("订单事件管理器初始化完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册事件监听器
|
||||
*
|
||||
* @param listener 监听器实例
|
||||
*/
|
||||
public void registerListener(OrderEventListener listener) {
|
||||
if (listener != null && !listeners.contains(listener)) {
|
||||
listeners.add(listener);
|
||||
log.info("注册订单事件监听器: {}", listener.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除事件监听器
|
||||
*
|
||||
* @param listener 监听器实例
|
||||
*/
|
||||
public void removeListener(OrderEventListener listener) {
|
||||
if (listeners.remove(listener)) {
|
||||
log.info("移除订单事件监听器: {}", listener.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布支付状态变更事件
|
||||
*
|
||||
* @param event 支付状态变更事件
|
||||
*/
|
||||
public void publishPaymentStatusChangeEvent(PaymentStatusChangeEvent event) {
|
||||
log.info("发布支付状态变更事件: orderId={}, {} -> {}",
|
||||
event.getOrderId(), event.getOldPaymentStatus(), event.getNewPaymentStatus());
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (OrderEventListener listener : listeners) {
|
||||
try {
|
||||
listener.onPaymentStatusChanged(event);
|
||||
} catch (Exception e) {
|
||||
log.error("处理支付状态变更事件失败: listener={}, orderId={}",
|
||||
listener.getClass().getSimpleName(), event.getOrderId(), e);
|
||||
}
|
||||
}
|
||||
}, eventExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布退款状态变更事件
|
||||
*
|
||||
* @param event 退款状态变更事件
|
||||
*/
|
||||
public void publishRefundStatusChangeEvent(RefundStatusChangeEvent event) {
|
||||
log.info("发布退款状态变更事件: orderId={}, refundId={}, {} -> {}",
|
||||
event.getOrderId(), event.getRefundId(),
|
||||
event.getOldRefundStatus(), event.getNewRefundStatus());
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (OrderEventListener listener : listeners) {
|
||||
try {
|
||||
listener.onRefundStatusChanged(event);
|
||||
} catch (Exception e) {
|
||||
log.error("处理退款状态变更事件失败: listener={}, orderId={}, refundId={}",
|
||||
listener.getClass().getSimpleName(), event.getOrderId(), event.getRefundId(), e);
|
||||
}
|
||||
}
|
||||
}, eventExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布订单状态变更事件
|
||||
*
|
||||
* @param event 订单状态变更事件
|
||||
*/
|
||||
public void publishOrderStatusChangeEvent(OrderStatusChangeEvent event) {
|
||||
log.info("发布订单状态变更事件: orderId={}, {} -> {}",
|
||||
event.getOrderId(), event.getOldOrderStatus(), event.getNewOrderStatus());
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (OrderEventListener listener : listeners) {
|
||||
try {
|
||||
listener.onOrderStatusChanged(event);
|
||||
} catch (Exception e) {
|
||||
log.error("处理订单状态变更事件失败: listener={}, orderId={}",
|
||||
listener.getClass().getSimpleName(), event.getOrderId(), e);
|
||||
}
|
||||
}
|
||||
}, eventExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已注册的监听器数量
|
||||
*
|
||||
* @return 监听器数量
|
||||
*/
|
||||
public int getListenerCount() {
|
||||
return listeners.size();
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package com.ycwl.basic.order.event;
|
||||
|
||||
import com.ycwl.basic.order.enums.OrderStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单状态变更事件
|
||||
*/
|
||||
@Data
|
||||
public class OrderStatusChangeEvent {
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 旧的订单状态
|
||||
*/
|
||||
private OrderStatus oldOrderStatus;
|
||||
|
||||
/**
|
||||
* 新的订单状态
|
||||
*/
|
||||
private OrderStatus newOrderStatus;
|
||||
|
||||
/**
|
||||
* 变更时间
|
||||
*/
|
||||
private Date changeTime;
|
||||
|
||||
/**
|
||||
* 变更原因
|
||||
*/
|
||||
private String changeReason;
|
||||
|
||||
/**
|
||||
* 操作人ID
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
public OrderStatusChangeEvent(Long orderId, String orderNo,
|
||||
OrderStatus oldStatus, OrderStatus newStatus,
|
||||
String changeReason, Long operatorId) {
|
||||
this.orderId = orderId;
|
||||
this.orderNo = orderNo;
|
||||
this.oldOrderStatus = oldStatus;
|
||||
this.newOrderStatus = newStatus;
|
||||
this.changeReason = changeReason;
|
||||
this.operatorId = operatorId;
|
||||
this.changeTime = new Date();
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package com.ycwl.basic.order.event;
|
||||
|
||||
import com.ycwl.basic.order.enums.PaymentStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付状态变更事件
|
||||
*/
|
||||
@Data
|
||||
public class PaymentStatusChangeEvent {
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 旧的支付状态
|
||||
*/
|
||||
private PaymentStatus oldPaymentStatus;
|
||||
|
||||
/**
|
||||
* 新的支付状态
|
||||
*/
|
||||
private PaymentStatus newPaymentStatus;
|
||||
|
||||
/**
|
||||
* 变更时间
|
||||
*/
|
||||
private Date changeTime;
|
||||
|
||||
/**
|
||||
* 变更原因
|
||||
*/
|
||||
private String changeReason;
|
||||
|
||||
/**
|
||||
* 操作人ID
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
public PaymentStatusChangeEvent(Long orderId, String orderNo,
|
||||
PaymentStatus oldStatus, PaymentStatus newStatus,
|
||||
String changeReason, Long operatorId) {
|
||||
this.orderId = orderId;
|
||||
this.orderNo = orderNo;
|
||||
this.oldPaymentStatus = oldStatus;
|
||||
this.newPaymentStatus = newStatus;
|
||||
this.changeReason = changeReason;
|
||||
this.operatorId = operatorId;
|
||||
this.changeTime = new Date();
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
package com.ycwl.basic.order.event;
|
||||
|
||||
import com.ycwl.basic.order.enums.RefundStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 退款状态变更事件
|
||||
*/
|
||||
@Data
|
||||
public class RefundStatusChangeEvent {
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 退款记录ID
|
||||
*/
|
||||
private Long refundId;
|
||||
|
||||
/**
|
||||
* 退款单号
|
||||
*/
|
||||
private String refundNo;
|
||||
|
||||
/**
|
||||
* 旧的退款状态
|
||||
*/
|
||||
private RefundStatus oldRefundStatus;
|
||||
|
||||
/**
|
||||
* 新的退款状态
|
||||
*/
|
||||
private RefundStatus newRefundStatus;
|
||||
|
||||
/**
|
||||
* 退款金额
|
||||
*/
|
||||
private BigDecimal refundAmount;
|
||||
|
||||
/**
|
||||
* 变更时间
|
||||
*/
|
||||
private Date changeTime;
|
||||
|
||||
/**
|
||||
* 变更原因
|
||||
*/
|
||||
private String changeReason;
|
||||
|
||||
/**
|
||||
* 操作人ID
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
public RefundStatusChangeEvent(Long orderId, String orderNo, Long refundId, String refundNo,
|
||||
RefundStatus oldStatus, RefundStatus newStatus,
|
||||
BigDecimal refundAmount, String changeReason, Long operatorId) {
|
||||
this.orderId = orderId;
|
||||
this.orderNo = orderNo;
|
||||
this.refundId = refundId;
|
||||
this.refundNo = refundNo;
|
||||
this.oldRefundStatus = oldStatus;
|
||||
this.newRefundStatus = newStatus;
|
||||
this.refundAmount = refundAmount;
|
||||
this.changeReason = changeReason;
|
||||
this.operatorId = operatorId;
|
||||
this.changeTime = new Date();
|
||||
}
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
package com.ycwl.basic.order.event.impl;
|
||||
|
||||
import com.ycwl.basic.order.event.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 支付状态变更监听器示例
|
||||
* 应用启动后自动注册到事件管理器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PaymentStatusChangeListener implements OrderEventListener {
|
||||
|
||||
@Resource
|
||||
private OrderEventManager orderEventManager;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// 应用启动后自动注册到事件管理器
|
||||
orderEventManager.registerListener(this);
|
||||
log.info("支付状态变更监听器注册完成");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPaymentStatusChanged(PaymentStatusChangeEvent event) {
|
||||
log.info("处理支付状态变更事件: orderId={}, orderNo={}, {} -> {}, reason={}",
|
||||
event.getOrderId(), event.getOrderNo(),
|
||||
event.getOldPaymentStatus(), event.getNewPaymentStatus(),
|
||||
event.getChangeReason());
|
||||
|
||||
// 根据支付状态执行相应的业务逻辑
|
||||
switch (event.getNewPaymentStatus()) {
|
||||
case PAID:
|
||||
handlePaymentSuccess(event);
|
||||
break;
|
||||
case REFUNDED:
|
||||
handlePaymentRefunded(event);
|
||||
break;
|
||||
case UNPAID:
|
||||
handlePaymentPending(event);
|
||||
break;
|
||||
default:
|
||||
log.warn("未处理的支付状态: {}", event.getNewPaymentStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefundStatusChanged(RefundStatusChangeEvent event) {
|
||||
log.info("处理退款状态变更事件: orderId={}, refundId={}, {} -> {}",
|
||||
event.getOrderId(), event.getRefundId(),
|
||||
event.getOldRefundStatus(), event.getNewRefundStatus());
|
||||
|
||||
// 可以在这里添加退款相关的业务逻辑
|
||||
// 比如发送通知、更新库存等
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOrderStatusChanged(OrderStatusChangeEvent event) {
|
||||
log.info("处理订单状态变更事件: orderId={}, {} -> {}",
|
||||
event.getOrderId(), event.getOldOrderStatus(), event.getNewOrderStatus());
|
||||
|
||||
// 可以在这里添加订单状态相关的业务逻辑
|
||||
// 比如发送用户通知、触发后续流程等
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付成功事件
|
||||
*/
|
||||
private void handlePaymentSuccess(PaymentStatusChangeEvent event) {
|
||||
log.info("处理支付成功: orderId={}", event.getOrderId());
|
||||
|
||||
// 这里可以添加支付成功后的业务逻辑:
|
||||
// 1. 发送支付成功通知
|
||||
// 2. 更新商品库存
|
||||
// 3. 生成相关凭证
|
||||
// 4. 发送短信/邮件通知
|
||||
// 5. 启动履约流程
|
||||
|
||||
// 示例:记录支付成功日志
|
||||
log.info("订单支付成功处理完成: orderId={}, changeTime={}",
|
||||
event.getOrderId(), event.getChangeTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付退款事件
|
||||
*/
|
||||
private void handlePaymentRefunded(PaymentStatusChangeEvent event) {
|
||||
log.info("处理支付退款: orderId={}", event.getOrderId());
|
||||
|
||||
// 这里可以添加支付退款后的业务逻辑:
|
||||
// 1. 恢复商品库存
|
||||
// 2. 取消相关服务
|
||||
// 3. 发送退款通知
|
||||
// 4. 更新会员积分
|
||||
|
||||
// 示例:记录退款处理日志
|
||||
log.info("订单退款处理完成: orderId={}, changeTime={}",
|
||||
event.getOrderId(), event.getChangeTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付待处理事件
|
||||
*/
|
||||
private void handlePaymentPending(PaymentStatusChangeEvent event) {
|
||||
log.info("处理支付待处理: orderId={}", event.getOrderId());
|
||||
|
||||
// 这里可以添加支付待处理的业务逻辑:
|
||||
// 1. 设置支付超时提醒
|
||||
// 2. 预留库存
|
||||
// 3. 发送支付提醒
|
||||
|
||||
// 示例:记录待支付处理日志
|
||||
log.info("订单待支付处理完成: orderId={}, changeTime={}",
|
||||
event.getOrderId(), event.getChangeTime());
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.order.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.order.entity.OrderDiscountV2;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单优惠记录表Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderDiscountMapper extends BaseMapper<OrderDiscountV2> {
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.order.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.order.entity.OrderItemV2;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单商品明细表Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderItemMapper extends BaseMapper<OrderItemV2> {
|
||||
}
|
12
src/main/java/com/ycwl/basic/order/mapper/OrderMapper.java
Normal file
12
src/main/java/com/ycwl/basic/order/mapper/OrderMapper.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.order.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.order.entity.OrderV2;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单表Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderMapper extends BaseMapper<OrderV2> {
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.order.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.order.entity.OrderRefundV2;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单退款记录表Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderRefundMapper extends BaseMapper<OrderRefundV2> {
|
||||
}
|
119
src/main/java/com/ycwl/basic/order/service/IOrderService.java
Normal file
119
src/main/java/com/ycwl/basic/order/service/IOrderService.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package com.ycwl.basic.order.service;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.dto.MobileOrderRequest;
|
||||
import com.ycwl.basic.order.dto.*;
|
||||
import com.ycwl.basic.order.entity.OrderV2;
|
||||
import com.ycwl.basic.order.enums.RefundStatus;
|
||||
import com.ycwl.basic.pricing.dto.PriceCalculationResult;
|
||||
|
||||
/**
|
||||
* 订单服务接口
|
||||
*/
|
||||
public interface IOrderService {
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*
|
||||
* @param request 移动端下单请求
|
||||
* @param userId 用户ID
|
||||
* @param scenicId 景区ID
|
||||
* @param priceResult 价格计算结果
|
||||
* @return 订单ID
|
||||
*/
|
||||
Long createOrder(MobileOrderRequest request, Long userId, Long scenicId, PriceCalculationResult priceResult);
|
||||
|
||||
/**
|
||||
* 根据订单号查询订单
|
||||
*
|
||||
* @param orderNo 订单号
|
||||
* @return 订单信息
|
||||
*/
|
||||
OrderV2 getByOrderNo(String orderNo);
|
||||
|
||||
/**
|
||||
* 根据订单ID查询订单
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @return 订单信息
|
||||
*/
|
||||
OrderV2 getById(Long orderId);
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param orderStatus 订单状态
|
||||
* @param paymentStatus 支付状态
|
||||
* @return 更新结果
|
||||
*/
|
||||
boolean updateOrderStatus(Long orderId, String orderStatus, String paymentStatus);
|
||||
|
||||
/**
|
||||
* 生成订单号
|
||||
*
|
||||
* @return 订单号
|
||||
*/
|
||||
String generateOrderNo();
|
||||
|
||||
// ====== 新增方法 ======
|
||||
|
||||
/**
|
||||
* 分页查询订单列表
|
||||
*
|
||||
* @param request 分页查询请求
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<OrderV2ListResponse> pageOrders(OrderV2PageRequest request);
|
||||
|
||||
/**
|
||||
* 查询订单详情(包含商品明细、优惠记录、退款记录)
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @return 订单详情
|
||||
*/
|
||||
OrderV2DetailResponse getOrderDetail(Long orderId);
|
||||
|
||||
/**
|
||||
* 更新订单备注
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param remarks 备注内容
|
||||
* @return 更新结果
|
||||
*/
|
||||
boolean updateOrderRemarks(Long orderId, String remarks);
|
||||
|
||||
/**
|
||||
* 更新支付状态
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param paymentStatus 支付状态
|
||||
* @return 更新结果
|
||||
*/
|
||||
boolean updatePaymentStatus(Long orderId, String paymentStatus);
|
||||
|
||||
/**
|
||||
* 更新退款状态
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param refundStatus 退款状态
|
||||
* @return 更新结果
|
||||
*/
|
||||
boolean updateRefundStatus(Long orderId, RefundStatus refundStatus);
|
||||
|
||||
/**
|
||||
* 创建退款记录
|
||||
*
|
||||
* @param request 退款申请请求
|
||||
* @return 退款记录ID
|
||||
*/
|
||||
Long createRefundRecord(RefundRequest request);
|
||||
|
||||
/**
|
||||
* 根据用户ID分页查询订单列表(移动端使用)
|
||||
*
|
||||
* @param request 分页查询请求(已设置用户ID)
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<OrderV2ListResponse> pageOrdersByUser(OrderV2PageRequest request);
|
||||
}
|
@@ -0,0 +1,530 @@
|
||||
package com.ycwl.basic.order.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.dto.MobileOrderRequest;
|
||||
import com.ycwl.basic.order.dto.*;
|
||||
import com.ycwl.basic.order.entity.OrderDiscountV2;
|
||||
import com.ycwl.basic.order.entity.OrderItemV2;
|
||||
import com.ycwl.basic.order.entity.OrderRefundV2;
|
||||
import com.ycwl.basic.order.entity.OrderV2;
|
||||
import com.ycwl.basic.order.enums.*;
|
||||
import com.ycwl.basic.order.mapper.OrderDiscountMapper;
|
||||
import com.ycwl.basic.order.mapper.OrderItemMapper;
|
||||
import com.ycwl.basic.order.mapper.OrderMapper;
|
||||
import com.ycwl.basic.order.mapper.OrderRefundMapper;
|
||||
import com.ycwl.basic.order.service.IOrderService;
|
||||
import com.ycwl.basic.order.event.*;
|
||||
import com.ycwl.basic.pricing.dto.DiscountDetail;
|
||||
import com.ycwl.basic.pricing.dto.PriceCalculationResult;
|
||||
import com.ycwl.basic.pricing.dto.ProductItem;
|
||||
import com.ycwl.basic.pricing.dto.VoucherInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 订单服务实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OrderServiceImpl implements IOrderService {
|
||||
|
||||
private final OrderMapper orderMapper;
|
||||
private final OrderItemMapper orderItemMapper;
|
||||
private final OrderDiscountMapper orderDiscountMapper;
|
||||
private final OrderRefundMapper orderRefundMapper;
|
||||
private final OrderEventManager orderEventManager;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Long createOrder(MobileOrderRequest request, Long userId, Long scenicId, PriceCalculationResult priceResult) {
|
||||
Date now = new Date();
|
||||
|
||||
// 1. 生成订单号
|
||||
String orderNo = generateOrderNo();
|
||||
|
||||
// 2. 创建订单基础信息
|
||||
OrderV2 order = new OrderV2();
|
||||
order.setOrderNo(orderNo);
|
||||
order.setMemberId(userId);
|
||||
order.setOpenId(request.getFaceId().toString()); // 临时使用faceId,实际应传入openId
|
||||
order.setFaceId(request.getFaceId());
|
||||
order.setScenicId(scenicId);
|
||||
|
||||
order.setOriginalAmount(priceResult.getOriginalAmount());
|
||||
order.setDiscountAmount(priceResult.getDiscountAmount());
|
||||
order.setFinalAmount(priceResult.getFinalAmount());
|
||||
|
||||
order.setOrderStatus(OrderStatus.PENDING_PAYMENT);
|
||||
order.setPaymentStatus(PaymentStatus.UNPAID);
|
||||
order.setRefundStatus(RefundStatus.NO_REFUND);
|
||||
order.setTotalRefundAmount(BigDecimal.ZERO);
|
||||
|
||||
order.setRemarks(request.getRemarks());
|
||||
order.setCreateTime(now);
|
||||
order.setUpdateTime(now);
|
||||
order.setCreateBy(userId);
|
||||
order.setUpdateBy(userId);
|
||||
order.setDeleted(0);
|
||||
|
||||
// 保存订单
|
||||
orderMapper.insert(order);
|
||||
Long orderId = order.getId();
|
||||
|
||||
log.info("订单基础信息创建成功: orderId={}, orderNo={}", orderId, orderNo);
|
||||
|
||||
// 3. 保存订单商品明细
|
||||
for (ProductItem product : request.getProducts()) {
|
||||
OrderItemV2 orderItem = new OrderItemV2();
|
||||
orderItem.setOrderId(orderId);
|
||||
orderItem.setProductType(product.getProductType().name());
|
||||
orderItem.setProductId(product.getProductId());
|
||||
orderItem.setProductName(getProductName(product)); // 根据商品类型和ID获取商品名称
|
||||
orderItem.setQuantity(product.getQuantity());
|
||||
orderItem.setUnitPrice(product.getUnitPrice());
|
||||
orderItem.setOriginalAmount(product.getOriginalPrice());
|
||||
orderItem.setFinalAmount(product.getSubtotal());
|
||||
orderItem.setCreateTime(now);
|
||||
orderItem.setUpdateTime(now);
|
||||
|
||||
orderItemMapper.insert(orderItem);
|
||||
}
|
||||
|
||||
log.info("订单商品明细保存成功: orderId={}, itemCount={}", orderId, request.getProducts().size());
|
||||
|
||||
// 4. 记录使用的优惠券信息
|
||||
if (priceResult.getUsedCoupon() != null) {
|
||||
OrderDiscountV2 couponDiscount = new OrderDiscountV2();
|
||||
couponDiscount.setOrderId(orderId);
|
||||
couponDiscount.setDiscountType(DiscountType.COUPON);
|
||||
couponDiscount.setDiscountName(priceResult.getUsedCoupon().getCouponName());
|
||||
couponDiscount.setDiscountAmount(priceResult.getUsedCoupon().getActualDiscountAmount());
|
||||
couponDiscount.setSortOrder(3); // 优惠券显示顺序
|
||||
couponDiscount.setCouponId(priceResult.getUsedCoupon().getCouponId());
|
||||
couponDiscount.setCreateTime(now);
|
||||
|
||||
orderDiscountMapper.insert(couponDiscount);
|
||||
log.info("优惠券记录保存成功: orderId={}, couponId={}, discountAmount={}",
|
||||
orderId, priceResult.getUsedCoupon().getCouponId(), priceResult.getUsedCoupon().getActualDiscountAmount());
|
||||
}
|
||||
|
||||
// 5. 记录使用的券码信息
|
||||
if (priceResult.getUsedVoucher() != null) {
|
||||
VoucherInfo voucherInfo = priceResult.getUsedVoucher();
|
||||
OrderDiscountV2 voucherDiscount = new OrderDiscountV2();
|
||||
voucherDiscount.setOrderId(orderId);
|
||||
voucherDiscount.setDiscountType(DiscountType.VOUCHER);
|
||||
voucherDiscount.setDiscountName(voucherInfo.getBatchName());
|
||||
voucherDiscount.setDiscountAmount(voucherInfo.getActualDiscountAmount());
|
||||
voucherDiscount.setSortOrder(1); // 券码显示顺序最高
|
||||
voucherDiscount.setVoucherCode(voucherInfo.getVoucherCode());
|
||||
voucherDiscount.setCreateTime(now);
|
||||
|
||||
orderDiscountMapper.insert(voucherDiscount);
|
||||
log.info("券码记录保存成功: orderId={}, voucherCode={}, discountAmount={}",
|
||||
orderId, voucherInfo.getVoucherCode(), voucherInfo.getActualDiscountAmount());
|
||||
}
|
||||
|
||||
// 6. 记录其他优惠信息(如限时立减等)
|
||||
if (priceResult.getDiscountDetails() != null) {
|
||||
for (DiscountDetail discount : priceResult.getDiscountDetails()) {
|
||||
// 跳过已经记录的优惠券和券码
|
||||
if ("VOUCHER".equals(discount.getDiscountType()) || "COUPON".equals(discount.getDiscountType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OrderDiscountV2 otherDiscount = new OrderDiscountV2();
|
||||
otherDiscount.setOrderId(orderId);
|
||||
otherDiscount.setDiscountType(DiscountType.fromCode(discount.getDiscountType()));
|
||||
otherDiscount.setDiscountName(discount.getDiscountName());
|
||||
otherDiscount.setDiscountAmount(discount.getDiscountAmount());
|
||||
otherDiscount.setSortOrder(discount.getSortOrder());
|
||||
otherDiscount.setCreateTime(now);
|
||||
|
||||
orderDiscountMapper.insert(otherDiscount);
|
||||
log.info("其他优惠记录保存成功: orderId={}, type={}, discountAmount={}",
|
||||
orderId, discount.getDiscountType(), discount.getDiscountAmount());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("订单创建完成: orderId={}, orderNo={}, finalAmount={}",
|
||||
orderId, orderNo, priceResult.getFinalAmount());
|
||||
|
||||
return orderId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderV2 getByOrderNo(String orderNo) {
|
||||
QueryWrapper<OrderV2> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("order_no", orderNo);
|
||||
queryWrapper.eq("deleted", 0);
|
||||
return orderMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderV2 getById(Long orderId) {
|
||||
return orderMapper.selectById(orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOrderStatus(Long orderId, String orderStatus, String paymentStatus) {
|
||||
OrderV2 order = new OrderV2();
|
||||
order.setId(orderId);
|
||||
order.setOrderStatus(OrderStatus.fromCode(orderStatus));
|
||||
order.setPaymentStatus(PaymentStatus.fromCode(paymentStatus));
|
||||
order.setUpdateTime(new Date());
|
||||
|
||||
if ("PAID".equals(paymentStatus)) {
|
||||
order.setPayTime(new Date());
|
||||
}
|
||||
|
||||
if ("COMPLETED".equals(orderStatus)) {
|
||||
order.setCompleteTime(new Date());
|
||||
}
|
||||
|
||||
return orderMapper.updateById(order) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateOrderNo() {
|
||||
// 生成订单号:ORDER + 时间戳 + 3位随机数
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
String timestamp = sdf.format(new Date());
|
||||
int random = (int) (Math.random() * 900) + 100;
|
||||
return "ORDER" + timestamp + random;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品类型和ID获取商品名称
|
||||
* TODO: 实际应该从商品配置表或其他数据源获取
|
||||
*/
|
||||
private String getProductName(ProductItem product) {
|
||||
return product.getProductType().getDescription() + "-" + product.getProductId();
|
||||
}
|
||||
|
||||
// ====== 新增方法实现 ======
|
||||
|
||||
@Override
|
||||
public PageInfo<OrderV2ListResponse> pageOrders(OrderV2PageRequest request) {
|
||||
PageHelper.startPage(request.getPageNum(), request.getPageSize());
|
||||
|
||||
QueryWrapper<OrderV2> queryWrapper = buildOrderQueryWrapper(request);
|
||||
List<OrderV2> orders = orderMapper.selectList(queryWrapper);
|
||||
|
||||
// 转换为响应DTO
|
||||
List<OrderV2ListResponse> responseList = orders.stream()
|
||||
.map(this::convertToListResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new PageInfo<>(responseList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderV2DetailResponse getOrderDetail(Long orderId) {
|
||||
// 查询订单基础信息
|
||||
OrderV2 order = orderMapper.selectById(orderId);
|
||||
if (order == null || order.getDeleted() == 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 查询订单商品明细
|
||||
QueryWrapper<OrderItemV2> itemQuery = new QueryWrapper<>();
|
||||
itemQuery.eq("order_id", orderId);
|
||||
List<OrderItemV2> orderItems = orderItemMapper.selectList(itemQuery);
|
||||
|
||||
// 查询订单优惠记录
|
||||
QueryWrapper<OrderDiscountV2> discountQuery = new QueryWrapper<>();
|
||||
discountQuery.eq("order_id", orderId).orderByAsc("sort_order");
|
||||
List<OrderDiscountV2> orderDiscounts = orderDiscountMapper.selectList(discountQuery);
|
||||
|
||||
// 查询订单退款记录
|
||||
QueryWrapper<OrderRefundV2> refundQuery = new QueryWrapper<>();
|
||||
refundQuery.eq("order_id", orderId).orderByDesc("create_time");
|
||||
List<OrderRefundV2> orderRefunds = orderRefundMapper.selectList(refundQuery);
|
||||
|
||||
// 转换为响应DTO
|
||||
return convertToDetailResponse(order, orderItems, orderDiscounts, orderRefunds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean updateOrderRemarks(Long orderId, String remarks) {
|
||||
OrderV2 order = new OrderV2();
|
||||
order.setId(orderId);
|
||||
order.setRemarks(remarks);
|
||||
order.setUpdateTime(new Date());
|
||||
|
||||
return orderMapper.updateById(order) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean updatePaymentStatus(Long orderId, String paymentStatus) {
|
||||
// 先查询当前订单状态
|
||||
OrderV2 currentOrder = orderMapper.selectById(orderId);
|
||||
if (currentOrder == null) {
|
||||
log.warn("订单不存在: orderId={}", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
PaymentStatus oldPaymentStatus = currentOrder.getPaymentStatus();
|
||||
PaymentStatus newPaymentStatus = PaymentStatus.fromCode(paymentStatus);
|
||||
|
||||
// 更新订单支付状态
|
||||
OrderV2 order = new OrderV2();
|
||||
order.setId(orderId);
|
||||
order.setPaymentStatus(newPaymentStatus);
|
||||
order.setUpdateTime(new Date());
|
||||
|
||||
if ("PAID".equals(paymentStatus)) {
|
||||
order.setPayTime(new Date());
|
||||
// 支付完成后,订单状态也需要更新
|
||||
order.setOrderStatus(OrderStatus.PAID);
|
||||
}
|
||||
|
||||
boolean success = orderMapper.updateById(order) > 0;
|
||||
|
||||
// 发布支付状态变更事件
|
||||
if (success && !oldPaymentStatus.equals(newPaymentStatus)) {
|
||||
PaymentStatusChangeEvent event = new PaymentStatusChangeEvent(
|
||||
orderId, currentOrder.getOrderNo(),
|
||||
oldPaymentStatus, newPaymentStatus,
|
||||
"支付状态更新", null
|
||||
);
|
||||
orderEventManager.publishPaymentStatusChangeEvent(event);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean updateRefundStatus(Long orderId, RefundStatus refundStatus) {
|
||||
// 先查询当前订单状态
|
||||
OrderV2 currentOrder = orderMapper.selectById(orderId);
|
||||
if (currentOrder == null) {
|
||||
log.warn("订单不存在: orderId={}", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
RefundStatus oldRefundStatus = currentOrder.getRefundStatus();
|
||||
|
||||
// 更新订单退款状态
|
||||
OrderV2 order = new OrderV2();
|
||||
order.setId(orderId);
|
||||
order.setRefundStatus(refundStatus);
|
||||
order.setUpdateTime(new Date());
|
||||
|
||||
// 根据退款状态更新订单状态
|
||||
if (RefundStatus.FULL_REFUND.equals(refundStatus)) {
|
||||
order.setOrderStatus(OrderStatus.REFUNDED);
|
||||
} else if (RefundStatus.REFUND_PROCESSING.equals(refundStatus)) {
|
||||
order.setOrderStatus(OrderStatus.REFUNDING);
|
||||
}
|
||||
|
||||
boolean success = orderMapper.updateById(order) > 0;
|
||||
|
||||
// 发布退款状态变更事件
|
||||
if (success && !oldRefundStatus.equals(refundStatus)) {
|
||||
RefundStatusChangeEvent event = new RefundStatusChangeEvent(
|
||||
orderId, currentOrder.getOrderNo(), null, null,
|
||||
oldRefundStatus, refundStatus, null,
|
||||
"退款状态更新", null
|
||||
);
|
||||
orderEventManager.publishRefundStatusChangeEvent(event);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Long createRefundRecord(RefundRequest request) {
|
||||
Date now = new Date();
|
||||
|
||||
// 生成退款单号
|
||||
String refundNo = generateRefundNo();
|
||||
|
||||
// 创建退款记录
|
||||
OrderRefundV2 refund = new OrderRefundV2();
|
||||
refund.setOrderId(request.getOrderId());
|
||||
refund.setRefundNo(refundNo);
|
||||
refund.setRefundType(RefundType.fromCode(request.getRefundType()));
|
||||
refund.setRefundAmount(request.getRefundAmount());
|
||||
refund.setRefundFee(request.getRefundFee());
|
||||
refund.setRefundStatus(com.ycwl.basic.order.enums.RefundStatus.REFUND_PROCESSING);
|
||||
refund.setRefundReason(request.getRefundReason());
|
||||
refund.setRefundDescription(request.getRefundDescription());
|
||||
refund.setOperatorRemarks(request.getOperatorRemarks());
|
||||
refund.setRefundChannel(request.getRefundChannel());
|
||||
refund.setApplyTime(now);
|
||||
refund.setCreateTime(now);
|
||||
refund.setUpdateTime(now);
|
||||
|
||||
orderRefundMapper.insert(refund);
|
||||
|
||||
// 更新订单退款状态
|
||||
updateRefundStatus(request.getOrderId(), com.ycwl.basic.order.enums.RefundStatus.REFUND_PROCESSING);
|
||||
|
||||
log.info("退款记录创建成功: refundId={}, refundNo={}, orderId={}, refundAmount={}",
|
||||
refund.getId(), refundNo, request.getOrderId(), request.getRefundAmount());
|
||||
|
||||
return refund.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<OrderV2ListResponse> pageOrdersByUser(OrderV2PageRequest request) {
|
||||
// 移动端查询,确保只查询当前用户的订单
|
||||
return pageOrders(request);
|
||||
}
|
||||
|
||||
// ====== 私有辅助方法 ======
|
||||
|
||||
/**
|
||||
* 构建订单查询条件
|
||||
*/
|
||||
private QueryWrapper<OrderV2> buildOrderQueryWrapper(OrderV2PageRequest request) {
|
||||
QueryWrapper<OrderV2> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("deleted", 0);
|
||||
|
||||
if (request.getOrderNo() != null && !request.getOrderNo().trim().isEmpty()) {
|
||||
queryWrapper.like("order_no", request.getOrderNo().trim());
|
||||
}
|
||||
|
||||
if (request.getMemberId() != null) {
|
||||
queryWrapper.eq("member_id", request.getMemberId());
|
||||
}
|
||||
|
||||
if (request.getScenicId() != null) {
|
||||
queryWrapper.eq("scenic_id", request.getScenicId());
|
||||
}
|
||||
|
||||
if (request.getOrderStatus() != null && !request.getOrderStatus().trim().isEmpty()) {
|
||||
queryWrapper.eq("order_status", request.getOrderStatus().trim());
|
||||
}
|
||||
|
||||
if (request.getPaymentStatus() != null && !request.getPaymentStatus().trim().isEmpty()) {
|
||||
queryWrapper.eq("payment_status", request.getPaymentStatus().trim());
|
||||
}
|
||||
|
||||
if (request.getRefundStatus() != null && !request.getRefundStatus().trim().isEmpty()) {
|
||||
queryWrapper.eq("refund_status", request.getRefundStatus().trim());
|
||||
}
|
||||
|
||||
if (request.getCreateTimeStart() != null) {
|
||||
queryWrapper.ge("create_time", request.getCreateTimeStart());
|
||||
}
|
||||
|
||||
if (request.getCreateTimeEnd() != null) {
|
||||
queryWrapper.le("create_time", request.getCreateTimeEnd());
|
||||
}
|
||||
|
||||
if (request.getPayTimeStart() != null) {
|
||||
queryWrapper.ge("pay_time", request.getPayTimeStart());
|
||||
}
|
||||
|
||||
if (request.getPayTimeEnd() != null) {
|
||||
queryWrapper.le("pay_time", request.getPayTimeEnd());
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc("create_time");
|
||||
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为列表响应DTO
|
||||
*/
|
||||
private OrderV2ListResponse convertToListResponse(OrderV2 order) {
|
||||
OrderV2ListResponse response = new OrderV2ListResponse();
|
||||
response.setId(order.getId());
|
||||
response.setOrderNo(order.getOrderNo());
|
||||
response.setMemberId(order.getMemberId());
|
||||
response.setOpenId(order.getOpenId());
|
||||
response.setFaceId(order.getFaceId());
|
||||
response.setScenicId(order.getScenicId());
|
||||
response.setOriginalAmount(order.getOriginalAmount());
|
||||
response.setDiscountAmount(order.getDiscountAmount());
|
||||
response.setFinalAmount(order.getFinalAmount());
|
||||
response.setOrderStatus(order.getOrderStatus());
|
||||
response.setOrderStatusDesc(order.getOrderStatus().getDescription());
|
||||
response.setPaymentStatus(order.getPaymentStatus());
|
||||
response.setPaymentStatusDesc(order.getPaymentStatus().getDescription());
|
||||
response.setRefundStatus(order.getRefundStatus());
|
||||
response.setRefundStatusDesc(order.getRefundStatus().getDescription());
|
||||
response.setTotalRefundAmount(order.getTotalRefundAmount());
|
||||
response.setRemarks(order.getRemarks());
|
||||
response.setPayTime(order.getPayTime());
|
||||
response.setCompleteTime(order.getCompleteTime());
|
||||
response.setCreateTime(order.getCreateTime());
|
||||
response.setUpdateTime(order.getUpdateTime());
|
||||
|
||||
// 查询商品数量信息
|
||||
QueryWrapper<OrderItemV2> itemQuery = new QueryWrapper<>();
|
||||
itemQuery.eq("order_id", order.getId());
|
||||
List<OrderItemV2> items = orderItemMapper.selectList(itemQuery);
|
||||
response.setItemCount(items.size());
|
||||
response.setTotalQuantity(items.stream().mapToInt(OrderItemV2::getQuantity).sum());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为详情响应DTO
|
||||
*/
|
||||
private OrderV2DetailResponse convertToDetailResponse(OrderV2 order,
|
||||
List<OrderItemV2> orderItems,
|
||||
List<OrderDiscountV2> orderDiscounts,
|
||||
List<OrderRefundV2> orderRefunds) {
|
||||
OrderV2DetailResponse response = new OrderV2DetailResponse();
|
||||
response.setId(order.getId());
|
||||
response.setOrderNo(order.getOrderNo());
|
||||
response.setMemberId(order.getMemberId());
|
||||
response.setOpenId(order.getOpenId());
|
||||
response.setFaceId(order.getFaceId());
|
||||
response.setScenicId(order.getScenicId());
|
||||
response.setOriginalAmount(order.getOriginalAmount());
|
||||
response.setDiscountAmount(order.getDiscountAmount());
|
||||
response.setFinalAmount(order.getFinalAmount());
|
||||
response.setOrderStatus(order.getOrderStatus());
|
||||
response.setOrderStatusDesc(order.getOrderStatus().getDescription());
|
||||
response.setPaymentStatus(order.getPaymentStatus());
|
||||
response.setPaymentStatusDesc(order.getPaymentStatus().getDescription());
|
||||
response.setRefundStatus(order.getRefundStatus());
|
||||
response.setRefundStatusDesc(order.getRefundStatus().getDescription());
|
||||
response.setTotalRefundAmount(order.getTotalRefundAmount());
|
||||
response.setRemarks(order.getRemarks());
|
||||
response.setPayTime(order.getPayTime());
|
||||
response.setCompleteTime(order.getCompleteTime());
|
||||
response.setCreateTime(order.getCreateTime());
|
||||
response.setUpdateTime(order.getUpdateTime());
|
||||
response.setCreateBy(order.getCreateBy());
|
||||
response.setUpdateBy(order.getUpdateBy());
|
||||
|
||||
response.setOrderItems(orderItems);
|
||||
response.setOrderDiscounts(orderDiscounts);
|
||||
response.setOrderRefunds(orderRefunds);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成退款单号
|
||||
*/
|
||||
private String generateRefundNo() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
String timestamp = sdf.format(new Date());
|
||||
int random = (int) (Math.random() * 900) + 100;
|
||||
return "REFUND" + timestamp + random;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user