Commit 2ae39b4a by 王祖波

Merge remote-tracking branch 'origin/feature-content2' into feature-content2

parents bdf2b1eb 33929f74
......@@ -22,6 +22,11 @@ public class PotentialCustomerDTO implements Serializable {
private String memberName;
/**
* 会员昵称
*/
private String memberNickName;
/**
* 会员头像
*/
private String memberImageUrl;
......@@ -222,4 +227,12 @@ public class PotentialCustomerDTO implements Serializable {
public void setBizType(Integer bizType) {
this.bizType = bizType;
}
public String getMemberNickName() {
return memberNickName;
}
public void setMemberNickName(String memberNickName) {
this.memberNickName = memberNickName;
}
}
......@@ -11,6 +11,7 @@ public enum NoticeMessageCategoryTypeEnum {
TASK(1, "任务相关"),
ACTIVITY(2, "活动相关"),
MATERIAL(4, "素材相关"),
POTENTIAL_CUSTOMER(5, "销售线索"),
OTHER(3, "其它"),;
private int type;
private String name;
......
......@@ -61,6 +61,8 @@ public enum NoticeMessageTypeEnum {
MATERIAL_NEW_NOTIFY(6001, "素材上新通知", NoticeMessageCategoryTypeEnum.MATERIAL.getType(), "material_new_notify", "/pages/route/index?pageType=", "hbapp_material_center"),
MATERIAL_WEEK_REPORT(6002, "素材周报通知", NoticeMessageCategoryTypeEnum.MATERIAL.getType(), "material_week_notify", "/pages/route/index?pageType=", "hbapp_material_report"),
POTENTIAL_CUSTOMER_NOTIFY(6003, "销售线索通知", NoticeMessageCategoryTypeEnum.POTENTIAL_CUSTOMER.getType(), "potential_customer_notify", "/pages/route/index?pageType=", "hbapp_sales_clue_center");
;
/**
* 消息类型
......
......@@ -52,4 +52,11 @@ public interface QywxGroupMsgTaskApiService {
* @return
*/
ServiceResponse<Void> doHandlerMaterialOneStaffReportMQ(String params);
/**
* 销售线索 通知job
* @param params
* @return
*/
ServiceResponse<Void> potentialCustomerJob(String params);
}
......@@ -398,4 +398,13 @@ public interface TabHaobanExternalClerkRelatedMapper {
*/
List<String> queryExternalUserIdWithStaffId(@Param("staffId") String staffId);
/**
* 查询会员与导购的好友关系
* @param clerkId
* @param memberIds
* @return
*/
List<TabHaobanExternalClerkRelated> queryClerkMemberRelations(@Param("clerkId") String clerkId, @Param("memberIds") List<String> memberIds);
}
\ No newline at end of file
......@@ -120,5 +120,5 @@ public interface TabHaobanStaffClerkRelationMapper {
List<StaffClerkRelationDTO> listByStoreIds(@Param("wxEnterpriseId") String wxEnterpriseId,@Param("storeIds") List<String> storeIds);
List<StaffClerkRelationDTO> listAllRelationDtosByEnterpriseId(@Param("enterpriseId") String enterpriseId);
List<String> listAllClerkIdsByEnterpriseId(@Param("enterpriseId") String enterpriseId);
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.gic.haoban.manage.service.dao.mapper.content;
import com.gic.haoban.manage.service.entity.content.TabHaobanInteractRecord;
import com.gic.haoban.manage.service.entity.content.TabHaobanPotentialCustomer;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO;
import com.gic.haoban.manage.service.pojo.qo.content.InteractRecordQO;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.domain.Pageable;
......@@ -97,5 +98,12 @@ public interface TabHaobanInteractRecordMapper {
*/
List<TabHaobanInteractRecord> queryInteractRecordList(InteractRecordQO interactRecordQO);
/**
* 统计互动记录总数
* @param interactRecordQO
* @return
*/
List<PotentialCustomerStaticsBO> staticsClerkInteractRecordNew(InteractRecordQO interactRecordQO);
}
......@@ -56,15 +56,6 @@ public interface TabHaobanPotentialCustomerMapper {
int insertBatch(@Param("entities") List<TabHaobanPotentialCustomer> entities);
/**
* 批量新增或按主键更新数据(MyBatis原生foreach方法)
*
* @param entities List<TabHaobanPotentialCustomer> 实例对象列表
* @return 影响行数
* @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参
*/
int insertOrUpdateBatch(@Param("entities") List<TabHaobanPotentialCustomer> entities);
/**
* 修改数据
*
* @param tabHaobanPotentialCustomer 实例对象
......
package com.gic.haoban.manage.service.entity.content;
import lombok.Data;
import java.util.Date;
import java.io.Serializable;
......@@ -9,6 +11,7 @@ import java.io.Serializable;
* @author makejava
* @since 2023-03-28 09:48:07
*/
@Data
public class TabHaobanPotentialCustomer implements Serializable {
private static final long serialVersionUID = -28370046858269747L;
......@@ -67,6 +70,11 @@ public class TabHaobanPotentialCustomer implements Serializable {
* 会员昵称
*/
private String memberNickName;
/**
* 会员头像
*/
private String memberImageUrl;
/**
* 会员手机号
*/
......@@ -99,182 +107,5 @@ public class TabHaobanPotentialCustomer implements Serializable {
* 更新时间
*/
private Date updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEnterpriseId() {
return enterpriseId;
}
public void setEnterpriseId(String enterpriseId) {
this.enterpriseId = enterpriseId;
}
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
public String getClerkId() {
return clerkId;
}
public void setClerkId(String clerkId) {
this.clerkId = clerkId;
}
public String getBizId() {
return bizId;
}
public void setBizId(String bizId) {
this.bizId = bizId;
}
public Integer getBizType() {
return bizType;
}
public void setBizType(Integer bizType) {
this.bizType = bizType;
}
public String getStoreId() {
return storeId;
}
public void setStoreId(String storeId) {
this.storeId = storeId;
}
public Integer getChannelSource() {
return channelSource;
}
public void setChannelSource(Integer channelSource) {
this.channelSource = channelSource;
}
public Integer getEventType() {
return eventType;
}
public void setEventType(Integer eventType) {
this.eventType = eventType;
}
public Integer getDurationTime() {
return durationTime;
}
public void setDurationTime(Integer durationTime) {
this.durationTime = durationTime;
}
public String getMemberName() {
return memberName;
}
public void setMemberName(String memberName) {
this.memberName = memberName;
}
public String getMemberNickName() {
return memberNickName;
}
public void setMemberNickName(String memberNickName) {
this.memberNickName = memberNickName;
}
public String getMemberPhone() {
return memberPhone;
}
public void setMemberPhone(String memberPhone) {
this.memberPhone = memberPhone;
}
public Integer getDealRecordNum() {
return dealRecordNum;
}
public void setDealRecordNum(Integer dealRecordNum) {
this.dealRecordNum = dealRecordNum;
}
public Integer getStarFlag() {
return starFlag;
}
public void setStarFlag(Integer starFlag) {
this.starFlag = starFlag;
}
public Integer getSeeFlag() {
return seeFlag;
}
public void setSeeFlag(Integer seeFlag) {
this.seeFlag = seeFlag;
}
public Date getLastAccessTime() {
return lastAccessTime;
}
public void setLastAccessTime(Date lastAccessTime) {
this.lastAccessTime = lastAccessTime;
}
public Integer getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(Integer deleteFlag) {
this.deleteFlag = deleteFlag;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getTimes() {
return times;
}
public void setTimes(Integer times) {
this.times = times;
}
}
......@@ -68,6 +68,11 @@ public class PotentialCustomerBO {
* 会员昵称
*/
private String memberNickName;
/**
* 会员头像
*/
private String memberImageUrl;
/**
* 会员手机号
*/
......@@ -100,4 +105,16 @@ public class PotentialCustomerBO {
* 更新时间
*/
private Date updateTime;
/**
* 导购与会员是否有好友
* 1 是好友; 0不是
*/
private Integer hasMemberRelation;
/**
* 会员全渠道成交
* 1 有过成交; 0 没有成交
*/
private Integer dealRecord;
}
package com.gic.haoban.manage.service.pojo.bo.content;
import lombok.Data;
import java.io.Serializable;
/**
* @Author MUSI
* @Date 2023/3/30 11:12 AM
* @Description
* @Version
**/
@Data
public class PotentialCustomerStaticsBO implements Serializable {
/**
* 导购id
*/
private String clerkId;
/**
* 数量
*/
private Integer num;
}
package com.gic.haoban.manage.service.pojo.bo.content.context;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.service.pojo.bo.NoticeMessageBO;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.gic.haoban.manage.api.enums.NoticeMessageTypeEnum.MATERIAL_WEEK_REPORT;
import static com.gic.haoban.manage.api.enums.NoticeMessageTypeEnum.POTENTIAL_CUSTOMER_NOTIFY;
/**
* @Author MUSI
* @Date 2023/3/30 10:55 AM
* @Description
* @Version
**/
@Slf4j
@Data
@Builder
public class PotentialCustomerNotifyContext {
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* 企业id
*/
private String enterpriseId;
/**
* 企业下的导购id
*/
private List<String> clerkIds;
/**
* 导购关联关系
*/
private List<StaffClerkRelationDTO> staffClerkRelations;
/**
* 导购新销售线索统计
*/
List<PotentialCustomerStaticsBO> customerStaticsBos;
/**
* 构建小程序消息通知
* @return
*/
public List<NoticeMessageBO> buildNoticeMessage() {
if (CollectionUtils.isEmpty(this.customerStaticsBos)) {
return Collections.emptyList();
}
if (CollectionUtils.isEmpty(this.staffClerkRelations)) {
return Collections.emptyList();
}
Map<String, Integer> customerStaticsMap = this.customerStaticsBos.stream()
.collect(Collectors.toMap(PotentialCustomerStaticsBO::getClerkId,
item -> Optional.ofNullable(item.getNum()).orElse(0),
(v1, v2) -> v1));
return this.staffClerkRelations
.stream()
.filter(item -> customerStaticsMap.get(item.getClerkId()) > 0)
.map(item -> {
NoticeMessageBO noticeMessageBO = new NoticeMessageBO();
noticeMessageBO.setCategoryType(POTENTIAL_CUSTOMER_NOTIFY.getCategory());
noticeMessageBO.setMessageType(POTENTIAL_CUSTOMER_NOTIFY.getType());
noticeMessageBO.setClerkId(item.getClerkId());
noticeMessageBO.setStoreId(StringUtils.isNotBlank(item.getStoreId()) ? item.getStoreId() : "-1");
noticeMessageBO.setTitle("销售线索通知");
noticeMessageBO.setTemplateCode(POTENTIAL_CUSTOMER_NOTIFY.getTemplateCode());
noticeMessageBO.setDescription(String.format("新增%s个客户的销售线索,请及时跟进", customerStaticsMap.get(item.getClerkId())));
noticeMessageBO.setEnterpriseId(this.enterpriseId);
noticeMessageBO.setRelationId(item.getClerkId());
noticeMessageBO.setMessageContent("");
return noticeMessageBO;
})
.collect(Collectors.toList());
}
}
......@@ -14,6 +14,8 @@ import java.util.Date;
@Data
public class InteractRecordQO extends BasePageInfo {
private String enterpriseId;
/**
* 导购id
*/
......@@ -30,8 +32,13 @@ public class InteractRecordQO extends BasePageInfo {
private String unionId;
/**
* 开始时间
* 开始时间-创建时间
*/
private Date startTime;
/**
* 结束时间-创建时间
*/
private Date endTime;
}
......@@ -90,4 +90,12 @@ public interface ExternalClerkRelatedService {
*/
List<String> queryExternalRelatedWithStaffId(String staffId);
/***
* 查询会员与导购的关系
* @param clerkId
* @param memberIds
* @return
*/
List<TabHaobanExternalClerkRelated> queryClerkMemberRelations(String clerkId, List<String> memberIds);
}
......@@ -176,5 +176,5 @@ public interface StaffClerkRelationService {
* @param enterpriseId
* @return
*/
List<StaffClerkRelationDTO> listAllRelationDtosByEnterpriseId(String enterpriseId);
List<String> listAllClerkIdsByEnterpriseId(String enterpriseId);
}
......@@ -2,8 +2,11 @@ package com.gic.haoban.manage.service.service.content;
import com.gic.api.base.commons.Page;
import com.gic.haoban.manage.service.pojo.bo.content.InteractRecordBO;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO;
import com.gic.haoban.manage.service.pojo.qo.content.InteractRecordQO;
import java.util.List;
/**
* 互动记录明细(TabHaobanInteractRecord)表服务接口
*
......@@ -40,4 +43,12 @@ public interface InteractRecordService {
* @return
*/
Long saveOrUpdateInteractRecord(InteractRecordBO interactRecordBO);
/**
* 统计导购的互动记录总数
* @param interactRecordQO
* @return
*/
List<PotentialCustomerStaticsBO> staticsClerkNewInteractRecord(InteractRecordQO interactRecordQO);
}
......@@ -2,6 +2,7 @@ package com.gic.haoban.manage.service.service.content;
import com.gic.api.base.commons.Page;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerBO;
import com.gic.haoban.manage.service.pojo.bo.content.context.PotentialCustomerNotifyContext;
import com.gic.haoban.manage.service.pojo.qo.content.PotentialCustomerQO;
/**
......@@ -48,4 +49,10 @@ public interface PotentialCustomerService {
* @return
*/
Long saveOrUpdatePotentialCustomer(PotentialCustomerBO potentialCustomerBO);
/**
* 销售线索通知
* @param context
*/
void sendPotentialCustomerNotice(PotentialCustomerNotifyContext context);
}
......@@ -42,20 +42,31 @@ public class InteractRecordBuilder {
* @return
*/
public String buildDesc(TabHaobanInteractRecord interactRecord) {
return this.buildDesc(interactRecord.getChannelSource(), interactRecord.getEventType());
}
/**
* 基于渠道和事件类型拼接信息
* @param channelSource
* @param eventType
* @return
*/
public String buildDesc(Integer channelSource, Integer eventType) {
StringBuilder stringBuilder = new StringBuilder();
if (TriggerCustomerChannelType.showDescChannel().contains(interactRecord.getChannelSource())) {
TriggerCustomerChannelType channelType = TriggerCustomerChannelType.getInstance(interactRecord.getChannelSource());
if (TriggerCustomerChannelType.showDescChannel().contains(channelSource)) {
TriggerCustomerChannelType channelType = TriggerCustomerChannelType.getInstance(channelSource);
if (channelType != null) {
stringBuilder.append(String.format("通过[%s]", channelType.getDesc()));
}
}
MaterialInteractRecordEventType instance = MaterialInteractRecordEventType.getInstance(interactRecord.getEventType());
MaterialInteractRecordEventType instance = MaterialInteractRecordEventType.getInstance(eventType);
if (instance != null) {
stringBuilder.append(instance.getDesc());
}
return stringBuilder.toString();
}
/**
* 互动记录转换扩展信息
*
......@@ -110,8 +121,7 @@ public class InteractRecordBuilder {
extendGoodsInfo.setGoodsName(item.getGoodsName());
extendGoodsInfo.setGoodsCode(item.getGoodsCode());
extendGoodsInfo.setGoodsImageUrl(item.getGoodsImageUrl());
// todo 商品价格 待订单迭代上线后再调整
// extendGoodsInfo.setSalePrice(item.getStatus());
extendGoodsInfo.setSalePrice(item.getSalePrice());
return extendGoodsInfo;
})
.collect(Collectors.toList());
......
package com.gic.haoban.manage.service.service.content.adaptor;
import com.alibaba.fastjson.JSON;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.StaffDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.service.StaffApiService;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.entity.TabHaobanClerkMainStoreRelated;
import com.gic.haoban.manage.service.pojo.bo.NoticeMessageBO;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO;
import com.gic.haoban.manage.service.pojo.bo.content.context.PotentialCustomerNotifyContext;
import com.gic.haoban.manage.service.service.ClerkMainStoreRelatedService;
import com.gic.haoban.manage.service.service.StaffClerkRelationService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.service.notify.NoticeMessageService;
import com.gic.wechat.api.dto.qywx.ItemDTO;
import com.gic.wechat.api.dto.qywx.QywxNewsArticleMessageDTO;
import com.gic.wechat.api.dto.qywx.QywxNewsSendMessageDTO;
import com.gic.wechat.api.dto.qywx.QywxXcxSendMessageDTO;
import com.gic.wechat.api.service.qywx.QywxSuiteApiService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @Author MUSI
* @Date 2023/3/30 10:58 AM
* @Description
* @Version
**/
@Slf4j
@Component
public class PotentialCustomerNotifyBuilder {
@Autowired
StaffClerkRelationService staffClerkRelationService;
@Autowired
private ClerkMainStoreRelatedService clerkMainStoreRelatedService;
@Autowired
private NoticeMessageService noticeMessageService;
@Autowired
private QywxSuiteApiService qywxSuiteApiService;
@Autowired
private WxEnterpriseService wxEnterpriseService;
@Autowired
private Config config;
@Autowired
private StaffApiService staffApiService;
/**
* 获取企业下所有导购id
*
* @param context
*/
public void buildEnterpriseClerkIds(PotentialCustomerNotifyContext context) {
if (StringUtils.isBlank(context.getEnterpriseId())) {
return;
}
List<String> clerkIds =
staffClerkRelationService.listAllClerkIdsByEnterpriseId(context.getEnterpriseId());
if (CollectionUtils.isEmpty(clerkIds)) {
return;
}
context.setClerkIds(clerkIds);
}
/**
* 获取导购的绑定关系
*
* @param context
*/
public void buildClerkRelations(PotentialCustomerNotifyContext context) {
List<String> clerkIds = context.getCustomerStaticsBos()
.stream()
.map(PotentialCustomerStaticsBO::getClerkId)
.collect(Collectors.toList());
context.setClerkIds(clerkIds);
List<StaffClerkRelationDTO> staffClerkRelations = staffClerkRelationService.listByClerkIds(context.getClerkIds());
context.setStaffClerkRelations(staffClerkRelations);
}
/**
* 过滤区经
*
* @param context
*/
public void filterAreaManage(PotentialCustomerNotifyContext context) {
List<StaffClerkRelationDTO> clerkRelations = context.getStaffClerkRelations()
.stream()
.filter(item -> !Objects.equals(2, item.getClerkType()))
.collect(Collectors.toList());
context.setStaffClerkRelations(clerkRelations);
}
/**
* 发送好办小程序消息
*
* @param context
*/
public void sendHaoBanNotifyMessage(PotentialCustomerNotifyContext context) {
List<NoticeMessageBO> noticeMessageBos = context.buildNoticeMessage();
if (CollectionUtils.isEmpty(noticeMessageBos)) {
log.info("好办消息为空");
return;
}
noticeMessageService.addNoticeMessageBatch(noticeMessageBos);
}
/**
* 发送应用消息
*
* @param context
*/
public void sendApplicationMessage(PotentialCustomerNotifyContext context) {
if (CollectionUtils.isEmpty(context.getCustomerStaticsBos()) || CollectionUtils.isEmpty(context.getStaffClerkRelations())) {
log.info("发送应用消息 参数缺失 {}");
return;
}
Map<String, PotentialCustomerStaticsBO> customerStaticsBOMap = context.getCustomerStaticsBos()
.stream()
.collect(Collectors.toMap(PotentialCustomerStaticsBO::getClerkId, Function.identity(), (v1, v2) -> v1));
Map<String, TabHaobanClerkMainStoreRelated> clerkMainStoreMap = new HashMap<>();
Map<String, WxEnterpriseQwDTO> clerkEnterpriseMap = new HashMap<>();
for (StaffClerkRelationDTO staffClerkRelation : context.getStaffClerkRelations()) {
PotentialCustomerStaticsBO customerStaticsBO = customerStaticsBOMap.get(staffClerkRelation.getClerkId());
if (customerStaticsBO == null || customerStaticsBO.getNum() == null || customerStaticsBO.getNum() == 0) {
log.info("导购不存在新访问");
continue;
}
String staffId = staffClerkRelation.getStaffId();
TabHaobanClerkMainStoreRelated temp = clerkMainStoreMap.get(staffId);
if (temp == null) {
TabHaobanClerkMainStoreRelated tabHaobanClerkMainStoreRelated = clerkMainStoreRelatedService.selectByWxEnterpriseIdAndStoreId(staffId, staffClerkRelation.getWxEnterpriseId());
if (tabHaobanClerkMainStoreRelated == null) {
tabHaobanClerkMainStoreRelated = new TabHaobanClerkMainStoreRelated();
}
clerkMainStoreMap.put(staffId, tabHaobanClerkMainStoreRelated);
temp = clerkMainStoreMap.get(staffId);
}
if (temp != null) {
if (StringUtils.isBlank(temp.getStoreId())) {
// 该成员无主门店
log.info("成员无主门店 {}", staffId);
continue;
}
if (StringUtils.isBlank(temp.getStoreId())) {
log.info("成员不存在主门店 {}", staffId);
continue;
}
// 需要发送应用消息
WxEnterpriseQwDTO wxEnterpriseQwDTO = clerkEnterpriseMap.get(staffClerkRelation.getWxEnterpriseId());
if (wxEnterpriseQwDTO == null) {
wxEnterpriseQwDTO = wxEnterpriseService.getQwInfo(staffClerkRelation.getWxEnterpriseId());
clerkEnterpriseMap.put(staffClerkRelation.getWxEnterpriseId(), wxEnterpriseQwDTO);
}
wxEnterpriseQwDTO = clerkEnterpriseMap.get(staffClerkRelation.getWxEnterpriseId());
if (wxEnterpriseQwDTO == null) {
log.info("企业信息不存在 {}", staffClerkRelation.getWxEnterpriseId());
return;
}
QywxXcxSendMessageDTO messageDTO = this.buildApplicationMessage(staffClerkRelation, wxEnterpriseQwDTO, customerStaticsBO.getNum());
boolean sendMessage = qywxSuiteApiService.sendMessage(wxEnterpriseQwDTO.getThirdCorpid(), config.getWxSuiteid(), messageDTO);
log.info("发送应用消息结果 {}", sendMessage);
}
}
}
public QywxXcxSendMessageDTO buildApplicationMessage(StaffClerkRelationDTO staffClerkRelation, WxEnterpriseQwDTO wxEnterpriseQwDTO, int count) {
StaffDTO staffDTO = staffApiService.selectById(staffClerkRelation.getStaffId());
String wxUserId = staffDTO.getWxUserId();
if (wxEnterpriseQwDTO.needOpenUserId3th()) {
wxUserId = staffDTO.getWxOpenUseId();
}
QywxXcxSendMessageDTO messageDTO = new QywxXcxSendMessageDTO();
ItemDTO itemDTO = new ItemDTO();
itemDTO.setKey("事件");
itemDTO.setValue(String.format("新增%s个客户的销售线索,请及时跟进", count));
ArrayList<String> list = new ArrayList<>();
list.add(wxUserId);
messageDTO.setAppid(config.getAppid());
messageDTO.setUserIds(list);
messageDTO.setPage("/pageurl?");
messageDTO.setTitle("销售线索通知");
messageDTO.setItems(Collections.singletonList(itemDTO));
return messageDTO;
}
}
......@@ -7,6 +7,7 @@ import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.manage.service.dao.mapper.content.TabHaobanInteractRecordMapper;
import com.gic.haoban.manage.service.entity.content.TabHaobanInteractRecord;
import com.gic.haoban.manage.service.pojo.bo.content.InteractRecordBO;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO;
import com.gic.haoban.manage.service.pojo.qo.content.InteractRecordQO;
import com.gic.haoban.manage.service.service.content.InteractRecordService;
import com.gic.haoban.manage.service.service.content.adaptor.InteractRecordBuilder;
......@@ -140,4 +141,15 @@ public class InteractRecordServiceImpl implements InteractRecordService {
}
return temp.getId();
}
/**
* 统计导购的互动记录总数
*
* @param interactRecordQO
* @return
*/
@Override
public List<PotentialCustomerStaticsBO> staticsClerkNewInteractRecord(InteractRecordQO interactRecordQO) {
return this.tabHaobanInteractRecordMapper.staticsClerkInteractRecordNew(interactRecordQO);
}
}
package com.gic.haoban.manage.service.service.content.impl;
import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.Page;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.manage.service.dao.mapper.content.TabHaobanPotentialCustomerMapper;
import com.gic.haoban.manage.service.entity.TabHaobanExternalClerkRelated;
import com.gic.haoban.manage.service.entity.content.TabHaobanPotentialCustomer;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerBO;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO;
import com.gic.haoban.manage.service.pojo.bo.content.context.PotentialCustomerNotifyContext;
import com.gic.haoban.manage.service.pojo.qo.content.InteractRecordQO;
import com.gic.haoban.manage.service.pojo.qo.content.PotentialCustomerQO;
import com.gic.haoban.manage.service.service.ExternalClerkRelatedService;
import com.gic.haoban.manage.service.service.content.InteractRecordService;
import com.gic.haoban.manage.service.service.content.PotentialCustomerService;
import com.gic.haoban.manage.service.service.content.adaptor.PotentialCustomerNotifyBuilder;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 销售线索(TabHaobanPotentialCustomer)表服务实现类
......@@ -30,7 +44,12 @@ public class PotentialCustomerServiceImpl implements PotentialCustomerService {
@Resource
private TabHaobanPotentialCustomerMapper potentialCustomerMapper;
@Autowired
private PotentialCustomerNotifyBuilder potentialCustomerNotifyBuilder;
@Autowired
private InteractRecordService interactRecordService;
@Autowired
private ExternalClerkRelatedService externalClerkRelatedService;
/**
* 查询销售线索
......@@ -48,7 +67,57 @@ public class PotentialCustomerServiceImpl implements PotentialCustomerService {
PageHelper.startPage(potentialCustomerQO.getPageNum(), potentialCustomerQO.getPageSize());
com.github.pagehelper.Page<TabHaobanPotentialCustomer> pageResult =
(com.github.pagehelper.Page<TabHaobanPotentialCustomer>) potentialCustomerMapper.queryPotentialCustomerList(potentialCustomerQO);
return PageUtil.changePageHelperToCurrentPage(pageResult, PotentialCustomerBO.class);
Page<PotentialCustomerBO> customerBOPage = PageUtil.changePageHelperToCurrentPage(pageResult, PotentialCustomerBO.class);
if (CollectionUtils.isEmpty(customerBOPage.getResult())) {
log.info("查询销售线索列表为空 params: {}", JSON.toJSONString(potentialCustomerQO));
return customerBOPage;
}
List<String> memberIds = customerBOPage.getResult()
.stream()
.map(PotentialCustomerBO::getMemberId)
.distinct()
.collect(Collectors.toList());
Map<String, Integer> clerkMemberRelationMap = this.queryMemberRelation(potentialCustomerQO.getClerkId(), memberIds, potentialCustomerQO.getHasMemberRelation());
// 构建是否是会员
for (PotentialCustomerBO potentialCustomerBO : customerBOPage.getResult()) {
// 默认未成交过
potentialCustomerBO.setDealRecord(0);
if (potentialCustomerBO.getDealRecordNum() != null && potentialCustomerBO.getDealRecordNum() > 0) {
potentialCustomerBO.setDealRecord(1);
}
if (potentialCustomerQO.getHasMemberRelation() != null) {
// 查询条件是有好友关系的
potentialCustomerBO.setHasMemberRelation(1);
continue;
}
// 获取有好友关系的
Integer hasRelation = clerkMemberRelationMap.get(potentialCustomerBO.getMemberId());
potentialCustomerBO.setHasMemberRelation(Optional.ofNullable(hasRelation).orElse(0));
}
return customerBOPage;
}
/**
* 查询与导购的关系
*
* @param clerkId
* @param memberIds
* @return
*/
private Map<String, Integer> queryMemberRelation(String clerkId, List<String> memberIds, Integer hasMemberRelation) {
if (hasMemberRelation != null) {
log.info("按好友条件搜索 无须查询");
return Collections.emptyMap();
}
List<TabHaobanExternalClerkRelated> clerkRelateds = externalClerkRelatedService.queryClerkMemberRelations(clerkId, memberIds);
if (CollectionUtils.isEmpty(clerkRelateds)) {
log.info("查询导购与本批次会员不存在好友关系 clerkId:{}", clerkId);
return Collections.emptyMap();
}
return clerkRelateds
.stream()
.collect(Collectors.toMap(TabHaobanExternalClerkRelated::getMemberId, item -> 1, (v1, v2) -> v1));
}
/**
......@@ -123,9 +192,41 @@ public class PotentialCustomerServiceImpl implements PotentialCustomerService {
if (temp.getId() == null) {
temp.setId(UniqueIdUtils.uniqueLong());
potentialCustomerMapper.insert(temp);
}else {
} else {
potentialCustomerMapper.update(temp);
}
return temp.getId();
}
/**
* 销售线索通知
*
* @param context
*/
@Override
public void sendPotentialCustomerNotice(PotentialCustomerNotifyContext context) {
log.info("处理企业{}下的销售线索通知", context.getEnterpriseId());
// 根据企业id + 时间 循环查询时间段内的有新互动记录的导购id 去重
InteractRecordQO searchQo = new InteractRecordQO();
searchQo.setEnterpriseId(context.getEnterpriseId());
searchQo.setStartTime(context.getStartTime());
searchQo.setEndTime(context.getEndTime());
List<PotentialCustomerStaticsBO> customerStaticsBos = interactRecordService.staticsClerkNewInteractRecord(searchQo);
if (CollectionUtils.isEmpty(customerStaticsBos)) {
log.info("企业下不存在新增线索的导购 {}", JSON.toJSONString(context));
return;
}
context.setCustomerStaticsBos(customerStaticsBos);
// 获取导购与成员关联关联关系
potentialCustomerNotifyBuilder.buildClerkRelations(context);
// 获取成员的主门店
// 区经 忽略
potentialCustomerNotifyBuilder.filterAreaManage(context);
// 构建应用内消息
potentialCustomerNotifyBuilder.sendHaoBanNotifyMessage(context);
// 如果该导购id是成员在主门店时的导购id 发送应用消息
potentialCustomerNotifyBuilder.sendApplicationMessage(context);
}
}
......@@ -112,7 +112,6 @@ public class InteractRecordMessageService {
potentialCustomerBO.setDurationTime(interactRecordBO.getDurationTime());
potentialCustomerBO.setTimes(interactRecordBO.getTimes());
potentialCustomerService.saveOrUpdatePotentialCustomer(potentialCustomerBO);
// 累计 该导购 + 时间段内 未读数量
}
}
......
......@@ -501,4 +501,23 @@ public class ExternalClerkRelatedServiceImpl implements ExternalClerkRelatedServ
public List<String> queryExternalRelatedWithStaffId(String staffId) {
return this.mapper.queryExternalUserIdWithStaffId(staffId);
}
/***
* 查询会员与导购的关系
* @param clerkId
* @param memberIds
* @return
*/
@Override
public List<TabHaobanExternalClerkRelated> queryClerkMemberRelations(String clerkId, List<String> memberIds) {
if (StringUtils.isBlank(clerkId)) {
logger.info("查询导购与会员的关系,导购id不存在 {}", clerkId);
return Collections.emptyList();
}
if (CollectionUtils.isEmpty(memberIds)) {
logger.info("查询导购与会员的关系,会员id数组为空 {}", clerkId);
return Collections.emptyList();
}
return this.mapper.queryClerkMemberRelations(clerkId, memberIds);
}
}
package com.gic.haoban.manage.service.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
......@@ -421,7 +420,7 @@ public class StaffClerkRelationServiceImpl implements StaffClerkRelationService
* @return
*/
@Override
public List<StaffClerkRelationDTO> listAllRelationDtosByEnterpriseId(String enterpriseId) {
return this.mapper.listAllRelationDtosByEnterpriseId(enterpriseId);
public List<String> listAllClerkIdsByEnterpriseId(String enterpriseId) {
return this.mapper.listAllClerkIdsByEnterpriseId(enterpriseId);
}
}
......@@ -9,6 +9,7 @@ import com.gic.haoban.manage.api.service.content.PotentialCustomerApiService;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerBO;
import com.gic.haoban.manage.service.pojo.qo.content.PotentialCustomerQO;
import com.gic.haoban.manage.service.service.content.PotentialCustomerService;
import com.gic.haoban.manage.service.service.content.adaptor.InteractRecordBuilder;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -28,6 +29,8 @@ public class PotentialCustomerApiServiceImpl implements PotentialCustomerApiServ
@Autowired
PotentialCustomerService potentialCustomerService;
@Autowired
InteractRecordBuilder interactRecordBuilder;
/**
* 查询销售线索记录
......@@ -50,6 +53,8 @@ public class PotentialCustomerApiServiceImpl implements PotentialCustomerApiServ
.map(item -> {
PotentialCustomerDTO temp = new PotentialCustomerDTO();
BeanUtils.copyProperties(item, temp);
temp.setPotentialCustomerId(item.getId());
temp.setDesc(interactRecordBuilder.buildDesc(item.getChannelSource(), item.getEventType()));
return temp;
})
.collect(Collectors.toList());
......@@ -70,6 +75,8 @@ public class PotentialCustomerApiServiceImpl implements PotentialCustomerApiServ
if (potentialCustomerBO == null) {
return ServiceResponse.failure("-701", "数据不存在");
}
potentialCustomerBO.setSeeFlag(potentialCustomerMarkRecordDTO.getSeeFlag());
potentialCustomerBO.setStarFlag(potentialCustomerMarkRecordDTO.getStarFlag());
potentialCustomerService.markPotentialCustomer(potentialCustomerBO);
return ServiceResponse.success(potentialCustomerBO.getId());
}
......
package com.gic.haoban.manage.service.service.out.impl.content.task;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.DateUtil;
......@@ -10,18 +11,22 @@ import com.gic.haoban.manage.api.enums.content.MaterialReportType;
import com.gic.haoban.manage.api.enums.content.TriggerCustomerChannelType;
import com.gic.haoban.manage.api.service.content.task.QywxGroupMsgTaskApiService;
import com.gic.haoban.manage.service.pojo.bo.content.GroupMessageInfoBo;
import com.gic.haoban.manage.service.pojo.bo.content.context.PotentialCustomerNotifyContext;
import com.gic.haoban.manage.service.service.StaffService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.service.content.GroupMessageService;
import com.gic.haoban.manage.service.service.content.MaterialReportService;
import com.gic.haoban.manage.service.service.content.PotentialCustomerService;
import com.gic.haoban.manage.service.task.RouterConstant;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.Now;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
......@@ -43,6 +48,8 @@ public class QywxGroupMsgTaskApiServiceImpl implements QywxGroupMsgTaskApiServic
private StaffService staffService;
@Autowired
private WxEnterpriseService wxEnterpriseService;
@Autowired
private PotentialCustomerService potentialCustomerService;
@Override
public ServiceResponse<Void> groupMsgTaskJob(String params) {
......@@ -115,6 +122,7 @@ public class QywxGroupMsgTaskApiServiceImpl implements QywxGroupMsgTaskApiServic
/**
* 发送企业周报/月报素材
*
* @param reportType
* @return
*/
......@@ -153,9 +161,9 @@ public class QywxGroupMsgTaskApiServiceImpl implements QywxGroupMsgTaskApiServic
/**
* 处理单成员素材使用周报/月报
*
* @see RouterConstant#DEAL_ONE_STAFF_MATERIAL_REPORT
* @param params
* @return
* @see RouterConstant#DEAL_ONE_STAFF_MATERIAL_REPORT
*/
@Override
public ServiceResponse<Void> doHandlerMaterialOneStaffReportMQ(String params) {
......@@ -171,6 +179,7 @@ public class QywxGroupMsgTaskApiServiceImpl implements QywxGroupMsgTaskApiServic
/**
* 发送成员使用素材消息MQ
*
* @param materialReportDTO
* @return
*/
......@@ -179,9 +188,71 @@ public class QywxGroupMsgTaskApiServiceImpl implements QywxGroupMsgTaskApiServic
GICMQClientUtil.getClientInstance()
.sendMessage(RouterConstant.DEAL_ONE_STAFF_MATERIAL_REPORT, JSON.toJSONString(materialReportDTO));
return true;
}catch (Exception ex){
} catch (Exception ex) {
log.warn("发送成员使用素材周报/月报MQ异常, 参数: {}", JSON.toJSONString(materialReportDTO), ex);
}
return false;
}
/**
* 销售线索 通知job
*
* @param params
* @return 每半小时通知一次,提醒时间段:当天 8:00~23:00
* 当天23:00~第二天8:00产生的线索动态,第二天 8:00 提醒
* 区经不发应用、小程序消息
* 导购、店长 应用只发主门店数据的应用消息
*/
@Override
public ServiceResponse<Void> potentialCustomerJob(String params) {
Date now = new Date();
log.info("potentialCustomerJob 执行销售线索通知 {}", cn.hutool.core.date.DateUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
int currentHour = cn.hutool.core.date.DateUtil.hour(now, true);
if (currentHour >= 23 || currentHour < 8) {
log.info("当前时间处于消息禁发时间, 忽略{}", cn.hutool.core.date.DateUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
return ServiceResponse.success();
}
List<String> enterpriseIds = groupMessageService.hasMaterialRightEnterprise();
if (CollectionUtils.isEmpty(enterpriseIds)) {
log.info("开通内容权限的企业为空");
return ServiceResponse.success();
}
Date startTime = cn.hutool.core.date.DateUtil.offsetMinute(now, -30).toJdkDate();
// 如果是8点那次的执行 需要获取 23 ~ 8点的数据
if (checkIsTodayFirst(now)) {
log.info("本次执行为当天第一次执行 {}", cn.hutool.core.date.DateUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
Date yesterday = cn.hutool.core.date.DateUtil.yesterday().toJdkDate();
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTime(yesterday);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
startTime = calendar.getTime();
}
for (String enterpriseId : enterpriseIds) {
PotentialCustomerNotifyContext context = PotentialCustomerNotifyContext.builder()
.enterpriseId(enterpriseId)
.startTime(startTime)
.endTime(now)
.build();
potentialCustomerService.sendPotentialCustomerNotice(context);
}
return ServiceResponse.success();
}
/**
* 判断是否是当天第一次
* 执行时间处于 8:00 ~ 8:30
*
* @param now
* @return
*/
int hour_sec = 30 * 60 + 1;
private boolean checkIsTodayFirst(Date now) {
DateTime temp = cn.hutool.core.date.DateUtil.offsetSecond(now, -(hour_sec + 1));
return cn.hutool.core.date.DateUtil.hour(temp, true) < 8;
}
}
......@@ -768,4 +768,15 @@
and status_flag in (1, 3, 4);
</select>
<select id="queryClerkMemberRelations" resultMap="BaseResultMap">
select <include refid="Base_Column_List"/>
from tab_haoban_external_clerk_related
where clerk_id = #{clerkId}
and status_flag in (1, 3, 4)
and member_id in
<foreach collection="memberIds" item="memberId" open="(" close=")" separator=",">
#{memberId}
</foreach>
</select>
</mapper>
\ No newline at end of file
......@@ -447,9 +447,10 @@
</if>
</select>
<select id="listAllRelationDtosByEnterpriseId" resultType="com.gic.haoban.manage.api.dto.StaffClerkRelationDTO">
<include refid="leftJoinStaffSQL"/>
where a.enterprise_id = #{wxEnterpriseId} and a.status_flag=1 and b.status_flag = 1
<select id="listAllClerkIdsByEnterpriseId" resultType="java.lang.String">
select a.clerk_id clerkId
from tab_haoban_staff_clerk_relation a inner join tab_haoban_staff b on b.staff_id = a.staff_id
where a.enterprise_id = #{enterpriseId} and a.status_flag=1 and b.status_flag = 1
</select>
</mapper>
\ No newline at end of file
......@@ -268,9 +268,32 @@
<if test="startTime != null">
and create_time >= #{startTime}
</if>
<if test="endTime != null">
and create_time <![CDATA[ <= ]]> #{endTime}
</if>
</where>
order by id desc
</select>
<select id="staticsClerkInteractRecordNew" resultType="com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerStaticsBO">
select clerk_id clerkId, count(1) num
from tab_haoban_interact_record
where delete_flag = 0
<if test="clerkId != null and clerkId != ''">
and clerk_id = #{clerkId}
</if>
<if test="enterpriseId != null and enterpriseId != ''">
and enterprise_id = #{enterpriseId}
</if>
<if test="startTime != null">
and create_time >= #{startTime}
</if>
<if test="endTime != null">
and create_time <![CDATA[ <= ]]> #{endTime}
</if>
group by clerk_id
order by null
</select>
</mapper>
......@@ -18,6 +18,7 @@
<result property="times" column="times" jdbcType="INTEGER"/>
<result property="memberName" column="member_name" jdbcType="VARCHAR"/>
<result property="memberNickName" column="member_nick_name" jdbcType="VARCHAR"/>
<result property="memberImageUrl" column="member_image_url" jdbcType="VARCHAR"/>
<result property="memberPhone" column="member_phone" jdbcType="VARCHAR"/>
<result property="dealRecordNum" column="deal_record_num" jdbcType="INTEGER"/>
<result property="starFlag" column="star_flag" jdbcType="INTEGER"/>
......@@ -42,6 +43,7 @@
times,
member_name,
member_nick_name,
member_image_url,
member_phone,
deal_record_num,
star_flag,
......@@ -54,28 +56,7 @@
<!--查询单个-->
<select id="queryById" resultMap="TabHaobanPotentialCustomerMap">
select id,
enterprise_id,
member_id,
union_id,
clerk_id,
biz_id,
biz_type,
store_id,
channel_source,
event_type,
duration_time,
times,
member_name,
member_nick_name,
member_phone,
deal_record_num,
star_flag,
see_flag,
last_access_time,
delete_flag,
create_time,
update_time
select <include refid="baseSql"/>
from tab_haoban_potential_customer
where id = #{id} and clerk_id = #{clerkId} and delete_flag = 0
</select>
......@@ -155,64 +136,28 @@
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into tab_haoban_potential_customer(id, enterprise_id, member_id, union_id, clerk_id, biz_id, biz_type,
store_id, channel_source, event_type, duration_time, times, member_name,
member_nick_name, member_phone, deal_record_num, star_flag, see_flag,
member_nick_name, member_image_url, member_phone, deal_record_num, star_flag, see_flag,
last_access_time, delete_flag, create_time, update_time)
values (#{id}, #{enterpriseId}, #{memberId}, #{unionId}, #{clerkId}, #{bizId}, #{bizType}, #{storeId},
#{channelSource}, #{eventType}, #{durationTime}, #{times},#{memberName}, #{memberNickName}, #{memberPhone},
#{channelSource}, #{eventType}, #{durationTime}, #{times},#{memberName}, #{memberNickName}, #{memberImageUrl}, #{memberPhone},
#{dealRecordNum}, #{starFlag}, #{seeFlag}, #{lastAccessTime}, #{deleteFlag}, #{createTime},
#{updateTime})
</insert>
<insert id="insertBatch" keyProperty="id" useGeneratedKeys="true">
insert into tab_haoban_potential_customer(enterprise_id, member_id, union_id, clerk_id, biz_id, biz_type,
store_id, channel_source, event_type, duration_time, times, member_name, member_nick_name, member_phone,
insert into tab_haoban_potential_customer(id, enterprise_id, member_id, union_id, clerk_id, biz_id, biz_type,
store_id, channel_source, event_type, duration_time, times, member_name, member_nick_name, member_image_url, member_phone,
deal_record_num, star_flag, see_flag, last_access_time, delete_flag, create_time, update_time)
values
<foreach collection="entities" item="entity" separator=",">
(#{entity.enterpriseId}, #{entity.memberId}, #{entity.unionId}, #{entity.clerkId}, #{entity.bizId},
(#{entity.id}, #{entity.enterpriseId}, #{entity.memberId}, #{entity.unionId}, #{entity.clerkId}, #{entity.bizId},
#{entity.bizType}, #{entity.storeId}, #{entity.channelSource}, #{entity.eventType}, #{entity.durationTime},#{entity.times},
#{entity.memberName}, #{entity.memberNickName}, #{entity.memberPhone}, #{entity.dealRecordNum},
#{entity.memberName}, #{entity.memberNickName}, #{entity.memberImageUrl}, #{entity.memberPhone}, #{entity.dealRecordNum},
#{entity.starFlag}, #{entity.seeFlag}, #{entity.lastAccessTime}, #{entity.deleteFlag}, #{entity.createTime},
#{entity.updateTime})
</foreach>
</insert>
<insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true">
insert into tab_haoban_potential_customer(enterprise_id, member_id, union_id, clerk_id, biz_id, biz_type,
store_id, channel_source, event_type, duration_time, times, member_name, member_nick_name, member_phone,
deal_record_num, star_flag, see_flag, last_access_time, delete_flag, create_time, update_time)
values
<foreach collection="entities" item="entity" separator=",">
(#{entity.enterpriseId}, #{entity.memberId}, #{entity.unionId}, #{entity.clerkId}, #{entity.bizId},
#{entity.bizType}, #{entity.storeId}, #{entity.channelSource}, #{entity.eventType}, #{entity.durationTime}, #{times},
#{entity.memberName}, #{entity.memberNickName}, #{entity.memberPhone}, #{entity.dealRecordNum},
#{entity.starFlag}, #{entity.seeFlag}, #{entity.lastAccessTime}, #{entity.deleteFlag}, #{entity.createTime},
#{entity.updateTime})
</foreach>
on duplicate key update
enterprise_id = values(enterprise_id),
member_id = values(member_id),
union_id = values(union_id),
clerk_id = values(clerk_id),
biz_id = values(biz_id),
biz_type = values(biz_type),
store_id = values(store_id),
channel_source = values(channel_source),
event_type = values(event_type),
duration_time = values(duration_time),
times = #{times},
member_name = values(member_name),
member_nick_name = values(member_nick_name),
member_phone = values(member_phone),
deal_record_num = values(deal_record_num),
star_flag = values(star_flag),
see_flag = values(see_flag),
last_access_time = values(last_access_time),
delete_flag = values(delete_flag),
create_time = values(create_time),
update_time = values(update_time)
</insert>
<!--通过主键修改数据-->
<update id="update">
update tab_haoban_potential_customer
......@@ -312,7 +257,7 @@
<if test="starFlag != null">
and customer.star_flag = #{starFlag}
</if>
<if test="hasMemberRelation = null">
<if test="hasMemberRelation != null">
<!-- 企微好友 -->
and related.clerk_id is not null
</if>
......
import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.DateUtil;
import com.gic.haoban.manage.api.dto.content.log.TriggerCustomerDetailLogDTO;
import com.gic.haoban.manage.api.enums.content.ClerkShareMaterialType;
......@@ -7,8 +8,10 @@ import com.gic.haoban.manage.api.enums.content.TriggerCustomerChannelType;
import com.gic.haoban.manage.api.service.content.task.QywxGroupMsgTaskApiService;
import com.gic.haoban.manage.service.pojo.bo.content.ClerkShareLogBO;
import com.gic.haoban.manage.service.pojo.bo.content.GroupMessageInfoBo;
import com.gic.haoban.manage.service.pojo.bo.content.context.PotentialCustomerNotifyContext;
import com.gic.haoban.manage.service.service.content.ClerkShareLogService;
import com.gic.haoban.manage.service.service.content.GroupMessageService;
import com.gic.haoban.manage.service.service.content.PotentialCustomerService;
import com.squareup.moshi.Json;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -33,6 +36,9 @@ public class GroupMessageServiceTest {
private ClerkShareLogService clerkShareLogService;
@Autowired
private QywxGroupMsgTaskApiService qywxGroupMsgTaskApiService;
@Autowired
PotentialCustomerService potentialCustomerService;
String eid = "ff8080815dacd3a2015dacd3ef5c0000";
String wxEid = "ca66a01b79474c40b3e7c7f93daf1a3b";
......@@ -70,4 +76,14 @@ public class GroupMessageServiceTest {
groupMessageInfoBo.setEndTime(currentTime);
groupMessageService.handlerGroupMessage(groupMessageInfoBo);
}
@Test
public void potentialCustomerMessageTest(){
PotentialCustomerNotifyContext context = PotentialCustomerNotifyContext.builder()
.enterpriseId(eid)
.startTime(cn.hutool.core.date.DateUtil.beginOfDay(new Date()))
.endTime(cn.hutool.core.date.DateUtil.endOfDay(new Date()))
.build();
potentialCustomerService.sendPotentialCustomerNotice(context);
}
}
import cn.hutool.crypto.digest.MD5;
import com.gic.haoban.manage.api.dto.chat.ChatOwnerTotalDTO;
import com.gic.haoban.manage.api.dto.qdto.chat.GroupChatPlanSearchQDTO;
import com.gic.haoban.manage.api.enums.content.MaterialInteractRecordEventType;
import com.gic.haoban.manage.api.enums.content.TriggerCustomerChannelType;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatPlanOwnerLogMapper;
import com.gic.haoban.manage.service.pojo.bo.content.message.InteractRecordMessageBO;
import com.gic.haoban.manage.service.pojo.qo.content.InteractRecordQO;
import com.gic.haoban.manage.service.service.content.InteractRecordService;
......@@ -13,6 +16,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
......@@ -69,4 +73,14 @@ public class InteractRecordTest {
System.out.println(MD5.create().digestHex("song"));
}
}
@Autowired
GroupChatPlanOwnerLogMapper groupChatPlanOwnerLogMapper;
@Test
public void caseWhenTest(){
GroupChatPlanSearchQDTO search = new GroupChatPlanSearchQDTO();
search.setWxEnterpriseId("f5f8c78e395e4ca1a493707316096097");
List<ChatOwnerTotalDTO> chatOwnerTotalDTOS = groupChatPlanOwnerLogMapper.listOwnerLogPageForWxaTotal(search);
}
}
import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.Page;
import com.gic.haoban.manage.service.pojo.bo.content.PotentialCustomerBO;
import com.gic.haoban.manage.service.pojo.qo.content.PotentialCustomerQO;
import com.gic.haoban.manage.service.service.content.PotentialCustomerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @Author MUSI
* @Date 2023/3/30 10:15 PM
* @Description
* @Version
**/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-conf.xml"})
public class PotentialCustomerServiceTest {
@Autowired
PotentialCustomerService potentialCustomerService;
String eid = "ff8080815dacd3a2015dacd3ef5c0000";
String wxEid = "ca66a01b79474c40b3e7c7f93daf1a3b";
String staffId = "e608b51b267e4943b87e222a343b4f25";
String clerkId = "fbc508e395f846ef9005852c420e1c4f";
String memberId = "ff8080818147efc8018148d1759903c8";
@Test
public void queryPotentialCustomerTest(){
PotentialCustomerQO potentialCustomerQO = new PotentialCustomerQO();
potentialCustomerQO.setEnterpriseId(eid);
potentialCustomerQO.setWxEnterpriseId(wxEid);
potentialCustomerQO.setClerkId(clerkId);
potentialCustomerQO.setSeeFlag(0);
potentialCustomerQO.setStarFlag(0);
Page<PotentialCustomerBO> customerBOPage =
potentialCustomerService.queryPotentialCustomerPage(potentialCustomerQO);
System.out.println(JSON.toJSONString(customerBOPage));
}
}
......@@ -4,16 +4,18 @@ import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.webapi.reponse.RestResponse;
import com.gic.content.api.dto.material.ContentGoodsDTO;
import com.gic.content.api.dto.material.ContentMaterialLandingPageInfoDTO;
import com.gic.content.api.qdto.material.ContentMaterialLandingPageQDTO;
import com.gic.content.api.service.ContentMaterialShareApiService;
import com.gic.haoban.common.utils.StringUtil;
import com.gic.haoban.manage.api.dto.content.log.ClerkShareMaterialLogDTO;
import com.gic.haoban.manage.api.enums.content.ShareBizType;
import com.gic.haoban.manage.api.service.content.MaterialShareLogApiService;
import com.gic.haoban.manage.web.qo.content.ContentMaterialBaseQO;
import com.gic.haoban.manage.web.qo.content.log.MaterialShareLogQO;
import com.gic.haoban.manage.web.vo.content.SimpleGoodsInfoVO;
import com.gic.haoban.manage.web.vo.content.share.ContentMaterialLandingPageVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -24,6 +26,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
/**
* 导购分享素材 与素材落地页
*/
......@@ -83,6 +88,18 @@ public class ClerkMaterialShareController {
return RestResponse.failure(serviceResponse.getCode(), serviceResponse.getMessage());
}
ContentMaterialLandingPageVO materialLandingPageVO = EntityUtil.changeEntityByJSON(ContentMaterialLandingPageVO.class, serviceResponse.getResult());
List<ContentGoodsDTO> goodsInfos = serviceResponse.getResult().getGoodsInfos();
if (CollectionUtils.isNotEmpty(goodsInfos)) {
List<SimpleGoodsInfoVO> goodsInfoVOS = goodsInfos.stream()
.map(item -> {
SimpleGoodsInfoVO temp = new SimpleGoodsInfoVO();
BeanUtils.copyProperties(item, temp);
temp.setGoodsImg(item.getGoodsImageUrl());
return temp;
})
.collect(Collectors.toList());
materialLandingPageVO.setGoodsInfos(goodsInfoVOS);
}
return RestResponse.successResult(materialLandingPageVO);
}
}
......@@ -121,7 +121,13 @@ public class ContentMaterialController {
}
if (contentMaterialQO.getSearchType() != null && contentMaterialQO.getSearchType().equals(1)) {
if (StringUtils.isNotBlank(contentMaterialQO.getSearch())) {
// 搜索条件需要置为空
contentMaterialPageFrontQDTO.setKeyWord(null);
List<String> goodsIds = goodsInfoAdaptor.queryGoodsIdWithSearch(contentMaterialQO.getEnterpriseId(), contentMaterialQO.getSearch());
if (CollectionUtils.isEmpty(goodsIds)) {
log.info("搜索商品不存在 {}", contentMaterialQO.getSearch());
return RestResponse.successResult(new Page<>());
}
contentMaterialPageFrontQDTO.setGoodsIdList(goodsIds);
}
}
......
......@@ -81,14 +81,4 @@ public class InteractRecordController {
return RestResponse.successResult(result);
}
// /**
// * 查询互动记录扩展信息
// * @param interactRecordQO
// * @return
// */
// @RequestMapping(path = "/relation/extend/info")
// public RestResponse<InteractRecordExtendInfoVO> queryInteractRecordRelationGoods(InteractRecordQO interactRecordQO) {
// return RestResponse.successResult();
// }
}
package com.gic.haoban.manage.web.controller.content;
import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.webapi.reponse.RestResponse;
......@@ -10,11 +11,13 @@ import com.gic.haoban.manage.api.dto.qdto.content.PotentialCustomerQDTO;
import com.gic.haoban.manage.api.enums.content.ShareBizType;
import com.gic.haoban.manage.api.service.content.PotentialCustomerApiService;
import com.gic.haoban.manage.web.controller.content.adaptor.ContentMaterialAdaptor;
import com.gic.haoban.manage.web.controller.content.adaptor.MaterialDataAdaptor;
import com.gic.haoban.manage.web.qo.content.potential.PotentialCustomerMarkRecordVO;
import com.gic.haoban.manage.web.qo.content.potential.PotentialCustomerQO;
import com.gic.haoban.manage.web.vo.content.ContentMaterialInfoVO;
import com.gic.haoban.manage.web.vo.content.potential.PotentialCustomerVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
......@@ -23,6 +26,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
......@@ -37,6 +41,10 @@ public class PotentialCustomerController {
private PotentialCustomerApiService potentialCustomerApiService;
@Autowired
ContentMaterialAdaptor contentMaterialAdaptor;
@Autowired
MaterialDataAdaptor materialDataAdaptor;
/**
* 销售线索列表
*
......@@ -51,8 +59,13 @@ public class PotentialCustomerController {
ServiceResponse<Page<PotentialCustomerDTO>> serviceResponse =
potentialCustomerApiService.queryPotentialCustomer(searchQDTO);
if (!serviceResponse.isSuccess()) {
log.info("查询销售线索异常 {}", JSON.toJSONString(serviceResponse));
return RestResponse.failure(serviceResponse.getCode(), serviceResponse.getMessage());
}
if (CollectionUtils.isEmpty(serviceResponse.getResult().getResult())) {
log.info("查询销售线索为空 params: {}", JSON.toJSONString(potentialCustomerQO));
return RestResponse.successResult();
}
List<PotentialCustomerDTO> customerDTOS = serviceResponse.getResult().getResult();
List<Long> materialIds = customerDTOS
.stream()
......@@ -61,6 +74,13 @@ public class PotentialCustomerController {
.collect(Collectors.toList());
Map<Long, ContentMaterialBaseDTO> materialInfoMap = contentMaterialAdaptor.queryMaterialInfoMap(potentialCustomerQO.getEnterpriseId(), materialIds);
List<String> memberIds = customerDTOS
.stream()
.filter(item -> ShareBizType.MATERIAL.getCode().equals(item.getBizType()))
.map(PotentialCustomerDTO::getMemberId)
.collect(Collectors.toList());
Map<String, Integer> memberVisitMap =
materialDataAdaptor.queryMemberVisitMap(potentialCustomerQO.getEnterpriseId(), null, potentialCustomerQO.getClerkId(), memberIds);
List<PotentialCustomerVO> customerVOS = customerDTOS
.stream()
.map(item -> {
......@@ -73,6 +93,8 @@ public class PotentialCustomerController {
BeanUtils.copyProperties(contentMaterialBaseDTO, contentMaterialInfoVO);
temp.setContentMaterialInfoVO(contentMaterialInfoVO);
}
Integer visitNum = memberVisitMap.get(item.getMemberId());
temp.setVisitNum(Optional.ofNullable(visitNum).orElse(0));
return temp;
})
.collect(Collectors.toList());
......@@ -83,7 +105,6 @@ public class PotentialCustomerController {
}
/**
* 标记销售线索为已看
*
......
......@@ -11,6 +11,7 @@ import com.gic.haoban.manage.web.vo.content.statistics.MaterialClerkUsedDataVO;
import com.gic.haoban.manage.web.vo.content.statistics.MaterialDataOverviewVO;
import com.gic.haoban.manage.web.vo.content.statistics.MaterialStoreUsedDataVO;
import com.gic.haoban.manage.web.vo.content.statistics.bo.MaterialTodayDataBO;
import com.gic.haoban.manage.web.vo.content.statistics.bo.MemberVisitMaterialBO;
import com.gic.haoban.manage.web.vo.content.statistics.report.MaterialPersonalUsedDataVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
......@@ -22,6 +23,8 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @Author MUSI
......@@ -79,6 +82,11 @@ public class MaterialDataAdaptor {
*/
private static final String MATERIAL_AREA_MONTH_DATA = "data_cms_store_month_report_total";
/**
* 会员最近30天访问素材总数
*/
private static final String MEMBER_RECENTLY_30_DAY_VISIT = "data_matl_haoban_user_30day_stats_real";
/**
* 查询素材首页使用数据
......@@ -340,6 +348,7 @@ public class MaterialDataAdaptor {
/**
* 取经数据概览数据
*
* @return
*/
public MaterialStoreUsedDataVO queryMaterialAreaOverviewData(String enterpriseId, String clerkId,
......@@ -397,4 +406,37 @@ public class MaterialDataAdaptor {
return Collections.emptyMap();
}
/**
* 会员最近30天的浏览素材数量
*
* @param enterpriseId
* @param storeId
* @param clerkId
* @param memberIds
* @return
*/
public Map<String, Integer> queryMemberVisitMap(String enterpriseId, String storeId, String clerkId, List<String> memberIds) {
Map<String, Object> params = new HashMap<>();
Map<String, Object> inlineParams = new HashMap<>();
params.put("inFields", inlineParams);
if (StringUtils.isNotBlank(clerkId)) {
inlineParams.put("clerkId", clerkId);
}
inlineParams.put("enterprsieId", enterpriseId);
inlineParams.put("customerId", StringUtils.join(memberIds, ","));
Map<String, Object> result = this.doHttp(JSON.toJSONString(params), MEMBER_RECENTLY_30_DAY_VISIT);
if (result.get("data") == null) {
return Collections.emptyMap();
}
List<MemberVisitMaterialBO> memberVisitMaterialBos = JSON.parseArray(JSON.toJSONString(result.get("data")), MemberVisitMaterialBO.class);
if (CollectionUtils.isEmpty(memberVisitMaterialBos)) {
return Collections.emptyMap();
}
return memberVisitMaterialBos
.stream()
.collect(Collectors.toMap(MemberVisitMaterialBO::getCustomerId, item -> Optional.ofNullable(item.getMatlNum30Day())
.map(Integer::new).orElse(0), (v1, v2) -> v1));
}
}
......@@ -34,6 +34,11 @@ public class MaterialClerkInfo implements Serializable {
private String clerkCode;
/**
* 导购头像图片
*/
private String clerkImgUrl;
/**
* 与会员是否是好友关系
* 1 是; 0否
*/
......@@ -91,4 +96,12 @@ public class MaterialClerkInfo implements Serializable {
public void setClerkHmUrl(String clerkHmUrl) {
this.clerkHmUrl = clerkHmUrl;
}
public String getClerkImgUrl() {
return clerkImgUrl;
}
public void setClerkImgUrl(String clerkImgUrl) {
this.clerkImgUrl = clerkImgUrl;
}
}
......@@ -25,11 +25,16 @@ public class PotentialCustomerVO implements Serializable {
private Long potentialCustomerId;
/**
* 会员
* 会员
*/
private String memberName;
/**
* 会员昵称
*/
private String memberNickName;
/**
* 会员头像
*/
private String memberImageUrl;
......
package com.gic.haoban.manage.web.vo.content.statistics.bo;
import lombok.Data;
import java.io.Serializable;
/**
* @Author MUSI
* @Date 2023/3/30 10:59 PM
* @Description
* @Version
**/
@Data
public class MemberVisitMaterialBO implements Serializable {
private String enterpriseId;
private String clerkId;
/**
* 会员id
*/
private String customerId;
/**
* 最近30天访问素材数
*/
private String matlNum30Day;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment