From c4aab3efa239bb2b151baee038c7deec5f83302f Mon Sep 17 00:00:00 2001 From: jiangyunjie Date: Mon, 13 Apr 2020 09:38:30 +0800 Subject: [PATCH] =?UTF-8?q?=E9=97=A8=E5=BA=97=E6=8E=A8=E5=B9=BF=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 + .../kiisoo/ic/store/constant/Constants.java | 22 +++ .../StorePromotionDataController.java | 70 ++++++++ .../ic/store/entity/StorePromotionDataDO.java | 80 +++++++++ .../ic/store/entity/WxCusInfoReqDO.java | 40 +++++ .../ic/store/entity/WxCusInfoRespDO.java | 41 +++++ .../mapper/StorePromotionDataDOMapper.java | 99 +++++++++++ .../store/service/StorePromotionDataJob.java | 40 +++++ .../service/StorePromotionDataService.java | 160 +++++++++++++++++ .../mapper/StorePromotionDataDOMapper.xml | 161 ++++++++++++++++++ 10 files changed, 719 insertions(+) create mode 100644 src/main/java/com/kiisoo/ic/store/controller/StorePromotionDataController.java create mode 100644 src/main/java/com/kiisoo/ic/store/entity/StorePromotionDataDO.java create mode 100644 src/main/java/com/kiisoo/ic/store/entity/WxCusInfoReqDO.java create mode 100644 src/main/java/com/kiisoo/ic/store/entity/WxCusInfoRespDO.java create mode 100644 src/main/java/com/kiisoo/ic/store/mapper/StorePromotionDataDOMapper.java create mode 100644 src/main/java/com/kiisoo/ic/store/service/StorePromotionDataJob.java create mode 100644 src/main/java/com/kiisoo/ic/store/service/StorePromotionDataService.java create mode 100644 src/main/resources/mapper/StorePromotionDataDOMapper.xml diff --git a/pom.xml b/pom.xml index a629c66..547a02e 100644 --- a/pom.xml +++ b/pom.xml @@ -215,6 +215,12 @@ thymeleaf-extras-shiro 1.2.1 + + + com.xuxueli + xxl-job-core + 1.9.0 + diff --git a/src/main/java/com/kiisoo/ic/store/constant/Constants.java b/src/main/java/com/kiisoo/ic/store/constant/Constants.java index 33162cc..2ab5597 100644 --- a/src/main/java/com/kiisoo/ic/store/constant/Constants.java +++ b/src/main/java/com/kiisoo/ic/store/constant/Constants.java @@ -11,6 +11,28 @@ public class Constants { */ public static final String DATABASE_STORE_ID_KEY = "store_id"; + /** + * 客户统计数据 0 + */ + public static int CONTACT_COUNT = 0; + + /** + * 新增失败 + */ + public static int INSERT_FAIL = 0; + + /** + * 门店数据查询类型 "region".区域 + */ + public static final String STORE_DATA_TYPE_REGION = "region"; + /** + * 门店数据查询类型 "store".店铺 + */ + public static final String STORE_DATA_TYPE_STORE = "store"; + /** + * 门店数据查询类型 "seller".店铺 + */ + public static final String STORE_DATA_TYPE_SELLER = "seller"; } diff --git a/src/main/java/com/kiisoo/ic/store/controller/StorePromotionDataController.java b/src/main/java/com/kiisoo/ic/store/controller/StorePromotionDataController.java new file mode 100644 index 0000000..8d32437 --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/controller/StorePromotionDataController.java @@ -0,0 +1,70 @@ +package com.kiisoo.ic.store.controller; + +import com.github.pagehelper.PageInfo; +import com.kiisoo.ic.common.BaseController; +import com.kiisoo.ic.store.entity.StorePromotionDataDO; +import com.kiisoo.ic.store.service.StoreEmployeeService; +import com.kiisoo.ic.store.service.StorePromotionDataService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author yunjie.jiang + * @date 2020/4/10 10:49 + * @company kiisoo + * @details 门店推广数据controller + */ +@Controller +@RequestMapping("/store/promotion/data") +@Slf4j +public class StorePromotionDataController extends BaseController { + + /** + * 推广数据数据 + */ + @Autowired + private StorePromotionDataService storePromotionDataService; + + /** + * 查询门店推广数据列表 + * @param userId + * @param storeId + * @param regionId + * @param sellerId + * @param startDate + * @param endDate + * @param type 页面类型 "region".区域, "store".门店, "seller".导购 + * @param pageNum + * @param pageSize + * @return + */ + @RequestMapping(value = "list",method = RequestMethod.POST) + @ResponseBody + public Map listStorePromotionDate(@RequestParam("userId") Long userId, + @RequestParam("storeId") Long storeId, + @RequestParam("regionId") Long regionId, + @RequestParam("sellerId") Long sellerId, + @RequestParam("startDate") Date startDate, + @RequestParam("endDate") Date endDate, + @RequestParam("type") String type, + @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum, + @RequestParam(value = "pageSize", required = false, defaultValue = "15") int pageSize){ + try { + PageInfo storePromotionDataDOS = storePromotionDataService.listStorePromotionDate(userId, storeId, + regionId, sellerId, startDate, endDate, type, pageNum, pageSize); + return data(storePromotionDataDOS); + }catch (Exception e){ + log.error("查询门店推广数据列表",e); + return fail(); + } + } +} diff --git a/src/main/java/com/kiisoo/ic/store/entity/StorePromotionDataDO.java b/src/main/java/com/kiisoo/ic/store/entity/StorePromotionDataDO.java new file mode 100644 index 0000000..54cd8ca --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/entity/StorePromotionDataDO.java @@ -0,0 +1,80 @@ +package com.kiisoo.ic.store.entity; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @Description: + * @Author: JYJ + * @Date: 2020/4/10 14:39 + * @Version: v1.0 + */ +@Data +public class StorePromotionDataDO { + + /** + * 主键 + */ + public Long id; + + /** + * 客户id + */ + public String userId; + + /** + * 店铺id + */ + public Long storeId; + + /** + * 店铺名 + */ + public Long storeName; + + /** + * 区域id + */ + public Long regionId; + + /** + * 区域名 + */ + public String regionName; + + /** + * 导购id + */ + public Long sellerId; + + /** + * 导购名 + */ + public String sellerName; + + /** + * 总客户数 + */ + public Integer cusNum; + + /** + * 新增客户数 + */ + public Integer newCusNum; + + /** + * 日增客户平均 + */ + public Integer avgNewCusNum; + + /** + * 删除/拉黑成员客户数(累计) + */ + public Integer delCusNum; + + /** + * 拉黑率(累计) + */ + public Float delCusRate; +} diff --git a/src/main/java/com/kiisoo/ic/store/entity/WxCusInfoReqDO.java b/src/main/java/com/kiisoo/ic/store/entity/WxCusInfoReqDO.java new file mode 100644 index 0000000..95622a8 --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/entity/WxCusInfoReqDO.java @@ -0,0 +1,40 @@ +package com.kiisoo.ic.store.entity; + +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.Date; + +/** + * @Description: 微信获取外部联系人请求类 + * @Author: JYJ + * @Date: 2020/4/10 16:12 + * @Version: v1.0 + */ +@Data +public class WxCusInfoReqDO { + + /** + * 调用接口凭证 + */ + private String access_token; + + /** + * 客户id + */ + private String userid; + + /** + * 开始时间 + */ + private Long start_time; + + /** + * 结束时间 + */ + private Long end_time; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } +} diff --git a/src/main/java/com/kiisoo/ic/store/entity/WxCusInfoRespDO.java b/src/main/java/com/kiisoo/ic/store/entity/WxCusInfoRespDO.java new file mode 100644 index 0000000..4d2b818 --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/entity/WxCusInfoRespDO.java @@ -0,0 +1,41 @@ +package com.kiisoo.ic.store.entity; + +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.Date; + +/** + * @Description: 微信获取外部联系人请求类 + * @Author: JYJ + * @Date: 2020/4/10 16:12 + * @Version: v1.0 + */ +@Data +public class WxCusInfoRespDO { + + /** + * 删除/拉黑成员的客户数 (被拉黑数) + */ + private Integer negative_feedback_cnt; + + /** + * 新增客户数 + */ + private Integer new_contact_cnt; + + /** + * 店铺id + */ + private Long storeId; + + /** + * 区域id + */ + private Long regionId; + + /** + * 统计时间 + */ + private Date statTime; +} diff --git a/src/main/java/com/kiisoo/ic/store/mapper/StorePromotionDataDOMapper.java b/src/main/java/com/kiisoo/ic/store/mapper/StorePromotionDataDOMapper.java new file mode 100644 index 0000000..f7dab23 --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/mapper/StorePromotionDataDOMapper.java @@ -0,0 +1,99 @@ +package com.kiisoo.ic.store.mapper; + +import com.kiisoo.ic.store.entity.StorePromotionDataDO; +import com.kiisoo.ic.store.entity.WxCusInfoRespDO; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; + + +/** + * 店铺-企业微信账号-关联表 Mapper + * @author yechenhao + * @since 2020-04-09 + */ +@Repository +public interface StorePromotionDataDOMapper { + + /** + * 查询门店推广数据列表 区域 + * @param storeIds + * @param regionId + * @param startDate + * @param endDate + * @return + */ + List selectPromotionDataGroupByRegion(@Param("storeIds") List storeIds, + @Param("regionId") Long regionId, + @Param("startDate") Date startDate, + @Param("endDate") Date endDate); + + /** + * 查询门店推广数据列表 店铺 + * @param storeIds + * @param storeId + * @param regionId + * @param startDate + * @param endDate + * @return + */ + List selectPromotionDataGroupByStore(@Param("storeIds") List storeIds, + @Param("storeId") Long storeId, + @Param("regionId") Long regionId, + @Param("startDate") Date startDate, + @Param("endDate") Date endDate); + + /** + * 查询门店推广数据列表 导购 + * @param storeIds + * @param storeId + * @param regionId + * @param sellerId + * @param startDate + * @param endDate + * @return + */ + List selectPromotionDataGroupBySeller(@Param("storeIds") List storeIds, + @Param("storeId") Long storeId, + @Param("regionId") Long regionId, + @Param("sellerId") Long sellerId, + @Param("startDate") Date startDate, + @Param("endDate") Date endDate); + + /** + * 查询所有导购的客户 + * @return storePromotionDataDO + */ + List selectCustomer(); + + /** + * 新增门店企业微信的联系人数据到数据库 + * @param wxCusInfoRespDO + * @return + */ + int insertStorePromotionData(WxCusInfoRespDO wxCusInfoRespDO); + + /** + * 查询门店企业微信的联系人数据 按区域 + * @param regionId + * @param startDate + * @param endDate + * @return + */ + StorePromotionDataDO selectWxCusInfoByRegionId(@Param("regionId") Long regionId, + @Param("startDate") Date startDate, + @Param("endDate") Date endDate); + + /** + * 查询门店企业微信的联系人数据 按店铺 + * @param storeId + * @param startDate + * @param endDate + * @return + */ + StorePromotionDataDO selectWxCusInfoByStoreId(@Param("storeId") Long storeId, + @Param("startDate") Date startDate, + @Param("endDate") Date endDate); +} diff --git a/src/main/java/com/kiisoo/ic/store/service/StorePromotionDataJob.java b/src/main/java/com/kiisoo/ic/store/service/StorePromotionDataJob.java new file mode 100644 index 0000000..f2a2b32 --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/service/StorePromotionDataJob.java @@ -0,0 +1,40 @@ +package com.kiisoo.ic.store.service; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.handler.annotation.JobHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author jinchaofan + * @date 2019/4/28 15:20 + * @company kiisoo + * @details 获取联系客户统计数据定时任务 job 0 0 1 * * ? + */ +@JobHandler(value="storePromotionData") +@Component +@Slf4j +public class StorePromotionDataJob extends IJobHandler { + + /** + * 客流定时任务 service + */ + @Autowired + private StorePromotionDataService storePromotionDataService; + + @Override + public ReturnT execute(String s) throws Exception { + try { + log.info("<--获取联系客户统计数据定时任务执行-->"); + storePromotionDataService.syncCustomerBlackList(); + log.info("<--获取联系客户统计数据定时任务结束-->"); + } catch (Exception e) { + log.error("获取联系客户统计数据任务出错", e); + } + return SUCCESS; + } + + +} diff --git a/src/main/java/com/kiisoo/ic/store/service/StorePromotionDataService.java b/src/main/java/com/kiisoo/ic/store/service/StorePromotionDataService.java new file mode 100644 index 0000000..5bf6a7f --- /dev/null +++ b/src/main/java/com/kiisoo/ic/store/service/StorePromotionDataService.java @@ -0,0 +1,160 @@ +package com.kiisoo.ic.store.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.kiisoo.ic.config.WxCpConfiguration; +import com.kiisoo.ic.domain.service.PrivilageDomainService; +import com.kiisoo.ic.store.constant.Constants; +import com.kiisoo.ic.store.entity.StorePromotionDataDO; +import com.kiisoo.ic.store.entity.WxCusInfoReqDO; +import com.kiisoo.ic.store.entity.WxCusInfoRespDO; +import com.kiisoo.ic.store.mapper.StorePromotionDataDOMapper; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +/** + * @Description: + * @Author: JYJ + * @Date: 2020/4/10 10:50 + * @Version: v1.0 + */ +@Service +@Slf4j +public class StorePromotionDataService { + + private WxCpService mainService = WxCpConfiguration.getCpService(1000037); + + /** + * 门店数据mapper + */ + @Autowired + private StorePromotionDataDOMapper storePromotionDataDOMapper; + + /** + * 权限业务 + */ + @Autowired + private PrivilageDomainService privilageDomainService; + /** + * 查询门店推广数据列表 + * @param storeId + * @param regionId + * @param sellerId + * @param startDate + * @param endDate + * @param pageNum + * @param pageSize + * @return + */ + public PageInfo listStorePromotionDate(Long userId, Long storeId, Long regionId, Long sellerId, + Date startDate, Date endDate, String type, int pageNum, int pageSize) { + //用户权限下的店铺 + List storeIds = privilageDomainService.listUserDatePermission(userId); + List promotionDataDOS; + if (Constants.STORE_DATA_TYPE_REGION.equals(type)) { + PageHelper.startPage(pageNum, pageSize); + promotionDataDOS = storePromotionDataDOMapper.selectPromotionDataGroupByRegion(storeIds, regionId, startDate, endDate); + } else if (Constants.STORE_DATA_TYPE_STORE.equals(type)){ + PageHelper.startPage(pageNum, pageSize); + promotionDataDOS = storePromotionDataDOMapper.selectPromotionDataGroupByStore(storeIds, storeId, regionId, startDate, endDate); + } else { + PageHelper.startPage(pageNum, pageSize); + promotionDataDOS = storePromotionDataDOMapper.selectPromotionDataGroupBySeller(storeIds, storeId, regionId, sellerId, startDate, endDate); + } + if (!Constants.STORE_DATA_TYPE_SELLER.equals(type)) { + promotionDataDOS.forEach(promotionDataDO -> { + Long storeIdKey = promotionDataDO.getStoreId(); + Long regionIdKey = promotionDataDO.getRegionId(); + // 查询新增客户数 拉黑数量 + StorePromotionDataDO wxCusInfoDO = null; + if (Constants.STORE_DATA_TYPE_REGION.equals(type)) { + wxCusInfoDO = storePromotionDataDOMapper.selectWxCusInfoByRegionId(regionIdKey, startDate, endDate); + } else if (Constants.STORE_DATA_TYPE_STORE.equals(type)) { + wxCusInfoDO = storePromotionDataDOMapper.selectWxCusInfoByStoreId(storeIdKey, startDate, endDate); + } + if (null != wxCusInfoDO) { + Integer newCusNum = wxCusInfoDO.getNewCusNum(); + Integer delCusNum = wxCusInfoDO.getDelCusNum(); + promotionDataDO.setNewCusNum(newCusNum); + promotionDataDO.setDelCusNum(delCusNum); + // 日增好友平均 + int nDay = (int) ((startDate.getTime() - endDate.getTime()) / (24 * 60 * 60 * 1000)); + promotionDataDO.setAvgNewCusNum(newCusNum / nDay); + // 拉黑率 + Integer cusNum = promotionDataDO.getCusNum(); + promotionDataDO.setDelCusRate(cusNum == null || cusNum == Constants.CONTACT_COUNT ? + 0 : delCusNum * 1f / promotionDataDO.getCusNum()); + } + }); + } + return new PageInfo<>(promotionDataDOS); + } + + /** + * 同步企业微信的拉黑和新增客户信息 + * @throws Exception + */ + @Transactional(rollbackFor = Exception.class) + public void syncCustomerBlackList() throws Exception{ + //获取token + String token = mainService.getAccessToken(); + List cusList = storePromotionDataDOMapper.selectCustomer(); + cusList.forEach(customer -> { + // 返回 + try { + String userId = customer.getUserId(); + WxCusInfoReqDO wxCusInfoReqDO = new WxCusInfoReqDO(); + wxCusInfoReqDO.setAccess_token(token); + wxCusInfoReqDO.setUserid(userId); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + //todo 分开写便于同步历史数据 最大跨度30天 最久当天往前180天 上线时改为System.currentTimeMillis() + Date startDate = sdf.parse("2020-04-12"); + Date endDate = sdf.parse("2020-04-12"); + wxCusInfoReqDO.setStart_time(startDate.getTime()/1000); + wxCusInfoReqDO.setEnd_time(endDate.getTime()/1000); + WxCusInfoRespDO wxCusInfoRespDO = getWxCusInfo(wxCusInfoReqDO); + if (wxCusInfoRespDO.getNegative_feedback_cnt() == Constants.CONTACT_COUNT && + wxCusInfoRespDO.getNew_contact_cnt() == Constants.CONTACT_COUNT) { + return; + } + wxCusInfoRespDO.setStoreId(customer.getStoreId()); + wxCusInfoRespDO.setRegionId(customer.getRegionId()); + wxCusInfoRespDO.setStatTime(startDate); + int syncRes = storePromotionDataDOMapper.insertStorePromotionData(wxCusInfoRespDO); + if (syncRes == Constants.INSERT_FAIL) { + throw new RuntimeException("向数据库导入客户统计数据时出错"); + } + } catch (WxErrorException | ParseException e) { + log.error("请求企业微信api获取客户统计数据或日期转换出错!", e); + } + }); + } + + + /** + * 获取联系客户统计数据 + * + * @param wxCusInfoReqDO + * @return + * @throws WxErrorException + */ + public WxCusInfoRespDO getWxCusInfo(WxCusInfoReqDO wxCusInfoReqDO) throws WxErrorException { + String url = mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/externalcontact/get_user_behavior_data"); + String result = mainService.post(url, wxCusInfoReqDO.toJson()); + JSONObject parseObject = JSON.parseObject(result); + System.out.println(parseObject); + String[] behavior_data = JSONObject.parseObject(parseObject.getString("behavior_data"), String[].class); + return JSONObject.parseObject(behavior_data[0], WxCusInfoRespDO.class); + } +} diff --git a/src/main/resources/mapper/StorePromotionDataDOMapper.xml b/src/main/resources/mapper/StorePromotionDataDOMapper.xml new file mode 100644 index 0000000..ff98974 --- /dev/null +++ b/src/main/resources/mapper/StorePromotionDataDOMapper.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + INSERT INTO poi_customer_contact_data_stat (store_id, region_id, + negative_feedback_cnt, new_contact_cnt, stat_time, create_time) VALUES (#{storeId}, #{regionId}, + #{negative_feedback_cnt}, #{new_contact_cnt}, #{statTime}, NOW()) + + + + + +