Scheduler.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. package com.cyksj.task;
  2. import cn.hutool.core.date.DateField;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.core.date.DateUtil;
  5. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  6. import com.cyksj.common.exception.BusinessRuntimeException;
  7. import com.cyksj.common.util.Jsons;
  8. import com.cyksj.dto.RedisKey;
  9. import com.cyksj.mapper.*;
  10. import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
  11. import com.cyksj.model.dto.WxMpTemplateData;
  12. import com.cyksj.model.dto.WxMpTemplateMessage;
  13. import com.cyksj.model.entity.*;
  14. import com.cyksj.redis.RedisService;
  15. import com.cyksj.service.order.OrderDonService;
  16. import com.cyksj.service.register.RegisterOrderDonService;
  17. import com.cyksj.service.register.SpotifyService;
  18. import com.cyksj.service.wechat.WeChatService;
  19. import lombok.RequiredArgsConstructor;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.springframework.dao.DuplicateKeyException;
  22. import org.springframework.scheduling.annotation.Scheduled;
  23. import org.springframework.stereotype.Component;
  24. import org.springframework.transaction.annotation.Transactional;
  25. import java.util.ArrayList;
  26. import java.util.Date;
  27. import java.util.List;
  28. import java.util.Optional;
  29. import java.util.*;
  30. import java.util.stream.Collectors;
  31. import static com.cyksj.common.constant.WeChatTemplateConst.EXPIRY_TEMPLATE;
  32. @Component
  33. @Slf4j
  34. @RequiredArgsConstructor
  35. public class Scheduler {
  36. private final GoodsDonMapper donMapper;
  37. private final GroupsMapper groupsMapper;
  38. private final OrderDonService orderDonService;
  39. private final GroupsRelationMapper groupsRelationMapper;
  40. private final UserMapper userMapper;
  41. private final GoodsDonSkuMapper skuMapper;
  42. private final WeChatService weChatService;
  43. private final AccountMapper accountMapper;
  44. private final CustomerServiceMapper customerServiceMapper;
  45. private final SpotifyService spotifyService;
  46. private final RegisterOrderDonMapper registerOrderDonMapper;
  47. private final RedisService redisService;
  48. private final SysConfigMapper sysConfigMapper;
  49. private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;
  50. private final RegisterOrderDonService registerOrderDonService;
  51. private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
  52. private final RealGoodsInterestUserMapper realGoodsInterestUserMapper;
  53. /**
  54. * 每5分钟清理过期账号
  55. */
  56. @Scheduled(cron = "0 0/5 * * * ?")
  57. @Transactional(rollbackFor = Throwable.class)
  58. public void clearExpiry() {
  59. DateTime now = new DateTime();
  60. List<GroupsRelation> expiryList = groupsRelationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).le(GroupsRelation::getExpiryTime, now));
  61. log.info("定时清理过期账号start ===> 数量:{}", expiryList.size());
  62. //过期账号清楚有效期
  63. expiryList.forEach(relation -> delRelation(relation));
  64. }
  65. @Scheduled(cron = "0 0 9 * * ?")
  66. public void expiryWxMsg() throws Exception {
  67. DateTime now = new DateTime();
  68. DateTime zero = DateUtil.offset(now, DateField.HOUR, -9);
  69. DateTime time = DateUtil.offset(zero, DateField.DAY_OF_MONTH, 5);
  70. List<GroupsRelation> groupsRelations = groupsRelationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).le(GroupsRelation::getExpiryTime, time));
  71. for (GroupsRelation relation : groupsRelations) {
  72. User user = userMapper.selectById(relation.getUserId());
  73. WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
  74. .setToUser(user.getOpenId())
  75. .setTemplateId(EXPIRY_TEMPLATE)
  76. .setUrl(" ");
  77. /**
  78. * 您的账号即将到期
  79. * 账号名称:Netflix账号
  80. * 平台:Netflix
  81. * 失效日期:5天后
  82. * 异常原因:账号即将到期
  83. * 请尽快续费,以免影响使用
  84. */
  85. GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
  86. GoodsDonSku donSku = skuMapper.selectById(groupsTrips.getSkuId());
  87. GoodsDon goodsDon = donMapper.selectById(donSku.getGoodsId());
  88. WxMpTemplateMessage.TemplateData data = templateMessage.getData();
  89. data.setFirst(new WxMpTemplateData("您的账号即将到期"));
  90. data.setKeyword1(new WxMpTemplateData(goodsDon.getTitle()));
  91. data.setKeyword2(new WxMpTemplateData(goodsDon.getTitle()));
  92. data.setKeyword3(new WxMpTemplateData(DateUtil.format(relation.getExpiryTime(), "yyyy-MM-dd HH:mm:ss")));
  93. data.setKeyword4(new WxMpTemplateData("账号即将到期"));
  94. data.setRemark(new WxMpTemplateData("请尽快续费,以免影响使用"));
  95. log.info("发送账号即将到期消息至用户:{}", user.getId());
  96. weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
  97. List<Account> accounts = accountMapper.selectList(Wrappers.lambdaQuery(Account.class).le(Account::getExpiryTime, time));
  98. List<CustomerService> customerServices = customerServiceMapper.selectList(null);
  99. if(!accounts.isEmpty()){
  100. for (CustomerService customerService : customerServices) {
  101. WxMpTemplateMessage manageMessage = new WxMpTemplateMessage()
  102. .setToUser(customerService.getOpenId())
  103. .setTemplateId(EXPIRY_TEMPLATE)
  104. .setUrl(" ");
  105. WxMpTemplateMessage.TemplateData data2 = manageMessage.getData();
  106. data2.setFirst(new WxMpTemplateData("您有" + accounts.size() + "个主账号即将到期"));
  107. data2.setKeyword1(new WxMpTemplateData("车队主账号"));
  108. data2.setKeyword2(new WxMpTemplateData("车队主账号"));
  109. data2.setKeyword3(new WxMpTemplateData("5天后"));
  110. data2.setKeyword4(new WxMpTemplateData("账号即将到期"));
  111. data2.setRemark(new WxMpTemplateData("请尽快登录后台-在账号管理中查看"));
  112. log.info("发送账号即将到期消息至客服:{}", customerService.getNickName());
  113. weChatService.sendTemplateMessage(weChatService.getAccessToken(),Jsons.toJson(manageMessage));
  114. }
  115. }
  116. }
  117. }
  118. private void delRelation(GroupsRelation relation) {
  119. Date expireTime = relation.getExpiryTime();
  120. relation.setStartTime(null);
  121. relation.setExpiryTime(null);
  122. relation.setUserId(0l);
  123. relation.setStatus(GroupsRelation.Status.none);
  124. relation.setIsHandle(false);
  125. relation.setRenewStatus(false);
  126. relation.setAccount(null);
  127. Integer success = groupsRelationMapper.updateExpiryTime(relation, expireTime);
  128. if (success == 1) {
  129. log.info("开始清除过期子账号,座位号:{}", relation.getId());
  130. int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
  131. if (count == 0) {
  132. log.error("车位异常 groupId:{}", relation.getGroupsId());
  133. throw new BusinessRuntimeException("车位异常");
  134. }
  135. }
  136. }
  137. /**
  138. * 定时关闭订单
  139. */
  140. @Scheduled(cron = "0 0/5 * * * ?")
  141. public void closeOrder() {
  142. //获取为支付订单
  143. DateTime now = new DateTime();
  144. Date newDate = DateUtil.offset(now, DateField.MINUTE, -5);
  145. List<OrderDon> list = orderDonService.list(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getStatus, OrderDon.Status.noPayment).le(OrderDon::getCreatedTime,newDate));
  146. log.info("定时任务 关闭 订单数:{}",list.size());
  147. list.forEach((orderDon)->{
  148. orderDonService.closeOrder(orderDon.getId());
  149. });
  150. }
  151. /**
  152. * spotify 注册
  153. */
  154. @Scheduled(cron = "0 0/5 * * * ?")
  155. public void spotify() {
  156. synchronized (this){
  157. List<RegisterOrderDon> spotify = registerOrderDonMapper.selectList(Wrappers.lambdaQuery(RegisterOrderDon.class)
  158. .select(RegisterOrderDon::getId)
  159. .eq(RegisterOrderDon::getPlatform, "spotify")
  160. .eq(RegisterOrderDon::getStatus, RegisterOrderDon.Status.hasPayment));
  161. spotify.forEach((orderDon)->{
  162. spotifyService.register(orderDon.getId());
  163. });
  164. }
  165. }
  166. /**
  167. * 每日免单重置
  168. */
  169. @Scheduled(cron = "0 0 0 * * ?")
  170. public void freeReset() {
  171. log.info("每日重置 spotify 免单账户数 [start]");
  172. SysConfig register_free_num = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "register_free_num"));
  173. redisService.set(RedisKey.SPOTIFY_FREE_NUM, Long.parseLong(register_free_num.getSysValue()));
  174. log.info("每日重置 spotify 免单账户数 [end] 数量:{}",register_free_num.getSysValue());
  175. }
  176. /**
  177. * 分销订单积分奖励分发
  178. */
  179. @Scheduled(cron = "0 0 0/2 * * ?")
  180. @Transactional(rollbackFor = Throwable.class)
  181. public void distributeOrdersSendPoints() {
  182. List<DistributeWaitingSendPoints> waitingSendPoints = Optional.ofNullable(distributeWaitingSendPointsMapper.selectList(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class)
  183. .eq(DistributeWaitingSendPoints::getSendStatus, DistributeWaitingSendPoints.Status.waiting)
  184. .lt(DistributeWaitingSendPoints::getSendTime, DateTime.now())
  185. .select(DistributeWaitingSendPoints::getId,
  186. DistributeWaitingSendPoints::getOrderId,
  187. DistributeWaitingSendPoints::getPoints,
  188. DistributeWaitingSendPoints::getUserId,
  189. DistributeWaitingSendPoints::getSharedId,
  190. DistributeWaitingSendPoints::getSendTime))).orElse(new ArrayList<>());
  191. log.info("查询分销订单积分分发记录开始,条数:{}=======》", waitingSendPoints.size());
  192. waitingSendPoints.forEach(wait -> {
  193. //积分待发人
  194. Long sharedId = wait.getSharedId();
  195. User user = userMapper.selectById(sharedId);
  196. if (user == null) {
  197. wait.setSendStatus(DistributeWaitingSendPoints.Status.not_exist);
  198. log.info("分销订单,发送积分用户不存在");
  199. distributeWaitingSendPointsMapper.updateById(wait);
  200. } else {
  201. wait.setSendStatus(DistributeWaitingSendPoints.Status.success);
  202. log.info("更新用户积分开始=====>");
  203. while (true) {
  204. user = userMapper.selectById(sharedId);
  205. if (user == null) {
  206. break;
  207. }
  208. Integer update = userMapper.updatePoints(user.getId(), user.getPoints(), wait.getPoints());
  209. if (update == 1) {
  210. distributeWaitingSendPointsMapper.updateById(wait);
  211. log.info("分销积分表订单id:{}发放积分success", wait.getOrderId());
  212. break;
  213. }
  214. }
  215. }
  216. });
  217. }
  218. /**
  219. * 定时更新未支付AppleID自动注册订单
  220. */
  221. @Scheduled(cron = "0 0/5 * * * ?")
  222. public void updateAppleAutoStatus() {
  223. //获取为支付订单
  224. DateTime now = new DateTime();
  225. Date newDate = DateUtil.offset(now, DateField.MINUTE, -5);
  226. List<Long> orderDons = appleAutoRegisterDataMapper.getAllNoPayOrders(newDate);
  227. log.info("定时更新未支付AppleID自动注册订单 订单数:{}",orderDons.size());
  228. orderDons.forEach((orderId)->{
  229. registerOrderDonService.updateAppleAutoStatus(orderId);
  230. });
  231. }
  232. /**
  233. * 实物订单意愿数据
  234. */
  235. @Scheduled(cron = "0 0/5 * * * ?")
  236. public void realGoodsInterestUser() {
  237. Optional.ofNullable(orderDonService.selectNoPaymentRealGoods()).ifPresent(list -> {
  238. if (list.size() > 0) {
  239. Map<String, List<RealGoodsInterestUser>> collect = list.stream().collect(Collectors.groupingBy(RealGoodsInterestUser::getGroupBy));
  240. log.info("实物订单意愿数据同步开始");
  241. collect.forEach((k, data) -> {
  242. RealGoodsInterestUser realGoodsInterestUser = null;
  243. if (data.size() == 0) {
  244. realGoodsInterestUser = data.get(0);
  245. } else {
  246. List<RealGoodsInterestUser> high = data.stream().sorted(Comparator.comparing(RealGoodsInterestUser::getMoney).thenComparing(RealGoodsInterestUser::getOrderCreatedTime).reversed()).collect(Collectors.toList());
  247. realGoodsInterestUser = high.get(0);
  248. }
  249. try {
  250. realGoodsInterestUserMapper.insert(realGoodsInterestUser);
  251. } catch (DuplicateKeyException e) {
  252. log.info("重复插入用户相同实物商品记录");
  253. }
  254. });
  255. log.info("实物订单意愿数据同步结束");
  256. }
  257. }
  258. );
  259. Integer update = orderDonService.updateHasPaymentInterestRealGoods();
  260. orderDonService.updateHasPaymentInterestRealGoodsPayTime();
  261. if (update > 0) {
  262. log.info("更新用户记录:{}已购买实物意愿商品状态成功", update);
  263. }
  264. }
  265. }