Authored by 匡佳华

指定uid发券

@@ -8,12 +8,14 @@ import com.yoho.ufo.service.model.ExportParam; @@ -8,12 +8,14 @@ import com.yoho.ufo.service.model.ExportParam;
8 import com.yoho.ufo.util.HttpUtil; 8 import com.yoho.ufo.util.HttpUtil;
9 import com.yohobuy.ufo.coupon.req.CouponQueryReq; 9 import com.yohobuy.ufo.coupon.req.CouponQueryReq;
10 import com.yohobuy.ufo.coupon.req.CouponSaveUpdateReq; 10 import com.yohobuy.ufo.coupon.req.CouponSaveUpdateReq;
  11 +import com.yohobuy.ufo.coupon.req.CouponSendReq;
11 import com.yohobuy.ufo.coupon.req.UserCouponQueryReq; 12 import com.yohobuy.ufo.coupon.req.UserCouponQueryReq;
  13 +import org.apache.commons.lang.StringUtils;
12 import org.slf4j.Logger; 14 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired; 16 import org.springframework.beans.factory.annotation.Autowired;
15 -import org.springframework.web.bind.annotation.RequestMapping;  
16 -import org.springframework.web.bind.annotation.RestController; 17 +import org.springframework.web.bind.annotation.*;
  18 +import org.springframework.web.multipart.MultipartFile;
17 19
18 import javax.servlet.http.HttpServletResponse; 20 import javax.servlet.http.HttpServletResponse;
19 import java.io.File; 21 import java.io.File;
@@ -88,4 +90,32 @@ public class CouponController { @@ -88,4 +90,32 @@ public class CouponController {
88 return HttpUtil.writeErrorInfo(response, "<p>导出失败</p>"); 90 return HttpUtil.writeErrorInfo(response, "<p>导出失败</p>");
89 } 91 }
90 } 92 }
  93 +
  94 + @RequestMapping(value = "/couponSend")
  95 + public ApiResponse sendCoupon(CouponSendReq req){
  96 + LOGGER.info("enter couponSend, param is {}", req);
  97 + return couponService.sendCoupon(req);
  98 + }
  99 +
  100 + @CrossOrigin(origins = "*")
  101 + @RequestMapping(value = "/couponSendByImport", method = RequestMethod.POST)
  102 + public ApiResponse sendCouponByImport(@RequestParam("file") MultipartFile file , @RequestParam("couponToken") String couponToken){
  103 + LOGGER.info("enter couponSendByImport with file is {}", file);
  104 + if (file == null || file.getSize() == 0) {
  105 + return new ApiResponse(201, "请选择需要上传的文件!", null);
  106 + }
  107 + if(StringUtils.isEmpty(couponToken)){
  108 + return new ApiResponse(201, "输入参数为空!", null);
  109 + }
  110 + try {
  111 + return couponService.sendCouponByImport(file, couponToken);
  112 + } catch (PlatformException px) {
  113 + LOGGER.warn("couponSendByImport PlatformException. errorMsg = {}", px.getMessage());
  114 + return new ApiResponse(px.getCode(), px.getMessage(), null);
  115 + } catch (Exception e) {
  116 + LOGGER.error("couponSendByImport error.", e);
  117 + return new ApiResponse(201, "系统异常", null);
  118 + }
  119 + }
  120 +
91 } 121 }
@@ -3,7 +3,11 @@ package com.yoho.ufo.coupon.service; @@ -3,7 +3,11 @@ package com.yoho.ufo.coupon.service;
3 import com.yoho.ufo.service.model.ApiResponse; 3 import com.yoho.ufo.service.model.ApiResponse;
4 import com.yohobuy.ufo.coupon.req.CouponQueryReq; 4 import com.yohobuy.ufo.coupon.req.CouponQueryReq;
5 import com.yohobuy.ufo.coupon.req.CouponSaveUpdateReq; 5 import com.yohobuy.ufo.coupon.req.CouponSaveUpdateReq;
  6 +import com.yohobuy.ufo.coupon.req.CouponSendReq;
6 import com.yohobuy.ufo.coupon.req.UserCouponQueryReq; 7 import com.yohobuy.ufo.coupon.req.UserCouponQueryReq;
  8 +import org.springframework.web.multipart.MultipartFile;
  9 +
  10 +import java.util.Set;
7 11
8 /** 12 /**
9 * Created by shengguo.cai on 2018/11/20. 13 * Created by shengguo.cai on 2018/11/20.
@@ -16,4 +20,8 @@ public interface ICouponService { @@ -16,4 +20,8 @@ public interface ICouponService {
16 ApiResponse getCouponInfo(Integer id); 20 ApiResponse getCouponInfo(Integer id);
17 21
18 ApiResponse queryUserCoupons(UserCouponQueryReq req); 22 ApiResponse queryUserCoupons(UserCouponQueryReq req);
  23 +
  24 + ApiResponse sendCoupon(CouponSendReq req);
  25 +
  26 + ApiResponse sendCouponByImport(MultipartFile file, String couponToken) throws Exception;
19 } 27 }
@@ -5,11 +5,13 @@ import com.alibaba.fastjson.JSONObject; @@ -5,11 +5,13 @@ import com.alibaba.fastjson.JSONObject;
5 import com.google.common.base.Splitter; 5 import com.google.common.base.Splitter;
6 import com.google.common.collect.Lists; 6 import com.google.common.collect.Lists;
7 import com.yoho.core.common.utils.DateUtil; 7 import com.yoho.core.common.utils.DateUtil;
  8 +import com.yoho.core.rabbitmq.YhProducer;
8 import com.yoho.error.exception.ServiceException; 9 import com.yoho.error.exception.ServiceException;
9 import com.yoho.ufo.coupon.service.ICouponService; 10 import com.yoho.ufo.coupon.service.ICouponService;
10 import com.yoho.ufo.dal.CouponMapper; 11 import com.yoho.ufo.dal.CouponMapper;
11 import com.yoho.ufo.dal.CouponProductLimitMapper; 12 import com.yoho.ufo.dal.CouponProductLimitMapper;
12 import com.yoho.ufo.dal.UserCouponMapper; 13 import com.yoho.ufo.dal.UserCouponMapper;
  14 +import com.yoho.ufo.dal.model.UidImportTranItem;
13 import com.yoho.ufo.exception.PlatformException; 15 import com.yoho.ufo.exception.PlatformException;
14 import com.yoho.ufo.model.coupon.Coupon; 16 import com.yoho.ufo.model.coupon.Coupon;
15 import com.yoho.ufo.model.coupon.CouponProductLimit; 17 import com.yoho.ufo.model.coupon.CouponProductLimit;
@@ -17,23 +19,25 @@ import com.yoho.ufo.model.coupon.UserCoupon; @@ -17,23 +19,25 @@ import com.yoho.ufo.model.coupon.UserCoupon;
17 import com.yoho.ufo.model.coupon.resp.CouponQueryResp; 19 import com.yoho.ufo.model.coupon.resp.CouponQueryResp;
18 import com.yoho.ufo.model.coupon.resp.UserCouponQueryResp; 20 import com.yoho.ufo.model.coupon.resp.UserCouponQueryResp;
19 import com.yoho.ufo.service.IBusinessExportService; 21 import com.yoho.ufo.service.IBusinessExportService;
  22 +import com.yoho.ufo.service.impl.BatchService;
20 import com.yoho.ufo.service.impl.UserHelper; 23 import com.yoho.ufo.service.impl.UserHelper;
21 import com.yoho.ufo.service.model.ApiResponse; 24 import com.yoho.ufo.service.model.ApiResponse;
22 import com.yohobuy.ufo.coupon.req.CouponQueryReq; 25 import com.yohobuy.ufo.coupon.req.CouponQueryReq;
23 import com.yohobuy.ufo.coupon.req.CouponSaveUpdateReq; 26 import com.yohobuy.ufo.coupon.req.CouponSaveUpdateReq;
  27 +import com.yohobuy.ufo.coupon.req.CouponSendReq;
24 import com.yohobuy.ufo.coupon.req.UserCouponQueryReq; 28 import com.yohobuy.ufo.coupon.req.UserCouponQueryReq;
25 import org.apache.commons.collections.CollectionUtils; 29 import org.apache.commons.collections.CollectionUtils;
  30 +import org.apache.commons.lang.math.NumberUtils;
26 import org.apache.commons.lang3.StringUtils; 31 import org.apache.commons.lang3.StringUtils;
27 import org.slf4j.Logger; 32 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 33 import org.slf4j.LoggerFactory;
29 import org.springframework.beans.factory.annotation.Autowired; 34 import org.springframework.beans.factory.annotation.Autowired;
30 import org.springframework.stereotype.Service; 35 import org.springframework.stereotype.Service;
  36 +import org.springframework.web.multipart.MultipartFile;
31 37
  38 +import javax.annotation.Resource;
32 import javax.servlet.http.HttpServletRequest; 39 import javax.servlet.http.HttpServletRequest;
33 -import java.util.ArrayList;  
34 -import java.util.List;  
35 -import java.util.Objects;  
36 -import java.util.UUID; 40 +import java.util.*;
37 import java.util.stream.Collectors; 41 import java.util.stream.Collectors;
38 42
39 /** 43 /**
@@ -42,15 +46,25 @@ import java.util.stream.Collectors; @@ -42,15 +46,25 @@ import java.util.stream.Collectors;
42 @Service("couponServiceImpl") 46 @Service("couponServiceImpl")
43 public class CouponServiceImpl implements ICouponService,IBusinessExportService{ 47 public class CouponServiceImpl implements ICouponService,IBusinessExportService{
44 private static final Logger LOGGER = LoggerFactory.getLogger(CouponServiceImpl.class); 48 private static final Logger LOGGER = LoggerFactory.getLogger(CouponServiceImpl.class);
  49 +
45 @Autowired 50 @Autowired
46 private CouponMapper couponMapper; 51 private CouponMapper couponMapper;
  52 +
47 @Autowired 53 @Autowired
48 private CouponProductLimitMapper couponProductLimitMapper; 54 private CouponProductLimitMapper couponProductLimitMapper;
  55 +
49 @Autowired 56 @Autowired
50 private UserCouponMapper userCouponMapper; 57 private UserCouponMapper userCouponMapper;
  58 +
51 @Autowired 59 @Autowired
52 private HttpServletRequest request; 60 private HttpServletRequest request;
53 61
  62 + @Autowired
  63 + private BatchService batchService;
  64 +
  65 + @Resource(name = "yhProducer")
  66 + private YhProducer yhProducer;
  67 +
54 @Override 68 @Override
55 public Class getDataClass() { 69 public Class getDataClass() {
56 return (Class)request.getAttribute("exportClassType"); 70 return (Class)request.getAttribute("exportClassType");
@@ -220,6 +234,80 @@ public class CouponServiceImpl implements ICouponService,IBusinessExportService{ @@ -220,6 +234,80 @@ public class CouponServiceImpl implements ICouponService,IBusinessExportService{
220 return new ApiResponse.ApiResponseBuilder().data(jsonObject).build(); 234 return new ApiResponse.ApiResponseBuilder().data(jsonObject).build();
221 } 235 }
222 236
  237 + @Override
  238 + public ApiResponse sendCoupon(CouponSendReq req) {
  239 + //(1) 参数非空校验
  240 + if(req == null || StringUtils.isEmpty(req.getCouponToken()) || StringUtils.isEmpty(req.getUids())){
  241 + LOGGER.info("sendCoupon failed with req is null, req is {}", req);
  242 + return new ApiResponse(201, "输入参数为空", null);
  243 + }
  244 + //(2) uid 校验数量是否超过限制,是否为数字
  245 + List<String> uidList = Arrays.asList(req.getUids().split(","));
  246 + if(uidList.size() > 50){
  247 + LOGGER.info("sendCoupon failed with uid size too large, size is {}", uidList.size());
  248 + return new ApiResponse(201, "单次至多输入50个uid", null);
  249 + }
  250 + Set<Integer> uidSet = new HashSet<>();
  251 + for(String uid: uidList){
  252 + if(!NumberUtils.isNumber(uid)){
  253 + LOGGER.info("sendCoupon failed with uid is not number, uid is {}", uid);
  254 + return new ApiResponse(201, "uid必须为数字", null);
  255 + }
  256 + uidSet.add(Integer.valueOf(uid));
  257 + }
  258 + //(3) 校验券 并通过mq发券
  259 + return sendCouponByMQ(req.getCouponToken(), uidSet);
  260 + }
  261 +
  262 + @Override
  263 + public ApiResponse sendCouponByImport(MultipartFile file, String couponToken) throws Exception {
  264 + //解析excel
  265 + List<UidImportTranItem> items = batchService.parseData(file, "batchImportUid", UidImportTranItem.class);
  266 + //校验uid 1.是否超过数量限制 2.是否合法
  267 + if(items.size() > 50){
  268 + LOGGER.info("sendCouponByImport item size too large, size is {}", items.size());
  269 + return new ApiResponse(201, "导入uid数量超过50!", null);
  270 + }
  271 + Set<Integer> uidSet = new HashSet<>();
  272 + for(int i = 0 ; i < items.size() ; i ++){
  273 + UidImportTranItem item = items.get(i);
  274 + Integer uid = item.getUid();
  275 + if(uid == null || uid < 1){
  276 + return new ApiResponse(201, "excel第"+ ( i + 1 ) + "行数据不合法", null);
  277 + }
  278 + uidSet.add(uid);
  279 + }
  280 + return sendCouponByMQ(couponToken, uidSet);
  281 + }
  282 +
  283 + private ApiResponse sendCouponByMQ(String couponToken, Set<Integer> uidSet){
  284 + // ufo券校验 1.是否有效 2.可用数量是否大于所需发送人数
  285 + Coupon coupon = couponMapper.selectValidByToken(couponToken);
  286 + if(coupon == null){
  287 + LOGGER.info("sendCoupon failed with coupon isn't exist or isn't valid, token is {}", couponToken);
  288 + return new ApiResponse(201, "优惠券未在使用中!", null);
  289 + }
  290 + int availableNum = coupon.getCouponNum() - coupon.getSendNum();
  291 + if(uidSet.size() > coupon.getCouponNum()){
  292 + LOGGER.info("sendCoupon failed with couponNum isn't enough, uidSize is {}, availableCouponNum is {}", uidSet.size(), availableNum);
  293 + return new ApiResponse(201, "uid数量大于当前券可用数量:"+ availableNum + "!" , null);
  294 + }
  295 + // 发券
  296 + for(Integer uid : uidSet){
  297 + try {
  298 + JSONObject sendCouponParam = new JSONObject();
  299 + sendCouponParam.put("uid", uid);
  300 + sendCouponParam.put("couponTokens", Collections.singletonList(coupon.getCouponToken()));
  301 + sendCouponParam.put("sendType", "1");//sendType 为1时, 若这张券已经领过,则仍然可以领
  302 + yhProducer.send("ufo.couponSendWithTradeMqNotify", sendCouponParam, null);
  303 + Thread.sleep(5);
  304 + }catch (Exception e){
  305 + LOGGER.info("sendCoupon by mq fail with uid is {}, token is {}", uid, couponToken);
  306 + }
  307 + }
  308 + return new ApiResponse();
  309 + }
  310 +
223 private void checkSaveOrUpdateCouponParam(CouponSaveUpdateReq req) { 311 private void checkSaveOrUpdateCouponParam(CouponSaveUpdateReq req) {
224 if(req == null){ 312 if(req == null){
225 LOGGER.info("checkSaveOrUpdateCouponParam failed! req is null"); 313 LOGGER.info("checkSaveOrUpdateCouponParam failed! req is null");
@@ -17,6 +17,8 @@ public interface CouponMapper { @@ -17,6 +17,8 @@ public interface CouponMapper {
17 17
18 Coupon selectById(@Param("id") Integer id); 18 Coupon selectById(@Param("id") Integer id);
19 19
  20 + Coupon selectValidByToken(@Param("token") String token);
  21 +
20 void insertOrUpdate(@Param("param") CouponSaveUpdateReq param); 22 void insertOrUpdate(@Param("param") CouponSaveUpdateReq param);
21 23
22 void insertByCouponSaveUpdateReq(@Param("param") CouponSaveUpdateReq param); 24 void insertByCouponSaveUpdateReq(@Param("param") CouponSaveUpdateReq param);
  1 +package com.yoho.ufo.dal.model;
  2 +
  3 +import com.yoho.ufo.annotation.BatchImportField;
  4 +import lombok.Data;
  5 +
  6 +@Data
  7 +public class UidImportTranItem {
  8 +
  9 + @BatchImportField(index = 0)
  10 + private Integer uid;
  11 +
  12 +}
@@ -222,4 +222,8 @@ @@ -222,4 +222,8 @@
222 <select id="selectById" resultType="com.yoho.ufo.model.coupon.Coupon"> 222 <select id="selectById" resultType="com.yoho.ufo.model.coupon.Coupon">
223 select <include refid="Base_Column_List" /> from coupon where id=#{id} limit 1; 223 select <include refid="Base_Column_List" /> from coupon where id=#{id} limit 1;
224 </select> 224 </select>
  225 + <select id="selectValidByToken" resultType="com.yoho.ufo.model.coupon.Coupon">
  226 + select <include refid="Base_Column_List" /> from coupon
  227 + where coupon_token =#{token} and status = 1 limit 1;
  228 + </select>
225 </mapper> 229 </mapper>
  1 +producer:
  2 + - address: 192.168.102.45:5672
  3 + producers:
  4 + - bean: yhProducer
  1 +producer:
  2 + - address: ${rabbit_ufo}
  3 + username: ${rabbit_ufo_user}
  4 + password: ${rabbit_ufo_password}
  5 + producers:
  6 + - bean: yhProducer
No preview for this file type