Jelajahi Sumber

优惠券定时推送

chao 3 tahun lalu
induk
melakukan
746e4744d9

+ 40 - 0
src/main/java/com/caimei365/tools/mapper/BaseMapper.java

@@ -1,5 +1,6 @@
 package com.caimei365.tools.mapper;
 
+import com.caimei365.tools.model.bo.CouponDateBo;
 import com.caimei365.tools.model.po.LogisticsInfoPo;
 import com.caimei365.tools.model.po.SuperVipPo;
 import org.apache.ibatis.annotations.Mapper;
@@ -33,4 +34,43 @@ public interface BaseMapper {
     List<SuperVipPo> findVip(Date startTime, Date endTime);
 
     String findMobile(Integer userId);
+    /**
+     * 获取时间到期且未下架的二手商品Id
+     */
+    List<Integer> getMaturitySecondProductIds(Date beforeDays);
+    /**
+     * 更新商品状态
+     */
+    void updateProductValidFlag(Integer productId, String validFlag);
+    /**
+     * 查询所有优惠券用户Id
+     */
+    List<Integer> getCouponUserIds();
+    /**
+     * 已领取优惠券
+     */
+    List<CouponDateBo> getReceivedCoupons(Integer userId);
+    /**
+     * 未领取优惠券
+     */
+    List<CouponDateBo> getUnclaimedCoupons(Integer userId);
+    /**
+     * 查询短链接是否存在
+     */
+    Integer findIdByShortLink(String shortLink);
+    /**
+     * 保存短链接信息
+     *
+     * @param markId    短信类型
+     * @param shortLink 短链接
+     * @param url       跳转地址
+     */
+    void insertShortLink(int markId, String shortLink, String url);
+    /**
+     * 保存短信发送条数+count
+     *
+     * @param markId 短信类型
+     * @param count  增加条数
+     */
+    void updateSmsSendCount(int markId, int count);
 }

+ 33 - 0
src/main/java/com/caimei365/tools/model/bo/CouponDateBo.java

@@ -0,0 +1,33 @@
+package com.caimei365.tools.model.bo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/10/26
+ */
+@Data
+public class CouponDateBo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 优惠券id
+     */
+    private Integer couponId;
+    /**
+     * 使用开始时间(有效期)
+     */
+    @JsonFormat(pattern = "yyyy.MM.dd", timezone = "GMT+8")
+    private Date startDate;
+
+    /**
+     * 使用结束时间(有效期)
+     */
+    @JsonFormat(pattern = "yyyy.MM.dd", timezone = "GMT+8")
+    private Date endDate;
+}

+ 10 - 0
src/main/java/com/caimei365/tools/service/ProductService.java

@@ -0,0 +1,10 @@
+package com.caimei365.tools.service;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/10/26
+ */
+public interface ProductService {
+}

+ 17 - 0
src/main/java/com/caimei365/tools/service/impl/ProductServiceImpl.java

@@ -0,0 +1,17 @@
+package com.caimei365.tools.service.impl;
+
+import com.caimei365.tools.mapper.BaseMapper;
+import com.caimei365.tools.service.ProductService;
+
+import javax.annotation.Resource;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/10/26
+ */
+public class ProductServiceImpl implements ProductService {
+    @Resource
+    private BaseMapper baseMapper;
+}

+ 126 - 0
src/main/java/com/caimei365/tools/task/CouponTask.java

@@ -0,0 +1,126 @@
+package com.caimei365.tools.task;
+
+import com.caimei365.tools.mapper.BaseMapper;
+import com.caimei365.tools.model.bo.CouponDateBo;
+import com.caimei365.tools.utils.CodeUtil;
+import com.caimei365.tools.utils.DateUtils;
+import com.caimei365.tools.utils.SmsUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 优惠券定时推送
+ *
+ * @author : Charles
+ * @date : 2021/10/26
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@RequiredArgsConstructor
+public class CouponTask {
+    @Resource
+    private BaseMapper baseMapper;
+    @Value("${spring.cloud.config.profile}")
+    private String profile;
+
+    /**
+     * 优惠券即将到期推送,定时中午12点推送
+     */
+    @Scheduled(cron = "0 0 12 * * ?")
+    public void couponExpiring() {
+        // 查询所有优惠券用户Id
+        List<Integer> userIds = baseMapper.getCouponUserIds();
+        int a = 0;
+        int b = 0;
+        int c = 0;
+        Date date = new Date();
+        //测试环境手机号允许发短信
+        List<String> list = new ArrayList<>();
+        list.add("15917362709");
+        list.add("15814011616");
+        list.add("15113936829");
+        A:
+        for (Integer userId : userIds) {
+            String mobile = baseMapper.findMobile(userId);
+            if (StringUtils.isBlank(mobile) || mobile.length() != 11) {
+                log.info("机构手机号异常,userId>>>>>" + userId);
+                continue;
+            }
+            // 正式环境或指定手机号
+            if ("prod".equals(profile) || list.contains(mobile)) {
+                // 已领取优惠券
+                List<CouponDateBo> couponList = baseMapper.getReceivedCoupons(userId);
+                String content = null;
+                if (couponList != null && couponList.size() > 0) {
+                    for (CouponDateBo coupon : couponList) {
+                        if (DateUtils.differentDays(coupon.getStartDate(), coupon.getEndDate()) >= 15 && DateUtils.differentDays(date, coupon.getEndDate()) == 7) {
+                            //7天后优惠券即将过期推送
+                            String shortLink = getShortLink(8, 12, "https://www.caimei365.com/user/coupon-collection.html");
+                            content = "您有优惠券即将过期,快戳采美网站链接www.caimei365.com/t/" + shortLink +
+                                    " 或微信搜索“采美采购商城”小程序登录采美平台查看使用吧。关注公众号“采美365网”获取更多优惠和精彩资讯。退订回T";
+                            String result = SmsUtil.sendSms(3, mobile, content);
+                            a++;
+                            continue A;
+                        }
+                        if (DateUtils.differentDays(date, coupon.getEndDate()) == 0) {
+                            //当天优惠券即将过期推送
+                            String shortLink = getShortLink(8, 13, "https://www.caimei365.com/user/coupon-collection.html");
+                            content = "您有优惠券今日过期,快戳采美网站链接www.caimei365.com/t/" + shortLink +
+                                    "  或微信搜索“采美采购商城”小程序登录采美平台查看使用吧。关注公众号“采美365网”获取更多优惠和精彩资讯。退订回T";
+                            String result = SmsUtil.sendSms(3, mobile, content);
+                            b++;
+                            continue A;
+                        }
+                    }
+                }
+                // 未领取优惠券
+                List<CouponDateBo> coupons = baseMapper.getUnclaimedCoupons(userId);
+                if (couponList != null && couponList.size() > 0) {
+                    for (CouponDateBo coupon : coupons) {
+                        if (DateUtils.differentDays(date, coupon.getEndDate()) == 7) {
+                            //7天后优惠券即将过期推送
+                            String shortLink = getShortLink(8, 14, "https://www.caimei365.com/user/coupon-collection.html");
+                            content = "您有优惠券尚未领取,优惠券即将失效,快戳采美网站链接www.caimei365.com/t/" + shortLink +
+                                    " 或微信搜索“采美采购商城”小程序登录采美平台领取使用吧。关注公众号“采美365网”获取更多优惠和精彩资讯。退订回T";
+                            String result = SmsUtil.sendSms(3, mobile, content);
+                            c++;
+                            continue A;
+                        }
+                    }
+                }
+            }
+        }
+        baseMapper.updateSmsSendCount(12, a);
+        baseMapper.updateSmsSendCount(13, b);
+        baseMapper.updateSmsSendCount(14, c);
+    }
+
+    /**
+     * 生成短链接
+     *
+     * @param length 链接长度
+     * @param markId 跳转类型
+     * @param url    跳转地址
+     */
+    private String getShortLink(int length, int markId, String url) {
+        String shortLink = CodeUtil.generateShortLink(length);
+        Integer id = baseMapper.findIdByShortLink(shortLink);
+        if (id != null && id > 0) {
+            getShortLink(length, markId, url);
+        }
+        baseMapper.insertShortLink(markId, shortLink, url);
+        return shortLink;
+    }
+
+}

+ 60 - 0
src/main/java/com/caimei365/tools/task/ProductTask.java

@@ -0,0 +1,60 @@
+package com.caimei365.tools.task;
+
+import com.caimei365.tools.mapper.BaseMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import javax.annotation.Resource;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 商品定时器
+ *
+ * @author : Charles
+ * @date : 2021/10/26
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@RequiredArgsConstructor
+public class ProductTask {
+    @Resource
+    private BaseMapper baseMapper;
+    /**
+     * 每天凌晨1点执行一次
+     */
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void task() {
+        long currentTime = System.currentTimeMillis();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date currentDate = new Date(currentTime);
+        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>【自动】采美二手商品到期下架,时间:" + formatter.format(currentDate));
+        try {
+            //得到日历
+            Calendar calendar = Calendar.getInstance();
+            //把当前时间赋给日历
+            calendar.setTime(currentDate);
+            //设置为day月前
+            calendar.add(Calendar.MONTH, -3);
+            //得到3月前的时间
+            Date beforeDays = calendar.getTime();
+            // 获取时间到期且未下架的二手商品Id
+            List<Integer> secondIdList = baseMapper.getMaturitySecondProductIds(beforeDays);
+            if (CollectionUtils.isNotEmpty(secondIdList)) {
+                for (Integer productId : secondIdList) {
+                    baseMapper.updateProductValidFlag(productId, "3");
+                }
+            }
+        } catch (Exception e) {
+            log.error("try-catch:",e);
+            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>采美二手商品到期下架失败");
+        }
+    }
+}

+ 134 - 0
src/main/java/com/caimei365/tools/utils/CodeUtil.java

@@ -0,0 +1,134 @@
+package com.caimei365.tools.utils;
+
+import java.util.Random;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/7
+ */
+public class CodeUtil {
+    /**
+     * 随机数源
+     */
+    private static final char[] INT_SEQUENCE = {'2', '3', '4', '5', '6', '7', '8', '9'};
+    /**
+     * 随机字母源
+     */
+    private static final char[] LETTER_SEQUENCE = {
+            'A', 'a', 'B', 'b', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h',
+            'L', 'N', 'n', 'Q', 'q', 'R', 'r', 'T', 't', 'Y', 'y'
+    };
+    /**
+     * 随机字符源(排除歧义字符)
+     */
+    private static final char[] CODE_SEQUENCE = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+            'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+            'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7',
+            '8', '9'
+    };
+
+
+    private static final char[] SHORT_LINK_SEQUENCE = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
+            'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'O',
+            'W', 'X', 'Y', 'Z',
+            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
+            'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'o',
+            'w', 'x', 'y', 'z' ,
+            '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
+    };
+
+    /**
+     * 获取随机数字
+     * @param size 位数
+     * @return 随机数字符串
+     */
+    public static String randomInt(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < INT_SEQUENCE.length && i < size; ++i) {
+            sb.append(INT_SEQUENCE[random.nextInt(INT_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 获取随机字母
+     * @param size 位数
+     * @return 随机字母字符串
+     */
+    public static String randomLetter(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < LETTER_SEQUENCE.length && i < size; ++i) {
+            sb.append(LETTER_SEQUENCE[random.nextInt(LETTER_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 获取随机码(字母+数字)
+     * @param size 位数
+     * @return 随机码字符串
+     */
+    public static String generateCode(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < CODE_SEQUENCE.length && i < size; ++i) {
+            sb.append(CODE_SEQUENCE[random.nextInt(CODE_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 生成主订单编号
+     * @param orderSource 订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     * @return 主订单编号
+     */
+    public static String generateOrderNo(Integer orderSource) {
+        String platform = "";
+        if (1 == orderSource){
+            platform = "W";
+        } else if (2 == orderSource) {
+            platform = "C";
+        } else if (4 == orderSource) {
+            platform = "P";
+        } else if (5 == orderSource) {
+            platform = "T";
+        } else if (6 == orderSource) {
+            platform = "X";
+        } else if (7 == orderSource) {
+            platform = "H";
+        } else if (8 == orderSource) {
+            platform = "A";
+        } else {
+            // 未知来源
+            platform = "E";
+        }
+        return platform + System.currentTimeMillis() + randomInt(2);
+    }
+
+    /**
+     * 生成短链接
+     * @param size 长度
+     * @return 短链接
+     */
+    public static String generateShortLink(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < SHORT_LINK_SEQUENCE.length && i < size; ++i) {
+            sb.append(SHORT_LINK_SEQUENCE[random.nextInt(SHORT_LINK_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+
+
+
+
+
+
+}

+ 105 - 0
src/main/java/com/caimei365/tools/utils/DateUtils.java

@@ -0,0 +1,105 @@
+package com.caimei365.tools.utils;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020\3\25 0025
+ */
+public class DateUtils {
+
+    /**
+     * 判断当前时间在时间区间内
+     *
+     * @param nowTime   当前时间
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return
+     */
+    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
+        if (nowTime.getTime() == startTime.getTime()
+                || nowTime.getTime() == endTime.getTime()) {
+            return true;
+        }
+
+        Calendar date = Calendar.getInstance();
+        date.setTime(nowTime);
+
+        Calendar begin = Calendar.getInstance();
+        begin.setTime(startTime);
+
+        Calendar end = Calendar.getInstance();
+        end.setTime(endTime);
+
+        if (date.after(begin) && date.before(end)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 获取当天的结束时间
+     */
+    public static Date getDayEnd() {
+        Calendar cal = new GregorianCalendar();
+        cal.set(Calendar.HOUR_OF_DAY, 23);
+        cal.set(Calendar.MINUTE, 59);
+        cal.set(Calendar.SECOND, 59);
+        return cal.getTime();
+    }
+
+    /**
+     * 在日期上增加数个整月
+     *
+     * @param date 日期
+     * @param n    要增加的月数
+     * @return
+     */
+    public static Date addMonth(Date date, int n) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.MONTH, n);
+        return cal.getTime();
+    }
+
+    /**
+     * date2比date1多的天数
+     *
+     * @param date1
+     * @param date2
+     * @return
+     */
+    public static int differentDays(Date date1, Date date2) {
+        Calendar cal1 = Calendar.getInstance();
+        cal1.setTime(date1);
+        Calendar cal2 = Calendar.getInstance();
+        cal2.setTime(date2);
+        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
+        int day2 = cal2.get(Calendar.DAY_OF_YEAR);
+        int year1 = cal1.get(Calendar.YEAR);
+        int year2 = cal2.get(Calendar.YEAR);
+        if (year1 != year2) {
+            //同一年
+            int timeDistance = 0;
+            for (int i = year1; i < year2; i++) {
+                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
+                    //闰年
+                    timeDistance += 366;
+                } else {
+                    //不是闰年
+                    timeDistance += 365;
+                }
+            }
+            return timeDistance + (day2 - day1);
+        } else {
+            //不同年
+            System.out.println("判断day2 - day1 : " + (day2 - day1));
+            return day2 - day1;
+        }
+    }
+}

+ 54 - 0
src/main/resources/mapper/BaseMapper.xml

@@ -42,4 +42,58 @@
         from user
         where userID = #{userid}
     </select>
+    <select id="getMaturitySecondProductIds" resultType="java.lang.Integer">
+        SELECT cshd.productID FROM cm_second_hand_detail cshd
+        LEFT JOIN product p ON p.productID = cshd.productID
+        WHERE p.validFlag = 2 AND cshd.onLineDate  <![CDATA[  <  ]]>  #{beforeDays}
+    </select>
+    <update id="updateProductValidFlag">
+        UPDATE product SET validFlag = #{validFlag} where productID = #{productId}
+    </update>
+    <select id="getCouponUserIds" resultType="java.lang.Integer">
+        SELECT userId FROM cm_coupon_club GROUP BY userId
+    </select>
+    <select id="getReceivedCoupons" resultType="com.caimei365.tools.model.bo.CouponDateBo">
+        SELECT
+            cc.id AS couponId,
+            cc.startDate,
+            cc.endDate
+        FROM cm_coupon_club a
+        LEFT JOIN cm_coupon cc ON a.couponId = cc.id
+        WHERE cc.delFlag = 0 AND a.delFlag = 0
+        AND a.status = 1 AND cc.status != 2
+        AND a.userId = #{userId}
+        AND NOW() BETWEEN cc.startDate AND cc.endDate
+        ORDER BY a.createDate DESC
+    </select>
+    <select id="getUnclaimedCoupons" resultType="com.caimei365.tools.model.bo.CouponDateBo">
+        SELECT
+            id AS couponId,
+            startDate,
+            endDate
+        FROM cm_coupon
+        WHERE delFlag = 0 AND couponsMode = 0 AND status != 2
+        AND NOW() BETWEEN startDate AND endDate
+        <if test="userId == null or userId == 0">
+            AND couponType != 2
+        </if>
+        <if test="userId > 0">
+            AND id NOT IN(SELECT couponId FROM cm_coupon_club WHERE userId = #{userId})
+            AND (couponType IN (0,1,3)
+            OR couponType = 2 AND userId = #{userId}
+            OR ((SELECT registerTime FROM USER WHERE userID = #{userId}) <![CDATA[ >= ]]> startDate
+            AND couponType = 4))
+        </if>
+        ORDER BY createDate DESC
+    </select>
+    <insert id="insertShortLink">
+        INSERT INTO cm_short_link (markId, shortLink, jumpLink, createTime)
+        VALUES (#{markId}, #{shortLink}, #{url},NOW())
+    </insert>
+    <update id="updateSmsSendCount">
+        UPDATE cm_sms_statistics SET sendNum = (sendNum + #{count}) WHERE markId = #{markId}
+    </update>
+    <select id="findIdByShortLink" resultType="java.lang.Integer">
+        SELECT id FROM cm_short_link WHERE shortLink = #{shortLink}
+    </select>
 </mapper>