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())
+
+
+
+
+
+