放弃 死信消息队列,采用 redis 过期事件监听,超时订单。

This commit is contained in:
Jack 2025-09-06 00:24:51 +08:00
parent ecaebfe229
commit f8172b49d6
16 changed files with 569 additions and 198 deletions

View File

@ -31,4 +31,8 @@ public class RedisConstant {
public static final String Product_Cate_Key = ConstantRedis.Cache_NameSpace + "product_cate_Key"; public static final String Product_Cate_Key = ConstantRedis.Cache_NameSpace + "product_cate_Key";
public static final String Store_Brand_Key = ConstantRedis.Cache_NameSpace + "store_brand_key"; public static final String Store_Brand_Key = ConstantRedis.Cache_NameSpace + "store_brand_key";
public static final String SF_Order_Proc_Expire_Key = ConstantRedis.Cache_NameSpace + "sf_order_proc_expire_key__";
public static final String Order_Pay_Retry_Count_Key = ConstantRedis.Cache_NameSpace + "order_pay_retry_count:";
} }

View File

@ -30,6 +30,12 @@ public class IpUtil implements ApplicationRunner {
* ip2region搜索器实例 * ip2region搜索器实例
*/ */
private static Searcher searcher = null; private static Searcher searcher = null;
/**
* 数据文件加载状态
*/
private static boolean dataFileLoaded = false;
private static String dataFileInfo = "未加载";
/** /**
* 根据IP地址获取地区信息 * 根据IP地址获取地区信息
@ -39,18 +45,23 @@ public class IpUtil implements ApplicationRunner {
*/ */
public static String getRegion(String ip) { public static String getRegion(String ip) {
if (Objects.isNull(searcher)) { if (Objects.isNull(searcher)) {
log.error("IP2RegionUtils 没有成功加载数据文件"); log.error("IP2RegionUtils 没有成功加载数据文件. 数据文件状态: {}, 文件信息: {}",
dataFileLoaded ? "已加载但searcher为null" : "未加载", dataFileInfo);
return null; return null;
} }
if (CheckUtil.isEmpty(ip)) { if (CheckUtil.isEmpty(ip)) {
log.debug("传入的IP地址为空");
return null; return null;
} }
try { try {
return searcher.search(ip); String result = searcher.search(ip);
log.debug("IP地址 {} 解析成功,结果: {}", ip, result);
return result;
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
log.error("IP{} 解析时发生数组越界异常,可能是数据文件损坏或不兼容", ip, e); log.error("IP{} 解析时发生数组越界异常,可能是数据文件损坏或不兼容. 数据文件状态: {}, 文件信息: {}",
ip, dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
return null; return null;
} catch (Exception e) { } catch (Exception e) {
String errorMsg = e.getMessage(); String errorMsg = e.getMessage();
@ -60,7 +71,8 @@ public class IpUtil implements ApplicationRunner {
errorMsg += " -> " + e.getCause().getMessage(); errorMsg += " -> " + e.getCause().getMessage();
} }
} }
log.error("IP{} 格式错误:{}", ip, errorMsg, e); log.error("IP{} 格式错误:{}. 数据文件状态: {}, 文件信息: {}",
ip, errorMsg, dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
return null; return null;
} }
} }
@ -97,17 +109,24 @@ public class IpUtil implements ApplicationRunner {
districtVo.setCountry(parts[0] != null ? parts[0] : ""); // 设置国家 districtVo.setCountry(parts[0] != null ? parts[0] : ""); // 设置国家
districtVo.setProvince(parts[2] != null ? parts[2] : ""); // 设置省份 districtVo.setProvince(parts[2] != null ? parts[2] : ""); // 设置省份
districtVo.setCity(parts[3] != null ? parts[3] : ""); // 设置城市 districtVo.setCity(parts[3] != null ? parts[3] : ""); // 设置城市
log.debug("IP地址 {} 解析为地区信息成功. 国家: {}, 省份: {}, 城市: {}",
ip, districtVo.getCountry(), districtVo.getProvince(), districtVo.getCity());
} else { } else {
log.debug("IP{} 解析结果格式不符合要求,原始数据: {}", ip, ss); log.debug("IP{} 解析结果格式不符合要求,原始数据: {}", ip, ss);
return null; return null;
} }
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
log.error("解析IP地址 {} 的地区信息时发生数组越界异常,原始数据: {}", ip, ss, e); log.error("解析IP地址 {} 的地区信息时发生数组越界异常,原始数据: {}. 数据文件状态: {}, 文件信息: {}",
ip, ss, dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
return null; return null;
} catch (Exception e) { } catch (Exception e) {
log.error("解析IP地址 {} 的地区信息时发生异常: {}", ip, e.getMessage(), e); log.error("解析IP地址 {} 的地区信息时发生异常: {}. 数据文件状态: {}, 文件信息: {}",
ip, e.getMessage(), dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
return null; return null;
} }
} else {
log.debug("IP地址 {} 未解析到地区信息", ip);
} }
return districtVo; return districtVo;
@ -137,16 +156,29 @@ public class IpUtil implements ApplicationRunner {
buffer.flush(); buffer.flush();
byte[] bytes = buffer.toByteArray(); byte[] bytes = buffer.toByteArray();
// 记录数据文件信息
dataFileInfo = String.format("文件大小: %d 字节", bytes.length);
log.info("读取到 ip2region 数据文件,{}", dataFileInfo);
inputStream.close(); inputStream.close();
searcher = Searcher.newWithBuffer(bytes); searcher = Searcher.newWithBuffer(bytes);
log.info("成功加载 ip2region 数据文件。"); dataFileLoaded = true;
// 测试搜索器
if (searcher != null) {
String testResult = searcher.search("8.8.8.8");
log.info("成功加载 ip2region 数据文件。测试搜索 8.8.8.8 结果: {}", testResult);
} else {
log.error("加载 ip2region 数据文件失败searcher 实例为 null");
}
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
log.error("解析IP地址的地区信息时发生数组越界异常原始数据: {}", e); dataFileLoaded = true;
log.error("解析IP地址的地区信息时发生数组越界异常。数据文件状态: 已加载, 文件信息: {}", dataFileInfo, e);
} catch (IOException e) { } catch (IOException e) {
log.error("加载 ip2region 失败。", e); log.error("加载 ip2region 失败。数据文件状态: 未加载, 文件信息: {}", dataFileInfo, e);
} catch (Exception e) { } catch (Exception e) {
log.error("初始化 ip2region 搜索器失败。", e); log.error("初始化 ip2region 搜索器失败。数据文件状态: 未加载, 文件信息: {}", dataFileInfo, e);
} }
} }
} }

View File

@ -1,12 +1,46 @@
package com.suisung.mall.shop.config; package com.suisung.mall.shop.config;
import com.suisung.mall.core.config.BaseRedisConfig; import com.suisung.mall.core.config.BaseRedisConfig;
import com.suisung.mall.shop.order.listener.RedisKeyExpiredListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
/** /**
* Redis相关配置 * Redis相关配置
*/ */
@Slf4j
@Configuration @Configuration
public class RedisConfig extends BaseRedisConfig { public class RedisConfig extends BaseRedisConfig {
@Bean
RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,
MessageListenerAdapter keyExpiredListener) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(keyExpiredListener, new PatternTopic("__keyevent@*__:expired"));
return container;
}
@Bean
MessageListenerAdapter keyExpiredListener() {
return new MessageListenerAdapter(new RedisKeyExpiredListener());
}
// /**
// * 监听Redis键过期事件
// */
// public static class KeyExpiredListener implements MessageListener {
// @Override
// public void onMessage(org.springframework.data.redis.connection.Message message,
// byte[] pattern) {
// String expiredKey = new String(message.getBody());
// // 在这里处理过期键的逻辑
// log.info("Redis 过期事件监听 Key expired: {}", expiredKey);
// // 您可以在这里添加自己的业务逻辑比如清理相关资源发送通知等
// }
// }
} }

View File

@ -1582,7 +1582,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
/** /**
* 拉卡拉订单分账用户下单成功之后大约15秒后进行分账 * 拉卡拉订单分账用户确认收货成功之后大约15秒后进行分账
* 说明分账指令是异步处理模式响应报文成功时指令状态是status: PROCESSING需要等待分账结果通知或者主动发起查询建议主动发起查询与分账指令动作之间间隔15秒以上 * 说明分账指令是异步处理模式响应报文成功时指令状态是status: PROCESSING需要等待分账结果通知或者主动发起查询建议主动发起查询与分账指令动作之间间隔15秒以上
* 参考https://o.lakala.com/#/home/document/detail?id=389 * 参考https://o.lakala.com/#/home/document/detail?id=389
* *
@ -1649,10 +1649,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// continue; // continue;
// } // }
// 分账总金额单位() // 分账总金额支付金额-运费运费不参与分账单位()
Integer splitAmount = totalAmt - shoppingFee; Integer splitAmount = totalAmt - shoppingFee;
if (splitAmount <= 0) { if (splitAmount <= 0) {
String errorMsg = String.format("店铺[%s]订单分账金额异常,跳过分账", shopOrderLkl.getStore_id()); String errorMsg = String.format("店铺[%s]订单%s分账金额异常,跳过分账", shopOrderLkl.getStore_id(), orderId);
log.error(errorMsg); log.error(errorMsg);
errorMessages.append(errorMsg).append("; "); errorMessages.append(errorMsg).append("; ");
lklOrderSeparateService.updateRemark(lklOrderSeparateExist.getId(), errorMsg); lklOrderSeparateService.updateRemark(lklOrderSeparateExist.getId(), errorMsg);
@ -1667,7 +1667,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
String errorMsg = String.format("店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id()); String errorMsg = String.format("店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
log.error(errorMsg); log.error(errorMsg);
errorMessages.append(errorMsg).append("; "); errorMessages.append(errorMsg).append("; ");
// lklOrderSeparateService.updateRemark(lklOrderSeparateExist.getId(), errorMsg);
continue; continue;
} }

View File

@ -116,7 +116,8 @@ public class DelayMessageReceiver {
// 根据消息分类处理不同类型的消息 // 根据消息分类处理不同类型的消息
if (MqConstant.DEAD_EVENT_CATE_ORDER_EXPIRED.equals(category)) { if (MqConstant.DEAD_EVENT_CATE_ORDER_EXPIRED.equals(category)) {
log.info("处理订单超时消息: {}", message); log.info("处理订单超时消息: {}", message);
return handleOrderExpiredMessage(message); // return handleOrderExpiredMessage(message);
return true;
} else if (MqConstant.DEAD_EVENT_CATE_PRE_ORDER.equals(category)) { } else if (MqConstant.DEAD_EVENT_CATE_PRE_ORDER.equals(category)) {
log.info("处理预订单消息: {}", message); log.info("处理预订单消息: {}", message);
return handlePreOrderMessage(message); return handlePreOrderMessage(message);

View File

@ -7,9 +7,10 @@ import com.rabbitmq.client.Channel;
import com.suisung.mall.common.api.StateCode; import com.suisung.mall.common.api.StateCode;
import com.suisung.mall.common.constant.CommonConstant; import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.constant.MqConstant; import com.suisung.mall.common.constant.MqConstant;
import com.suisung.mall.common.constant.RedisConstant;
import com.suisung.mall.common.modules.order.ShopOrderInfo; import com.suisung.mall.common.modules.order.ShopOrderInfo;
import com.suisung.mall.common.utils.DateTimeUtils; import com.suisung.mall.common.utils.DateTimeUtils;
import com.suisung.mall.shop.message.service.MqMessageService; import com.suisung.mall.core.web.service.RedisService;
import com.suisung.mall.shop.message.service.PushMessageService; import com.suisung.mall.shop.message.service.PushMessageService;
import com.suisung.mall.shop.order.service.ShopOrderBaseService; import com.suisung.mall.shop.order.service.ShopOrderBaseService;
import com.suisung.mall.shop.order.service.ShopOrderInfoService; import com.suisung.mall.shop.order.service.ShopOrderInfoService;
@ -41,6 +42,9 @@ public class OrderPayedListener {
private static final Logger logger = LoggerFactory.getLogger(OrderPayedListener.class); private static final Logger logger = LoggerFactory.getLogger(OrderPayedListener.class);
// 最大重试次数
private static final int MAX_RETRY_COUNT = 5;
@Lazy @Lazy
@Autowired @Autowired
private ShopOrderBaseService shopOrderBaseService; private ShopOrderBaseService shopOrderBaseService;
@ -56,7 +60,7 @@ public class OrderPayedListener {
@Lazy @Lazy
@Autowired @Autowired
private MqMessageService mqMessageService; private RedisService redisService;
@RabbitHandler @RabbitHandler
public void listener(byte[] data, Channel channel, Message message) throws IOException, InterruptedException { public void listener(byte[] data, Channel channel, Message message) throws IOException, InterruptedException {
@ -69,53 +73,72 @@ public class OrderPayedListener {
public void listener(String data, Channel channel, Message message) throws IOException, InterruptedException { public void listener(String data, Channel channel, Message message) throws IOException, InterruptedException {
// String messageId = message.getMessageProperties().getMessageId(); // String messageId = message.getMessageProperties().getMessageId();
if (StrUtil.isBlank(data)) { if (StrUtil.isBlank(data)) {
logger.info("收到空订单消息"); logger.info("[订单支付监听] 收到空订单消息");
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
return; return;
} }
List<String> order_id_row = Convert.toList(String.class, data); List<String> order_id_row = Convert.toList(String.class, data);
try { long deliveryTag = message.getMessageProperties().getDeliveryTag();
boolean flag = false; boolean isRedelivered = message.getMessageProperties().isRedelivered();
logger.info("收到微信异步通知消息data:{}-chanel:{}-message:{},订单ID:{}", data, channel, message, order_id_row);
String retryCountKey = RedisConstant.Order_Pay_Retry_Count_Key + order_id_row.toString();
try {
logger.info("[订单支付监听] 收到微信异步通知消息. 数据: {}, 订单ID: {}, 是否重投: {}", data, order_id_row, isRedelivered);
// 检查重试次数
int retryCount = getRetryCount(retryCountKey);
if (retryCount >= MAX_RETRY_COUNT) {
logger.error("[订单支付监听] 订单处理已达到最大重试次数: {}, 订单ID: {}, 不再处理该消息", MAX_RETRY_COUNT, order_id_row);
channel.basicAck(deliveryTag, false); // 确认消息避免无限重试
redisService.del(retryCountKey); // 清除重试计数
return;
}
boolean flag = false;
for (String orderId : order_id_row) { for (String orderId : order_id_row) {
//判断是否为线下支付订单 //判断是否为线下支付订单
ShopOrderInfo orderInfoOld = shopOrderInfoService.get(orderId); ShopOrderInfo orderInfoOld = shopOrderInfoService.get(orderId);
if (orderInfoOld == null) { if (orderInfoOld == null) {
// 记录重试次数
incrementRetryCount(retryCountKey);
logger.warn("[订单支付监听] 订单在数据库中不存在,增加重试计数. 订单ID: {}, 当前重试次数: {}", orderId, retryCount + 1);
continue; continue;
} }
// 订单状态 // 订单状态
int order_state_id = orderInfoOld.getOrder_state_id().intValue(); int order_state_id = orderInfoOld.getOrder_state_id().intValue();
logger.info("#### 当前订单状态: {} ####", order_state_id); logger.info("[订单支付监听] 当前订单状态: {}, 订单ID: {}", order_state_id, orderId);
// 检查订单是否已经处理过幂等性检查 // 检查订单是否已经处理过幂等性检查
// if (isOrderPaid(orderInfoOld)) { if (isOrderPaid(orderInfoOld)) {
// logger.info("订单已支付无需重复处理订单ID: {}", orderId); logger.info("[订单支付监听] 订单已支付无需重复处理订单ID: {}", orderId);
// flag = true; flag = true;
// continue; continue;
// } }
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) { if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) {
// 待支付状态 // 待支付状态
logger.info("#### 待支付业务分支 ####"); logger.info("[订单支付监听] 处理待支付订单. 订单ID: {}", orderId);
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId)); flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
} else { } else {
//判断是否线下支付 //判断是否线下支付
if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) { if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) {
//线下支付直接处理订单支付状态 不处理订单状态 //线下支付直接处理订单支付状态 不处理订单状态
logger.info("#### 线下业务分支 ####"); logger.info("[订单支付监听] 处理线下支付订单. 订单ID: {}", orderId);
ShopOrderInfo orderInfo = new ShopOrderInfo(); ShopOrderInfo orderInfo = new ShopOrderInfo();
orderInfo.setOrder_id(orderId); orderInfo.setOrder_id(orderId);
orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES); orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES);
flag = shopOrderInfoService.edit(orderInfo); flag = shopOrderInfoService.edit(orderInfo);
} else { } else {
logger.info("#### 非线下业务分支 ####"); logger.info("[订单支付监听] 处理其他支付订单. 订单ID: {}", orderId);
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId)); flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
} }
} }
logger.info("#### 支付异步通知回调处理是否成功:{} ####", flag); logger.info("[订单支付监听] 支付异步通知回调处理结果: {}, 订单ID: {}", flag, orderId);
// 生成取单号和打印小票 // 生成取单号和打印小票
if (flag) { if (flag) {
// TODO 以下仅处理下单打印的情况还需要处理退单打印分支 // TODO 以下仅处理下单打印的情况还需要处理退单打印分支
@ -134,16 +157,16 @@ public class OrderPayedListener {
// 发送顺丰同城快递 // 发送顺丰同城快递
Pair<Boolean, String> pairCreateSfOrder = sfExpressApiService.innerCreateSfExpressOrder(orderId, orderPickupNum); Pair<Boolean, String> pairCreateSfOrder = sfExpressApiService.innerCreateSfExpressOrder(orderId, orderPickupNum);
if (pairCreateSfOrder == null) { if (pairCreateSfOrder == null) {
logger.error("顺丰同城下单失败pairCreateSfOrder 返回空值"); logger.error("[订单支付监听] 顺丰同城下单失败pairCreateSfOrder 返回空值. 订单ID: {}", orderId);
return; continue;
} }
if (!pairCreateSfOrder.getFirst()) { if (!pairCreateSfOrder.getFirst()) {
logger.error("顺丰同城下单失败:{}", pairCreateSfOrder.getSecond()); logger.error("[订单支付监听] 顺丰同城下单失败: {}, 订单ID: {}", pairCreateSfOrder.getSecond(), orderId);
return; continue;
} }
logger.info("顺丰同城下单成功"); logger.info("[订单支付监听] 顺丰同城下单成功. 订单ID: {}", orderId);
} }
@ -158,18 +181,12 @@ public class OrderPayedListener {
payload.put("orderId", orderId); payload.put("orderId", orderId);
pushMessageService.noticeMerchantEmployeeOrderAction(orderInfoOld.getStore_id(), orderId, title, content, payload); pushMessageService.noticeMerchantEmployeeOrderAction(orderInfoOld.getStore_id(), orderId, title, content, payload);
// 发送 预过期 MQ 的推送消息 // 发送延迟消息 25分钟拣货配送时间提前5分钟下单20分钟后提醒商家及时拣货
JSONObject jsonObject = new JSONObject(); Long mchOrderExpireSeconds = shopOrderBaseService.sameCityOrderExpireSeconds(1500L) - 300;
jsonObject.put("category", MqConstant.DEAD_EVENT_CATE_ORDER_EXPIRED); // 消息分类1-订单超时消息 redisService.set(RedisConstant.SF_Order_Proc_Expire_Key + String.format("%d&%s", orderInfoOld.getStore_id(), orderId), orderId, mchOrderExpireSeconds);
jsonObject.put("orderId", orderId); // 订单ID
jsonObject.put("storeId", orderInfoOld.getStore_id()); // 店铺ID
jsonObject.put("title", "您有一笔将超时的订单。"); // 消息标题
jsonObject.put("message", String.format("您有一笔将超时的订单:%s请您及时处理。", orderId)); // 消息内容
// 发送延迟消息提前10分钟
Long mchOrderExpireSeconds = shopOrderBaseService.sameCityOrderExpireSeconds(1500L) - 600;
mqMessageService.sendDelayMessage(jsonObject.toString(), mchOrderExpireSeconds * 1000); // 转换为毫秒
} catch (Exception e) { } catch (Exception e) {
log.error("发送推送消息失败:{}", e.getMessage()); log.error("[订单支付监听] 发送推送消息失败. 订单ID: {}", orderId, e);
} }
} }
} }
@ -177,15 +194,22 @@ public class OrderPayedListener {
if (flag) { if (flag) {
// 操作成功标记消息消费成功 // 操作成功标记消息消费成功
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); logger.info("[订单支付监听] 消息处理成功,确认消息. 订单ID: {}", order_id_row);
channel.basicAck(deliveryTag, false);
// 清除重试计数
redisService.del(RedisConstant.Order_Pay_Retry_Count_Key + order_id_row);
} else { } else {
log.error("消息消费失败执行setPaidYes异常当前订单编号{}", order_id_row); log.error("[订单支付监听] 消息处理失败执行setPaidYes异常当前订单编号{}", order_id_row);
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); // 增加重试计数
incrementRetryCount(retryCountKey);
channel.basicReject(deliveryTag, true);
Thread.sleep(1000); Thread.sleep(1000);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("消息消费失败执行setPaidYes异常当前订单编号{},失败原因:", order_id_row, e); log.error("[订单支付监听] 消息处理异常,当前订单编号:{},异常信息:", order_id_row, e);
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); // 增加重试计数
incrementRetryCount(retryCountKey);
channel.basicReject(deliveryTag, true);
Thread.sleep(1000); Thread.sleep(1000);
} }
} }
@ -197,12 +221,33 @@ public class OrderPayedListener {
* @return 是否已支付 * @return 是否已支付
*/ */
private boolean isOrderPaid(ShopOrderInfo orderInfo) { private boolean isOrderPaid(ShopOrderInfo orderInfo) {
// public static final int ORDER_PAID_STATE_NO = 3010; //未付款 // ORDER_PAID_STATE_NO = 3010; //未付款
// public static final int ORDER_PAID_STATE_FINANCE_REVIEW = 3011; //待付款审核 // ORDER_PAID_STATE_FINANCE_REVIEW = 3011; //待付款审核
// public static final int ORDER_PAID_STATE_PART = 3012; //部分付款 // ORDER_PAID_STATE_PART = 3012; //部分付款
// public static final int ORDER_PAID_STATE_YES = 3013; //已付款 // ORDER_PAID_STATE_YES = 3013; //已付款
return orderInfo.getOrder_is_paid() != null && return orderInfo.getOrder_is_paid() != null &&
orderInfo.getOrder_is_paid().equals(StateCode.ORDER_PAID_STATE_YES); orderInfo.getOrder_is_paid().intValue() == StateCode.ORDER_PAID_STATE_YES;
}
/**
* 获取重试次数
*
* @param retryCountKey 重试计数键
* @return 当前重试次数
*/
private int getRetryCount(String retryCountKey) {
Object countObj = redisService.get(retryCountKey);
return countObj == null ? 0 : Convert.toInt(countObj, 0);
}
/**
* 增加重试次数
*
* @param retryCountKey 重试计数键
*/
private void incrementRetryCount(String retryCountKey) {
int currentCount = getRetryCount(retryCountKey);
redisService.set(retryCountKey, currentCount + 1, 3600); // 1小时过期
} }
} }

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.order.listener;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.constant.RedisConstant;
import com.suisung.mall.shop.message.service.PushMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import javax.annotation.Resource;
@Slf4j
public class RedisKeyExpiredListener implements MessageListener {
@Lazy
@Resource
private PushMessageService pushMessageService;
/**
* Callback for processing received objects through Redis.
*
* @param message message must not be {@literal null}.
* @param pattern pattern matching the channel (if specified) - can be {@literal null}.
*/
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = new String(message.getBody());
String patternStr = pattern != null ? new String(pattern) : "无模式";
// 基本日志记录
log.info("[Redis过期监听] 接收到Redis键过期事件. 过期键: {}, 订阅模式: {}", expiredKey, patternStr);
// 参数验证
if (StrUtil.isBlank(expiredKey)) {
log.warn("[Redis过期监听] 接收到空的过期键. 订阅模式: {}", patternStr);
return;
}
if (expiredKey.startsWith(RedisConstant.SF_Order_Proc_Expire_Key)) {
log.debug("[Redis过期监听] 开始处理订单超时事件. 过期键: {}", expiredKey);
// storeId&orderId
String[] args = expiredKey.replace(RedisConstant.SF_Order_Proc_Expire_Key, "").split("&");
if (ArrayUtil.isEmpty(args) || args.length < 2) {
log.error("[Redis过期监听] 订单处理超时键格式错误. 键: {} 不符合预期格式", expiredKey);
return;
}
log.info("[Redis过期监听] 处理订单超时消息. 店铺ID: {}, 订单号: {}", args[0], args[1]);
boolean result = handleOrderExpiredMessage(args[0], args[1]);
if (result) {
log.info("[Redis过期监听] 订单超时事件处理成功. 店铺ID: {}, 订单号: {}", args[0], args[1]);
} else {
log.error("[Redis过期监听] 订单超时事件处理失败. 店铺ID: {}, 订单号: {}", args[0], args[1]);
}
} else {
log.debug("[Redis过期监听] 忽略非订单超时事件. 过期键: {}", expiredKey);
}
}
/**
* 处理订单超时消息
*
* @param storeId 店铺ID
* @param orderId 订单ID
* @return 处理结果
*/
private boolean handleOrderExpiredMessage(String storeId, String orderId) {
try {
log.debug("[订单超时处理] 开始处理订单超时消息. 店铺ID: {}, 订单号: {}", storeId, orderId);
// 参数验证
if (StrUtil.isBlank(orderId) && StrUtil.isBlank(storeId)) {
log.warn("[订单超时处理] 订单ID和店铺ID不能同时为空. 店铺ID: {}, 订单号: {}", storeId, orderId);
return false;
}
if (StrUtil.isBlank(orderId)) {
log.warn("[订单超时处理] 订单号为空. 店铺ID: {}", storeId);
return false;
}
if (StrUtil.isBlank(storeId)) {
log.warn("[订单超时处理] 店铺ID为空. 订单号: {}", orderId);
return false;
}
String title = "有一笔即将超时的订单!";
String content = "您有一笔即将超时的订单[" + orderId + "],请及时处理。";
log.debug("[订单超时处理] 准备推送消息. 标题: {}, 内容: {}", title, content);
// 构造推送消息内容
JSONObject payload = new JSONObject();
payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ABNORMAL_ORDER_LIST);
payload.put("orderId", orderId);
log.debug("[订单超时处理] 推送消息载荷已准备: {}", payload);
// 发送推送消息给商家员工
log.debug("[订单超时处理] 发送推送消息给商家员工. 店铺ID: {}, 订单号: {}", storeId, orderId);
pushMessageService.noticeMerchantEmployeeOrderAction(
Convert.toInt(storeId), orderId, title,
content, payload);
log.info("[订单超时处理] 订单超时消息处理完成. 订单号: {}, 店铺ID: {}, 推送类别: {}",
orderId, storeId, CommonConstant.PUSH_MSG_CATE_MCH_ABNORMAL_ORDER_LIST);
return true;
} catch (Exception e) {
log.error("[订单超时处理] 处理订单超时消息时发生异常. 订单号: {}, 店铺ID: {}", orderId, storeId, e);
return false;
}
}
}

View File

@ -214,7 +214,7 @@ public interface ShopMchEntryService {
* @param storeId * @param storeId
* @return * @return
*/ */
Boolean updateMerchEntryStoreId(Long id, Integer storeId); Boolean updateMerchEntryStoreStatus(Long id, Integer storeId);
/** /**
* 更新商户入驻信息的拉卡拉电子合同相关信息 * 更新商户入驻信息的拉卡拉电子合同相关信息

View File

@ -17,6 +17,14 @@ import java.util.Map;
*/ */
public interface ShopStoreAnalyticsService extends IBaseService<ShopStoreAnalytics> { public interface ShopStoreAnalyticsService extends IBaseService<ShopStoreAnalytics> {
/**
* 根据店铺id查询店铺统计信息
*
* @param storeId
* @return
*/
ShopStoreAnalytics getByStoreId(Integer storeId);
List<Map> getAnalytics(List<Integer> store_id); List<Map> getAnalytics(List<Integer> store_id);
boolean saveProductAnalyticsNum(Integer store_id); boolean saveProductAnalyticsNum(Integer store_id);

View File

@ -14,5 +14,13 @@ import com.suisung.mall.core.web.service.IBaseService;
*/ */
public interface ShopStoreCompanyService extends IBaseService<ShopStoreCompany> { public interface ShopStoreCompanyService extends IBaseService<ShopStoreCompany> {
/**
* 获取店铺公司信息
*
* @param storeId
* @return
*/
ShopStoreCompany getCompany(Integer storeId);
boolean saveOrUpdateCompany(ShopStoreCompany shopStoreCompany); boolean saveOrUpdateCompany(ShopStoreCompany shopStoreCompany);
} }

View File

@ -38,6 +38,17 @@ public interface ShopStoreEmployeeService extends IBaseService<ShopStoreEmployee
*/ */
List<Integer> selectEmployeeByStoreId(Integer storeId, String rightsGroupName); List<Integer> selectEmployeeByStoreId(Integer storeId, String rightsGroupName);
/**
* 根据店铺Id和员工Id获取员工信息
*
* @param storeId
* @param userId
* @param isAdmin
* @return
*/
List<ShopStoreEmployee> selectEmployeeByCondition(Integer storeId, Integer userId, Boolean isAdmin);
/** /**
* 根据店铺Id获取店铺的所有员工的个推 CID 列表 * 根据店铺Id获取店铺的所有员工的个推 CID 列表
* *

View File

@ -637,7 +637,6 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
// === 拉卡拉签约逻辑 === // === 拉卡拉签约逻辑 ===
Long mchId = record.getId(); Long mchId = record.getId();
if (CommonConstant.Enable.equals(record.getHas_ec_signed())) { if (CommonConstant.Enable.equals(record.getHas_ec_signed())) {
LklLedgerEc ec = lklLedgerEcService.getByMchId( LklLedgerEc ec = lklLedgerEcService.getByMchId(
record.getId(), record.getId(),
@ -658,17 +657,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
} }
// RMK 补偿机制入驻总状态店铺创建和初始化 // RMK 补偿机制入驻总状态店铺创建和初始化
checkAndFixMchStoreInfo(mchId);
// 创建店铺并初始化
// 新建一个正式的已审核通过的店铺不要抛异常使用补偿机制可以独立初始化店铺
// 重要包含了更改 merchEntryInfo 的状态 使用法人小微个人的手机号注册商家账号作为店铺的管理员
Pair<Integer, String> retPair = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false);
if (retPair.getFirst() <= 0) {
updateMerchEntryApprovalByMchId(mchId, null, "创建并初始化店铺失败:" + retPair.getSecond());
log.error("进件成功,但初始化店铺失败: mchId={}, reason={}", mchId, retPair.getSecond());
} else {
log.debug("进件成功创建并初始化店铺成功mchId={}", mchId);
}
// 8. 检查商户绑定状态是否完成 更改总的审核状态 // 8. 检查商户绑定状态是否完成 更改总的审核状态
checkMerchEntryFinished(mchId); checkMerchEntryFinished(mchId);
@ -737,6 +726,32 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return false; return false;
} }
// 2. 查询商户入驻记录
List<ShopMchEntry> entryRecords = selectByMobile(loginMobile);
if (CollUtil.isEmpty(entryRecords)) {
log.debug("未找到商户入驻记录,手机号: {}", loginMobile);
return false;
}
int fixCount = 0;
// 3. 遍历处理每个入驻记录
for (ShopMchEntry entry : entryRecords) {
// 3.1 验证入驻记录有效性
if (checkAndFixMchStoreInfo(entry.getId())) {
fixCount++;
}
}
return fixCount > 0;
}
public Boolean checkAndFixMchStoreInfo(Long mchId) {
// 1. 参数校验
if (CheckUtil.isEmpty(mchId)) {
log.warn("商户入驻ID为空");
return false;
}
try { try {
// 2. 获取当前商户用户信息 // 2. 获取当前商户用户信息
UserDto currentUser = getCurrentUser(); UserDto currentUser = getCurrentUser();
@ -745,80 +760,72 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return false; return false;
} }
// 3. 查询商户入驻记录 // 4.3 获取用户基础信息
List<ShopMchEntry> entryRecords = selectByMobile(loginMobile); AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
if (CollUtil.isEmpty(entryRecords)) { if (userBase == null) {
log.debug("未找到商户入驻记录,手机号: {}", loginMobile); log.warn("商户用户基础信息不存在用户ID: {}", currentUser.getId());
return false; return false;
} }
int fixCount = 0; // 3. 查询商户入驻记录
// 4. 遍历处理每个入驻记录 ShopMchEntry shopMchEntry = get(mchId);
for (ShopMchEntry entry : entryRecords) { if (shopMchEntry == null) {
// 4.1 验证入驻记录有效性 log.debug("未找到商户入驻记录 mchId {}", mchId);
if (entry == null || entry.getId() == null) { return false;
log.warn("无效的入驻记录"); }
continue;
}
// 4.2 检查入驻状态 // 4.2 检查入驻状态
boolean isValidStatus = CommonConstant.Enable.equals(entry.getHas_ec_signed()) boolean isValidStatus = CommonConstant.Enable.equals(shopMchEntry.getHas_ec_signed())
&& CommonConstant.Enable.equals(entry.getHas_apply_mer()) && CommonConstant.Enable.equals(shopMchEntry.getHas_apply_mer())
&& CommonConstant.Enable.equals(entry.getHas_apply_split()) && CommonConstant.Enable.equals(shopMchEntry.getHas_apply_split())
&& CommonConstant.Enable.equals(entry.getHas_apply_receiver()) && CommonConstant.Enable.equals(shopMchEntry.getHas_apply_receiver())
&& CommonConstant.Enable.equals(entry.getHas_bind_receiver()); && CommonConstant.Enable.equals(shopMchEntry.getHas_bind_receiver());
if (!isValidStatus) { if (isValidStatus) {
log.debug("入驻记录状态不满足修复条件入驻ID: {}", entry.getId()); log.debug("入驻记录状态都通过了审核进一步验证修复条件入驻ID: {}", mchId);
continue; } else {
} log.debug("入驻记录状态个别未通过审核接着检查验证修复条件入驻ID: {}", mchId);
}
// 4.3 获取用户基础信息
AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
if (userBase == null) {
log.warn("商户用户基础信息不存在用户ID: {}", currentUser.getId());
continue;
}
// 4.4 获取店铺员工信息 // 4.4 获取店铺员工信息
ShopStoreEmployee storeEmployee = null; ShopStoreEmployee storeEmployee = null;
if (StrUtil.isNotBlank(entry.getStore_id())) { if (StrUtil.isNotBlank(shopMchEntry.getStore_id())) {
storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId( storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId(
Convert.toInt(entry.getStore_id()), Convert.toInt(shopMchEntry.getStore_id()),
currentUser.getId() currentUser.getId()
); );
} }
// 4.5 检查店铺关联关系 // 4.5 检查店铺关联关系
boolean hasStoreRelation = StrUtil.isNotBlank(userBase.getStore_ids()) && boolean hasStoreRelation = StrUtil.isNotBlank(userBase.getStore_ids()) &&
userBase.getStore_ids().contains(entry.getStore_id()); userBase.getStore_ids().contains(shopMchEntry.getStore_id());
// 4.6 检查权限组信息 // 4.6 检查权限组信息
boolean hasPermission = storeEmployee != null && boolean hasRoles = storeEmployee != null &&
StrUtil.isNotBlank(storeEmployee.getRights_group_id()); StrUtil.isNotBlank(storeEmployee.getRights_group_id());
// 4.7 当以下任一条件满足时需要进行修复 // 4.7 当以下任一条件满足时需要进行修复
// - 无店铺员工信息 // - 无店铺员工信息
// - 无权限组信息 // - 无权限组信息
// - 无店铺关联 // - 无店铺关联
if (storeEmployee == null || if (storeEmployee == null ||
!hasPermission || !hasRoles ||
!hasStoreRelation) { !hasStoreRelation) {
// 4.8 补偿创建初始化店铺部分赋值 // 4.8 补偿创建初始化店铺部分赋值
Pair<Integer, String> result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(entry.getId(), false); Pair<Integer, String> result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false);
if (result != null && result.getFirst() > 0) { if (result != null && result.getFirst() > 0) {
fixCount++; log.warn("商户信息修复成功入驻ID: {}", mchId);
log.warn("商户信息修复成功入驻ID: {}", entry.getId()); } else {
} else { log.error("商户信息修复失败入驻ID: {}, 错误信息:{}", mchId, result != null ? result.getSecond() : "未知错误");
log.error("商户信息修复失败入驻ID: {}, 错误信息:{}", entry.getId(), result != null ? result.getSecond() : "未知错误"); return false;
}
} }
} }
return fixCount > 0; return true;
} catch (Exception e) { } catch (Exception e) {
log.error("商户信息修复异常,手机号: {}", loginMobile, e); log.error("商户信息修复异常,mchId: {}", mchId, e);
return false; return false;
} }
} }
@ -1391,7 +1398,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
* @return * @return
*/ */
@Override @Override
public Boolean updateMerchEntryStoreId(Long id, Integer storeId) { public Boolean updateMerchEntryStoreStatus(Long id, Integer storeId) {
if (ObjectUtil.isEmpty(id) && ObjectUtil.isEmpty(storeId)) { if (ObjectUtil.isEmpty(id) && ObjectUtil.isEmpty(storeId)) {
return false; return false;
} }

View File

@ -35,6 +35,22 @@ public class ShopStoreAnalyticsServiceImpl extends BaseServiceImpl<ShopStoreAnal
@Autowired @Autowired
private ShopProductBaseService shopProductBaseService; private ShopProductBaseService shopProductBaseService;
/**
* 根据店铺id查询店铺统计信息
*
* @param storeId
* @return
*/
@Override
public ShopStoreAnalytics getByStoreId(Integer storeId) {
try {
return getById(storeId);
} catch (Exception e) {
return null;
}
}
/** /**
* 根据主键值从数据库读取数据, 必须获取主键后再读取数据 * 根据主键值从数据库读取数据, 必须获取主键后再读取数据
* *

View File

@ -3253,75 +3253,85 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
// 初始化默认公司信息避免商家编辑不了申请入驻即使是个人类型的也需要保存相关应有信息公司信息不能空着 // 初始化默认公司信息避免商家编辑不了申请入驻即使是个人类型的也需要保存相关应有信息公司信息不能空着
// shop_store_company // shop_store_company
ShopStoreCompany shopStoreCompany = new ShopStoreCompany(); ShopStoreCompany shopStoreCompany = shopStoreCompanyService.getCompany(storeId);
shopStoreCompany.setUser_id(userId); if (shopStoreCompany == null) {
shopStoreCompany.setStore_id(storeId); shopStoreCompany.setUser_id(userId);
shopStoreCompany.setStore_id(storeId);
// 联系人 // 联系人
shopStoreCompany.setContacts_name(shopMchEntry.getContact_name()); shopStoreCompany.setContacts_name(shopMchEntry.getContact_name());
shopStoreCompany.setContacts_phone(contact_mobile); shopStoreCompany.setContacts_phone(contact_mobile);
// 公司名 // 公司名
String companyName = StrUtil.isBlank(shopMchEntry.getBiz_license_company()) ? shopMchEntry.getStore_name() : shopMchEntry.getBiz_license_company(); String companyName = StrUtil.isBlank(shopMchEntry.getBiz_license_company()) ? shopMchEntry.getStore_name() : shopMchEntry.getBiz_license_company();
shopStoreCompany.setCompany_name(companyName); shopStoreCompany.setCompany_name(companyName);
shopStoreCompany.setCompany_area(shopStoreBase.getStore_area()); shopStoreCompany.setCompany_area(shopStoreBase.getStore_area());
shopStoreCompany.setCompany_address(shopMchEntry.getStore_address()); shopStoreCompany.setCompany_address(shopMchEntry.getStore_address());
// 营业执照 // 营业执照
shopStoreCompany.setBusiness_id(shopMchEntry.getBiz_license_number()); shopStoreCompany.setBusiness_id(shopMchEntry.getBiz_license_number());
shopStoreCompany.setBusiness_license_electronic(shopMchEntry.getBiz_license_image()); shopStoreCompany.setBusiness_license_electronic(shopMchEntry.getBiz_license_image());
// 企业法人 // 企业法人
shopStoreCompany.setLegal_person(shopMchEntry.getLegal_person_name()); shopStoreCompany.setLegal_person(shopMchEntry.getLegal_person_name());
shopStoreCompany.setLegal_person_number(shopMchEntry.getLegal_person_id_number()); shopStoreCompany.setLegal_person_number(shopMchEntry.getLegal_person_id_number());
shopStoreCompany.setLegal_person_electronic(shopMchEntry.getLegal_person_id_images()); shopStoreCompany.setLegal_person_electronic(shopMchEntry.getLegal_person_id_images());
// 银行对公账号 // 银行对公账号
shopStoreCompany.setBank_account_name(shopMchEntry.getAccount_holder_name()); shopStoreCompany.setBank_account_name(shopMchEntry.getAccount_holder_name());
shopStoreCompany.setBank_account_number(shopMchEntry.getAccount_number()); shopStoreCompany.setBank_account_number(shopMchEntry.getAccount_number());
shopStoreCompany.setBank_name(shopMchEntry.getBank_name()); shopStoreCompany.setBank_name(shopMchEntry.getBank_name());
Date today = new Date(); // 当前时间 Date today = new Date(); // 当前时间
shopStoreCompany.setOrganization_code_start(today); shopStoreCompany.setOrganization_code_start(today);
shopStoreCompany.setOrganization_code_end(DateUtil.offsetDay(today, 365 * 5));// 五年 shopStoreCompany.setOrganization_code_end(DateUtil.offsetDay(today, 365 * 5));// 五年
shopStoreCompany.setEstablish_date(today); shopStoreCompany.setEstablish_date(today);
shopStoreCompany.setBusiness_licence_start(today); shopStoreCompany.setBusiness_licence_start(today);
shopStoreCompany.setBusiness_licence_end(DateUtil.offsetDay(today, 365 * 10)); shopStoreCompany.setBusiness_licence_end(DateUtil.offsetDay(today, 365 * 10));
shopStoreCompany.setCompany_description(shopMchEntry.getStore_name()); shopStoreCompany.setCompany_description(shopMchEntry.getStore_name());
shopStoreCompany.setStore_class_ids(""); shopStoreCompany.setStore_class_ids("");
shopStoreCompany.setStore_class_names(""); shopStoreCompany.setStore_class_names("");
shopStoreCompany.setStore_class_commission(""); shopStoreCompany.setStore_class_commission("");
if (!shopStoreCompanyService.save(shopStoreCompany)) { if (!shopStoreCompanyService.save(shopStoreCompany)) {
logger.error("生成店铺:新增店铺公司失败"); logger.error("生成店铺:新增店铺公司失败");
if (allowThrown) { if (allowThrown) {
throw new ApiException(I18nUtil._("新增店铺公司失败")); throw new ApiException(I18nUtil._("新增店铺公司失败"));
}
return Pair.of(0, "新增店铺公司失败");
} }
return Pair.of(0, "新增店铺公司失败");
} }
List<ShopStoreEmployee> shopStoreEmployees = shopStoreEmployeeService.selectEmployeeByCondition(storeId, null, null);
QueryWrapper<ShopStoreEmployee> queryWrapper = new QueryWrapper<>(); ShopStoreEmployee shopStoreEmployee = new ShopStoreEmployee();
queryWrapper.eq("store_id", storeId).eq("user_id", userId).eq("employee_is_admin", CommonConstant.Enable); shopStoreEmployee.setStore_id(storeId);
if (shopStoreEmployeeService.count(queryWrapper) <= 0) { shopStoreEmployee.setUser_id(userId);
shopStoreEmployee.setRights_group_id(""); // 店铺管理员,店铺
shopStoreEmployee.setEmployee_is_kefu(CommonConstant.Enable);
if (CollUtil.isEmpty(shopStoreEmployees)) { // 添加管理员
// shop_store_employee 店铺员工添加管理员 // shop_store_employee 店铺员工添加管理员
ShopStoreEmployee shopStoreEmployee = new ShopStoreEmployee();
shopStoreEmployee.setStore_id(storeId);
shopStoreEmployee.setUser_id(userId);
shopStoreEmployee.setRights_group_id(""); // 店铺管理员,店铺
shopStoreEmployee.setEmployee_is_admin(CommonConstant.Enable); shopStoreEmployee.setEmployee_is_admin(CommonConstant.Enable);
shopStoreEmployee.setEmployee_is_kefu(CommonConstant.Enable); } else { // 添加店员或管理员
if (!shopStoreEmployeeService.save(shopStoreEmployee)) { shopStoreEmployees = shopStoreEmployeeService.selectEmployeeByCondition(storeId, userId, null);
logger.error("生成店铺:新增店铺员工失败"); if (CollUtil.isEmpty(shopStoreEmployees)) {
if (allowThrown) { shopStoreEmployee.setEmployee_is_admin(CommonConstant.Disable);
throw new ApiException(I18nUtil._("新增店铺员工失败")); } else {
} shopStoreEmployee.setEmployee_is_admin(shopStoreEmployees.get(0).getEmployee_is_admin());
return Pair.of(0, "新增店铺员工失败");
} }
} }
if (!shopStoreEmployeeService.save(shopStoreEmployee)) {
logger.error("生成店铺:新增店铺员工失败");
if (allowThrown) {
throw new ApiException(I18nUtil._("新增店铺员工失败"));
}
return Pair.of(0, "新增店铺员工失败");
}
// 生成店铺的太阳码 2025-03-31 // 生成店铺的太阳码 2025-03-31
if (StrUtil.isBlank(shopStoreBase.getWx_qrcode())) { if (StrUtil.isBlank(shopStoreBase.getWx_qrcode())) {
Pair<String, String> resp = wxQrCodeService.genUnlimitedWxQrCode("pagesub/index/store", "store_id=" + storeId); Pair<String, String> resp = wxQrCodeService.genUnlimitedWxQrCode("pagesub/index/store", "store_id=" + storeId);
@ -3331,10 +3341,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
} }
// 注意关联店铺到用户给用户增加店铺管理员权限 // 注意关联店铺到用户给用户增加店铺管理员权限
initStoreExtraInfo(userId, storeId); initStoreExtraInfo(userId, storeId, allowThrown);
// 更改店铺Id和状态 // 更改店铺Id和状态
shopMchEntryService.updateMerchEntryStoreId(shopMchEntry.getId(), storeId); shopMchEntryService.updateMerchEntryStoreStatus(shopMchEntry.getId(), storeId);
// 立即创建顺丰店铺附带初始化同城配送默认设置 // 立即创建顺丰店铺附带初始化同城配送默认设置
String[] areaNames = StrUtil.isNotBlank(shopMchEntry.getStore_area()) ? shopMchEntry.getStore_area().split("/") : new String[0]; String[] areaNames = StrUtil.isNotBlank(shopMchEntry.getStore_area()) ? shopMchEntry.getStore_area().split("/") : new String[0];
@ -3357,7 +3367,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
* @param userId * @param userId
* @param storeId * @param storeId
*/ */
private void initStoreExtraInfo(Integer userId, Integer storeId) { private void initStoreExtraInfo(Integer userId, Integer storeId, Boolean allowThrown) {
if (ObjectUtil.isNull(userId) || ObjectUtil.isNull(storeId)) { if (ObjectUtil.isNull(userId) || ObjectUtil.isNull(storeId)) {
return; return;
} }
@ -3365,10 +3375,16 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
Date today = new Date(); // 当前时间 Date today = new Date(); // 当前时间
// 初始化时添加一条店铺分析信息 // 初始化时添加一条店铺分析信息
ShopStoreAnalytics store_analytics_column = new ShopStoreAnalytics(); ShopStoreAnalytics storeAnalytics = shopStoreAnalyticsService.getByStoreId(storeId);
store_analytics_column.setStore_id(storeId); if (storeAnalytics == null) {
if (!shopStoreAnalyticsService.saveOrUpdate(store_analytics_column)) { storeAnalytics = new ShopStoreAnalytics();
throw new ApiException(ResultCode.FAILED); storeAnalytics.setStore_id(storeId);
if (!shopStoreAnalyticsService.add(storeAnalytics)) {
if (allowThrown) {
throw new ApiException(ResultCode.FAILED);
}
log.error("初始化店铺分析信息失败");
}
} }
// 初始化店铺商品标签 // 初始化店铺商品标签
@ -3387,7 +3403,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
if (CollUtil.isNotEmpty(store_product_tag_row)) { if (CollUtil.isNotEmpty(store_product_tag_row)) {
if (!shopStoreProductTagService.saveOrUpdate(store_product_tag_row)) { if (!shopStoreProductTagService.saveOrUpdate(store_product_tag_row)) {
throw new ApiException(ResultCode.FAILED); if (allowThrown) {
throw new ApiException(ResultCode.FAILED);
}
log.error("初始化店铺商品标签失败");
} }
} }
@ -3399,7 +3418,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
invoicingWarehouseBase.setWarehouse_number(""); invoicingWarehouseBase.setWarehouse_number("");
invoicingWarehouseBase.setWarehouse_contact(""); invoicingWarehouseBase.setWarehouse_contact("");
if (!invoicingWarehouseBaseService.saveOrUpdate(invoicingWarehouseBase)) { if (!invoicingWarehouseBaseService.saveOrUpdate(invoicingWarehouseBase)) {
throw new ApiException(ResultCode.FAILED); if (allowThrown) {
throw new ApiException(ResultCode.FAILED);
}
log.error("初始化默认店铺仓库失败");
} }
//初始化默认权限 //初始化默认权限
@ -3487,7 +3509,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
shopStoreEmployeeRightsGroups.add(extension2); shopStoreEmployeeRightsGroups.add(extension2);
if (!shopStoreEmployeeRightsGroupService.saveOrUpdate(shopStoreEmployeeRightsGroups)) { if (!shopStoreEmployeeRightsGroupService.saveOrUpdate(shopStoreEmployeeRightsGroups)) {
throw new ApiException(ResultCode.FAILED); if (allowThrown) {
throw new ApiException(ResultCode.FAILED);
}
log.error("初始化店铺员工默认权限失败");
} }
// 添加店铺到用户 // 添加店铺到用户
@ -3501,7 +3526,9 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
.set("employee_is_admin", CommonConstant.Enable) .set("employee_is_admin", CommonConstant.Enable)
.set("employee_is_kefu", CommonConstant.Enable); .set("employee_is_kefu", CommonConstant.Enable);
if (!shopStoreEmployeeService.update(queryWrapper)) { if (!shopStoreEmployeeService.update(queryWrapper)) {
// throw new ApiException(I18nUtil._("设置店铺管理员权限失败")); if (allowThrown) {
throw new ApiException(I18nUtil._("设置店铺管理员权限失败"));
}
log.error("设置店铺管理员权限失败!"); log.error("设置店铺管理员权限失败!");
} }
@ -3515,7 +3542,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
String storeIds = appendStoreIdToAccount(userId, storeId); String storeIds = appendStoreIdToAccount(userId, storeId);
accountUserBase.setStore_ids(storeIds); // 重要给用户添加上这个店铺的归属权 accountUserBase.setStore_ids(storeIds); // 重要给用户添加上这个店铺的归属权
if (!accountService.saveOrUpdateUserBase(accountUserBase)) { if (!accountService.saveOrUpdateUserBase(accountUserBase)) {
throw new ApiException(I18nUtil._("店铺关联到用户失败")); if (allowThrown) {
throw new ApiException(I18nUtil._("店铺关联到用户失败"));
}
log.error("店铺关联到用户失败!");
} }
// 添加默认运输模板 // 添加默认运输模板
@ -3527,7 +3557,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
shopStoreTransportType.setTransport_type_freight_free(BigDecimal.ZERO); // 免运费额度 shopStoreTransportType.setTransport_type_freight_free(BigDecimal.ZERO); // 免运费额度
shopStoreTransportType.setTransport_type_free(1); shopStoreTransportType.setTransport_type_free(1);
if (!shopStoreTransportTypeService.saveOrUpdate(shopStoreTransportType)) { if (!shopStoreTransportTypeService.saveOrUpdate(shopStoreTransportType)) {
throw new ApiException(I18nUtil._("添加运输模板失败")); if (allowThrown) {
throw new ApiException(I18nUtil._("添加运输模板失败"));
}
log.error("添加运输模板失败!");
} }
// 店铺配置 // 店铺配置
@ -3566,7 +3599,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
shopStoreConfig.setSc_festival_amount_upper(BigDecimal.ZERO); shopStoreConfig.setSc_festival_amount_upper(BigDecimal.ZERO);
shopStoreConfig.setSc_festival_float_proportion(BigDecimal.ZERO); shopStoreConfig.setSc_festival_float_proportion(BigDecimal.ZERO);
if (!shopStoreConfigService.saveOrUpdate(shopStoreConfig)) { if (!shopStoreConfigService.saveOrUpdate(shopStoreConfig)) {
throw new ApiException(I18nUtil._("添加订单流转配置失败")); if (allowThrown) {
throw new ApiException(I18nUtil._("添加订单流转配置失败"));
}
log.error("添加订单流转配置失败!");
} }
// 添加默认客户等级 // 添加默认客户等级
@ -3577,7 +3613,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
invoicingCustomerLevel.setCustomer_level_desc(""); invoicingCustomerLevel.setCustomer_level_desc("");
if (!invoicingCustomerLevelService.saveOrUpdate(invoicingCustomerLevel)) { if (!invoicingCustomerLevelService.saveOrUpdate(invoicingCustomerLevel)) {
throw new ApiException(I18nUtil._("添加默认客户等级失败")); if (allowThrown) {
throw new ApiException(I18nUtil._("添加默认客户等级失败"));
}
log.error("添加默认客户等级失败!");
} }
} }

View File

@ -1,6 +1,7 @@
package com.suisung.mall.shop.store.service.impl; package com.suisung.mall.shop.store.service.impl;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.api.ResultCode; import com.suisung.mall.common.api.ResultCode;
import com.suisung.mall.common.exception.ApiException; import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.modules.store.ShopStoreCompany; import com.suisung.mall.common.modules.store.ShopStoreCompany;
@ -30,6 +31,19 @@ public class ShopStoreCompanyServiceImpl extends BaseServiceImpl<ShopStoreCompan
@Autowired @Autowired
private ShopStoreEmployeeService shopStoreEmployeeService; private ShopStoreEmployeeService shopStoreEmployeeService;
/**
* 获取店铺公司信息
*
* @param storeId
* @return
*/
@Override
public ShopStoreCompany getCompany(Integer storeId) {
QueryWrapper<ShopStoreCompany> queryWrapper = new QueryWrapper();
queryWrapper.eq("store_id", storeId).orderByAsc("company_id");
return findOne(queryWrapper);
}
@Override @Override
public boolean saveOrUpdateCompany(ShopStoreCompany shopStoreCompany) { public boolean saveOrUpdateCompany(ShopStoreCompany shopStoreCompany) {

View File

@ -243,6 +243,33 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmplo
return shopStoreEmployeeMapper.selectByStoreIdRightGroupId(storeId, rightsGroupId); return shopStoreEmployeeMapper.selectByStoreIdRightGroupId(storeId, rightsGroupId);
} }
/**
* 根据店铺Id和员工Id获取员工信息
*
* @param storeId
* @param userId
* @param isAdmin
* @return
*/
@Override
public List<ShopStoreEmployee> selectEmployeeByCondition(Integer storeId, Integer userId, Boolean isAdmin) {
if (CheckUtil.isEmpty(storeId)) {
return null;
}
QueryWrapper<ShopStoreEmployee> queryWrapper = new QueryWrapper();
queryWrapper.eq("store_id", storeId);
if (CheckUtil.isNotEmpty(userId)) {
queryWrapper.eq("user_id", userId);
}
if (isAdmin != null) {
queryWrapper.eq("employee_is_admin", isAdmin);
}
return list(queryWrapper);
}
/** /**
* 根据店铺Id获取店铺的所有员工的个推 CID 列表 * 根据店铺Id获取店铺的所有员工的个推 CID 列表
* *