放弃 死信消息队列,采用 redis 过期事件监听,超时订单。
This commit is contained in:
parent
ecaebfe229
commit
f8172b49d6
@ -31,4 +31,8 @@ public class RedisConstant {
|
||||
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 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:";
|
||||
}
|
||||
|
||||
@ -30,6 +30,12 @@ public class IpUtil implements ApplicationRunner {
|
||||
* ip2region搜索器实例
|
||||
*/
|
||||
private static Searcher searcher = null;
|
||||
|
||||
/**
|
||||
* 数据文件加载状态
|
||||
*/
|
||||
private static boolean dataFileLoaded = false;
|
||||
private static String dataFileInfo = "未加载";
|
||||
|
||||
/**
|
||||
* 根据IP地址获取地区信息
|
||||
@ -39,18 +45,23 @@ public class IpUtil implements ApplicationRunner {
|
||||
*/
|
||||
public static String getRegion(String ip) {
|
||||
if (Objects.isNull(searcher)) {
|
||||
log.error("IP2RegionUtils 没有成功加载数据文件");
|
||||
log.error("IP2RegionUtils 没有成功加载数据文件. 数据文件状态: {}, 文件信息: {}",
|
||||
dataFileLoaded ? "已加载但searcher为null" : "未加载", dataFileInfo);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (CheckUtil.isEmpty(ip)) {
|
||||
log.debug("传入的IP地址为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return searcher.search(ip);
|
||||
String result = searcher.search(ip);
|
||||
log.debug("IP地址 {} 解析成功,结果: {}", ip, result);
|
||||
return result;
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
log.error("IP:{} 解析时发生数组越界异常,可能是数据文件损坏或不兼容", ip, e);
|
||||
log.error("IP:{} 解析时发生数组越界异常,可能是数据文件损坏或不兼容. 数据文件状态: {}, 文件信息: {}",
|
||||
ip, dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
String errorMsg = e.getMessage();
|
||||
@ -60,7 +71,8 @@ public class IpUtil implements ApplicationRunner {
|
||||
errorMsg += " -> " + e.getCause().getMessage();
|
||||
}
|
||||
}
|
||||
log.error("IP:{} 格式错误:{}", ip, errorMsg, e);
|
||||
log.error("IP:{} 格式错误:{}. 数据文件状态: {}, 文件信息: {}",
|
||||
ip, errorMsg, dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -97,17 +109,24 @@ public class IpUtil implements ApplicationRunner {
|
||||
districtVo.setCountry(parts[0] != null ? parts[0] : ""); // 设置国家
|
||||
districtVo.setProvince(parts[2] != null ? parts[2] : ""); // 设置省份
|
||||
districtVo.setCity(parts[3] != null ? parts[3] : ""); // 设置城市
|
||||
|
||||
log.debug("IP地址 {} 解析为地区信息成功. 国家: {}, 省份: {}, 城市: {}",
|
||||
ip, districtVo.getCountry(), districtVo.getProvince(), districtVo.getCity());
|
||||
} else {
|
||||
log.debug("IP:{} 解析结果格式不符合要求,原始数据: {}", ip, ss);
|
||||
return null;
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
log.error("解析IP地址 {} 的地区信息时发生数组越界异常,原始数据: {}", ip, ss, e);
|
||||
log.error("解析IP地址 {} 的地区信息时发生数组越界异常,原始数据: {}. 数据文件状态: {}, 文件信息: {}",
|
||||
ip, ss, dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.error("解析IP地址 {} 的地区信息时发生异常: {}", ip, e.getMessage(), e);
|
||||
log.error("解析IP地址 {} 的地区信息时发生异常: {}. 数据文件状态: {}, 文件信息: {}",
|
||||
ip, e.getMessage(), dataFileLoaded ? "已加载" : "未加载", dataFileInfo, e);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
log.debug("IP地址 {} 未解析到地区信息", ip);
|
||||
}
|
||||
|
||||
return districtVo;
|
||||
@ -137,16 +156,29 @@ public class IpUtil implements ApplicationRunner {
|
||||
buffer.flush();
|
||||
byte[] bytes = buffer.toByteArray();
|
||||
|
||||
// 记录数据文件信息
|
||||
dataFileInfo = String.format("文件大小: %d 字节", bytes.length);
|
||||
log.info("读取到 ip2region 数据文件,{}", dataFileInfo);
|
||||
|
||||
inputStream.close();
|
||||
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) {
|
||||
log.error("解析IP地址的地区信息时发生数组越界异常,原始数据: {}", e);
|
||||
dataFileLoaded = true;
|
||||
log.error("解析IP地址的地区信息时发生数组越界异常。数据文件状态: 已加载, 文件信息: {}", dataFileInfo, e);
|
||||
} catch (IOException e) {
|
||||
log.error("加载 ip2region 失败。", e);
|
||||
log.error("加载 ip2region 失败。数据文件状态: 未加载, 文件信息: {}", dataFileInfo, e);
|
||||
} catch (Exception e) {
|
||||
log.error("初始化 ip2region 搜索器失败。", e);
|
||||
log.error("初始化 ip2region 搜索器失败。数据文件状态: 未加载, 文件信息: {}", dataFileInfo, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,46 @@
|
||||
package com.suisung.mall.shop.config;
|
||||
|
||||
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.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相关配置
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
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);
|
||||
// // 您可以在这里添加自己的业务逻辑,比如清理相关资源、发送通知等
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@ -1582,7 +1582,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
|
||||
/**
|
||||
* 拉卡拉订单分账,用户下单成功之后(大约15秒后),进行分账
|
||||
* 拉卡拉订单分账,用户确认收货成功之后(大约15秒后),进行分账
|
||||
* 说明:分账指令是异步处理模式,响应报文成功时,指令状态是”status”: “PROCESSING”,需要等待分账结果通知,或者主动发起查询,建议主动发起查询与分账指令动作之间间隔15秒以上。
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=389
|
||||
*
|
||||
@ -1649,10 +1649,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// 分账总金额,单位(分)
|
||||
// 分账总金额(支付金额-运费)运费不参与分账,单位(分)
|
||||
Integer splitAmount = totalAmt - shoppingFee;
|
||||
if (splitAmount <= 0) {
|
||||
String errorMsg = String.format("店铺[%s]订单分账金额异常,跳过分账", shopOrderLkl.getStore_id());
|
||||
String errorMsg = String.format("店铺[%s]订单%s分账金额异常,跳过分账", shopOrderLkl.getStore_id(), orderId);
|
||||
log.error(errorMsg);
|
||||
errorMessages.append(errorMsg).append("; ");
|
||||
lklOrderSeparateService.updateRemark(lklOrderSeparateExist.getId(), errorMsg);
|
||||
@ -1667,7 +1667,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
String errorMsg = String.format("店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
|
||||
log.error(errorMsg);
|
||||
errorMessages.append(errorMsg).append("; ");
|
||||
// lklOrderSeparateService.updateRemark(lklOrderSeparateExist.getId(), errorMsg);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +116,8 @@ public class DelayMessageReceiver {
|
||||
// 根据消息分类处理不同类型的消息
|
||||
if (MqConstant.DEAD_EVENT_CATE_ORDER_EXPIRED.equals(category)) {
|
||||
log.info("处理订单超时消息: {}", message);
|
||||
return handleOrderExpiredMessage(message);
|
||||
// return handleOrderExpiredMessage(message);
|
||||
return true;
|
||||
} else if (MqConstant.DEAD_EVENT_CATE_PRE_ORDER.equals(category)) {
|
||||
log.info("处理预订单消息: {}", message);
|
||||
return handlePreOrderMessage(message);
|
||||
|
||||
@ -7,9 +7,10 @@ import com.rabbitmq.client.Channel;
|
||||
import com.suisung.mall.common.api.StateCode;
|
||||
import com.suisung.mall.common.constant.CommonConstant;
|
||||
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.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.order.service.ShopOrderBaseService;
|
||||
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 int MAX_RETRY_COUNT = 5;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopOrderBaseService shopOrderBaseService;
|
||||
@ -56,7 +60,7 @@ public class OrderPayedListener {
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private MqMessageService mqMessageService;
|
||||
private RedisService redisService;
|
||||
|
||||
@RabbitHandler
|
||||
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 {
|
||||
// String messageId = message.getMessageProperties().getMessageId();
|
||||
if (StrUtil.isBlank(data)) {
|
||||
logger.info("收到空订单消息");
|
||||
logger.info("[订单支付监听] 收到空订单消息");
|
||||
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> order_id_row = Convert.toList(String.class, data);
|
||||
try {
|
||||
boolean flag = false;
|
||||
logger.info("收到微信异步通知消息data:{}-chanel:{}-message:{},订单ID:{}", data, channel, message, order_id_row);
|
||||
long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
||||
boolean isRedelivered = message.getMessageProperties().isRedelivered();
|
||||
|
||||
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) {
|
||||
//判断是否为线下支付订单
|
||||
ShopOrderInfo orderInfoOld = shopOrderInfoService.get(orderId);
|
||||
if (orderInfoOld == null) {
|
||||
// 记录重试次数
|
||||
incrementRetryCount(retryCountKey);
|
||||
logger.warn("[订单支付监听] 订单在数据库中不存在,增加重试计数. 订单ID: {}, 当前重试次数: {}", orderId, retryCount + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 订单状态
|
||||
int order_state_id = orderInfoOld.getOrder_state_id().intValue();
|
||||
logger.info("#### 当前订单状态: {} ####", order_state_id);
|
||||
logger.info("[订单支付监听] 当前订单状态: {}, 订单ID: {}", order_state_id, orderId);
|
||||
|
||||
// 检查订单是否已经处理过(幂等性检查)
|
||||
// if (isOrderPaid(orderInfoOld)) {
|
||||
// logger.info("订单已支付,无需重复处理,订单ID: {}", orderId);
|
||||
// flag = true;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (isOrderPaid(orderInfoOld)) {
|
||||
logger.info("[订单支付监听] 订单已支付,无需重复处理,订单ID: {}", orderId);
|
||||
flag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) {
|
||||
// 待支付状态
|
||||
logger.info("#### 待支付业务分支 ####");
|
||||
logger.info("[订单支付监听] 处理待支付订单. 订单ID: {}", orderId);
|
||||
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
|
||||
} else {
|
||||
//判断是否线下支付
|
||||
if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) {
|
||||
//线下支付,直接处理订单支付状态, 不处理订单状态
|
||||
logger.info("#### 线下业务分支 ####");
|
||||
logger.info("[订单支付监听] 处理线下支付订单. 订单ID: {}", orderId);
|
||||
ShopOrderInfo orderInfo = new ShopOrderInfo();
|
||||
orderInfo.setOrder_id(orderId);
|
||||
orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES);
|
||||
flag = shopOrderInfoService.edit(orderInfo);
|
||||
} else {
|
||||
logger.info("#### 非线下业务分支 ####");
|
||||
logger.info("[订单支付监听] 处理其他支付订单. 订单ID: {}", orderId);
|
||||
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("#### 支付异步通知回调处理是否成功:{} ####", flag);
|
||||
logger.info("[订单支付监听] 支付异步通知回调处理结果: {}, 订单ID: {}", flag, orderId);
|
||||
// 生成取单号和打印小票
|
||||
if (flag) {
|
||||
// TODO 以下仅处理下单打印的情况,还需要处理退单打印分支。
|
||||
@ -134,16 +157,16 @@ public class OrderPayedListener {
|
||||
// 发送顺丰同城快递
|
||||
Pair<Boolean, String> pairCreateSfOrder = sfExpressApiService.innerCreateSfExpressOrder(orderId, orderPickupNum);
|
||||
if (pairCreateSfOrder == null) {
|
||||
logger.error("顺丰同城下单失败!pairCreateSfOrder 返回空值");
|
||||
return;
|
||||
logger.error("[订单支付监听] 顺丰同城下单失败!pairCreateSfOrder 返回空值. 订单ID: {}", orderId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pairCreateSfOrder.getFirst()) {
|
||||
logger.error("顺丰同城下单失败:{}", pairCreateSfOrder.getSecond());
|
||||
return;
|
||||
logger.error("[订单支付监听] 顺丰同城下单失败: {}, 订单ID: {}", pairCreateSfOrder.getSecond(), orderId);
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.info("顺丰同城下单成功");
|
||||
logger.info("[订单支付监听] 顺丰同城下单成功. 订单ID: {}", orderId);
|
||||
|
||||
}
|
||||
|
||||
@ -158,18 +181,12 @@ public class OrderPayedListener {
|
||||
payload.put("orderId", orderId);
|
||||
pushMessageService.noticeMerchantEmployeeOrderAction(orderInfoOld.getStore_id(), orderId, title, content, payload);
|
||||
|
||||
// 发送 预过期 MQ 的推送消息
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("category", MqConstant.DEAD_EVENT_CATE_ORDER_EXPIRED); // 消息分类:1-订单超时消息
|
||||
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); // 转换为毫秒
|
||||
// 发送延迟消息 25分钟拣货配送时间(提前5分钟,下单20分钟后,提醒商家及时拣货)
|
||||
Long mchOrderExpireSeconds = shopOrderBaseService.sameCityOrderExpireSeconds(1500L) - 300;
|
||||
redisService.set(RedisConstant.SF_Order_Proc_Expire_Key + String.format("%d&%s", orderInfoOld.getStore_id(), orderId), orderId, mchOrderExpireSeconds);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送推送消息失败:{}", e.getMessage());
|
||||
log.error("[订单支付监听] 发送推送消息失败. 订单ID: {}", orderId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,15 +194,22 @@ public class OrderPayedListener {
|
||||
|
||||
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 {
|
||||
log.error("消息消费失败,执行setPaidYes异常,当前订单编号:{}", order_id_row);
|
||||
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
|
||||
log.error("[订单支付监听] 消息处理失败,执行setPaidYes异常,当前订单编号:{}", order_id_row);
|
||||
// 增加重试计数
|
||||
incrementRetryCount(retryCountKey);
|
||||
channel.basicReject(deliveryTag, true);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("消息消费失败,执行setPaidYes异常,当前订单编号:{},失败原因:", order_id_row, e);
|
||||
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
|
||||
log.error("[订单支付监听] 消息处理异常,当前订单编号:{},异常信息:", order_id_row, e);
|
||||
// 增加重试计数
|
||||
incrementRetryCount(retryCountKey);
|
||||
channel.basicReject(deliveryTag, true);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
@ -197,12 +221,33 @@ public class OrderPayedListener {
|
||||
* @return 是否已支付
|
||||
*/
|
||||
private boolean isOrderPaid(ShopOrderInfo orderInfo) {
|
||||
// public static final int ORDER_PAID_STATE_NO = 3010; //未付款
|
||||
// public static final int ORDER_PAID_STATE_FINANCE_REVIEW = 3011; //待付款审核
|
||||
// public static final int ORDER_PAID_STATE_PART = 3012; //部分付款
|
||||
// public static final int ORDER_PAID_STATE_YES = 3013; //已付款
|
||||
// ORDER_PAID_STATE_NO = 3010; //未付款
|
||||
// ORDER_PAID_STATE_FINANCE_REVIEW = 3011; //待付款审核
|
||||
// ORDER_PAID_STATE_PART = 3012; //部分付款
|
||||
// ORDER_PAID_STATE_YES = 3013; //已付款
|
||||
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小时过期
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +214,7 @@ public interface ShopMchEntryService {
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
Boolean updateMerchEntryStoreId(Long id, Integer storeId);
|
||||
Boolean updateMerchEntryStoreStatus(Long id, Integer storeId);
|
||||
|
||||
/**
|
||||
* 更新商户入驻信息的拉卡拉电子合同相关信息
|
||||
|
||||
@ -17,6 +17,14 @@ import java.util.Map;
|
||||
*/
|
||||
public interface ShopStoreAnalyticsService extends IBaseService<ShopStoreAnalytics> {
|
||||
|
||||
/**
|
||||
* 根据店铺id查询店铺统计信息
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
ShopStoreAnalytics getByStoreId(Integer storeId);
|
||||
|
||||
List<Map> getAnalytics(List<Integer> store_id);
|
||||
|
||||
boolean saveProductAnalyticsNum(Integer store_id);
|
||||
|
||||
@ -14,5 +14,13 @@ import com.suisung.mall.core.web.service.IBaseService;
|
||||
*/
|
||||
public interface ShopStoreCompanyService extends IBaseService<ShopStoreCompany> {
|
||||
|
||||
/**
|
||||
* 获取店铺公司信息
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
ShopStoreCompany getCompany(Integer storeId);
|
||||
|
||||
boolean saveOrUpdateCompany(ShopStoreCompany shopStoreCompany);
|
||||
}
|
||||
|
||||
@ -38,6 +38,17 @@ public interface ShopStoreEmployeeService extends IBaseService<ShopStoreEmployee
|
||||
*/
|
||||
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 列表
|
||||
*
|
||||
|
||||
@ -637,7 +637,6 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
// === 拉卡拉签约逻辑 ===
|
||||
|
||||
Long mchId = record.getId();
|
||||
|
||||
if (CommonConstant.Enable.equals(record.getHas_ec_signed())) {
|
||||
LklLedgerEc ec = lklLedgerEcService.getByMchId(
|
||||
record.getId(),
|
||||
@ -658,17 +657,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
}
|
||||
|
||||
// RMK 补偿机制(入驻总状态,店铺创建和初始化)
|
||||
|
||||
// 创建店铺,并初始化
|
||||
// 新建一个正式的已审核通过的店铺,不要抛异常,使用补偿机制,可以独立初始化店铺
|
||||
// 重要:包含了更改 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);
|
||||
}
|
||||
checkAndFixMchStoreInfo(mchId);
|
||||
|
||||
// 8. 检查商户绑定状态是否完成, 更改总的审核状态
|
||||
checkMerchEntryFinished(mchId);
|
||||
@ -737,6 +726,32 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
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 {
|
||||
// 2. 获取当前商户用户信息
|
||||
UserDto currentUser = getCurrentUser();
|
||||
@ -745,80 +760,72 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 查询商户入驻记录
|
||||
List<ShopMchEntry> entryRecords = selectByMobile(loginMobile);
|
||||
if (CollUtil.isEmpty(entryRecords)) {
|
||||
log.debug("未找到商户入驻记录,手机号: {}", loginMobile);
|
||||
// 4.3 获取用户基础信息
|
||||
AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
|
||||
if (userBase == null) {
|
||||
log.warn("商户用户基础信息不存在,用户ID: {}", currentUser.getId());
|
||||
return false;
|
||||
}
|
||||
|
||||
int fixCount = 0;
|
||||
// 4. 遍历处理每个入驻记录
|
||||
for (ShopMchEntry entry : entryRecords) {
|
||||
// 4.1 验证入驻记录有效性
|
||||
if (entry == null || entry.getId() == null) {
|
||||
log.warn("无效的入驻记录");
|
||||
continue;
|
||||
}
|
||||
// 3. 查询商户入驻记录
|
||||
ShopMchEntry shopMchEntry = get(mchId);
|
||||
if (shopMchEntry == null) {
|
||||
log.debug("未找到商户入驻记录 mchId {}", mchId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4.2 检查入驻状态
|
||||
boolean isValidStatus = CommonConstant.Enable.equals(entry.getHas_ec_signed())
|
||||
&& CommonConstant.Enable.equals(entry.getHas_apply_mer())
|
||||
&& CommonConstant.Enable.equals(entry.getHas_apply_split())
|
||||
&& CommonConstant.Enable.equals(entry.getHas_apply_receiver())
|
||||
&& CommonConstant.Enable.equals(entry.getHas_bind_receiver());
|
||||
// 4.2 检查入驻状态
|
||||
boolean isValidStatus = CommonConstant.Enable.equals(shopMchEntry.getHas_ec_signed())
|
||||
&& CommonConstant.Enable.equals(shopMchEntry.getHas_apply_mer())
|
||||
&& CommonConstant.Enable.equals(shopMchEntry.getHas_apply_split())
|
||||
&& CommonConstant.Enable.equals(shopMchEntry.getHas_apply_receiver())
|
||||
&& CommonConstant.Enable.equals(shopMchEntry.getHas_bind_receiver());
|
||||
|
||||
if (!isValidStatus) {
|
||||
log.debug("入驻记录状态不满足修复条件,入驻ID: {}", entry.getId());
|
||||
continue;
|
||||
}
|
||||
if (isValidStatus) {
|
||||
log.debug("入驻记录状态都通过了审核,进一步验证修复条件,入驻ID: {}", mchId);
|
||||
} else {
|
||||
log.debug("入驻记录状态个别未通过审核,接着检查验证修复条件,入驻ID: {}", mchId);
|
||||
}
|
||||
|
||||
// 4.3 获取用户基础信息
|
||||
AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
|
||||
if (userBase == null) {
|
||||
log.warn("商户用户基础信息不存在,用户ID: {}", currentUser.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4.4 获取店铺员工信息
|
||||
ShopStoreEmployee storeEmployee = null;
|
||||
if (StrUtil.isNotBlank(entry.getStore_id())) {
|
||||
storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId(
|
||||
Convert.toInt(entry.getStore_id()),
|
||||
currentUser.getId()
|
||||
);
|
||||
}
|
||||
// 4.4 获取店铺员工信息
|
||||
ShopStoreEmployee storeEmployee = null;
|
||||
if (StrUtil.isNotBlank(shopMchEntry.getStore_id())) {
|
||||
storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId(
|
||||
Convert.toInt(shopMchEntry.getStore_id()),
|
||||
currentUser.getId()
|
||||
);
|
||||
}
|
||||
|
||||
// 4.5 检查店铺关联关系
|
||||
boolean hasStoreRelation = StrUtil.isNotBlank(userBase.getStore_ids()) &&
|
||||
userBase.getStore_ids().contains(entry.getStore_id());
|
||||
// 4.5 检查店铺关联关系
|
||||
boolean hasStoreRelation = StrUtil.isNotBlank(userBase.getStore_ids()) &&
|
||||
userBase.getStore_ids().contains(shopMchEntry.getStore_id());
|
||||
|
||||
// 4.6 检查权限组信息
|
||||
boolean hasPermission = storeEmployee != null &&
|
||||
StrUtil.isNotBlank(storeEmployee.getRights_group_id());
|
||||
// 4.6 检查权限组信息
|
||||
boolean hasRoles = storeEmployee != null &&
|
||||
StrUtil.isNotBlank(storeEmployee.getRights_group_id());
|
||||
|
||||
// 4.7 当以下任一条件满足时,需要进行修复
|
||||
// - 无店铺员工信息
|
||||
// - 无权限组信息
|
||||
// - 无店铺关联
|
||||
if (storeEmployee == null ||
|
||||
!hasPermission ||
|
||||
!hasStoreRelation) {
|
||||
// 4.7 当以下任一条件满足时,需要进行修复
|
||||
// - 无店铺员工信息
|
||||
// - 无权限组信息
|
||||
// - 无店铺关联
|
||||
if (storeEmployee == null ||
|
||||
!hasRoles ||
|
||||
!hasStoreRelation) {
|
||||
|
||||
// 4.8 补偿创建初始化店铺部分赋值
|
||||
Pair<Integer, String> result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(entry.getId(), false);
|
||||
if (result != null && result.getFirst() > 0) {
|
||||
fixCount++;
|
||||
log.warn("商户信息修复成功,入驻ID: {}", entry.getId());
|
||||
} else {
|
||||
log.error("商户信息修复失败,入驻ID: {}, 错误信息:{}", entry.getId(), result != null ? result.getSecond() : "未知错误");
|
||||
}
|
||||
// 4.8 补偿创建初始化店铺部分赋值
|
||||
Pair<Integer, String> result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false);
|
||||
if (result != null && result.getFirst() > 0) {
|
||||
log.warn("商户信息修复成功,入驻ID: {}", mchId);
|
||||
} else {
|
||||
log.error("商户信息修复失败,入驻ID: {}, 错误信息:{}", mchId, result != null ? result.getSecond() : "未知错误");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return fixCount > 0;
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("商户信息修复异常,手机号: {}", loginMobile, e);
|
||||
log.error("商户信息修复异常,mchId: {}", mchId, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1391,7 +1398,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateMerchEntryStoreId(Long id, Integer storeId) {
|
||||
public Boolean updateMerchEntryStoreStatus(Long id, Integer storeId) {
|
||||
if (ObjectUtil.isEmpty(id) && ObjectUtil.isEmpty(storeId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -35,6 +35,22 @@ public class ShopStoreAnalyticsServiceImpl extends BaseServiceImpl<ShopStoreAnal
|
||||
@Autowired
|
||||
private ShopProductBaseService shopProductBaseService;
|
||||
|
||||
/**
|
||||
* 根据店铺id查询店铺统计信息
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ShopStoreAnalytics getByStoreId(Integer storeId) {
|
||||
try {
|
||||
return getById(storeId);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主键值,从数据库读取数据, 必须获取主键后再读取数据
|
||||
*
|
||||
|
||||
@ -3253,75 +3253,85 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
|
||||
// 初始化默认公司信息,避免商家编辑不了,申请入驻即使是个人类型的,也需要保存相关应有信息,公司信息不能空着
|
||||
// shop_store_company
|
||||
ShopStoreCompany shopStoreCompany = new ShopStoreCompany();
|
||||
shopStoreCompany.setUser_id(userId);
|
||||
shopStoreCompany.setStore_id(storeId);
|
||||
ShopStoreCompany shopStoreCompany = shopStoreCompanyService.getCompany(storeId);
|
||||
if (shopStoreCompany == null) {
|
||||
shopStoreCompany.setUser_id(userId);
|
||||
shopStoreCompany.setStore_id(storeId);
|
||||
|
||||
// 联系人
|
||||
shopStoreCompany.setContacts_name(shopMchEntry.getContact_name());
|
||||
shopStoreCompany.setContacts_phone(contact_mobile);
|
||||
// 联系人
|
||||
shopStoreCompany.setContacts_name(shopMchEntry.getContact_name());
|
||||
shopStoreCompany.setContacts_phone(contact_mobile);
|
||||
|
||||
// 公司名
|
||||
String companyName = StrUtil.isBlank(shopMchEntry.getBiz_license_company()) ? shopMchEntry.getStore_name() : shopMchEntry.getBiz_license_company();
|
||||
shopStoreCompany.setCompany_name(companyName);
|
||||
shopStoreCompany.setCompany_area(shopStoreBase.getStore_area());
|
||||
shopStoreCompany.setCompany_address(shopMchEntry.getStore_address());
|
||||
// 公司名
|
||||
String companyName = StrUtil.isBlank(shopMchEntry.getBiz_license_company()) ? shopMchEntry.getStore_name() : shopMchEntry.getBiz_license_company();
|
||||
shopStoreCompany.setCompany_name(companyName);
|
||||
shopStoreCompany.setCompany_area(shopStoreBase.getStore_area());
|
||||
shopStoreCompany.setCompany_address(shopMchEntry.getStore_address());
|
||||
|
||||
// 营业执照
|
||||
shopStoreCompany.setBusiness_id(shopMchEntry.getBiz_license_number());
|
||||
shopStoreCompany.setBusiness_license_electronic(shopMchEntry.getBiz_license_image());
|
||||
// 营业执照
|
||||
shopStoreCompany.setBusiness_id(shopMchEntry.getBiz_license_number());
|
||||
shopStoreCompany.setBusiness_license_electronic(shopMchEntry.getBiz_license_image());
|
||||
|
||||
// 企业法人
|
||||
shopStoreCompany.setLegal_person(shopMchEntry.getLegal_person_name());
|
||||
shopStoreCompany.setLegal_person_number(shopMchEntry.getLegal_person_id_number());
|
||||
shopStoreCompany.setLegal_person_electronic(shopMchEntry.getLegal_person_id_images());
|
||||
// 企业法人
|
||||
shopStoreCompany.setLegal_person(shopMchEntry.getLegal_person_name());
|
||||
shopStoreCompany.setLegal_person_number(shopMchEntry.getLegal_person_id_number());
|
||||
shopStoreCompany.setLegal_person_electronic(shopMchEntry.getLegal_person_id_images());
|
||||
|
||||
// 银行对公账号
|
||||
shopStoreCompany.setBank_account_name(shopMchEntry.getAccount_holder_name());
|
||||
shopStoreCompany.setBank_account_number(shopMchEntry.getAccount_number());
|
||||
shopStoreCompany.setBank_name(shopMchEntry.getBank_name());
|
||||
// 银行对公账号
|
||||
shopStoreCompany.setBank_account_name(shopMchEntry.getAccount_holder_name());
|
||||
shopStoreCompany.setBank_account_number(shopMchEntry.getAccount_number());
|
||||
shopStoreCompany.setBank_name(shopMchEntry.getBank_name());
|
||||
|
||||
Date today = new Date(); // 当前时间
|
||||
shopStoreCompany.setOrganization_code_start(today);
|
||||
shopStoreCompany.setOrganization_code_end(DateUtil.offsetDay(today, 365 * 5));// 五年
|
||||
shopStoreCompany.setEstablish_date(today);
|
||||
shopStoreCompany.setBusiness_licence_start(today);
|
||||
shopStoreCompany.setBusiness_licence_end(DateUtil.offsetDay(today, 365 * 10));
|
||||
Date today = new Date(); // 当前时间
|
||||
shopStoreCompany.setOrganization_code_start(today);
|
||||
shopStoreCompany.setOrganization_code_end(DateUtil.offsetDay(today, 365 * 5));// 五年
|
||||
shopStoreCompany.setEstablish_date(today);
|
||||
shopStoreCompany.setBusiness_licence_start(today);
|
||||
shopStoreCompany.setBusiness_licence_end(DateUtil.offsetDay(today, 365 * 10));
|
||||
|
||||
shopStoreCompany.setCompany_description(shopMchEntry.getStore_name());
|
||||
shopStoreCompany.setStore_class_ids("");
|
||||
shopStoreCompany.setStore_class_names("");
|
||||
shopStoreCompany.setStore_class_commission("");
|
||||
shopStoreCompany.setCompany_description(shopMchEntry.getStore_name());
|
||||
shopStoreCompany.setStore_class_ids("");
|
||||
shopStoreCompany.setStore_class_names("");
|
||||
shopStoreCompany.setStore_class_commission("");
|
||||
|
||||
if (!shopStoreCompanyService.save(shopStoreCompany)) {
|
||||
logger.error("生成店铺:新增店铺公司失败");
|
||||
if (allowThrown) {
|
||||
throw new ApiException(I18nUtil._("新增店铺公司失败"));
|
||||
if (!shopStoreCompanyService.save(shopStoreCompany)) {
|
||||
logger.error("生成店铺:新增店铺公司失败");
|
||||
if (allowThrown) {
|
||||
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<>();
|
||||
queryWrapper.eq("store_id", storeId).eq("user_id", userId).eq("employee_is_admin", CommonConstant.Enable);
|
||||
if (shopStoreEmployeeService.count(queryWrapper) <= 0) {
|
||||
ShopStoreEmployee shopStoreEmployee = new ShopStoreEmployee();
|
||||
shopStoreEmployee.setStore_id(storeId);
|
||||
shopStoreEmployee.setUser_id(userId);
|
||||
shopStoreEmployee.setRights_group_id(""); // 店铺管理员,店铺
|
||||
shopStoreEmployee.setEmployee_is_kefu(CommonConstant.Enable);
|
||||
|
||||
if (CollUtil.isEmpty(shopStoreEmployees)) { // 添加管理员
|
||||
// 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_kefu(CommonConstant.Enable);
|
||||
if (!shopStoreEmployeeService.save(shopStoreEmployee)) {
|
||||
logger.error("生成店铺:新增店铺员工失败");
|
||||
if (allowThrown) {
|
||||
throw new ApiException(I18nUtil._("新增店铺员工失败"));
|
||||
}
|
||||
return Pair.of(0, "新增店铺员工失败");
|
||||
} else { // 添加店员或管理员
|
||||
shopStoreEmployees = shopStoreEmployeeService.selectEmployeeByCondition(storeId, userId, null);
|
||||
if (CollUtil.isEmpty(shopStoreEmployees)) {
|
||||
shopStoreEmployee.setEmployee_is_admin(CommonConstant.Disable);
|
||||
} else {
|
||||
shopStoreEmployee.setEmployee_is_admin(shopStoreEmployees.get(0).getEmployee_is_admin());
|
||||
}
|
||||
}
|
||||
|
||||
if (!shopStoreEmployeeService.save(shopStoreEmployee)) {
|
||||
logger.error("生成店铺:新增店铺员工失败");
|
||||
if (allowThrown) {
|
||||
throw new ApiException(I18nUtil._("新增店铺员工失败"));
|
||||
}
|
||||
return Pair.of(0, "新增店铺员工失败");
|
||||
}
|
||||
|
||||
// 生成店铺的太阳码 2025-03-31
|
||||
if (StrUtil.isBlank(shopStoreBase.getWx_qrcode())) {
|
||||
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和状态
|
||||
shopMchEntryService.updateMerchEntryStoreId(shopMchEntry.getId(), storeId);
|
||||
shopMchEntryService.updateMerchEntryStoreStatus(shopMchEntry.getId(), storeId);
|
||||
|
||||
// 立即创建顺丰店铺,附带初始化同城配送默认设置
|
||||
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 storeId
|
||||
*/
|
||||
private void initStoreExtraInfo(Integer userId, Integer storeId) {
|
||||
private void initStoreExtraInfo(Integer userId, Integer storeId, Boolean allowThrown) {
|
||||
if (ObjectUtil.isNull(userId) || ObjectUtil.isNull(storeId)) {
|
||||
return;
|
||||
}
|
||||
@ -3365,10 +3375,16 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
Date today = new Date(); // 当前时间
|
||||
|
||||
// 初始化时添加一条店铺分析信息
|
||||
ShopStoreAnalytics store_analytics_column = new ShopStoreAnalytics();
|
||||
store_analytics_column.setStore_id(storeId);
|
||||
if (!shopStoreAnalyticsService.saveOrUpdate(store_analytics_column)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
ShopStoreAnalytics storeAnalytics = shopStoreAnalyticsService.getByStoreId(storeId);
|
||||
if (storeAnalytics == null) {
|
||||
storeAnalytics = new ShopStoreAnalytics();
|
||||
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 (!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_contact("");
|
||||
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);
|
||||
|
||||
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_kefu", CommonConstant.Enable);
|
||||
if (!shopStoreEmployeeService.update(queryWrapper)) {
|
||||
// throw new ApiException(I18nUtil._("设置店铺管理员权限失败"));
|
||||
if (allowThrown) {
|
||||
throw new ApiException(I18nUtil._("设置店铺管理员权限失败"));
|
||||
}
|
||||
log.error("设置店铺管理员权限失败!");
|
||||
}
|
||||
|
||||
@ -3515,7 +3542,10 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
String storeIds = appendStoreIdToAccount(userId, storeId);
|
||||
accountUserBase.setStore_ids(storeIds); // 重要,给用户添加上这个店铺的归属权
|
||||
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_free(1);
|
||||
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_float_proportion(BigDecimal.ZERO);
|
||||
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("");
|
||||
|
||||
if (!invoicingCustomerLevelService.saveOrUpdate(invoicingCustomerLevel)) {
|
||||
throw new ApiException(I18nUtil._("添加默认客户等级失败"));
|
||||
if (allowThrown) {
|
||||
throw new ApiException(I18nUtil._("添加默认客户等级失败"));
|
||||
}
|
||||
log.error("添加默认客户等级失败!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.suisung.mall.shop.store.service.impl;
|
||||
|
||||
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.exception.ApiException;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreCompany;
|
||||
@ -30,6 +31,19 @@ public class ShopStoreCompanyServiceImpl extends BaseServiceImpl<ShopStoreCompan
|
||||
@Autowired
|
||||
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
|
||||
public boolean saveOrUpdateCompany(ShopStoreCompany shopStoreCompany) {
|
||||
|
||||
|
||||
@ -243,6 +243,33 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmplo
|
||||
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 列表
|
||||
*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user