Browse Source

对接拼团数据1

master
wangfukang 1 month ago
parent
commit
e3e066ee82
  1. 7
      hiver-admin/src/main/resources/application.yml
  2. 5
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java
  3. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java
  4. 10
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java
  5. 148
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopIndexCountCacheUtil.java
  6. 22
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopStatsCountDTO.java
  7. 10
      hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderMapper.xml

7
hiver-admin/src/main/resources/application.yml

@ -83,7 +83,7 @@ spring:
max-active: 20 # 最大连接数,建议从默认的 8 调大到 20 或更高 max-active: 20 # 最大连接数,建议从默认的 8 调大到 20 或更高
max-wait: 2000ms # 获取连接的最大等待时间,避免无限期阻塞 max-wait: 2000ms # 获取连接的最大等待时间,避免无限期阻塞
max-idle: 10 # 最大空闲连接数 max-idle: 10 # 最大空闲连接数
min-idle: 1 # 最小空闲连接数 min-idle: 4 # 最小空闲连接数
# Elasticsearch # Elasticsearch
data: data:
elasticsearch: elasticsearch:
@ -143,6 +143,11 @@ spring:
fail-on-empty-beans: false fail-on-empty-beans: false
boot: boot:
admin: admin:
monitor:
# 将默认超时时间从 10000ms 调整为 30000ms (30秒)
default-timeout: 30000
# 检查状态的间隔,默认是 10000ms
status-interval: 15000
# 修改上下文路径 # 修改上下文路径
context-path: /hiver/admin context-path: /hiver/admin
client: client:

5
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java

@ -102,6 +102,9 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
@Autowired @Autowired
private WaitOrderCacheUtil waitOrderCacheUtil; private WaitOrderCacheUtil waitOrderCacheUtil;
@Autowired
private ShopIndexCountCacheUtil shopIndexCountCacheUtil;
@Autowired @Autowired
private MallOrderGoodsMapper mallOrderGoodsMapper; private MallOrderGoodsMapper mallOrderGoodsMapper;
@ -206,7 +209,7 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
for (String orderId : orderIds) { for (String orderId : orderIds) {
MallOrder orderInner = mallOrderService.getById(orderId); MallOrder orderInner = mallOrderService.getById(orderId);
if (orderInner != null) { if (orderInner != null && orderInner.getStatus() == ORDER_STATUS_WAIT_DELIVERY) {
String latestSeq = merchantOrderSeqUtil.generateOrderSequence(order.getShopId(), 1); String latestSeq = merchantOrderSeqUtil.generateOrderSequence(order.getShopId(), 1);
LambdaUpdateWrapper<MallOrder> oUw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MallOrder> oUw = new LambdaUpdateWrapper<>();
oUw.eq(MallOrder::getId, orderId) oUw.eq(MallOrder::getId, orderId)

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java

@ -93,6 +93,9 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
@Autowired @Autowired
private UserPendingOrderCacheUtil userPendingOrderCacheUtil; private UserPendingOrderCacheUtil userPendingOrderCacheUtil;
@Autowired
private ShopIndexCountCacheUtil shopIndexCountCacheUtil;
@Autowired @Autowired
private RefundOrderCacheUtil refundOrderCacheUtil; private RefundOrderCacheUtil refundOrderCacheUtil;
@ -987,9 +990,13 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
waitOrderCacheUtil.remove(delivery.getRegionId(), delivery.getId()); waitOrderCacheUtil.remove(delivery.getRegionId(), delivery.getId());
} }
} else { } else {
// 自取(待消费)→ 直接退款 // 自取(待消费)→ 如果没有点击立即出餐直接退款
if(order.getUserRequireMake() == null){
autoRefund(order, "用户取消订单,系统退款"); autoRefund(order, "用户取消订单,系统退款");
restoreStock(order.getId()); restoreStock(order.getId());
}else{
applyMerchantRefund(null,order, "用户申请取消订单", refundType, refundTypeStatus);
}
} }
} }

10
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java

@ -10,10 +10,7 @@ import cc.hiver.mall.pojo.vo.MallOrderVO;
import cc.hiver.mall.service.mybatis.MallOrderService; import cc.hiver.mall.service.mybatis.MallOrderService;
import cc.hiver.mall.service.mybatis.MallRefundRecordService; import cc.hiver.mall.service.mybatis.MallRefundRecordService;
import cc.hiver.mall.service.mybatis.MallUserCouponService; import cc.hiver.mall.service.mybatis.MallUserCouponService;
import cc.hiver.mall.utils.RefundOrderCacheUtil; import cc.hiver.mall.utils.*;
import cc.hiver.mall.utils.UserPendingOrderCacheUtil;
import cc.hiver.mall.utils.WechatPayUtil;
import cc.hiver.mall.utils.WorkerOrderCacheUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@ -59,6 +56,9 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
@Autowired @Autowired
private MallReturnOrderGoodsMapper mallReturnOrderGoodsMapper; private MallReturnOrderGoodsMapper mallReturnOrderGoodsMapper;
@Autowired
private ShopIndexCountCacheUtil shopIndexCountCacheUtil;
@Autowired @Autowired
private MallOrderService mallOrderService; private MallOrderService mallOrderService;
@ -266,7 +266,7 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
//拒绝退款 //拒绝退款
MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId()); MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
//如果是自取订单,则恢复待消费状态 //如果是自取订单,则恢复待消费状态
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_SELF){ if(order.getDeliveryType() == DELIVERY_TYPE_SELF){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_WAIT_PICKUP); updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_WAIT_PICKUP);
//更新缓存 //更新缓存
MallOrderVO vo = userPendingOrderCacheUtil.get(order.getUserId(), order.getId()); MallOrderVO vo = userPendingOrderCacheUtil.get(order.getUserId(), order.getId());

148
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopIndexCountCacheUtil.java

@ -0,0 +1,148 @@
package cc.hiver.mall.utils;
import cc.hiver.core.common.redis.RedisTemplateHelper;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 店铺主页数缓存工具类
* <p>
* 底层使用 Redis Hash 结构保证按 shopId + countType 维度的 O(1) 读写效率
* <pre>
* Key = SHOP_INDEX_COUNT:{shopId}
* Field = countType
* Value = Map<String,Integer> JSON 序列化
* </pre>
* <p>
*
* @author system
*/
@Slf4j
@Component
public class ShopIndexCountCacheUtil {
/** Redis Key 前缀 */
private static final String KEY_PREFIX = "SHOP:STATS:COUNT:";
@Autowired
private RedisTemplateHelper redisTemplateHelper;
// ================================================================
// Key 构建
// ================================================================
private String buildKey(String shopId) {
return KEY_PREFIX + shopId;
}
// ================================================================
// 核心:更新操作 (增/改)
// ================================================================
/**
* 更新单个字段的数值支持原子增减
* 场景订单状态变更时只修改特定计数待出餐 +1
*
* @param shopId 店铺ID
* @param field 字段名 "pendingCooking"
* @param delta 变化量正数表示增加负数表示减少
*/
public void incrementField(String shopId, String field, long delta) {
if (StringUtils.isBlank(shopId) || StringUtils.isBlank(field)) {
return;
}
try {
String key = buildKey(shopId);
// Redis hIncrBy 自动处理不存在的情况(默认为0)
redisTemplateHelper.hIncrBy(key, field, delta);
log.debug("更新计数缓存: shopId={}, field={}, delta={}", shopId, field, delta);
} catch (Exception e) {
log.error("更新计数缓存失败: shopId={}, field={}", shopId, field, e);
}
}
/**
* 覆盖式更新全量替换
* 场景后台管理手动修正数据或初始化数据
*/
public void put(String shopId, ShopStatsCountDTO statsDTO) {
if (StringUtils.isBlank(shopId) || statsDTO == null) {
return;
}
try {
String key = buildKey(shopId);
String json = JSONUtil.toJsonStr(statsDTO);
redisTemplateHelper.hPut(key, statsDTO.getShopId(), json);
log.info("全量覆盖计数缓存: shopId={}", shopId);
} catch (Exception e) {
log.error("全量覆盖计数缓存失败: shopId={}", shopId, e);
}
}
// ================================================================
// 查询操作 (查)
// ================================================================
/**
* 获取所有统计数据
*/
public ShopStatsCountDTO getAll(String shopId) {
if (StringUtils.isBlank(shopId)) {
return null;
}
try {
String key = buildKey(shopId);
Map<Object, Object> entries = redisTemplateHelper.hGetAll(key);
if (entries == null || entries.isEmpty()) {
return null;
}
// 将 Map 转回 DTO 对象
String json = JSONUtil.toJsonStr(entries);
return JSONUtil.toBean(json, ShopStatsCountDTO.class);
} catch (Exception e) {
log.error("获取计数缓存失败: shopId={}", shopId, e);
return null;
}
}
/**
* 获取单个字段的数值
* 场景首页只展示待出餐数量无需查出整个对象
*/
public Integer getCount(String shopId, String field) {
if (StringUtils.isBlank(shopId) || StringUtils.isBlank(field)) {
return 0;
}
try {
Object val = redisTemplateHelper.hGet(buildKey(shopId), field);
return val == null ? 0 : Integer.parseInt(val.toString());
} catch (Exception e) {
log.error("获取单个计数失败: shopId={}, field={}", shopId, field, e);
return 0;
}
}
// ================================================================
// 删除操作 (删)
// ================================================================
/**
* 删除指定店铺的所有统计数据缓存
*/
public void remove(String shopId) {
if (StringUtils.isBlank(shopId)) {
return;
}
try {
redisTemplateHelper.delete(buildKey(shopId));
log.info("清除店铺计数缓存: shopId={}", shopId);
} catch (Exception e) {
log.error("清除店铺计数缓存失败: shopId={}", shopId, e);
}
}
}

22
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ShopStatsCountDTO.java

@ -0,0 +1,22 @@
package cc.hiver.mall.utils;
import lombok.Data;
import java.io.Serializable;
@Data
public class ShopStatsCountDTO implements Serializable {
private static final long serialVersionUID = 1L;
private String shopId; // 冗余存储,方便排查
private Integer pendingConsumption = 0; // 待消费
private Integer pendingCooking = 0; // 待出餐
private Integer pendingPickup = 0; // 待取货
private Integer pendingDelivery = 0; // 待送达
public ShopStatsCountDTO() {}
public ShopStatsCountDTO(String shopId) {
this.shopId = shopId;
}
}

10
hiver-modules/hiver-mall/src/main/resources/mapper/MallOrderMapper.xml

@ -43,10 +43,14 @@
SELECT SELECT
COUNT(*) AS count, COUNT(*) AS count,
CASE CASE
WHEN (`status` = 3 AND delivery_type = 1) THEN 'daiqu' WHEN (`status` = 3 AND delivery_type = 1 AND shop_make_time IS NOT NULL) THEN 'daiqu'
WHEN (`status` = 4 AND delivery_type = 1) THEN 'daisong' WHEN (`status` = 3 AND delivery_type = 2 AND user_require_make = 1)
OR
(`status` = 3 AND delivery_type = 1 AND shop_make_time IS NULL)
THEN 'daichucan'
WHEN (`status` = 3 AND delivery_type = 2 AND user_require_make IS NULL) THEN 'daixiaofei' WHEN (`status` = 3 AND delivery_type = 2 AND user_require_make IS NULL) THEN 'daixiaofei'
WHEN (`status` = 3 AND delivery_type = 2 AND user_require_make = 1) THEN 'daichucan' WHEN (`status` = 4 AND delivery_type = 1) THEN 'daisong'
ELSE 'other'
END AS counttype END AS counttype
FROM mall_order FROM mall_order
<include refid="commonShopIdWhere"/> <include refid="commonShopIdWhere"/>

Loading…
Cancel
Save