|
|
@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
@@ -44,6 +45,7 @@ import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
@RequiredArgsConstructor
|
|
|
public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeUserOrder> {
|
|
|
@@ -1088,6 +1090,68 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
|
|
|
/**
|
|
|
* 查询用户订单列表(包含各状态订单数量统计)
|
|
|
+ * <p>
|
|
|
+ * 此方法用于查询订单列表并统计各状态订单数量,返回订单列表和统计信息
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param page 页码,必须大于0
|
|
|
+ * @param size 每页数量,必须大于0
|
|
|
+ * @param userId 用户id,可为空
|
|
|
+ * @param storeId 商户id,可为空
|
|
|
+ * @param couponType 订单类型,-1表示全部
|
|
|
+ * @param orderStatus 订单状态,-1表示全部
|
|
|
+ * @param name 订单名称,可为空
|
|
|
+ * @param startTime 开始时间,格式:yyyy-MM-dd,可为空
|
|
|
+ * @param endTime 结束时间,格式:yyyy-MM-dd,可为空
|
|
|
+ * @return 订单列表及统计信息Map,包含订单列表和各状态订单数量
|
|
|
+ */
|
|
|
+ public Map<String, Object> queryUserOrderListWithStatistics(
|
|
|
+ Integer page, Integer size, String userId, String storeId, String couponType,
|
|
|
+ String orderStatus, String name, String startTime, String endTime) {
|
|
|
+ log.info("查询用户订单列表(包含统计)开始,page={}, size={}, userId={}, storeId={}, couponType={}, "
|
|
|
+ + "orderStatus={}, name={}, startTime={}, endTime={}",
|
|
|
+ page, size, userId, storeId, couponType, orderStatus, name, startTime, endTime);
|
|
|
+
|
|
|
+ // 参数校验(Controller层已有默认值,此处仅做防御性校验,不影响正常调用)
|
|
|
+ // 注意:如果page或size为null或<=0,Page构造函数可能会抛出异常,保持与原代码行为一致
|
|
|
+ if (page == null || page <= 0) {
|
|
|
+ log.warn("查询用户订单列表(包含统计)参数校验失败:页码必须大于0,page={}", page);
|
|
|
+ throw new IllegalArgumentException("页码必须大于0");
|
|
|
+ }
|
|
|
+ if (size == null || size <= 0) {
|
|
|
+ log.warn("查询用户订单列表(包含统计)参数校验失败:每页数量必须大于0,size={}", size);
|
|
|
+ throw new IllegalArgumentException("每页数量必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询订单列表
|
|
|
+ IPage<LifeUserOrderVo> orderList = queryUserOrderListForStatistics(
|
|
|
+ page, size, userId, storeId, couponType, orderStatus, name, startTime, endTime);
|
|
|
+
|
|
|
+ // 构建统计查询条件
|
|
|
+ QueryWrapper<LifeUserOrderVo> statisticsQueryWrapper = buildStatisticsQueryWrapper(
|
|
|
+ userId, storeId, couponType, name, startTime, endTime);
|
|
|
+
|
|
|
+ // 统计各状态订单数量
|
|
|
+ List<Map<String, Object>> statusCountList = lifeUserOrderMapper.countOrdersByStatus(statisticsQueryWrapper);
|
|
|
+
|
|
|
+ // 统计全部订单数量
|
|
|
+ Long totalOrderCount = getTotalOrderCount(statisticsQueryWrapper);
|
|
|
+
|
|
|
+ // 构建返回结果
|
|
|
+ Map<String, Object> result = buildResultMap(orderList, totalOrderCount, statusCountList);
|
|
|
+
|
|
|
+ log.info("查询用户订单列表(包含统计)成功,page={}, size={}, totalOrderCount={}, orderListSize={}",
|
|
|
+ page, size, totalOrderCount, orderList.getRecords().size());
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询用户订单列表(用于统计接口)
|
|
|
+ * <p>
|
|
|
+ * 此方法用于queryUserOrderListWithStatistics接口,逻辑与queryUserOrderList相同
|
|
|
+ * 但不修改原queryUserOrderList方法
|
|
|
+ * </p>
|
|
|
*
|
|
|
* @param page 页码
|
|
|
* @param size 每页数量
|
|
|
@@ -1098,34 +1162,232 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
* @param name 订单名称
|
|
|
* @param startTime 开始时间
|
|
|
* @param endTime 结束时间
|
|
|
- * @return 订单列表及统计信息Map
|
|
|
+ * @return 订单列表分页结果
|
|
|
*/
|
|
|
- public Map<String, Object> queryUserOrderListWithStatistics(
|
|
|
+ private IPage<LifeUserOrderVo> queryUserOrderListForStatistics(
|
|
|
Integer page, Integer size, String userId, String storeId, String couponType,
|
|
|
String orderStatus, String name, String startTime, String endTime) {
|
|
|
- // 查询订单列表
|
|
|
- IPage<LifeUserOrderVo> orderList = queryUserOrderList(page, size, userId, storeId,
|
|
|
- couponType, orderStatus, name, startTime, endTime);
|
|
|
+ // 构建分页对象
|
|
|
+ IPage<LifeUserOrderVo> brandedPage = new Page<>(page, size);
|
|
|
|
|
|
- // 构建统计查询条件
|
|
|
- QueryWrapper<LifeUserOrderVo> statisticsQueryWrapper = buildStatisticsQueryWrapper(
|
|
|
- userId, storeId, couponType, name, startTime, endTime);
|
|
|
+ // 构建查询条件
|
|
|
+ QueryWrapper<LifeUserOrderVo> queryWrapper = buildOrderListQueryWrapper(
|
|
|
+ userId, storeId, couponType, orderStatus, name, startTime, endTime);
|
|
|
|
|
|
- // 统计各状态订单数量
|
|
|
- List<Map<String, Object>> statusCountList = lifeUserOrderMapper.countOrdersByStatus(statisticsQueryWrapper);
|
|
|
+ // 执行查询
|
|
|
+ IPage<LifeUserOrderVo> lifeUserOrderVoIPage = lifeUserOrderMapper.queryUserOrderList(
|
|
|
+ brandedPage, queryWrapper);
|
|
|
|
|
|
- // 统计全部订单数量
|
|
|
- Long totalOrderCount = lifeUserOrderMapper.countTotalOrders(statisticsQueryWrapper);
|
|
|
- if (totalOrderCount == null) {
|
|
|
- totalOrderCount = DEFAULT_ORDER_COUNT;
|
|
|
+ // 设置订单状态
|
|
|
+ setOrderStatus(lifeUserOrderVoIPage, orderStatus);
|
|
|
+
|
|
|
+ // 处理订单数据(计算退款金额等)
|
|
|
+ processOrderRecords(lifeUserOrderVoIPage.getRecords());
|
|
|
+
|
|
|
+ return lifeUserOrderVoIPage;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建订单列表查询条件
|
|
|
+ *
|
|
|
+ * @param userId 用户id
|
|
|
+ * @param storeId 商户id
|
|
|
+ * @param couponType 订单类型
|
|
|
+ * @param orderStatus 订单状态
|
|
|
+ * @param name 订单名称
|
|
|
+ * @param startTime 开始时间
|
|
|
+ * @param endTime 结束时间
|
|
|
+ * @return 查询条件包装器
|
|
|
+ */
|
|
|
+ private QueryWrapper<LifeUserOrderVo> buildOrderListQueryWrapper(
|
|
|
+ String userId, String storeId, String couponType, String orderStatus,
|
|
|
+ String name, String startTime, String endTime) {
|
|
|
+ QueryWrapper<LifeUserOrderVo> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq(org.apache.commons.lang3.StringUtils.isNotBlank(userId), "luo.user_id", userId);
|
|
|
+ queryWrapper.eq(org.apache.commons.lang3.StringUtils.isNotBlank(storeId), "luo.store_id", storeId);
|
|
|
+ queryWrapper.eq(null != couponType && !ALL_COUPON_TYPE.equals(couponType),
|
|
|
+ "luo.coupon_type", couponType);
|
|
|
+
|
|
|
+ // 构建订单状态查询条件
|
|
|
+ buildOrderStatusQueryCondition(queryWrapper, orderStatus, storeId);
|
|
|
+
|
|
|
+ queryWrapper.like(org.apache.commons.lang3.StringUtils.isNotBlank(name), "tc.coupon_name", name);
|
|
|
+ queryWrapper.gt(org.apache.commons.lang3.StringUtils.isNotBlank(startTime),
|
|
|
+ "luo.created_time", startTime + TIME_START_SUFFIX);
|
|
|
+ queryWrapper.lt(org.apache.commons.lang3.StringUtils.isNotBlank(endTime),
|
|
|
+ "luo.created_time", endTime + TIME_END_SUFFIX);
|
|
|
+ queryWrapper.eq("luo.delete_flag", DELETE_FLAG_NOT_DELETED);
|
|
|
+ queryWrapper.orderByDesc("luo.created_time");
|
|
|
+ queryWrapper.groupBy("luo.coupon_type", "luo.id");
|
|
|
+
|
|
|
+ return queryWrapper;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建订单状态查询条件
|
|
|
+ *
|
|
|
+ * @param queryWrapper 查询条件包装器
|
|
|
+ * @param orderStatus 订单状态
|
|
|
+ * @param storeId 商户id
|
|
|
+ */
|
|
|
+ private void buildOrderStatusQueryCondition(QueryWrapper<LifeUserOrderVo> queryWrapper,
|
|
|
+ String orderStatus, String storeId) {
|
|
|
+ String baseSql = "select DISTINCT ocm1.order_id from order_coupon_middle ocm1 where 1=1";
|
|
|
+
|
|
|
+ if (!ALL_COUPON_TYPE.equals(orderStatus)) {
|
|
|
+ // 非-1状态:直接添加状态条件
|
|
|
+ String sql = baseSql + " and ocm1.status = " + orderStatus;
|
|
|
+ if ("2".equals(orderStatus)) {
|
|
|
+ // 已完成状态进行特殊处理:排除待使用订单
|
|
|
+ sql = sql + " and ocm1.order_id not in (\n" +
|
|
|
+ "\tselect\n" +
|
|
|
+ "\tDISTINCT ocm2.order_id\n" +
|
|
|
+ "from\n" +
|
|
|
+ "\torder_coupon_middle ocm2\n" +
|
|
|
+ "where\n" +
|
|
|
+ "\t ocm2.status = 1\n" +
|
|
|
+ "\t)";
|
|
|
+ }
|
|
|
+ queryWrapper.inSql("luo.id", sql);
|
|
|
+ } else {
|
|
|
+ // -1状态且storeId不为空时添加条件:排除待支付、已过期、已取消、已退款订单
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isNotBlank(storeId)) {
|
|
|
+ String sql = baseSql + " and ocm1.status not in (" + OrderStatusEnum.WAIT_PAY.getStatus()
|
|
|
+ + "," + OrderStatusEnum.EXPIRE.getStatus()
|
|
|
+ + "," + OrderStatusEnum.CANCEL.getStatus()
|
|
|
+ + "," + OrderStatusEnum.REFUND.getStatus()
|
|
|
+ + ")";
|
|
|
+ queryWrapper.inSql("luo.id", sql);
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // 构建返回结果Map
|
|
|
+ /**
|
|
|
+ * 设置订单状态
|
|
|
+ * <p>
|
|
|
+ * 保持与原queryUserOrderList方法相同的逻辑:如果orderStatus格式错误,会抛出NumberFormatException
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param lifeUserOrderVoIPage 订单分页结果
|
|
|
+ * @param orderStatus 订单状态
|
|
|
+ */
|
|
|
+ private void setOrderStatus(IPage<LifeUserOrderVo> lifeUserOrderVoIPage, String orderStatus) {
|
|
|
+ if (!ALL_COUPON_TYPE.equals(orderStatus)) {
|
|
|
+ // 保持与原代码相同的逻辑:直接解析,如果失败会抛出NumberFormatException
|
|
|
+ Integer status = Integer.parseInt(orderStatus);
|
|
|
+ lifeUserOrderVoIPage.getRecords().forEach(x -> x.setStatus(status));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理订单记录(计算退款金额等)
|
|
|
+ *
|
|
|
+ * @param records 订单记录列表
|
|
|
+ */
|
|
|
+ private void processOrderRecords(List<LifeUserOrderVo> records) {
|
|
|
+ if (records == null || records.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (LifeUserOrderVo record : records) {
|
|
|
+ // 设置订单优惠券中间表数据
|
|
|
+ setOrderCouponMiddleList(record);
|
|
|
+
|
|
|
+ // 计算预期收入
|
|
|
+ calcExpectIncome(record);
|
|
|
+
|
|
|
+ // 计算平台优惠券金额(如果是商户查询)
|
|
|
+ calculatePlatformCouponAmount(record);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置订单优惠券中间表数据
|
|
|
+ *
|
|
|
+ * @param record 订单记录
|
|
|
+ */
|
|
|
+ private void setOrderCouponMiddleList(LifeUserOrderVo record) {
|
|
|
+ if (record == null || record.getId() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ QueryWrapper<OrderCouponMiddle> middleQueryWrapper = new QueryWrapper<>();
|
|
|
+ middleQueryWrapper.eq("order_id", record.getId());
|
|
|
+ record.setOrderCouponMiddleList(orderCouponMiddleMapper.selectList(middleQueryWrapper));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算平台优惠券金额(如果是商户查询)
|
|
|
+ * <p>
|
|
|
+ * 如果代金券为平台优惠券(type=3)并且是商户查询,则需要计算代金券金额
|
|
|
+ * 保持与原queryUserOrderList方法相同的逻辑:如果finalPrice为null,会抛出NullPointerException
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param record 订单记录
|
|
|
+ */
|
|
|
+ private void calculatePlatformCouponAmount(LifeUserOrderVo record) {
|
|
|
+ if (record == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果代金券为平台优惠券并且是商户查询
|
|
|
+ if (!"3".equals(record.getType()) || org.apache.commons.lang3.StringUtils.isBlank(record.getStoreId())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保持与原代码相同的逻辑:直接调用equals,如果finalPrice为null会抛出NullPointerException
|
|
|
+ // 如果付款为0,商家收入为套餐原价*数量
|
|
|
+ if (record.getFinalPrice().equals("0")) {
|
|
|
+ // 如果付款为0,商家收入为套餐原价*数量
|
|
|
+ record.setFinalPrice(new BigDecimal(record.getPrice())
|
|
|
+ .multiply(new BigDecimal(record.getCouponCount().toString())).toString());
|
|
|
+ } else {
|
|
|
+ // 如果付款不为0,商家收入为面额+最终价格
|
|
|
+ record.setFinalPrice(record.getNominalValue()
|
|
|
+ .add(new BigDecimal(record.getFinalPrice())).toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取全部订单数量
|
|
|
+ *
|
|
|
+ * @param statisticsQueryWrapper 统计查询条件
|
|
|
+ * @return 全部订单数量,如果为null则返回默认值0
|
|
|
+ */
|
|
|
+ private Long getTotalOrderCount(QueryWrapper<LifeUserOrderVo> statisticsQueryWrapper) {
|
|
|
+ Long totalOrderCount = lifeUserOrderMapper.countTotalOrders(statisticsQueryWrapper);
|
|
|
+ return totalOrderCount == null ? DEFAULT_ORDER_COUNT : totalOrderCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建返回结果Map
|
|
|
+ *
|
|
|
+ * @param orderList 订单列表分页结果
|
|
|
+ * @param totalOrderCount 全部订单数量
|
|
|
+ * @param statusCountList 各状态订单数量统计列表
|
|
|
+ * @return 包含订单列表和统计信息的结果Map
|
|
|
+ */
|
|
|
+ private Map<String, Object> buildResultMap(IPage<LifeUserOrderVo> orderList,
|
|
|
+ Long totalOrderCount,
|
|
|
+ List<Map<String, Object>> statusCountList) {
|
|
|
Map<String, Object> result = new HashMap<>(16);
|
|
|
result.put(KEY_ORDER_LIST, orderList.getRecords());
|
|
|
result.put(KEY_TOTAL_ORDER_COUNT, totalOrderCount);
|
|
|
|
|
|
- // 初始化各状态订单数量
|
|
|
+ // 初始化各状态订单数量为默认值
|
|
|
+ initializeStatusCounts(result);
|
|
|
+
|
|
|
+ // 填充各状态订单数量
|
|
|
+ fillStatusCountsToMap(result, statusCountList);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化各状态订单数量为默认值
|
|
|
+ *
|
|
|
+ * @param result 结果Map
|
|
|
+ */
|
|
|
+ private void initializeStatusCounts(Map<String, Object> result) {
|
|
|
result.put(KEY_WAIT_PAY_COUNT, DEFAULT_ORDER_COUNT);
|
|
|
result.put(KEY_WAIT_USE_COUNT, DEFAULT_ORDER_COUNT);
|
|
|
result.put(KEY_USED_COUNT, DEFAULT_ORDER_COUNT);
|
|
|
@@ -1134,11 +1396,6 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
result.put(KEY_REFUND_COUNT, DEFAULT_ORDER_COUNT);
|
|
|
result.put(KEY_REFUND_FAILED_COUNT, DEFAULT_ORDER_COUNT);
|
|
|
result.put(KEY_COMPLETE_COUNT, DEFAULT_ORDER_COUNT);
|
|
|
-
|
|
|
- // 填充各状态订单数量
|
|
|
- fillStatusCountsToMap(result, statusCountList);
|
|
|
-
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1173,6 +1430,9 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
|
|
|
/**
|
|
|
* 填充各状态订单数量到Map
|
|
|
+ * <p>
|
|
|
+ * 遍历状态统计列表,将各状态的订单数量填充到结果Map中
|
|
|
+ * </p>
|
|
|
*
|
|
|
* @param result 结果Map
|
|
|
* @param statusCountList 状态统计列表
|
|
|
@@ -1180,6 +1440,7 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
private void fillStatusCountsToMap(Map<String, Object> result,
|
|
|
List<Map<String, Object>> statusCountList) {
|
|
|
if (statusCountList == null || statusCountList.isEmpty()) {
|
|
|
+ log.debug("状态统计列表为空,跳过填充");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -1188,12 +1449,17 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
Long count = getLongValue(item.get(KEY_ORDER_COUNT));
|
|
|
if (status != null && count != null) {
|
|
|
setStatusCountToMap(result, status, count);
|
|
|
+ } else {
|
|
|
+ log.warn("状态统计项数据异常,status={}, count={}", status, count);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据订单状态设置对应的数量到Map
|
|
|
+ * <p>
|
|
|
+ * 根据订单状态枚举值,将对应的订单数量设置到结果Map的相应key中
|
|
|
+ * </p>
|
|
|
*
|
|
|
* @param result 结果Map
|
|
|
* @param status 订单状态
|
|
|
@@ -1216,6 +1482,8 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
|
|
|
result.put(KEY_REFUND_FAILED_COUNT, count);
|
|
|
} else if (OrderStatusEnum.COMPLETE.getStatus().equals(status)) {
|
|
|
result.put(KEY_COMPLETE_COUNT, count);
|
|
|
+ } else {
|
|
|
+ log.warn("未知的订单状态,status={}, count={}", status, count);
|
|
|
}
|
|
|
}
|
|
|
|