feat(shop): 添加用户订单和卡包统计功能
- 在 ShopOrderMapper 中新增 selectUserOrderStats 方法用于订单状态统计 - 在 ShopOrderService 和 ShopOrderServiceImpl 中实现用户订单统计功能 - 添加 UserOrderStats DTO 类定义订单各状态数量统计 - 创建 UserOrderController 提供用户订单统计 API 接口 - 实现用户卡包统计功能,包括余额、积分、优惠券、礼品卡统计 - 添加 UserCardController 和 UserCardStats DTO 类 - 优化 Swagger 配置以支持 /api/user/** 路径的 API 文档 - 为统计接口添加 Redis 缓存以提升性能 - 清理 ShopOrderController 中不必要的导入依赖
This commit is contained in:
@@ -80,7 +80,8 @@ public class SwaggerConfig {
|
|||||||
public GroupedOpenApi shopApi() {
|
public GroupedOpenApi shopApi() {
|
||||||
return GroupedOpenApi.builder()
|
return GroupedOpenApi.builder()
|
||||||
.group("shop")
|
.group("shop")
|
||||||
.pathsToMatch("/api/shop/**")
|
// 订单等用户侧接口在 shop 包内,但路径使用 /api/user/**(前端统一 user 侧 API 前缀)
|
||||||
|
.pathsToMatch("/api/shop/**", "/api/user/**")
|
||||||
.packagesToScan("com.gxwebsoft.shop")
|
.packagesToScan("com.gxwebsoft.shop")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.gxwebsoft.shop.controller;
|
package com.gxwebsoft.shop.controller;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateField;
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
@@ -14,9 +12,7 @@ import com.gxwebsoft.common.core.utils.WechatCertAutoConfig;
|
|||||||
import com.gxwebsoft.common.core.utils.WechatPayConfigValidator;
|
import com.gxwebsoft.common.core.utils.WechatPayConfigValidator;
|
||||||
import com.gxwebsoft.common.core.web.BaseController;
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
import com.gxwebsoft.common.system.entity.Payment;
|
import com.gxwebsoft.common.system.entity.Payment;
|
||||||
import com.gxwebsoft.shop.entity.ShopExpress;
|
|
||||||
import com.gxwebsoft.shop.entity.ShopOrderDelivery;
|
import com.gxwebsoft.shop.entity.ShopOrderDelivery;
|
||||||
import com.gxwebsoft.shop.entity.ShopUserAddress;
|
|
||||||
import com.gxwebsoft.shop.service.*;
|
import com.gxwebsoft.shop.service.*;
|
||||||
import com.gxwebsoft.shop.service.impl.KuaiDi100Impl;
|
import com.gxwebsoft.shop.service.impl.KuaiDi100Impl;
|
||||||
import com.gxwebsoft.shop.task.OrderAutoCancelTask;
|
import com.gxwebsoft.shop.task.OrderAutoCancelTask;
|
||||||
@@ -31,7 +27,6 @@ import com.gxwebsoft.common.core.web.ApiResult;
|
|||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
import com.gxwebsoft.common.core.web.BatchParam;
|
import com.gxwebsoft.common.core.web.BatchParam;
|
||||||
import com.gxwebsoft.common.system.entity.User;
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
import com.kuaidi100.sdk.request.BOrderReq;
|
|
||||||
import com.wechat.pay.java.core.notification.NotificationConfig;
|
import com.wechat.pay.java.core.notification.NotificationConfig;
|
||||||
import com.wechat.pay.java.core.notification.NotificationParser;
|
import com.wechat.pay.java.core.notification.NotificationParser;
|
||||||
import com.wechat.pay.java.core.notification.RequestParam;
|
import com.wechat.pay.java.core.notification.RequestParam;
|
||||||
@@ -51,7 +46,6 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package com.gxwebsoft.shop.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
|
import com.gxwebsoft.shop.dto.UserCardStats;
|
||||||
|
import com.gxwebsoft.shop.entity.ShopGift;
|
||||||
|
import com.gxwebsoft.shop.entity.ShopUserCoupon;
|
||||||
|
import com.gxwebsoft.shop.service.ShopGiftService;
|
||||||
|
import com.gxwebsoft.shop.service.ShopUserCouponService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Tag(name = "用户卡包")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/user/card")
|
||||||
|
public class UserCardController extends BaseController {
|
||||||
|
|
||||||
|
private static final long USER_CARD_STATS_CACHE_SECONDS = 60L;
|
||||||
|
private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisUtil redisUtil;
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
|
@Resource
|
||||||
|
private ShopUserCouponService shopUserCouponService;
|
||||||
|
@Resource
|
||||||
|
private ShopGiftService shopGiftService;
|
||||||
|
|
||||||
|
@Operation(summary = "获取当前用户卡包统计(余额/积分/优惠券/礼品卡,60s 缓存)")
|
||||||
|
@GetMapping("/stats")
|
||||||
|
public ApiResult<UserCardStats> getUserCardStats() {
|
||||||
|
Integer userId = getLoginUserId();
|
||||||
|
if (userId == null) {
|
||||||
|
return fail("请先登录", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
String cacheKey = "UserCard:Stats:"
|
||||||
|
+ (getTenantId() == null ? "0" : getTenantId())
|
||||||
|
+ ":" + userId;
|
||||||
|
UserCardStats cached = redisUtil.get(cacheKey, UserCardStats.class);
|
||||||
|
if (cached != null) {
|
||||||
|
return success("ok", cached);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额/积分从用户表取;优惠券/礼品卡用 COUNT 聚合
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
BigDecimal balance = user == null || user.getBalance() == null ? BigDecimal.ZERO : user.getBalance();
|
||||||
|
Integer points = user == null || user.getPoints() == null ? 0 : user.getPoints();
|
||||||
|
|
||||||
|
long coupons = shopUserCouponService.count(new LambdaQueryWrapper<ShopUserCoupon>()
|
||||||
|
.eq(ShopUserCoupon::getUserId, userId)
|
||||||
|
.eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_UNUSED));
|
||||||
|
|
||||||
|
long giftCards = shopGiftService.count(new LambdaQueryWrapper<ShopGift>()
|
||||||
|
.eq(ShopGift::getUserId, userId)
|
||||||
|
.eq(ShopGift::getStatus, 0));
|
||||||
|
|
||||||
|
UserCardStats stats = new UserCardStats();
|
||||||
|
stats.setBalance(balance.setScale(2, RoundingMode.HALF_UP).toPlainString());
|
||||||
|
stats.setPoints(points);
|
||||||
|
stats.setCoupons(toInt(coupons));
|
||||||
|
stats.setGiftCards(toInt(giftCards));
|
||||||
|
stats.setLastUpdateTime(LocalDateTime.now().format(DATETIME_FMT));
|
||||||
|
|
||||||
|
redisUtil.set(cacheKey, stats, USER_CARD_STATS_CACHE_SECONDS, TimeUnit.SECONDS);
|
||||||
|
return success("ok", stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer toInt(long value) {
|
||||||
|
if (value <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (value > Integer.MAX_VALUE) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
return (int) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.gxwebsoft.shop.controller;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.shop.dto.UserOrderStats;
|
||||||
|
import com.gxwebsoft.shop.service.ShopOrderService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户侧订单接口
|
||||||
|
*/
|
||||||
|
@Tag(name = "用户订单")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/user/orders")
|
||||||
|
public class UserOrderController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ShopOrderService shopOrderService;
|
||||||
|
|
||||||
|
@Operation(summary = "获取当前用户订单状态统计(一次聚合查询,带 60s 缓存)")
|
||||||
|
@GetMapping("/stats")
|
||||||
|
public ApiResult<UserOrderStats> getUserOrderStats(@RequestParam(value = "type", required = false) Integer type) {
|
||||||
|
Integer userId = getLoginUserId();
|
||||||
|
if (userId == null) {
|
||||||
|
return fail("用户未登录", null);
|
||||||
|
}
|
||||||
|
return success(shopOrderService.getUserOrderStats(userId, getTenantId(), type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
31
src/main/java/com/gxwebsoft/shop/dto/UserCardStats.java
Normal file
31
src/main/java/com/gxwebsoft/shop/dto/UserCardStats.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package com.gxwebsoft.shop.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户卡包统计(余额/积分/优惠券/礼品卡)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "UserCardStats", description = "用户卡包统计")
|
||||||
|
public class UserCardStats implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "用户余额(字符串/BigDecimal 字符串)")
|
||||||
|
private String balance;
|
||||||
|
|
||||||
|
@Schema(description = "用户积分")
|
||||||
|
private Integer points;
|
||||||
|
|
||||||
|
@Schema(description = "可用优惠券数量(按 status=0 口径)")
|
||||||
|
private Integer coupons;
|
||||||
|
|
||||||
|
@Schema(description = "未使用礼品卡数量(按 status=0 口径)")
|
||||||
|
private Integer giftCards;
|
||||||
|
|
||||||
|
@Schema(description = "最后更新时间(yyyy-MM-dd HH:mm:ss)")
|
||||||
|
private String lastUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
50
src/main/java/com/gxwebsoft/shop/dto/UserOrderStats.java
Normal file
50
src/main/java/com/gxwebsoft/shop/dto/UserOrderStats.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package com.gxwebsoft.shop.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户订单各状态数量统计(用于订单页徽标/统计)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "UserOrderStats", description = "用户订单各状态数量统计")
|
||||||
|
public class UserOrderStats implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "全部(默认过滤已取消订单:order_status != 2)")
|
||||||
|
private Long total;
|
||||||
|
|
||||||
|
@Schema(description = "待支付(statusFilter=0)")
|
||||||
|
private Long waitPay;
|
||||||
|
|
||||||
|
@Schema(description = "待发货(statusFilter=1)")
|
||||||
|
private Long waitDeliver;
|
||||||
|
|
||||||
|
@Schema(description = "待核销(statusFilter=2)")
|
||||||
|
private Long waitVerify;
|
||||||
|
|
||||||
|
@Schema(description = "待收货(statusFilter=3)")
|
||||||
|
private Long waitReceive;
|
||||||
|
|
||||||
|
@Schema(description = "待评价(statusFilter=4)")
|
||||||
|
private Long waitComment;
|
||||||
|
|
||||||
|
@Schema(description = "已完成(statusFilter=5)")
|
||||||
|
private Long completed;
|
||||||
|
|
||||||
|
@Schema(description = "退款/售后(statusFilter=6)")
|
||||||
|
private Long refund;
|
||||||
|
|
||||||
|
@Schema(description = "已删除(statusFilter=7)")
|
||||||
|
private Long deleted;
|
||||||
|
|
||||||
|
@Schema(description = "已取消(statusFilter=8)")
|
||||||
|
private Long canceled;
|
||||||
|
|
||||||
|
@Schema(description = "按 statusFilter 聚合的数量映射,key 为 \"0\"~\"8\"")
|
||||||
|
private Map<String, Long> statusFilter;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单Mapper
|
* 订单Mapper
|
||||||
@@ -52,4 +53,11 @@ public interface ShopOrderMapper extends BaseMapper<ShopOrder> {
|
|||||||
*/
|
*/
|
||||||
@Select("SELECT COALESCE(SUM(pay_price), 0) FROM shop_order WHERE pay_status = 1 AND deleted = 0 AND pay_price IS NOT NULL")
|
@Select("SELECT COALESCE(SUM(pay_price), 0) FROM shop_order WHERE pay_status = 1 AND deleted = 0 AND pay_price IS NOT NULL")
|
||||||
BigDecimal selectTotalAmount();
|
BigDecimal selectTotalAmount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户订单各状态数量(用于前端订单页徽标/统计,一次查询返回多项聚合结果)
|
||||||
|
*/
|
||||||
|
Map<String, Object> selectUserOrderStats(@Param("userId") Integer userId,
|
||||||
|
@Param("tenantId") Integer tenantId,
|
||||||
|
@Param("type") Integer type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,6 +281,33 @@
|
|||||||
<include refid="selectSql"></include>
|
<include refid="selectSql"></include>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
用户订单状态统计:
|
||||||
|
对齐 ShopOrderMapper.xml 里 statusFilter 的含义(0/1/2/3/4/5/6/7/8),避免前端通过分页接口串行请求统计数量。
|
||||||
|
-->
|
||||||
|
<select id="selectUserOrderStats" resultType="java.util.HashMap">
|
||||||
|
SELECT
|
||||||
|
-- “全部”默认也会过滤已关闭(取消)订单:statusFilter != 8 时会加 a.order_status != 2
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 THEN 1 ELSE 0 END), 0) AS total,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND a.pay_status = 0 AND a.order_status = 0 THEN 1 ELSE 0 END), 0) AS waitPay,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND a.pay_status = 1 AND a.delivery_status = 10 AND a.order_status = 0 THEN 1 ELSE 0 END), 0) AS waitDeliver,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND a.pay_status = 1 AND a.order_status = 0 THEN 1 ELSE 0 END), 0) AS waitVerify,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND a.delivery_status = 20 AND a.order_status != 1 THEN 1 ELSE 0 END), 0) AS waitReceive,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND a.order_status = 1 AND a.evaluate_status = 0 THEN 1 ELSE 0 END), 0) AS waitComment,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND a.order_status = 1 THEN 1 ELSE 0 END), 0) AS completed,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 AND (a.order_status = 4 OR a.order_status = 5 OR a.order_status = 6 OR a.order_status = 7) THEN 1 ELSE 0 END), 0) AS refund,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 1 THEN 1 ELSE 0 END), 0) AS deleted,
|
||||||
|
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status = 2 THEN 1 ELSE 0 END), 0) AS canceled
|
||||||
|
FROM shop_order a
|
||||||
|
WHERE a.user_id = #{userId}
|
||||||
|
<if test="tenantId != null">
|
||||||
|
AND a.tenant_id = #{tenantId}
|
||||||
|
</if>
|
||||||
|
<if test="type != null">
|
||||||
|
AND a.type = #{type}
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
<!-- 根据订单号查询订单 -->
|
<!-- 根据订单号查询订单 -->
|
||||||
<select id="getByOutTradeNo" resultType="com.gxwebsoft.shop.entity.ShopOrder">
|
<select id="getByOutTradeNo" resultType="com.gxwebsoft.shop.entity.ShopOrder">
|
||||||
SELECT * FROM shop_order WHERE order_no = #{outTradeNo}
|
SELECT * FROM shop_order WHERE order_no = #{outTradeNo}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.shop.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.shop.dto.UserOrderStats;
|
||||||
import com.gxwebsoft.shop.entity.ShopOrder;
|
import com.gxwebsoft.shop.entity.ShopOrder;
|
||||||
import com.gxwebsoft.shop.param.ShopOrderParam;
|
import com.gxwebsoft.shop.param.ShopOrderParam;
|
||||||
|
|
||||||
@@ -76,4 +77,13 @@ public interface ShopOrderService extends IService<ShopOrder> {
|
|||||||
* @return 是否更新成功
|
* @return 是否更新成功
|
||||||
*/
|
*/
|
||||||
boolean syncPaymentStatus(String orderNo, Integer paymentStatus, String transactionId, String payTime, Integer tenantId);
|
boolean syncPaymentStatus(String orderNo, Integer paymentStatus, String transactionId, String payTime, Integer tenantId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户订单状态统计(一次聚合查询,避免前端用分页接口串行拉取多个状态数量)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param tenantId 租户ID(可为空,优先走租户插件)
|
||||||
|
* @param type 订单类型(可为空)
|
||||||
|
*/
|
||||||
|
UserOrderStats getUserOrderStats(Integer userId, Integer tenantId, Integer type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import javax.annotation.Resource;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,6 +85,8 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
|
|||||||
@Resource
|
@Resource
|
||||||
private ShopExpressService shopExpressService;
|
private ShopExpressService shopExpressService;
|
||||||
|
|
||||||
|
private static final long USER_ORDER_STATS_CACHE_SECONDS = 60L;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<ShopOrder> pageRel(ShopOrderParam param) {
|
public PageResult<ShopOrder> pageRel(ShopOrderParam param) {
|
||||||
@@ -135,6 +138,80 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
|
|||||||
return param.getOne(baseMapper.selectListRel(param));
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public com.gxwebsoft.shop.dto.UserOrderStats getUserOrderStats(Integer userId, Integer tenantId, Integer type) {
|
||||||
|
if (userId == null) {
|
||||||
|
// 保持调用方逻辑简单:未登录场景由 controller 处理,这里返回全 0
|
||||||
|
return new com.gxwebsoft.shop.dto.UserOrderStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
String cacheKey = "ShopOrder:UserOrderStats:"
|
||||||
|
+ (tenantId == null ? "0" : tenantId)
|
||||||
|
+ ":" + userId
|
||||||
|
+ ":" + (type == null ? "all" : type);
|
||||||
|
|
||||||
|
com.gxwebsoft.shop.dto.UserOrderStats cached = redisUtil.get(cacheKey, com.gxwebsoft.shop.dto.UserOrderStats.class);
|
||||||
|
if (cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> raw = baseMapper.selectUserOrderStats(userId, tenantId, type);
|
||||||
|
if (raw == null) {
|
||||||
|
raw = Collections.emptyMap();
|
||||||
|
}
|
||||||
|
com.gxwebsoft.shop.dto.UserOrderStats stats = new com.gxwebsoft.shop.dto.UserOrderStats();
|
||||||
|
stats.setTotal(getLong(raw, "total"));
|
||||||
|
stats.setWaitPay(getLong(raw, "waitPay"));
|
||||||
|
stats.setWaitDeliver(getLong(raw, "waitDeliver"));
|
||||||
|
stats.setWaitVerify(getLong(raw, "waitVerify"));
|
||||||
|
stats.setWaitReceive(getLong(raw, "waitReceive"));
|
||||||
|
stats.setWaitComment(getLong(raw, "waitComment"));
|
||||||
|
stats.setCompleted(getLong(raw, "completed"));
|
||||||
|
stats.setRefund(getLong(raw, "refund"));
|
||||||
|
stats.setDeleted(getLong(raw, "deleted"));
|
||||||
|
stats.setCanceled(getLong(raw, "canceled"));
|
||||||
|
|
||||||
|
Map<String, Long> statusFilter = new HashMap<>();
|
||||||
|
statusFilter.put("0", stats.getWaitPay());
|
||||||
|
statusFilter.put("1", stats.getWaitDeliver());
|
||||||
|
statusFilter.put("2", stats.getWaitVerify());
|
||||||
|
statusFilter.put("3", stats.getWaitReceive());
|
||||||
|
statusFilter.put("4", stats.getWaitComment());
|
||||||
|
statusFilter.put("5", stats.getCompleted());
|
||||||
|
statusFilter.put("6", stats.getRefund());
|
||||||
|
statusFilter.put("7", stats.getDeleted());
|
||||||
|
statusFilter.put("8", stats.getCanceled());
|
||||||
|
stats.setStatusFilter(statusFilter);
|
||||||
|
|
||||||
|
redisUtil.set(cacheKey, stats, USER_ORDER_STATS_CACHE_SECONDS, TimeUnit.SECONDS);
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Long getLong(Map<String, Object> raw, String key) {
|
||||||
|
Object value = raw.get(key);
|
||||||
|
if (value == null) {
|
||||||
|
value = raw.get(key.toUpperCase(Locale.ROOT));
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
value = raw.get(key.toLowerCase(Locale.ROOT));
|
||||||
|
}
|
||||||
|
return toLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Long toLong(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
if (value instanceof Number) {
|
||||||
|
return ((Number) value).longValue();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Long.parseLong(String.valueOf(value));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashMap<String, String> createWxOrder(ShopOrder order) {
|
public HashMap<String, String> createWxOrder(ShopOrder order) {
|
||||||
Payment payment = null; // 声明在try块外面,这样catch块也能访问
|
Payment payment = null; // 声明在try块外面,这样catch块也能访问
|
||||||
|
|||||||
Reference in New Issue
Block a user