commit message

This commit is contained in:
Chopper
2021-05-13 10:41:46 +08:00
commit 3785bdb3bb
1424 changed files with 100110 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
package cn.lili;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 消费者
*
* @author Chopper
* @date 2020/11/16 10:03 下午
*/
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
System.setProperty("es.set.netty.runtime.available.processors", "false");
SpringApplication.run(ConsumerApplication.class, args);
}
}

View File

@@ -0,0 +1,20 @@
package cn.lili.event;
import cn.lili.modules.order.order.entity.dos.AfterSale;
/**
* 售后单改变状态
*
* @author Chopper
* @date 2020/11/17 7:13 下午
*/
public interface AfterSaleStatusChangeEvent {
/**
* 售后单改变
*
* @param afterSale 售后
*/
void afterSaleStatusChange(AfterSale afterSale);
}

View File

@@ -0,0 +1,18 @@
package cn.lili.event;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
/**
* 订单状态改变事件
*
* @author Chopper
* @date 2020/11/17 7:13 下午
*/
public interface GoodsCommentCompleteEvent {
/**
* 商品评价
* @param memberEvaluation 会员评价
*/
void goodsComment(MemberEvaluation memberEvaluation);
}

View File

@@ -0,0 +1,19 @@
package cn.lili.event;
import cn.lili.modules.member.entity.dto.MemberPointMessage;
/**
* 会员积分改变消息
*
* @author Chopper
* @date 2020/11/17 7:13 下午
*/
public interface MemberPointChangeEvent {
/**
* 会员积分改变消息
*
* @param memberPointMessage 会员积分消息
*/
void memberPointChange(MemberPointMessage memberPointMessage);
}

View File

@@ -0,0 +1,19 @@
package cn.lili.event;
import cn.lili.modules.member.entity.dos.Member;
/**
* 会员注册消息
*
* @author Chopper
* @date 2020/11/17 7:13 下午
*/
public interface MemberRegisterEvent {
/**
* 会员登录
*
* @param member 会员
*/
void memberRegister(Member member);
}

View File

@@ -0,0 +1,19 @@
package cn.lili.event;
import cn.lili.modules.member.entity.dto.MemberWithdrawalMessage;
/**
* 会员提现消息
*
* @author Chopper
* @date 2020/11/17 7:13 下午
*/
public interface MemberWithdrawalEvent {
/**
* 会员提现
*
* @param memberWithdrawalMessage 提现对象
*/
void memberWithdrawal(MemberWithdrawalMessage memberWithdrawalMessage);
}

View File

@@ -0,0 +1,18 @@
package cn.lili.event;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
/**
* 订单状态改变事件
*
* @author Chopper
* @date 2020/11/17 7:13 下午
*/
public interface OrderStatusChangeEvent {
/**
* 订单改变
* @param orderMessage 订单消息
*/
void orderChange(OrderMessage orderMessage);
}

View File

@@ -0,0 +1,20 @@
package cn.lili.event;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
/**
* 订单创建消息
*
* @author Chopper
* @date 2021/2/2 15:15
*/
public interface TradeEvent {
/**
* 订单创建
*
* @param tradeDTO 交易
*/
void orderCreate(TradeDTO tradeDTO);
}

View File

@@ -0,0 +1,71 @@
package cn.lili.event.impl;
import cn.hutool.core.date.DateTime;
import cn.lili.event.AfterSaleStatusChangeEvent;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.distribution.entity.dos.DistributionOrder;
import cn.lili.modules.distribution.entity.enums.DistributionOrderStatusEnum;
import cn.lili.modules.distribution.mapper.DistributionOrderMapper;
import cn.lili.modules.distribution.service.DistributionOrderService;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 分销订单入库
*
* @author Chopper
* @date 2020-07-03 11:20
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DistributionOrderExecute implements OrderStatusChangeEvent, EveryDayExecute, AfterSaleStatusChangeEvent {
//分销订单
private final DistributionOrderService distributionOrderService;
//分销订单持久层
private final DistributionOrderMapper distributionOrderMapper;
@Override
public void orderChange(OrderMessage orderMessage) {
switch (orderMessage.getNewStatus()) {
case PAID: {
//记录分销订单
distributionOrderService.payOrder(orderMessage.getOrderSn());
break;
}
case CANCELLED: {
//修改分销订单状态
distributionOrderService.cancelOrder(orderMessage.getOrderSn());
}
break;
}
}
@Override
public void execute() {
//计算分销提佣
distributionOrderMapper.rebate(DistributionOrderStatusEnum.WAIT_BILL.name(), new DateTime());
//修改分销订单状态
distributionOrderService.update(new LambdaUpdateWrapper<DistributionOrder>()
.eq(DistributionOrder::getDistributionOrderStatus, DistributionOrderStatusEnum.WAIT_BILL.name())
.le(DistributionOrder::getSettleCycle, new DateTime())
.set(DistributionOrder::getDistributionOrderStatus, DistributionOrderStatusEnum.WAIT_CASH.name()));
}
@Override
public void afterSaleStatusChange(AfterSale afterSale) {
if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.COMPLETE.name())) {
distributionOrderService.refundOrder(afterSale.getSn());
}
}
}

View File

@@ -0,0 +1,30 @@
package cn.lili.event.impl;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 商品SKU变化
*
* @author Chopper
* @date 2020-07-03 11:20
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GoodsSkuExecute implements GoodsCommentCompleteEvent {
//商品
private final GoodsSkuService goodsSkuService;
@Override
public void goodsComment(MemberEvaluation memberEvaluation) {
goodsSkuService.updateGoodsSkuCommentNum(memberEvaluation.getSkuId());
}
}

View File

@@ -0,0 +1,51 @@
package cn.lili.event.impl;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.member.service.MemberWalletService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.PointSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 会员积分
*
* @author Chopper
* @date 2020-07-03 11:20
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent {
//配置
private final SettingService settingService;
//会员
private final MemberService memberService;
@Override
public void memberRegister(Member member) {
//获取签到积分赠送设置
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
PointSetting pointSetting = new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
//赠送会员积分
memberService.updateMemberPoint(Long.valueOf(pointSetting.getRegister().longValue()), 1, member.getId(), "会员注册,赠送积分" + pointSetting.getRegister() + "");
}
@Override
public void goodsComment(MemberEvaluation memberEvaluation) {
//获取签到积分赠送设置
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
PointSetting pointSetting = new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
//赠送会员积分
memberService.updateMemberPoint(Long.valueOf(pointSetting.getComment().longValue()), 1, memberEvaluation.getMemberId(), "会员评价,赠送积分" + pointSetting.getComment() + "");
}
}

View File

@@ -0,0 +1,27 @@
package cn.lili.event.impl;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.service.MemberWalletService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 会员钱包创建
*
* @author Chopper
* @date 2020-07-03 11:20
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MemberWalletExecute implements MemberRegisterEvent {
private final MemberWalletService memberWalletService;
@Override
public void memberRegister(Member member) {
memberWalletService.save(member.getId(),member.getUsername());
}
}

View File

@@ -0,0 +1,196 @@
package cn.lili.event.impl;
import cn.lili.event.*;
import cn.lili.modules.member.entity.dto.MemberPointMessage;
import cn.lili.modules.member.entity.dto.MemberWithdrawalMessage;
import cn.lili.modules.member.entity.enums.MemberWithdrawalDestinationEnum;
import cn.lili.modules.message.entity.dto.NoticeMessageDTO;
import cn.lili.modules.message.entity.enums.NoticeMessageNodeEnum;
import cn.lili.modules.message.entity.enums.NoticeMessageParameterEnum;
import cn.lili.modules.message.service.NoticeMessageService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderTypeEnum;
import cn.lili.modules.order.order.entity.vo.OrderDetailVO;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.modules.order.trade.entity.enums.AfterSaleTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* 通知类消息实现
*
* @author Chopper
* @date 2020-07-03 11:20
**/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class NoticeMessageExecute implements TradeEvent, OrderStatusChangeEvent, AfterSaleStatusChangeEvent, MemberPointChangeEvent, MemberWithdrawalEvent {
private final NoticeMessageService noticeMessageService;
private final OrderService orderService;
@Override
public void orderCreate(TradeDTO tradeDTO) {
//订单创建发送订单创建站内信息
NoticeMessageDTO noticeMessageDTO = new NoticeMessageDTO();
noticeMessageDTO.setMemberId(tradeDTO.getMemberId());
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.ORDER_CREATE_SUCCESS);
Map<String, String> params = new HashMap<>();
params.put("goods", tradeDTO.getSkuList().get(0).getGoodsSku().getGoodsName());
noticeMessageDTO.setParameter(params);
//保存站内信
noticeMessageService.noticeMessage(noticeMessageDTO);
}
@Override
public void orderChange(OrderMessage orderMessage) {
//查询订单信息
OrderDetailVO orderDetailVO = orderService.queryDetail(orderMessage.getOrderSn());
NoticeMessageDTO noticeMessageDTO = new NoticeMessageDTO();
//如果订单状态不为空
if (orderDetailVO != null) {
Map<String, String> params = new HashMap<>();
switch (orderMessage.getNewStatus()){
//如果订单新的状态为已取消 则发送取消订单站内信
case CANCELLED:
params.put(NoticeMessageParameterEnum.CANCEL_REASON.getType(), orderDetailVO.getOrder().getCancelReason());
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.ORDER_CANCEL_SUCCESS);
break;
//如果订单新的状态为已经支付,则发送支付成功站内信
case PAID:
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.ORDER_PAY_SUCCESS);
break;
//如果订单新的状态为已发货,则发送已发货站内信
case DELIVERED:
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.ORDER_DELIVER);
break;
//如果订单新的状态为已完成,则发送已完成站内信
case COMPLETED:
//订单完成消息
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.ORDER_COMPLETE);
//订单完成也可以进行评价,所以要有评价消息
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.ORDER_EVALUATION);
break;
//如果是拼团订单,发送拼团成功消息
case UNDELIVERED:
if(orderDetailVO.getOrder().getOrderType().equals(OrderTypeEnum.PINTUAN.name())){
//拼团成功消息
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.PINTUAN_SUCCESS);
}
break;
default:
break;
}
noticeMessageDTO.setMemberId(orderDetailVO.getOrder().getMemberId());
//添加站内信参数
params.put(NoticeMessageParameterEnum.GOODS.getType(), orderDetailVO.getOrderItems().get(0).getGoodsName());
noticeMessageDTO.setParameter(params);
//保存站内信
noticeMessageService.noticeMessage(noticeMessageDTO);
}
}
@Override
public void afterSaleStatusChange(AfterSale afterSale) {
NoticeMessageDTO noticeMessageDTO = new NoticeMessageDTO();
noticeMessageDTO.setMemberId(afterSale.getMemberId());
Map<String, String> params = new HashMap<>();
params.put("goods", afterSale.getGoodsName());
params.put("refuse", afterSale.getAuditRemark());
noticeMessageDTO.setParameter(params);
//如果售后单是申请中 则发送申请中站内信
if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.APPLY.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.AFTER_SALE_CREATE_SUCCESS);
}
//售后审核同意切退货站内信通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.PASS.name()) && afterSale.getServiceType().equals(AfterSaleTypeEnum.RETURN_GOODS.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.RETURN_GOODS_PASS);
}
//售后审核拒绝且退货站内信通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.REFUSE.name()) && afterSale.getServiceType().equals(AfterSaleTypeEnum.RETURN_GOODS.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.RETURN_GOODS_REFUSE);
}
//售后审核同意切退款站内信通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.PASS.name()) && afterSale.getServiceType().equals(AfterSaleTypeEnum.RETURN_MONEY.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.RETURN_MONEY_PASS);
}
//售后审核拒绝且退款站内信通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.REFUSE.name()) && afterSale.getServiceType().equals(AfterSaleTypeEnum.RETURN_MONEY.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.RETURN_MONEY_REFUSE);
}
//售后商家确认收货站内信通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.SELLER_CONFIRM.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.AFTER_SALE_ROG_PASS);
}
//退货物品拒收站内信通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.SELLER_TERMINATION.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.AFTER_SALE_ROG_REFUSE);
}
//售后完成通知
else if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.COMPLETE.name())) {
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.AFTER_SALE_COMPLETE);
}
//保存站内信
if (noticeMessageDTO.getNoticeMessageNodeEnum() != null) {
noticeMessageService.noticeMessage(noticeMessageDTO);
}
}
@Override
public void memberPointChange(MemberPointMessage memberPointMessage) {
//组织站内信参数
NoticeMessageDTO noticeMessageDTO = new NoticeMessageDTO();
noticeMessageDTO.setMemberId(memberPointMessage.getMemberId());
Map<String, String> params = new HashMap<>();
if (memberPointMessage.getType().equals(1)) {
params.put("expenditure_points", "0");
params.put("income_points", memberPointMessage.getPoint().toString());
} else {
params.put("expenditure_points", memberPointMessage.getPoint().toString());
params.put("income_points", "0");
}
noticeMessageDTO.setParameter(params);
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.POINT_CHANGE);
//发送站内通知信息
noticeMessageService.noticeMessage(noticeMessageDTO);
}
@Override
public void memberWithdrawal(MemberWithdrawalMessage memberWithdrawalMessage) {
//如果提现到余额
if (memberWithdrawalMessage.getDestination().equals(MemberWithdrawalDestinationEnum.WALLET.name())) {
//组织参数
NoticeMessageDTO noticeMessageDTO = new NoticeMessageDTO();
noticeMessageDTO.setMemberId(memberWithdrawalMessage.getMemberId());
Map<String, String> params = new HashMap<>();
params.put("income", memberWithdrawalMessage.getPrice().toString());
noticeMessageDTO.setParameter(params);
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.WALLET_WITHDRAWAL_SUCCESS);
//发送提现申请成功消息
noticeMessageService.noticeMessage(noticeMessageDTO);
params.put("income", memberWithdrawalMessage.getPrice().toString());
params.put("expenditure", "0");
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.WALLET_CHANGE);
noticeMessageDTO.setParameter(params);
//发送余额变动消息
noticeMessageService.noticeMessage(noticeMessageDTO);
}
}
}

View File

@@ -0,0 +1,58 @@
package cn.lili.event.impl;
import cn.hutool.json.JSONUtil;
import cn.lili.common.utils.BeanUtil;
import cn.lili.event.TradeEvent;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.entity.dos.Receipt;
import cn.lili.modules.order.order.entity.vo.OrderVO;
import cn.lili.modules.order.order.entity.vo.ReceiptVO;
import cn.lili.modules.order.order.service.ReceiptService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 订单创建发票相关处理
*
* @author Chopper
* @date 2020-07-03 11:20
**/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderCreateReceiptExecute implements TradeEvent {
private final ReceiptService receiptService;
@Override
public void orderCreate(TradeDTO tradeDTO) {
//根据交易sn查询订单信息
List<OrderVO> orderList = tradeDTO.getOrderVO();
//获取发票信息
ReceiptVO receiptVO = tradeDTO.getReceiptVO();
//如果需要获取发票则保存发票信息
if (tradeDTO.getNeedReceipt()) {
if (orderList.size() > 0) {
List<Receipt> receipts = new ArrayList<>();
for (OrderVO orderVO : orderList) {
Receipt receipt = new Receipt();
BeanUtil.copyProperties(receiptVO, receipt);
receipt.setMemberId(orderVO.getMemberId());
receipt.setMemberName(orderVO.getMemberName());
receipt.setStoreId(orderVO.getStoreId());
receipt.setStoreName(orderVO.getStoreName());
receipt.setOrderSn(orderVO.getSn());
receipt.setReceiptDetail(JSONUtil.toJsonStr(orderVO.getOrderItems()));
receipt.setReceiptPrice(orderVO.getFlowPrice());
receipt.setReceiptStatus(0);
receipts.add(receipt);
}
//保存发票
receiptService.saveBatch(receipts);
}
}
}
}

View File

@@ -0,0 +1,80 @@
package cn.lili.event.impl;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.SpringContextUtil;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.payment.entity.RefundLog;
import cn.lili.modules.payment.kit.Payment;
import cn.lili.modules.payment.kit.enums.PaymentMethodEnum;
import cn.lili.modules.payment.service.PaymentService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 支付
*
* @author Chopper
* @date 2021-03-13 16:58
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PaymentExecute implements OrderStatusChangeEvent {
//支付日志
private final PaymentService paymentService;
//订单
private final OrderService orderService;
@Override
public void orderChange(OrderMessage orderMessage) {
switch (orderMessage.getNewStatus()) {
case CANCELLED:
Order order = orderService.getBySn(orderMessage.getOrderSn());
//未付款不做处理 直接返回
if (order.getPayStatus() == PayStatusEnum.UNPAID.name()) {
return;
}
PaymentMethodEnum paymentMethodEnum = PaymentMethodEnum.valueOf(order.getPaymentMethod());
//进行退款操作
switch (paymentMethodEnum) {
case WALLET:
case ALIPAY:
case WECHAT:
//获取支付方式
Payment payment =
(Payment) SpringContextUtil.getBean(paymentMethodEnum.getPlugin());
RefundLog refundLog = RefundLog.builder()
.isRefund(false)
.totalAmount(order.getFlowPrice())
.payPrice(order.getFlowPrice())
.memberId(order.getMemberId())
.paymentName(order.getPaymentMethod())
.afterSaleNo("订单取消")
.orderSn(order.getSn())
.paymentReceivableNo(order.getReceivableNo())
.outOrderNo("AF" + SnowFlake.getIdStr())
.outOrderNo("AF" + SnowFlake.getIdStr())
.refundReason("订单取消")
.build();
payment.cancel(refundLog);
break;
case BANK_TRANSFER:
break;
}
default:
break;
}
}
}

View File

@@ -0,0 +1,191 @@
package cn.lili.event.impl;
import cn.lili.common.cache.Cache;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.order.order.entity.vo.OrderDetailVO;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.enums.PromotionTypeEnum;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 库存扣减,他表示了订单状态是否出库成功
*
* @author Chopper
* @date 2020-07-03 11:20
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StockUpdateExecute implements OrderStatusChangeEvent {
//Redis
private final StringRedisTemplate stringRedisTemplate;
private final DefaultRedisScript<Boolean> quantityScript;
//订单
private final OrderService orderService;
//规格商品
private final GoodsSkuService goodsSkuService;
//促销商品
private final PromotionGoodsService promotionGoodsService;
//缓存
private final Cache cache;
@Override
public void orderChange(OrderMessage orderMessage) {
switch (orderMessage.getNewStatus()) {
case PAID: {
OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn());
//库存key 和 扣减数量
List<String> keys = new ArrayList<>();
List<String> values = new ArrayList<>();
for (OrderItem orderItem : order.getOrderItems()) {
keys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
int i = -orderItem.getNum();
values.add(Integer.toString(i));
setPromotionStock(keys, values, orderItem);
}
//库存扣除结果
Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray());
//如果库存扣减都成功,则记录成交订单
if (Boolean.TRUE.equals(skuResult)) {
//库存确认之后对结构处理
orderService.afterOrderConfirm(orderMessage.getOrderSn());
//成功之后,同步库存
synchroDB(order);
} else {
//失败之后取消订单
this.errorOrder(orderMessage.getOrderSn());
}
break;
}
case CANCELLED: {
OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn());
if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name())) {
for (OrderItem orderItem : order.getOrderItems()) {
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
Integer goodsPromotionOriginStock = promotionGoodsService.getPromotionGoodsStock(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
int goodsPromotionStock = goodsPromotionOriginStock + orderItem.getNum();
String promotionGoodsStockCacheKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
stringRedisTemplate.opsForValue().set(promotionGoodsStockCacheKey, Integer.toString(goodsPromotionStock));
}
String stockCacheKey = GoodsSkuService.getStockCacheKey(orderItem.getSkuId());
Integer goodsOriginStock = goodsSkuService.getStock(orderItem.getSkuId());
int goodsStock = goodsOriginStock + orderItem.getNum();
stringRedisTemplate.opsForValue().set(stockCacheKey, Integer.toString(goodsStock));
}
}
break;
}
default:
break;
}
}
/**
* 订单出库失败
*
* @param orderSn 失败入库订单信息
*/
private void errorOrder(String orderSn) {
orderService.systemCancel(orderSn, "库存不足,出库失败");
}
/**
* 写入需要更改促销库存的商品
*
* @param keys 缓存key值
* @param values 缓存value值
* @param sku 购物车信息
*/
private void setPromotionStock(List<String> keys, List<String> values, OrderItem sku) {
if (sku.getPromotionType() != null) {
//如果此促销有库存概念,则计入
if (!PromotionTypeEnum.haveStock(sku.getPromotionType())) {
return;
}
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(sku.getPromotionType());
keys.add(PromotionGoodsService.getPromotionGoodsStockCacheKey(promotionTypeEnum, sku.getPromotionId(), sku.getSkuId()));
int i = -sku.getNum();
values.add(Integer.toString(i));
}
}
/**
* 写入需要更改促销库存的商品
*
* @param order 订单
*/
private void synchroDB(OrderDetailVO order) {
//sku商品
List<GoodsSku> goodsSkus = new ArrayList<>();
//促销商品
List<PromotionGoods> promotionGoods = new ArrayList<>();
//sku库存key 集合
List<String> skuKeys = new ArrayList<>();
//促销库存key 集合
List<String> promotionKey = new ArrayList<>();
// 循环订单
for (OrderItem orderItem : order.getOrderItems()) {
skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
GoodsSku goodsSku = new GoodsSku();
goodsSku.setId(orderItem.getSkuId());
//如果有促销信息
if (null != orderItem.getPromotionType() && null != orderItem.getPromotionId()) {
//如果促销有库存信息
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
PromotionGoods pGoods = promotionGoodsService.getPromotionGoods(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
promotionKey.add(
PromotionGoodsService.getPromotionGoodsStockCacheKey(
promotionTypeEnum,
orderItem.getPromotionId(), orderItem.getSkuId())
);
promotionGoods.add(pGoods);
}
}
goodsSkus.add(goodsSku);
}
List skuStocks = cache.multiGet(skuKeys);
//循环写入商品库存
for (int i = 0; i < skuStocks.size(); i++) {
goodsSkus.get(i).setQuantity(Integer.parseInt(skuStocks.get(i).toString()));
}
//批量修改商品库存
goodsSkuService.updateBatchById(goodsSkus);
//促销库存处理
if (!promotionKey.isEmpty()) {
List promotionStocks = cache.multiGet(promotionKey);
for (int i = 0; i < promotionKey.size(); i++) {
promotionGoods.get(i).setQuantity(Integer.parseInt(promotionStocks.get(i).toString()));
Integer num = promotionGoods.get(i).getNum();
promotionGoods.get(i).setNum((num != null ? num : 0) + order.getOrder().getGoodsNum());
}
promotionGoodsService.updateBatchById(promotionGoods);
}
goodsSkuService.updateGoodsStuck(goodsSkus);
}
}

View File

@@ -0,0 +1,58 @@
package cn.lili.event.impl;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.event.TradeEvent;
import cn.lili.modules.message.util.WechatMessageUtil;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.vo.OrderVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 微信消息执行器
*
* @author Chopper
* @version v1.0
* 2021-04-19 14:25
*/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WechatMessageExecute implements OrderStatusChangeEvent, TradeEvent {
@Autowired
private WechatMessageUtil wechatMessageUtil;
@Override
public void orderCreate(TradeDTO tradeDTO) {
for (OrderVO orderVO : tradeDTO.getOrderVO()) {
try {
wechatMessageUtil.sendWechatMessage(orderVO.getSn());
} catch (Exception e) {
log.error("微信消息发送失败:" + orderVO.getSn(), e);
}
}
}
@Override
public void orderChange(OrderMessage orderMessage) {
switch (orderMessage.getNewStatus()) {
case PAID:
case UNDELIVERED:
case DELIVERED:
case COMPLETED:
try {
wechatMessageUtil.sendWechatMessage(orderMessage.getOrderSn());
} catch (Exception e) {
log.error("微信消息发送失败", e);
}
default:
break;
}
}
}

View File

@@ -0,0 +1,51 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.common.rocketmq.tags.AfterSaleTagsEnum;
import cn.lili.event.AfterSaleStatusChangeEvent;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 售后通知
*
* @author paulG
* @since 2020/12/9
*/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.after-sale-topic}", consumerGroup = "${lili.data.rocketmq.after-sale-group}")
public class AfterSaleMessageListener implements RocketMQListener<MessageExt> {
//售后订单状态
private final List<AfterSaleStatusChangeEvent> afterSaleStatusChangeEvents;
@Override
public void onMessage(MessageExt messageExt) {
switch (AfterSaleTagsEnum.valueOf(messageExt.getTags())) {
case AFTER_SALE_STATUS_CHANGE:
for (AfterSaleStatusChangeEvent afterSaleStatusChangeEvent : afterSaleStatusChangeEvents) {
try {
AfterSale afterSale = JSONUtil.toBean(new String(messageExt.getBody()), AfterSale.class);
afterSaleStatusChangeEvent.afterSaleStatusChange(afterSale);
} catch (Exception e) {
log.error("售后{},在{}业务中,状态修改事件执行异常",
new String(messageExt.getBody()),
afterSaleStatusChangeEvent.getClass().getName(),
e);
}
}
break;
}
}
}

View File

@@ -0,0 +1,141 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.common.rocketmq.tags.GoodsTagsEnum;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.member.entity.dos.FootPrint;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.service.FootprintService;
import cn.lili.modules.member.service.GoodsCollectionService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.store.service.StoreService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 商品消息
*
* @author paulG
* @since 2020/12/9
**/
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.goods-topic}", consumerGroup = "${lili.data.rocketmq.goods-group}")
public class GoodsMessageListener implements RocketMQListener<MessageExt> {
//ES商品
private final EsGoodsIndexService goodsIndexService;
//店铺
private final StoreService storeService;
//商品
private final GoodsService goodsService;
//商品
private final GoodsSkuService goodsSkuService;
//用户足迹
private final FootprintService footprintService;
//商品收藏
private final GoodsCollectionService goodsCollectionService;
//商品评价
private final List<GoodsCommentCompleteEvent> goodsCommentCompleteEvents;
@Override
public void onMessage(MessageExt messageExt) {
switch (GoodsTagsEnum.valueOf(messageExt.getTags())) {
//查看商品
case VIEW_GOODS:
FootPrint footPrint = JSONUtil.toBean(new String(messageExt.getBody()), FootPrint.class);
footprintService.saveFootprint(footPrint);
break;
//生成索引
case GENERATOR_GOODS_INDEX:
String goodsIndexJsonStr = new String(messageExt.getBody());
List<EsGoodsIndex> goodsIndices = JSONUtil.toList(JSONUtil.parseArray(goodsIndexJsonStr), EsGoodsIndex.class);
for (EsGoodsIndex goodsIndex : goodsIndices) {
log.info("生成商品索引" + goodsIndex);
this.goodsIndexService.addIndex(goodsIndex);
}
break;
//审核商品
case GOODS_AUDIT:
//删除商品
case GOODS_DELETE:
storeService.updateStoreGoodsNum(new String(messageExt.getBody()));
break;
//规格删除
case SKU_DELETE:
String message = new String(messageExt.getBody());
List<String> skuIds = JSONUtil.toList(message, String.class);
goodsCollectionService.deleteSkuCollection(skuIds);
break;
//收藏商品
case GOODS_COLLECTION:
storeService.updateStoreCollectionNum(new String(messageExt.getBody()));
break;
//商品评价
case GOODS_COMMENT_COMPLETE:
for (GoodsCommentCompleteEvent goodsCommentCompleteEvent : goodsCommentCompleteEvents) {
try {
MemberEvaluation memberEvaluation = JSONUtil.toBean(new String(messageExt.getBody()), MemberEvaluation.class);
goodsCommentCompleteEvent.goodsComment(memberEvaluation);
} catch (Exception e) {
log.error("评价{},在{}业务中,状态修改事件执行异常",
new String(messageExt.getBody()),
goodsCommentCompleteEvent.getClass().getName(),
e);
}
}
break;
//购买商品完成
case BUY_GOODS_COMPLETE:
String goodsCompleteMessageStr = new String(messageExt.getBody());
List<GoodsCompleteMessage> goodsCompleteMessageList = JSONUtil.toList(JSONUtil.parseArray(goodsCompleteMessageStr), GoodsCompleteMessage.class);
for (GoodsCompleteMessage goodsCompleteMessage : goodsCompleteMessageList) {
Goods goods = goodsService.getById(goodsCompleteMessage.getGoodsId());
if (goods != null) {
// 更新商品购买数量
if (goods.getBuyCount() == null) {
goods.setBuyCount(0);
}
int buyCount = goods.getBuyCount() + goodsCompleteMessage.getBuyNum();
LambdaUpdateWrapper<Goods> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(Goods::getId, goodsCompleteMessage.getGoodsId());
updateWrapper.set(Goods::getBuyCount, buyCount);
goodsService.update(updateWrapper);
} else {
log.error("商品Id为[" + goodsCompleteMessage.getGoodsId() + "的商品不存在,更新商品失败!");
}
GoodsSku goodsSku = goodsSkuService.getById(goodsCompleteMessage.getSkuId());
if (goodsSku != null) {
// 更新商品购买数量
if (goodsSku.getBuyCount() == null) {
goodsSku.setBuyCount(0);
}
int buyCount = goodsSku.getBuyCount() + goodsCompleteMessage.getBuyNum();
goodsSku.setBuyCount(buyCount);
goodsSkuService.update(goodsSku);
goodsIndexService.updateIndexBuyNum(goodsCompleteMessage.getSkuId(), buyCount);
} else {
log.error("商品SkuId为[" + goodsCompleteMessage.getGoodsId() + "的商品不存在,更新商品失败!");
}
}
break;
}
}
}

View File

@@ -0,0 +1,99 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.common.rocketmq.tags.MemberTagsEnum;
import cn.lili.event.MemberPointChangeEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.event.MemberWithdrawalEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberSign;
import cn.lili.modules.member.entity.dto.MemberPointMessage;
import cn.lili.modules.member.entity.dto.MemberWithdrawalMessage;
import cn.lili.modules.member.service.MemberSignService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 会员消息
*
* @author paulG
* @since 2020/12/9
**/
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.member-topic}", consumerGroup = "${lili.data.rocketmq.member-group}")
public class MemberMessageListener implements RocketMQListener<MessageExt> {
//会员签到
private final MemberSignService memberSignService;
//会员积分变化
private final List<MemberPointChangeEvent> memberPointChangeEvents;
//会员提现
private final List<MemberWithdrawalEvent> memberWithdrawalEvents;
//会员注册
private final List<MemberRegisterEvent> memberSignEvents;
@Override
public void onMessage(MessageExt messageExt) {
switch (MemberTagsEnum.valueOf(messageExt.getTags())) {
//会员注册
case MEMBER_REGISTER:
for (MemberRegisterEvent memberRegisterEvent : memberSignEvents) {
try {
Member member = JSONUtil.toBean(new String(messageExt.getBody()), Member.class);
memberRegisterEvent.memberRegister(member);
} catch (Exception e) {
log.error("会员{},在{}业务中,状态修改事件执行异常",
new String(messageExt.getBody()),
memberRegisterEvent.getClass().getName(),
e);
}
}
break;
//会员签到
case MEMBER_SING:
MemberSign memberSign = JSONUtil.toBean(new String(messageExt.getBody()), MemberSign.class);
memberSignService.memberSignSendPoint(memberSign.getMemberId(), memberSign.getSignDay());
break;
//会员积分变动
case MEMBER_POINT_CHANGE:
for (MemberPointChangeEvent memberPointChangeEvent : memberPointChangeEvents) {
try {
MemberPointMessage memberPointMessage = JSONUtil.toBean(new String(messageExt.getBody()), MemberPointMessage.class);
memberPointChangeEvent.memberPointChange(memberPointMessage);
} catch (Exception e) {
log.error("会员{},在{}业务中,状态修改事件执行异常",
new String(messageExt.getBody()),
memberPointChangeEvent.getClass().getName(),
e);
}
}
break;
//会员提现
case MEMBER_WITHDRAWAL:
for (MemberWithdrawalEvent memberWithdrawalEvent : memberWithdrawalEvents) {
try {
MemberWithdrawalMessage memberWithdrawalMessage = JSONUtil.toBean(new String(messageExt.getBody()), MemberWithdrawalMessage.class);
memberWithdrawalEvent.memberWithdrawal(memberWithdrawalMessage);
} catch (Exception e) {
log.error("会员{},在{}业务中,提现事件执行异常",
new String(messageExt.getBody()),
memberWithdrawalEvent.getClass().getName(),
e);
}
}
default:
break;
}
}
}

View File

@@ -0,0 +1,32 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.message.entity.dto.NoticeMessageDTO;
import cn.lili.modules.message.service.NoticeMessageService;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 站内信通知
*
* @author paulG
* @since 2020/12/9
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.notice-topic}", consumerGroup = "${lili.data.rocketmq.notice-group}")
public class NoticeMessageListener implements RocketMQListener<MessageExt> {
//站内信
private final NoticeMessageService noticeMessageService;
@Override
public void onMessage(MessageExt messageExt) {
NoticeMessageDTO noticeMessageDTO = JSONUtil.toBean(new String(messageExt.getBody()), NoticeMessageDTO.class);
noticeMessageService.noticeMessage(noticeMessageDTO);
}
}

View File

@@ -0,0 +1,100 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.common.rocketmq.tags.OtherTagsEnum;
import cn.lili.common.sms.SmsUtil;
import cn.lili.modules.member.mapper.MemberMapper;
import cn.lili.modules.message.entity.dos.Message;
import cn.lili.modules.message.entity.dos.StoreMessage;
import cn.lili.modules.message.entity.dto.SmsReachDTO;
import cn.lili.modules.message.entity.enums.MessageStatusEnum;
import cn.lili.modules.message.entity.enums.RangeEnum;
import cn.lili.modules.message.service.StoreMessageService;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.service.StoreService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 消息发送
*
* @author paulG
* @since 2020/12/9
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.notice-send-topic}", consumerGroup = "${lili.data.rocketmq.notice-send-group}")
public class NoticeSendMessageListener implements RocketMQListener<MessageExt> {
//会员
private final MemberMapper memberMapper;
//短信
private final SmsUtil smsUtil;
//店铺消息
private final StoreMessageService storeMessageService;
//店铺
private final StoreService storeService;
@Override
public void onMessage(MessageExt messageExt) {
switch (OtherTagsEnum.valueOf(messageExt.getTags())) {
case SMS:
String smsJsonStr = new String(messageExt.getBody());
SmsReachDTO smsReachDTO = JSONUtil.toBean(smsJsonStr, SmsReachDTO.class);
//发送全部会员
if (smsReachDTO.getSmsRange().equals(RangeEnum.ALL.name())) {
//获取所有会员的手机号
List<String> list = memberMapper.getAllMemberMobile();
smsUtil.sendBatchSms(smsReachDTO.getSignName(), list, smsReachDTO.getMessageCode());
//判断为发送部分用户
} else if (smsReachDTO.getSmsRange().equals(RangeEnum.APPOINT.name())) {
smsUtil.sendBatchSms(smsReachDTO.getSignName(), smsReachDTO.getMobile(), smsReachDTO.getMessageCode());
}
break;
//管理员发送站内信
case MESSAGE:
Message message = JSONUtil.toBean(new String(messageExt.getBody()), Message.class);
List<StoreMessage> list = new ArrayList<>();
//保存商家记录
if (message.getMessageRange().equals("ALL")) {
List<Store> storeList = storeService.list(new QueryWrapper<Store>().eq("store_disable", "OPEN"));
storeList.forEach(item -> {
StoreMessage storeMessage = new StoreMessage();
storeMessage.setMessageId(message.getId());
storeMessage.setStoreName(item.getStoreName());
storeMessage.setStoreId(item.getId());
storeMessage.setStatus(MessageStatusEnum.UN_READY.name());
storeMessage.setTitle(message.getTitle());
storeMessage.setContent(message.getContent());
list.add(storeMessage);
});
} else {
int i = 0;
for (String str : message.getUserIds()) {
StoreMessage storeMessage = new StoreMessage();
storeMessage.setMessageId(message.getId());
storeMessage.setStoreId(str);
storeMessage.setStoreName(message.getUserNames()[i]);
storeMessage.setStatus(MessageStatusEnum.UN_READY.name());
storeMessage.setTitle(message.getTitle());
storeMessage.setContent(message.getContent());
list.add(storeMessage);
i++;
}
}
storeMessageService.save(list);
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,76 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.common.cache.Cache;
import cn.lili.common.rocketmq.tags.MqOrderTagsEnum;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.event.TradeEvent;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 订单消息
*
* @author paulG
* @since 2020/12/9
**/
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.order-topic}", consumerGroup = "${lili.data.rocketmq.order-group}")
public class OrderMessageListener implements RocketMQListener<MessageExt> {
//交易
private final List<TradeEvent> tradeEvent;
//订单状态
private final List<OrderStatusChangeEvent> orderStatusChangeEvents;
//缓存
private final Cache<Object> cache;
@Override
public void onMessage(MessageExt messageExt) {
switch (MqOrderTagsEnum.valueOf(messageExt.getTags())) {
//订单创建
case ORDER_CREATE:
String key = new String(messageExt.getBody());
TradeDTO tradeDTO = (TradeDTO) cache.get(key);
for (TradeEvent event : tradeEvent) {
try {
event.orderCreate(tradeDTO);
} catch (Exception e) {
log.error("交易{}入库,在{}业务中,状态修改事件执行异常",
tradeDTO.getSn(),
event.getClass().getName(),
e);
}
}
break;
//订单状态变更
case STATUS_CHANGE:
for (OrderStatusChangeEvent orderStatusChangeEvent : orderStatusChangeEvents) {
try {
OrderMessage orderMessage = JSONUtil.toBean(new String(messageExt.getBody()), OrderMessage.class);
orderStatusChangeEvent.orderChange(orderMessage);
} catch (Exception e) {
log.error("订单{},在{}业务中,状态修改事件执行异常",
new String(messageExt.getBody()),
orderStatusChangeEvent.getClass().getName(),
e);
}
}
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,22 @@
package cn.lili.service;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import org.springframework.stereotype.Component;
/**
* 消息发送
*
* @author paulG
* @since 2020/12/9
*/
@Component
public class NoticeSendMessageConsumer implements OrderStatusChangeEvent {
@Override
public void orderChange(OrderMessage orderMessage) {
}
}

View File

@@ -0,0 +1,104 @@
package cn.lili.timetask;
import cn.lili.timetask.handler.EveryDayExecute;
import cn.lili.timetask.handler.EveryHourExecute;
import cn.lili.timetask.handler.EveryMinuteExecute;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 定时器任务
*
* @author Chopper
* @version v1.0
* 2020-12-24 11:51
*/
@Slf4j
@Component
public class TimedTaskJobHandler {
@Autowired(required = false)
private List<EveryMinuteExecute> everyMinuteExecutes;
@Autowired(required = false)
private List<EveryHourExecute> everyHourExecutes;
@Autowired(required = false)
private List<EveryDayExecute> everyDayExecutes;
/**
* 每分钟任务
*
* @throws Exception
*/
@XxlJob("everyMinuteExecute")
public ReturnT<String> everyMinuteExecute(String param) {
log.info("每分钟任务执行");
if (everyMinuteExecutes == null || everyMinuteExecutes.size() == 0) {
return ReturnT.SUCCESS;
}
for (int i = 0; i < everyMinuteExecutes.size(); i++) {
try {
everyMinuteExecutes.get(i).execute();
} catch (Exception e) {
log.error("每分钟任务异常", e);
}
}
return ReturnT.SUCCESS;
}
/**
* 每小时任务
*
* @throws Exception
*/
@XxlJob("everyHourExecuteJobHandler")
public ReturnT<String> everyHourExecuteJobHandler(String param) {
log.info("每小时任务执行");
if (everyHourExecutes == null || everyHourExecutes.size() == 0) {
return ReturnT.SUCCESS;
}
for (int i = 0; i < everyHourExecutes.size(); i++) {
try {
everyHourExecutes.get(i).execute();
} catch (Exception e) {
log.error("每分钟任务异常", e);
}
}
return ReturnT.SUCCESS;
}
/**
* 每日任务
*
* @throws Exception
*/
@XxlJob("everyDayExecuteJobHandler")
public ReturnT<String> everyDayExecuteJobHandler(String param) {
log.info("每日任务执行");
if (everyDayExecutes == null || everyDayExecutes.size() == 0) {
return ReturnT.SUCCESS;
}
for (int i = 0; i < everyDayExecutes.size(); i++) {
try {
everyDayExecutes.get(i).execute();
} catch (Exception e) {
log.error("每分钟任务异常", e);
}
}
return ReturnT.SUCCESS;
}
}

View File

@@ -0,0 +1,78 @@
package cn.lili.timetask.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@Configuration
public class XxlJobConfig {
private final Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses:}")
private String adminAddresses;
@Value("${xxl.job.accessToken:}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP
*
* 1、引入依赖
* <dependency>
* <groupId>org.springframework.cloud</groupId>
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2、配置文件或者容器启动变量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3、获取IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}

View File

@@ -0,0 +1,18 @@
package cn.lili.timetask.handler;
/**
* 每日任务
* 每日凌晨1点执行
*
* @author Chopper
* @date 2020/12/24 11:52
*/
public interface EveryDayExecute {
/**
* 执行每日任务
*/
void execute();
}

View File

@@ -0,0 +1,17 @@
package cn.lili.timetask.handler;
/**
* 每小时任务
*
* @author Chopper
* @date 2020/12/24 11:52
*/
public interface EveryHourExecute {
/**
* 执行
*/
void execute();
}

View File

@@ -0,0 +1,17 @@
package cn.lili.timetask.handler;
/**
* 每分钟任务
*
* @author Chopper
* @date 2020/12/24 11:52
*/
public interface EveryMinuteExecute {
/**
* 执行
*/
void execute();
}

View File

@@ -0,0 +1,54 @@
package cn.lili.timetask.handler.impl.bill;
import cn.hutool.core.date.DateUtil;
import cn.lili.modules.store.entity.dto.StoreSettlementDay;
import cn.lili.modules.store.mapper.StoreDetailMapper;
import cn.lili.modules.store.service.BillService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 店铺结算执行
*
* @author Bulbasaur
* @date 2021/2/18 3:45 下午
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BillExecute implements EveryDayExecute {
//结算单
private final BillService billService;
//店铺详情
private final StoreDetailMapper storeDetailMapper;
/**
* 1.查询今日待结算的商家
* 2.查询商家上次结算日期,生成本次结算单
* 3.记录商家结算日
*/
@Override
public void execute() {
//获取当前时间的前一天
String day = "," + DateUtil.date().dayOfMonth() + ",";
//获取待结算商家列表
List<StoreSettlementDay> storeList = storeDetailMapper.getSettlementStore(new QueryWrapper<StoreSettlementDay>().like("settlement_cycle", day));
//批量商家结算
for (StoreSettlementDay storeSettlementDay : storeList) {
//生成结算单
billService.createBill(storeSettlementDay.getStoreId(), storeSettlementDay.getSettlementDay());
//修改店铺结算时间
storeDetailMapper.updateSettlementDay(storeSettlementDay.getStoreId(), DateUtil.date());
}
}
}

View File

@@ -0,0 +1,48 @@
package cn.lili.timetask.handler.impl.goods;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.lili.modules.goods.mapper.GoodsMapper;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.mapper.MemberEvaluationMapper;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* 商品定时器
*
* @author Chopper
* @date 2021/3/18 3:23 下午
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GoodsExecute implements EveryDayExecute {
//会员评价
private final MemberEvaluationMapper memberEvaluationMapper;
//商品
private final GoodsMapper goodsMapper;
/**
* 查询已上架的商品的评价数量并赋值
*/
@Override
public void execute() {
//查询上次统计到本次的评价数量
List<Map<String, Object>> list = memberEvaluationMapper.memberEvaluationNum(
new QueryWrapper<MemberEvaluation>()
.between("create_time", DateUtil.yesterday(), new DateTime()));
System.out.println("评论数量" + list.size());
for (Map<String, Object> map : list) {
goodsMapper.addGoodsCommentNum(Integer.parseInt(map.get("num").toString()), map.get("goods_id").toString());
}
}
}

View File

@@ -0,0 +1,57 @@
package cn.lili.timetask.handler.impl.order;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.OrderSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.timetask.handler.EveryMinuteExecute;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
* 订单自动取消(每分钟执行)
*
* @author paulG
* @date 2021/3/11
**/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CancelOrderTaskExecute implements EveryMinuteExecute {
//订单
private final OrderService orderService;
//设置
private final SettingService settingService;
@Override
public void execute() {
Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
if (orderSetting != null && orderSetting.getAutoCancel() != null) {
// 订单自动取消时间 = 当前时间 - 自动取消时间分钟数
DateTime cancelTime = DateUtil.offsetMinute(DateUtil.date(), -orderSetting.getAutoCancel());
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.UNPAID.name());
// 订单创建时间 <= 订单自动取消时间
queryWrapper.le(Order::getCreateTime, cancelTime);
List<Order> list = orderService.list(queryWrapper);
List<String> cancelSnList = list.stream().map(Order::getSn).collect(Collectors.toList());
for (String sn : cancelSnList) {
orderService.systemCancel(sn, "超时未支付自动取消");
}
}
}
}

View File

@@ -0,0 +1,121 @@
package cn.lili.timetask.handler.impl.order;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.member.entity.dto.MemberEvaluationDTO;
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
import cn.lili.modules.member.service.MemberEvaluationService;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.OrderSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author paulG
* @since 2021/3/11
**/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderEveryDayTaskExecute implements EveryDayExecute {
//订单
private final OrderService orderService;
//订单货物
private final OrderItemService orderItemService;
//设置
private final SettingService settingService;
//会员评价
private final MemberEvaluationService memberEvaluationService;
/**
* 执行每日任务
*/
@Override
public void execute() {
Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
//自动确认收货
OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
if (orderSetting == null) {
throw new ServiceException("系统配置异常");
}
//自动确认收货
completedOrder(orderSetting);
//自动好评
memberEvaluation(orderSetting);
}
/**
* 自动确认收获,订单完成
*
* @param orderSetting 订单设置
*/
private void completedOrder(OrderSetting orderSetting) {
// 订单自动收货时间 = 当前时间 - 自动收货时间天数
DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoEvaluation());
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.DELIVERED.name());
// 订单发货时间 >= 订单自动收货时间
queryWrapper.ge(Order::getLogisticsTime, receiveTime);
List<Order> list = orderService.list(queryWrapper);
List<String> receiveSnList = list.stream().map(Order::getSn).collect(Collectors.toList());
if (!receiveSnList.isEmpty()) {
LambdaUpdateWrapper<Order> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(Order::getSn, receiveSnList);
updateWrapper.set(Order::getOrderStatus, OrderStatusEnum.COMPLETED.name()).set(Order::getCompleteTime, new Date());
boolean update = orderService.update(updateWrapper);
if (Boolean.FALSE.equals(update)) {
log.error("自动收货订单失败!订单编号为[{}]", receiveSnList);
}
}
}
/**
* 自动好评
*
* @param orderSetting 订单设置
*/
private void memberEvaluation(OrderSetting orderSetting) {
// 订单自动收货时间 = 当前时间 - 自动收货时间天数
DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoReceive());
// 订单完成时间 <= 订单自动好评时间
List<OrderItem> orderItems = orderItemService.waitEvaluate(receiveTime);
for (OrderItem orderItem : orderItems) {
MemberEvaluationDTO memberEvaluationDTO = new MemberEvaluationDTO();
memberEvaluationDTO.setOrderItemSn(orderItem.getSn());
memberEvaluationDTO.setContent("系统默认好评");
memberEvaluationDTO.setGoodsId(orderItem.getGoodsId());
memberEvaluationDTO.setSkuId(orderItem.getSkuId());
memberEvaluationDTO.setGrade(EvaluationGradeEnum.GOOD.name());
memberEvaluationDTO.setDeliveryScore(5);
memberEvaluationDTO.setDescriptionScore(5);
memberEvaluationDTO.setServiceScore(5);
memberEvaluationService.addMemberEvaluation(memberEvaluationDTO);
}
}
}

View File

@@ -0,0 +1,131 @@
package cn.lili.timetask.handler.impl.promotion;
import cn.lili.modules.order.cart.entity.vo.FullDiscountVO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.entity.vos.CouponVO;
import cn.lili.modules.promotion.entity.vos.PintuanVO;
import cn.lili.modules.promotion.service.*;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 促销活动每日定时器
*
* @author Chopper
* @date 2021/3/18 3:23 下午
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PromotionEverydayExecute implements EveryDayExecute {
//Mongo
private final MongoTemplate mongoTemplate;
//满额活动
private final FullDiscountService fullDiscountService;
//拼团
private final PintuanService pintuanService;
//优惠券
private final CouponService couponService;
//会员优惠券
private final MemberCouponService memberCouponService;
//促销商品
private final PromotionGoodsService promotionGoodsService;
/**
* 将已过期的促销活动置为结束
*/
@Override
public void execute() {
Query query = new Query();
query.addCriteria(Criteria.where("promotionStatus").ne(PromotionStatusEnum.END.name()).orOperator(Criteria.where("promotionStatus").ne(PromotionStatusEnum.CLOSE.name())));
query.addCriteria(Criteria.where("endTime").lt(new Date()));
List<String> promotionIds = new ArrayList<>();
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
if (!fullDiscountVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
for (FullDiscountVO vo : fullDiscountVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
fullDiscountService.update(this.getUpdatePromotionWrapper(ids));
promotionIds.addAll(ids);
}
List<PintuanVO> pintuanVOS = mongoTemplate.find(query, PintuanVO.class);
if (!pintuanVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
for (PintuanVO vo : pintuanVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
pintuanService.update(this.getUpdatePromotionWrapper(ids));
promotionIds.addAll(ids);
}
List<CouponVO> couponVOS = mongoTemplate.find(query, CouponVO.class);
if (!couponVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
for (CouponVO vo : couponVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
couponService.update(this.getUpdatePromotionWrapper(ids));
LambdaUpdateWrapper<MemberCoupon> memberCouponLambdaUpdateWrapper = new LambdaUpdateWrapper<MemberCoupon>().in(MemberCoupon::getCouponId, ids).set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
memberCouponService.update(memberCouponLambdaUpdateWrapper);
promotionIds.addAll(ids);
}
promotionGoodsService.update(this.getUpdatePromotionGoodsWrapper(promotionIds));
}
private UpdateWrapper getUpdatePromotionWrapper(List<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.in("id", ids);
updateWrapper.set("promotion_status", PromotionStatusEnum.END.name());
return updateWrapper;
}
private UpdateWrapper getUpdatePromotionGoodsWrapper(List<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.in("promotion_id", ids);
updateWrapper.set("promotion_status", PromotionStatusEnum.END.name());
return updateWrapper;
}
}

View File

@@ -0,0 +1,71 @@
package cn.lili.timetask.handler.impl.statistics;
import cn.lili.modules.statistics.model.dos.MemberStatisticsData;
import cn.lili.modules.statistics.service.MemberStatisticsDataService;
import cn.lili.timetask.handler.EveryDayExecute;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
/**
* 会员数据统计
*
* @author Chopper
* @date 2021-03-02 14:56
*/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MemberStatisticsExecute implements EveryDayExecute {
//会员统计
private final MemberStatisticsDataService memberStatisticsDataService;
@Override
public void execute() {
try {
//统计的时间(开始。结束时间)
Date startTime, endTime;
//初始值
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
endTime = calendar.getTime();
//-1天即为开始时间
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 1);
startTime = calendar.getTime();
MemberStatisticsData memberStatisticsData = new MemberStatisticsData();
memberStatisticsData.setMemberCount(memberStatisticsDataService.memberCount(endTime));
memberStatisticsData.setCreateDate(startTime);
memberStatisticsData.setActiveQuantity(memberStatisticsDataService.activeQuantity(startTime));
memberStatisticsData.setNewlyAdded(memberStatisticsDataService.newlyAdded(startTime, endTime));
memberStatisticsDataService.save(memberStatisticsData);
} catch (Exception e) {
log.error("每日会员统计功能异常:", e);
}
}
public static void main(String[] args) {
//统计的时间(开始。结束时间)
Date startTime, endTime;
//初始值
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
endTime = calendar.getTime();
//-1天即为开始时间
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 1);
startTime = calendar.getTime();
System.out.println(startTime);
}
}

View File

@@ -0,0 +1,105 @@
package cn.lili.timetask.handler.impl.statistics;
import cn.lili.common.cache.Cache;
import cn.lili.common.cache.CachePrefix;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.config.properties.StatisticsProperties;
import cn.lili.modules.statistics.model.vo.OnlineMemberVO;
import cn.lili.timetask.handler.EveryHourExecute;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 实时在线人数统计
*
* @author Chopper
* @date 2021-02-21 09:47
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OnlineMemberStatistics implements EveryHourExecute {
//缓存
private final Cache cache;
//统计小时
private final StatisticsProperties statisticsProperties;
@Override
public void execute() {
Calendar calendar = Calendar.getInstance();
Object object = cache.get(CachePrefix.ONLINE_MEMBER.getPrefix());
List<OnlineMemberVO> onlineMemberVOS;
if (object == null) {
onlineMemberVOS = new ArrayList<>();
} else {
onlineMemberVOS = (List<OnlineMemberVO>) object;
}
//过滤 有效统计时间
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - statisticsProperties.getOnlineMember());
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Calendar finalCalendar = calendar;
onlineMemberVOS = onlineMemberVOS.stream()
.filter(onlineMemberVO -> onlineMemberVO.getDate().after(finalCalendar.getTime()))
.collect(Collectors.toList());
//计入新数据
calendar = Calendar.getInstance();
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size()));
//写入缓存
cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
}
/**
* 手动设置某一时间,活跃人数
*
* @param time 时间
* @param num 人数
*/
public void execute(Date time, Integer num) {
Object object = cache.get(CachePrefix.ONLINE_MEMBER.getPrefix());
List<OnlineMemberVO> onlineMemberVOS;
if (object == null) {
onlineMemberVOS = new ArrayList<>();
} else {
onlineMemberVOS = (List<OnlineMemberVO>) object;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(time);
//过滤 有效统计时间
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 48);
Calendar finalCalendar = calendar;
onlineMemberVOS = onlineMemberVOS.stream()
.filter(onlineMemberVO -> onlineMemberVO.getDate().after(finalCalendar.getTime()))
.collect(Collectors.toList());
onlineMemberVOS.add(new OnlineMemberVO(time, num));
//写入缓存
cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
}
}

View File

@@ -0,0 +1,60 @@
package cn.lili.timetask.handler.impl.storeRating;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.entity.vo.StoreRatingVO;
import cn.lili.modules.member.mapper.MemberEvaluationMapper;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.entity.enums.StoreStatusEnum;
import cn.lili.modules.store.service.StoreService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 店铺评分
*
* @author Chopper
* @date 2021/3/15 5:30 下午
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StoreRatingExecute implements EveryDayExecute {
//店铺
private final StoreService storeService;
//会员评价
private final MemberEvaluationMapper memberEvaluationMapper;
@Override
public void execute() {
//获取所有开启的店铺
List<Store> storeList = storeService.list(new LambdaQueryWrapper<Store>().eq(Store::getStoreDisable, StoreStatusEnum.OPEN.name()));
for (Store store : storeList) {
//店铺所有开启的评价
LambdaQueryWrapper<MemberEvaluation> QueryWrapper = Wrappers.lambdaQuery();
QueryWrapper.eq(MemberEvaluation::getStoreId, store.getId());
QueryWrapper.eq(MemberEvaluation::getStatus, SwitchEnum.OPEN.name());
StoreRatingVO storeRatingVO = memberEvaluationMapper.getStoreRatingVO(QueryWrapper);
if (storeRatingVO != null) {
//保存评分
LambdaUpdateWrapper<Store> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
lambdaUpdateWrapper.eq(Store::getId, store.getId());
lambdaUpdateWrapper.set(Store::getDescriptionScore, storeRatingVO.getDescriptionScore());
lambdaUpdateWrapper.set(Store::getDeliveryScore, storeRatingVO.getDeliveryScore());
lambdaUpdateWrapper.set(Store::getServiceScore, storeRatingVO.getServiceScore());
storeService.update(lambdaUpdateWrapper);
}
}
}
}

View File

@@ -0,0 +1,192 @@
package cn.lili.timetask.handler.impl.view;
import cn.lili.common.cache.Cache;
import cn.lili.common.cache.CachePrefix;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.DateUtil;
import cn.lili.modules.statistics.model.dos.PlatformViewData;
import cn.lili.modules.statistics.service.PlatformViewDataService;
import cn.lili.timetask.handler.EveryDayExecute;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* 统计 入库
*
* @author Chopper
* @date 2021-01-15 18:20
*/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PageViewStatisticsExecute implements EveryDayExecute {
//缓存
private final Cache cache;
//平台PV统计
private final PlatformViewDataService platformViewDataService;
@Override
public void execute() {
//1、缓存keys 模糊匹配
//2、过滤今日的数据即今天只能统计今日以前的数据
//4对key value 分别代表平台PV、平台UV、店铺PV、店铺UV
List<String> pvKeys = filterKeys(cache.keys(CachePrefix.PV.getPrefix() + "*"));
List<Integer> pvValues = cache.multiGet(pvKeys);
List<String> storePVKeys = filterKeys(cache.keys(CachePrefix.STORE_PV.getPrefix() + "*"));
List<Integer> storePvValues = cache.multiGet(storePVKeys);
//备份UV数据这里赋值之后会被删除
List<String> uvKeys = new ArrayList<>();
List<String> storeUvKeys = new ArrayList<>();
log.debug("开始统计平台数据PV共计【{}】条", pvKeys.size());
log.debug("开始统计店铺数据PV共计【{}】条", storePvValues.size());
//定义要统计的数据
List<PlatformViewData> platformViewDataList = new ArrayList<>();
//PV 统计
if (pvKeys.size() > 0) {
for (int i = 0; i < pvKeys.size(); i++) {
String key = pvKeys.get(i);
PageViewStatistics pageViewStatistics = new PageViewStatistics(key);
PlatformViewData platformPVData = new PlatformViewData();
BeanUtil.copyProperties(pageViewStatistics, platformPVData);
platformPVData.setPvNum(pvValues.get(i).longValue());
//根据pvkey 获取 uvkey
String uvKey = getUvKey(key);
uvKeys.add(uvKey);
platformPVData.setUvNum(cache.counter(uvKey));
platformPVData.setStoreId("-1");
platformViewDataList.add(platformPVData);
}
batchSave(pvKeys, uvKeys, platformViewDataList);
}
//店铺 PV 统计
if (storePVKeys.size() > 0) {
platformViewDataList = new ArrayList<>();
for (int i = 0; i < storePVKeys.size(); i++) {
String key = storePVKeys.get(i);
PageViewStatistics pageViewStatistics = new PageViewStatistics(key);
PlatformViewData storePVData = new PlatformViewData();
BeanUtil.copyProperties(pageViewStatistics, storePVData);
storePVData.setPvNum(storePvValues.get(i).longValue());
//根据pvkey 获取 uvkey
String uvKey = getUvKey(key);
uvKeys.add(uvKey);
storePVData.setUvNum(cache.counter(uvKey));
platformViewDataList.add(storePVData);
}
batchSave(storePVKeys, storeUvKeys, platformViewDataList);
}
}
/**
* 根据缓存的PVkey 获取对应的UVkey
*
* @param key
* @return
*/
private String getUvKey(String key) {
if (StringUtils.isNotEmpty(key)) {
key = key.replace(CachePrefix.PV.getPrefix(), CachePrefix.UV.getPrefix());
key = key.replace(CachePrefix.STORE_PV.getPrefix(), CachePrefix.STORE_UV.getPrefix());
return key;
}
return key;
}
/**
* 批量保存数据&&清除保存数据的缓存
*
* @param pvKeys PV key
* @param uvKeys UV key
* @param platformViewData DOS
*/
@Transactional(rollbackFor = Exception.class)
void batchSave(List<String> pvKeys, List<String> uvKeys, List<PlatformViewData> platformViewData) {
log.debug("批量保存流量数据,共计【{}】条", platformViewData.size());
platformViewDataService.saveBatch(platformViewData);
//批量删除缓存key
cache.multiDel(pvKeys);
cache.multiDel(uvKeys);
log.debug("流量数据保存完成");
}
/**
* 过滤缓存key
*
* @param keys 缓存key集合
*/
private static List<String> filterKeys(List<String> keys) {
//只统计一天前的数据
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, -24);
List<String> result = new ArrayList<>();
for (String key : keys) {
PageViewStatistics temp = new PageViewStatistics(key);
//如果需要统计则将key写入集合
if (temp.getDate().before(calendar.getTime())) {
result.add(key);
}
}
return result;
}
}
/**
* 根据缓存key 获取其中需要的参数,年月日,以及店铺信息
*/
@Data
class PageViewStatistics {
/**
* 年 、 月 、 日 、 店铺id
*/
private Date date;
private String storeId;
public PageViewStatistics(String str) {
//将字符串解析成需要的对象
str = str.substring(str.indexOf("}") + 2);
String[] dateStr = str.split("-");
Integer year = Integer.parseInt(dateStr[0]);
Integer month = Integer.parseInt(dateStr[1]);
Integer day;
//是否有店铺id
if (dateStr.length > 3) {
day = Integer.parseInt(dateStr[2]);
this.storeId = dateStr[3];
} else {
day = Integer.parseInt(dateStr[2]);
}
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
this.date = calendar.getTime();
System.out.println(DateUtil.toString(date,DateUtil.STANDARD_FORMAT));
}
}

View File

@@ -0,0 +1,53 @@
package cn.lili.trigger;
import cn.hutool.json.JSONUtil;
import cn.lili.common.cache.Cache;
import cn.lili.common.trigger.interfaces.TimeTriggerExecutor;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.common.trigger.util.TimeTriggerUtil;
import cn.lili.common.utils.SpringContextUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 事件触发消费者
*
* @author paulG
* @date 2020/11/17 7:19 下午
*/
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RocketMQMessageListener(topic = "${lili.data.rocketmq.promotion-topic}", consumerGroup = "${lili.data.rocketmq.promotion-group}")
public class TimeTriggerConsumer implements RocketMQListener<TimeTriggerMsg> {
private final Cache<Integer> cache;
@Override
public void onMessage(TimeTriggerMsg timeTriggerMsg) {
try {
String key = TimeTriggerUtil.generateKey(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getTriggerTime(), timeTriggerMsg.getUniqueKey());
if (cache.get(key) == null) {
log.info("执行器执行被取消:{} | 任务标识:{}", timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getUniqueKey());
return;
}
log.info("执行器执行:" + timeTriggerMsg.getTriggerExecutor());
log.info("执行器参数:" + JSONUtil.toJsonStr(timeTriggerMsg.getParam()));
cache.remove(key);
TimeTriggerExecutor executor = (TimeTriggerExecutor) SpringContextUtil.getBean(timeTriggerMsg.getTriggerExecutor());
executor.execute(timeTriggerMsg.getParam());
} catch (Exception e) {
log.error("mq延时任务异常", e);
}
}
}

View File

@@ -0,0 +1,74 @@
package cn.lili.trigger.executor;
import cn.hutool.json.JSONUtil;
import cn.lili.common.delayqueue.PintuanOrderMessage;
import cn.lili.common.delayqueue.PromotionMessage;
import cn.lili.common.trigger.interfaces.TimeTrigger;
import cn.lili.common.trigger.interfaces.TimeTriggerExecutor;
import cn.lili.common.trigger.model.TimeExecuteConstant;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.common.utils.DateUtil;
import cn.lili.config.rocketmq.RocketmqCustomProperties;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.service.PromotionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 促销事件触发
*
* @author Chopper
* @version v4.1
* @date 2020/11/17 7:20 下午
*/
@Slf4j
@Component(TimeExecuteConstant.PROMOTION_EXECUTOR)
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PromotionTimeTriggerExecutor implements TimeTriggerExecutor {
//促销
private final PromotionService promotionService;
//Rocketmq
private final RocketmqCustomProperties rocketmqCustomProperties;
//延时任务
private final TimeTrigger timeTrigger;
//订单
private final OrderService orderService;
@Override
public void execute(Object object) {
PromotionMessage promotionMessage = JSONUtil.toBean(JSONUtil.parseObj(object), PromotionMessage.class);
// 促销延时信息
if (promotionMessage != null && promotionMessage.getPromotionId() != null) {
log.info("促销活动信息消费:{}", promotionMessage);
// 如果为促销活动开始,则需要发布促销活动结束的定时任务
if (PromotionStatusEnum.START.name().equals(promotionMessage.getPromotionStatus())) {
if (!promotionService.updatePromotionStatus(promotionMessage)) {
log.error("开始促销活动失败: {}", promotionMessage);
return;
}
// 促销活动开始后,设置促销活动结束的定时任务
promotionMessage.setPromotionStatus(PromotionStatusEnum.END.name());
String uniqueKey = "{TIME_TRIGGER_" + promotionMessage.getPromotionType() + "}_" + promotionMessage.getPromotionId();
// 结束时间(延时一分钟)
long closeTime = promotionMessage.getEndTime().getTime() + 60000;
TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(TimeExecuteConstant.PROMOTION_EXECUTOR, closeTime, promotionMessage, uniqueKey, rocketmqCustomProperties.getPromotionTopic());
timeTrigger.addDelay(timeTriggerMsg, DateUtil.getDelayTime(promotionMessage.getEndTime().getTime()));
} else {
promotionService.updatePromotionStatus(promotionMessage);
}
return;
}
PintuanOrderMessage pintuanOrderMessage = JSONUtil.toBean(JSONUtil.parseObj(object), PintuanOrderMessage.class);
if (pintuanOrderMessage != null && pintuanOrderMessage.getPintuanId() != null) {
log.info("拼团订单信息消费:{}", pintuanOrderMessage);
// 拼团订单自动处理
orderService.agglomeratePintuanOrder(pintuanOrderMessage.getPintuanId(), pintuanOrderMessage.getOrderSn());
}
}
}

View File

@@ -0,0 +1,301 @@
server:
port: 8886
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
min-spare: 50
max: 1000
# 与Spring Boot 2一样默认情况下大多数端点都不通过http公开我们公开了所有端点。对于生产您应该仔细选择要公开的端点。
management:
# health:
# elasticsearch:
# enabled: false
# datasource:
# enabled: false
endpoints:
web:
exposure:
include: '*'
spring:
# 要在其中注册的Spring Boot Admin Server的URL。
boot:
admin:
client:
url: http://127.0.0.1:8000
# mongodb
data:
mongodb:
host: 127.0.0.1
port: 27017
database: lilishop
username: root
password: lilishop
authentication-database: admin
# replica-set-name: mongoreplset
cache:
type: redis
jpa:
# 自动生成表结构
generate-ddl: true
open-in-view: false
# Redis
redis:
host: 127.0.0.1
port: 6379
password: lilishop
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制) 默认 8
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-wait: 20
# 连接池中的最大空闲连接 默认 8
max-idle: 10
# 连接池中的最小空闲连接 默认 8
min-idle: 8
# 文件大小上传配置
servlet:
multipart:
max-file-size: 20MB
max-request-size: 20MB
jackson:
time-zone: GMT+8
serialization:
#关闭jackson 对json做解析
fail-on-empty-beans: false
shardingsphere:
datasource:
# 数据库名称,可自定义,可以为多个,以逗号隔开,每个在这里定义的库,都要在下面定义连接属性
names: default-datasource
default-datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: lilishop
maxActive: 20
initialSize: 5
maxWait: 60000
minIdle: 5
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
#是否缓存preparedStatement也就是PSCache。在mysql下建议关闭。 PSCache对支持游标的数据库性能提升巨大比如说oracle。
poolPreparedStatements: false
#要启用PSCache-1为关闭 必须配置大于0当大于0时poolPreparedStatements自动触发修改为true 可以把这个数值配置大一些比如说100
maxOpenPreparedStatements: -1
#配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,log4j2
#通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#合并多个DruidDataSource的监控数据
useGlobalDataSourceStat: true
loginUsername: druid
loginPassword: druid
# sharding:
# default-data-source-name: default-datasource
# #需要拆分的表,可以设置多个 在 li_order 级别即可
# tables:
# #需要进行分表的逻辑表名
# li_order:
# #实际的表结点,下面代表的是li_order_为开头的所有表如果能确定表的范围例如按月份分表这里的写法是data2020.li_order_$->{2020..2021}_$->{01..12} 表示例如 li_order_2020_01 li_order_2020_03 li_order_2021_01
# actual-data-nodes: data2020.li_order_$->{2019..2021}_$->{01..12}
# table-strategy:
# # 分表策略,根据创建日期
# standard:
# sharding-column: create_time
# #分表策略
# precise-algorithm-class-name: cn.lili.config.sharding.CreateTimeShardingTableAlgorithm
# #范围查询实现
# range-algorithm-class-name: cn.lili.config.sharding.CreateTimeShardingTableAlgorithm
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
# 忽略鉴权url
ignored:
urls:
- /editor-app/**
- /actuator**
- /actuator/**
- /MP_verify_qSyvBPhDsPdxvOhC.txt
- /weixin/**
- /source/**
- /buyer/mini-program/**
- /buyer/cashier/**
- /buyer/pageData/**
- /buyer/article/**
- /buyer/goods/**
- /buyer/category/**
- /buyer/shop/**
- /buyer/connect/**
- /buyer/members/smsLogin
- /buyer/members/refresh/*
- /buyer/members/refresh**
- /buyer/promotion/pintuan
- /buyer/promotion/seckill
- /buyer/memberEvaluation/**/goodsEvaluation
- /buyer/memberEvaluation/**/evaluationNumber
- /store/login/**
- /manager/user/login
- /manager/user/refresh/**
- /druid/**
- /swagger-ui.html
- /doc.html
- /swagger-resources/**
- /swagger/**
- /**/**.js
- /**/**.png
- /**/**.css
- /webjars/**
- /v2/api-docs
- /configuration/ui
- /boot-admin
statics:
- /**/*.js
- /**/*.css
- /**/*.png
- /**/*.ico
# Swagger界面内容配置
swagger:
title: lili API接口文档
description: lili Api Documentation
version: 1.0.0
termsOfServiceUrl: https://pickmall.cn
contact:
name: lili
url: https://pickmall.cn
email: admin@pickmall.com
# Mybatis-plus
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
configuration:
#缓存开启
cache-enabled: true
#日志
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 日志
logging:
# 输出级别
level:
cn.lili: info
# org.hibernate: debug
# org.springframework: debug
# org.springframework.data.mongodb.core: debug
file:
# 指定路径
path: lili-logs
# 最大保存天数
max-history: 7
# 每个文件最大大小
max-size: 5MB
#加密参数
jasypt:
encryptor:
password: lili
lili:
system:
isDemoSite: true
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数
onlineMember: 48
# 当前在线人数刷新时间间隔单位秒设置为600则每10分钟刷新一次
currentOnlineUpdate: 600
#qq lbs 申请
lbs:
key: 4BYBZ-7MT6S-PUAOA-6BNWL-FJUD7-UUFXT
sk: zhNKVrJK6UPOhqIjn8AQvG37b9sz6
#域名
domain:
pc: https://pc.b2b2c.pickmall.cn
wap: https://m.b2b2c.pickmall.cn
store: https://store.b2b2c.pickmall.cn
admin: https://admin.b2b2c.pickmall.cn
#api地址
api:
buyer: https://buyer-api.pickmall.cn
common: https://common-api.pickmall.cn
manager: https://admin-api.pickmall.cn
store: https://store-api.pickmall.cn
# jwt 细节设定
jwt-setting:
# token过期时间分钟
tokenExpireTime: 60
# 使用Spring @Cacheable注解失效时间
cache:
# 过期时间 单位秒 永久不过期设为-1
timeout: 1500
#多线程配置
thread:
corePoolSize: 5
maxPoolSize: 50
queueCapacity: 50
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 127.0.0.1:9200
index:
number-of-replicas: 0
number-of-shards: 3
index-prefix: lili
schema: http
# account:
# username: elastic
# password: LiLiShopES
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group
msg-ext-topic: lili_msg_topic
msg-ext-group: lili_msg_group
goods-topic: lili_goods_topic
goods-group: lili_goods_group
order-topic: lili_order_topic
order-group: lili_order_group
member-topic: lili_member_topic
member-group: lili_member_group
other-topic: lili_other_topic
other-group: lili_other_group
notice-topic: lili_notice_topic
notice-group: lili_notice_group
notice-send-topic: lili_send_notice_topic
notice-send-group: lili_send_notice_group
after-sale-topic: lili_after_sale_topic
after-sale-group: lili_after_sale_group
rocketmq:
name-server: 127.0.0.1:9876
producer:
group: lili_group
send-message-timeout: 30000
xxl:
job:
admin:
addresses: http://127.0.0.1:9001/xxl-job-admin
executor:
appname: xxl-job-executor-lilishop
address:
ip:
port: 8891
logpath: ./xxl-job/executor
logretentiondays: 7