MQTask.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. package com.iamberry.wechat.handles.mq;
  2. import java.lang.reflect.Method;
  3. import java.text.MessageFormat;
  4. import java.text.SimpleDateFormat;
  5. import java.util.*;
  6. import java.util.concurrent.locks.Lock;
  7. import java.util.concurrent.locks.ReentrantLock;
  8. import com.iamberry.wechat.core.entity.admin.ShopSystemRule;
  9. import com.iamberry.wechat.core.entity.order.NumberBacklogDto;
  10. import com.iamberry.wechat.face.admin.SystemService;
  11. import com.iamberry.wechat.face.agentInfo.AgentPurchaseOrderService;
  12. import com.iamberry.wechat.face.integral.UseIntegralService;
  13. import com.iamberry.wechat.face.order.AdminOrderService;
  14. import com.iamberry.wechat.service.ImberryConfig;
  15. import com.iamberry.wechat.tools.HttpClient431Util;
  16. import com.iamberry.wechat.tools.NameUtils;
  17. import com.iamberry.wechat.tools.SendMessageUtil;
  18. import org.apache.commons.lang.StringUtils;
  19. import org.springframework.beans.factory.InitializingBean;
  20. import org.springframework.beans.factory.annotation.Autowired;
  21. import org.springframework.context.annotation.Lazy;
  22. import org.springframework.scheduling.annotation.Scheduled;
  23. import org.springframework.stereotype.Component;
  24. import com.iamberry.app.tool.log.RatFWLogger;
  25. import com.iamberry.wechat.core.entity.mq.MQMessage;
  26. import com.iamberry.wechat.core.entity.order.ProbationOrderDto;
  27. import com.iamberry.wechat.core.entity.probation.ProbationAwardRelu;
  28. import com.iamberry.wechat.core.entity.probation.ProbationNewLogs;
  29. import com.iamberry.wechat.core.entity.task.TaskModel;
  30. import com.iamberry.wechat.core.entity.task.WechatTask;
  31. import com.iamberry.wechat.core.entity.task.WechatTaskLogs;
  32. import com.iamberry.wechat.face.order.CodeService;
  33. import com.iamberry.wechat.face.order.ProbationShopOrderService;
  34. import com.iamberry.wechat.face.reback.RebackServices;
  35. import com.iamberry.wechat.face.task.WechatTaskService;
  36. import com.iamberry.wechat.service.StaticCacheMemory;
  37. import com.iamberry.wechat.tools.DateTimeUtil;
  38. import com.iamberry.wechat.tools.ResultInfo;
  39. import com.iamberry.zk.SpringContextHolder;
  40. /**
  41. * @author:何秀刚
  42. * @description: MQ模拟实现,每天最多处理1382400条
  43. * @createDate:2016年5月25日
  44. */
  45. @Component(value="mqTask")
  46. @Lazy(false)
  47. public class MQTask implements InitializingBean {
  48. @Autowired
  49. private MQServiceProxy mQSerivce;
  50. @Autowired
  51. private RatFWLogger logger;
  52. @Autowired
  53. private WechatTaskService wechatTaskService;
  54. @Autowired
  55. private RebackServices rebackServices;
  56. @Autowired
  57. private ProbationShopOrderService probationShopOrderService;
  58. @Autowired
  59. private SendMessageUtil sendMessageUtil;
  60. @Autowired
  61. private CodeService codeService;
  62. @Autowired
  63. private SystemService systemService;
  64. @Autowired
  65. private AgentPurchaseOrderService agentPurchaseOrderService;
  66. @Autowired
  67. private UseIntegralService useIntegralService;
  68. @Autowired
  69. private AdminOrderService adminOrderService;
  70. private Lock lock = new ReentrantLock();
  71. @SuppressWarnings(value = {"unchecked", "rawtypes"})
  72. @Scheduled(cron = "0/30 * * * * ?")
  73. public void sendOrderService() {
  74. logger.info("------------task start-----------");
  75. // If the timer has not stopped, then the next time the timer can not start.
  76. lock.lock();
  77. try {
  78. // step 1, Gets the message that is not executed in the database.
  79. List<MQMessage> messages = mQSerivce.selectWaitHandlerMessage();
  80. if (messages == null || messages.size() <= 0) {
  81. return;
  82. }
  83. // step 2, Handle 10 messages at a time.
  84. for (MQMessage mqMessage : messages) {
  85. try {
  86. Object object = SpringContextHolder.getBean(mqMessage.getServiceHandlerObjectName());
  87. Class classes = object.getClass();
  88. Method method = classes.getMethod(mqMessage.getServiceHandlerMethodName(), MQMessage.class);
  89. if (method == null) {
  90. mqMessage.setServiceErrorMessage("Method is not defined:" + mqMessage.getServiceHandlerMethodName());
  91. mqMessage.setServiceStatus(2);
  92. continue;
  93. }
  94. // invoke Method.
  95. Object resultObject = method.invoke(object, mqMessage);
  96. if (!(resultObject instanceof Boolean)) {
  97. mqMessage.setServiceStatus(2);
  98. mqMessage.setServiceErrorMessage(mqMessage.getServiceHandlerObjectName() + "." + mqMessage.getServiceHandlerMethodName() + "()Return value is not type Boolean");
  99. continue;
  100. }
  101. if (!(Boolean) resultObject) {
  102. mqMessage.setServiceErrorMessage("invoke Method Error");
  103. mqMessage.setServiceStatus(2);
  104. continue;
  105. }
  106. mqMessage.setServiceStatus(1);
  107. continue;
  108. } catch (Exception e) {
  109. // TODO: handle exception
  110. mqMessage.setServiceErrorMessage(e.getMessage());
  111. mqMessage.setServiceStatus(2);
  112. continue;
  113. } finally {
  114. mqMessage.setServiceIsSend(1);
  115. }
  116. }
  117. // step 3, update Message status and serviceIsSend.
  118. mQSerivce.updateBatchMessage(messages);
  119. // step 4, is next ?
  120. if (messages.size() >= 10) {
  121. StaticCacheMemory.isStartTask = true;
  122. this.sendOrderService();
  123. }
  124. } catch (Exception e) {
  125. e.printStackTrace();
  126. logger.error(e, "MQ Task Error:" + e.getMessage());
  127. } finally {
  128. // reset lock
  129. lock.unlock();
  130. }
  131. logger.info("------------task invoke success-----------");
  132. }
  133. /**
  134. * 订阅消息
  135. */
  136. public void subscribeMessageQueue() {
  137. }
  138. // 强迫线程可见
  139. private volatile boolean oldState = true;
  140. /**
  141. * 微信定期任务奖励-上个月的定时器
  142. */
  143. @SuppressWarnings("deprecation")
  144. // @Scheduled(cron = "0/59 * * * * ?")
  145. public void oldMonthTask() {
  146. if (!oldState) {
  147. logger.info("线程正忙...");
  148. return;
  149. }
  150. oldState = false;
  151. try {
  152. // 判断上一个月的数据是否奖励完成
  153. logger.info("上一个月的定时奖励任务奖励...");
  154. // 当前时间
  155. Date nowDate = new Date();
  156. // 回到上一个月
  157. nowDate.setMonth(nowDate.getMonth() - 1);
  158. // 上一个月的结束时间 类似 :2016-02-29 23:59:59
  159. Date oldMonthLastDay = DateTimeUtil.getLastDayOfYear(nowDate);
  160. // 上一个月的开始时间 类似 :2016-02-01 00:00:00
  161. Date oldMonthFirstDay = DateTimeUtil.getFirstDayOfYear(nowDate);
  162. List<WechatTask> tasks = wechatTaskService.getRunTask(oldMonthFirstDay, oldMonthLastDay);
  163. if (tasks == null || tasks.size() == 0) {
  164. logger.info("暂时没有上一个月的任务奖励...");
  165. oldState = true;
  166. return;
  167. }
  168. // 获取在上一个月销售达到X台的数据
  169. for (WechatTask wechatTask : tasks) {
  170. List<TaskModel> models = rebackServices.getByDate(wechatTask.getTaskProductType(), oldMonthFirstDay, oldMonthLastDay, wechatTask.getTaskSalesNum());
  171. if (models == null || models.size() == 0) {
  172. logger.info("暂时没有人完成上一个月的任务" + wechatTask.getTaskId() + "奖励...");
  173. continue;
  174. }
  175. // 达到的用户是否已经领取奖励
  176. for (TaskModel taskModel : models) {
  177. WechatTaskLogs logs = new WechatTaskLogs();
  178. logs.setLogsTaskId(wechatTask.getTaskId());
  179. logs.setLogsUserOpenId(taskModel.getOpenID());
  180. Integer logsID = wechatTaskService.getByTaskIdAndOpenId(logs);
  181. if (logsID != null) {
  182. // 如果当前用户已经领取了奖励,那么跳过
  183. continue;
  184. }
  185. // 若用没有领取,那么奖励
  186. try {
  187. wechatTaskService.handlerTask(taskModel.getOpenID(), wechatTask.getTaskMoney(), wechatTask.getTaskId(), wechatTask.getTaskProductType());
  188. } catch (Exception e) {
  189. logger.error(this, "对:" + taskModel.getOpenID() + ",奖励失败!error:" + e.getMessage());
  190. }
  191. }
  192. }
  193. } catch (Exception e) {
  194. logger.error(this, "发生异常,奖励失败!error:" + e.getMessage());
  195. } finally {
  196. // 归还锁
  197. oldState = true;
  198. }
  199. }
  200. // 强迫线程可见
  201. private volatile boolean nowState = true;
  202. /**
  203. * 微信定期任务奖励-本月的定时器
  204. */
  205. // @Scheduled(cron = "0/59 * * * * ?")
  206. public void nowMonthTask() {
  207. if (!nowState) {
  208. logger.info("线程正忙...");
  209. return;
  210. }
  211. nowState = false;
  212. try {
  213. // 判断本月是否有奖励数据
  214. logger.info("本月的定时奖励任务奖励...");
  215. // 当前时间
  216. Date nowDate = new Date();
  217. // 上一个月的结束时间 类似 :2016-02-29 23:59:59
  218. Date oldMonthLastDay = DateTimeUtil.getLastDayOfYear(nowDate);
  219. // 上一个月的开始时间 类似 :2016-02-01 00:00:00
  220. Date oldMonthFirstDay = DateTimeUtil.getFirstDayOfYear(nowDate);
  221. List<WechatTask> tasks = wechatTaskService.getRunTask(oldMonthFirstDay, oldMonthLastDay);
  222. if (tasks == null || tasks.size() == 0) {
  223. logger.info("暂时没有本月的任务奖励...");
  224. nowState = true;
  225. return;
  226. }
  227. // 获取在上一个月销售达到X台的数据
  228. for (WechatTask wechatTask : tasks) {
  229. List<TaskModel> models = rebackServices.getByDate(wechatTask.getTaskProductType(), oldMonthFirstDay, oldMonthLastDay, wechatTask.getTaskSalesNum());
  230. if (models == null || models.size() == 0) {
  231. logger.info("暂时没有人完成本月的任务" + wechatTask.getTaskId() + "奖励...");
  232. continue;
  233. }
  234. // 达到的用户是否已经领取奖励
  235. for (TaskModel taskModel : models) {
  236. WechatTaskLogs logs = new WechatTaskLogs();
  237. logs.setLogsTaskId(wechatTask.getTaskId());
  238. logs.setLogsUserOpenId(taskModel.getOpenID());
  239. Integer logsID = wechatTaskService.getByTaskIdAndOpenId(logs);
  240. if (logsID != null) {
  241. // 如果当前用户已经领取了奖励,那么跳过
  242. continue;
  243. }
  244. // 若用没有领取,那么奖励
  245. try {
  246. wechatTaskService.handlerTask(taskModel.getOpenID(), wechatTask.getTaskMoney(), wechatTask.getTaskId(), wechatTask.getTaskProductType());
  247. } catch (Exception e) {
  248. logger.error(this, "对:" + taskModel.getOpenID() + ",奖励失败!error:" + e.getMessage());
  249. }
  250. }
  251. }
  252. } catch (Exception e) {
  253. // TODO: handle exception
  254. logger.error(this, "发生异常:" + e.getMessage());
  255. } finally {
  256. nowState = true;
  257. }
  258. }
  259. public void afterPropertiesSet() throws Exception {
  260. }
  261. /**
  262. * 试用订单短信推送服务(满足XX天奖励XX奖励)
  263. */
  264. // @Scheduled(cron = "0 0 */1 * * ?")//每小时执行一次
  265. public void probationRewardPush(){
  266. logger.info("------------执行推送满足奖励条件用户 start-----------");
  267. //查询奖励推送规则
  268. List<ProbationAwardRelu> reluList = probationShopOrderService.selectProbationAwardRelu();
  269. SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  270. if(reluList!=null && !reluList.isEmpty()){
  271. for(ProbationAwardRelu awardRelu : reluList){
  272. //查询所有待支付订单
  273. List<ProbationOrderDto> orderDtoList = probationShopOrderService.selectProbationStartOrder();
  274. if(orderDtoList!=null && !orderDtoList.isEmpty()){
  275. for(ProbationOrderDto orderDto : orderDtoList ){
  276. //计算总试用期限(小时)
  277. Long totalDate = (orderDto.getProbationEndTime().getTime() - orderDto.getProbationStartTime().getTime()) / 1000 / 60 / 60;
  278. //计算试用剩余期限(小时)
  279. Long remainingDate = (orderDto.getProbationEndTime().getTime() - new Date().getTime()) / 1000 / 60 / 60;
  280. //暂停时间
  281. /*Long pauseDate = 0l;
  282. if(orderDto.getProbationPauseStartTime() != null && orderDto.getProbationPauseEndTime() != null){
  283. pauseDate = (orderDto.getProbationPauseEndTime().getTime() - orderDto.getProbationPauseStartTime().getTime()) / 1000 / 60 / 60;
  284. }*/
  285. //实际试用时间 (总试用时间 - 试用剩余期限 - 暂停时间)
  286. Long actualProbationDate = totalDate - remainingDate - orderDto.getProbationPauseTotalLength() / 1000 / 60 / 60;
  287. //奖励奖品天数转换为小时
  288. Long awardDate = Long.valueOf(awardRelu.getAwardNum()) * 24;
  289. //奖励条件时间 - 实际试用时间 (大于23小时或者小于26小时则推送)
  290. if( awardDate -actualProbationDate > 23 && awardDate -actualProbationDate < 26 ){
  291. ProbationNewLogs probationNewLogs = probationShopOrderService.selectProbationNewLogsByOrderId(orderDto.getProbationOrderid());
  292. //添加日志信息
  293. ProbationNewLogs newLogs = new ProbationNewLogs();
  294. newLogs.setLogsPorderid(orderDto.getProbationOrderid());
  295. newLogs.setLogsTime(awardRelu.getAwardNum());
  296. newLogs.setLogsCreateTime(new Date());
  297. if(probationNewLogs == null){
  298. //推送操作
  299. sendMessageUtil.probationPush(awardRelu.getAwardInfo(),
  300. orderDto.getProductName(),
  301. orderDto.getProbationOrderid(),
  302. formatter.format(orderDto.getProbationStartTime()),
  303. formatter.format(
  304. new Date(
  305. orderDto.getProbationStartTime().getTime() +
  306. (awardRelu.getAwardNum() * 24 + orderDto.getProbationPauseTotalLength()) * 60 * 60 * 1000)),
  307. awardRelu.getAwardInfoTwo(),
  308. orderDto.getProbationOpenid(),
  309. ResultInfo.TRY_ORDER_DETAIL+"?orderId="+orderDto.getProbationOrderid());
  310. //添加日志
  311. probationShopOrderService.insertProbationLogs(newLogs);
  312. //发送短信给收货人
  313. if(StringUtils.isNotEmpty(orderDto.getProbationReceiveTel())){
  314. codeService.sendTextToUser(orderDto.getProbationReceiveTel(), 6);
  315. }
  316. }else if(probationNewLogs.getLogsTime() < awardRelu.getAwardNum()){
  317. //执行推送
  318. sendMessageUtil.probationPush(
  319. awardRelu.getAwardInfo(),
  320. orderDto.getProductName(),
  321. orderDto.getProbationOrderid(),
  322. formatter.format(orderDto.getProbationStartTime()),
  323. formatter.format(
  324. new Date(orderDto.getProbationStartTime().getTime()
  325. + (awardRelu.getAwardNum() * 24 + orderDto.getProbationPauseTotalLength()) * 60 * 60 * 1000)),
  326. awardRelu.getAwardInfoTwo(),
  327. orderDto.getProbationOpenid(),
  328. ResultInfo.TRY_ORDER_DETAIL+"?orderId="+orderDto.getProbationOrderid());
  329. //修改日志
  330. probationShopOrderService.updatePauseLogsDate(newLogs);
  331. //发送短信给收货人
  332. if(StringUtils.isNotEmpty(orderDto.getProbationReceiveTel())){
  333. codeService.sendTextToUser(orderDto.getProbationReceiveTel(), awardRelu.getAwardNum().intValue());
  334. }
  335. }
  336. }
  337. }
  338. }
  339. }
  340. }
  341. }
  342. /**
  343. * 保持百胜系统cookie的活性(每分钟执行一次)
  344. */
  345. @SuppressWarnings(value = {"unchecked", "rawtypes"})
  346. @Scheduled(cron = "0 0/1 * * * ?")
  347. public void selectEfastOrder() {
  348. try{
  349. //获取cookie值
  350. ShopSystemRule rule = systemService.selectOneShopRuleById(244);
  351. String phone = "13590159563";
  352. String url = NameUtils.getConfig("efast_order_url") + phone;
  353. Map<String,String> params = new HashMap<String,String>();
  354. String cookie = rule.getRuleDesc();
  355. //查询百胜订单信息
  356. String str = HttpClient431Util.doGet(params,url,null,null,cookie);
  357. } catch(Exception e) {
  358. System.out.println("------------请求百胜接口失败-------------");
  359. }
  360. }
  361. /**
  362. * 电动牙刷商城更换刷头提示(每小时执行一次)
  363. */
  364. /*@SuppressWarnings(value = {"unchecked", "rawtypes"})
  365. @Scheduled(cron = "0 0 0/1 * * ?")
  366. public void updateToothHint() {
  367. //获取更换刷头时间间隔
  368. ShopSystemRule rule = systemService.selectOneShopRuleById(245);
  369. List<OrderHint> list = new ArrayList<OrderHint>();
  370. OrderHint orderHint = new OrderHint();
  371. orderHint.setHintTime(new Date());
  372. orderHint.setHintStatus(1);
  373. //根据时间和状态获取需要提示的
  374. List<OrderHint> orderList = agentPurchaseOrderService.listOrderHint(orderHint);
  375. if (orderList == null || orderList.size() == 0) {
  376. return;
  377. }
  378. for (int i = 0;i < orderList.size();i++) {
  379. OrderHint order = orderList.get(i);
  380. Calendar cl = Calendar.getInstance();
  381. cl.setTime(order.getHintTime());
  382. cl.add(Calendar.MONTH, +rule.getRuleNum().intValue());
  383. OrderHint hint = new OrderHint();
  384. hint.setHintTime(cl.getTime());
  385. hint.setHintId(order.getHintId());
  386. hint.setHintNum(1);
  387. list.add(hint);
  388. //更换牙刷刷头提示
  389. sendMessageUtil.updateToothHint("上朵电动牙刷商城", "上朵电动牙刷","您的牙刷已使用三个月,请及时更换刷头!", "上朵电动牙刷商城", order.getUserOpenId(),NameUtils.getConfig("WECHAT_UPDATE_TOOTH_HINT")+order.getHintId());
  390. }
  391. //批量修改更换刷头信息
  392. int num = agentPurchaseOrderService.updateOrderHintList(list);
  393. }*/
  394. /**
  395. * 待入账积分更改为已入账积分(每小时执行一次)
  396. */
  397. @SuppressWarnings(value = {"unchecked", "rawtypes"})
  398. @Scheduled(cron = "0 0 0/1 * * ?")
  399. // @Scheduled(cron = "0 0/3 * * * ?")//每三分钟执行一次
  400. public void updateIntegralStayToAlready() {
  401. useIntegralService.updateIntegralStayToAlready();
  402. }
  403. /**
  404. * 待处理订单提醒(每天下午2:50点,短信提醒益霜、上朵运营一次(15814645335、13472545449)
  405. */
  406. @SuppressWarnings(value = {"unchecked", "rawtypes"})
  407. /*@Scheduled(cron = "0 0/3 * * * ?")//每三分钟执行一次*/
  408. @Scheduled(cron = "0 50 14 * * ?")//每天下午2点50分执行一次
  409. public void pendingOrderReminder() {
  410. //查询待发货事项、申请退款订单、申请退货订单、申请换货订单 的数量
  411. NumberBacklogDto numberBacklogDto = adminOrderService.selectNumberBacklog();
  412. Integer num = (numberBacklogDto.getExchange()+numberBacklogDto.getReturnGoods()+numberBacklogDto.getReturnRefund()+numberBacklogDto.getSendTheGoods());
  413. String text = MessageFormat.format(ImberryConfig.PENDING_ORDER_REMINDER, num);
  414. codeService.informShipping("15814645335", text);
  415. codeService.informShipping("13472545449", text);
  416. codeService.informShipping("18271840547", text);
  417. codeService.informShipping("13922874118", text);
  418. }
  419. }