动态任务自动分配逻辑提交

master
yqy 2 years ago
parent 7734c74ce6
commit 410efaa035

@ -0,0 +1,20 @@
package com.baiye.model.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class DynamicTaskDistributionDTO {
@NotNull(message = "任务ID不能为空")
private Long taskId;
@ApiModelProperty("是否开启了自动分配 0:关闭 1:开启")
@NotNull(message = "是否开启自动分配,不能为空")
private Integer isOpen;
List<DynamicTaskDistributionUserDTO> dynamicTaskDistributionUserDTOS;
}

@ -0,0 +1,11 @@
package com.baiye.model.dto;
import lombok.Data;
@Data
public class DynamicTaskDistributionUserDTO {
private Long id;
private Integer ratio;
}

@ -64,4 +64,8 @@ public class DynamicTaskDto {
*
*/
private String tag;
/**
*
*/
private String remark;
}

@ -77,5 +77,5 @@ public class BaseClue implements Serializable {
@ApiModelProperty(value = "此次线索是否加密手机号 0:不加密 1:加密")
@Column(name = "is_encryption")
private Integer isEncryption;
private Integer isEncryption = 0;
}

@ -28,9 +28,11 @@ public class BaseClueMiddle implements Serializable {
@ApiModelProperty(value = "线索阶段0新线索 1待沟通 2有意向 3已加微信 4无意向 5:邀约中 6到场7已成交")
@Column(name = "clue_stage")
private Integer clueStage;
@ApiModelProperty(value = "线索阶段修改时间")
@Column(name = "clue_stage_time")
private Date clueStageTime;
@ApiModelProperty(value = "线索通话状态0无状态 1未接听 2已接通")
@Column(name = "clue_call_status")
private Integer clueCallStatus;
@ -53,9 +55,11 @@ public class BaseClueMiddle implements Serializable {
@Convert(converter = JpaConverterListJson.class)
private List<String> sourceLabel;
@ApiModelProperty(value = "打标时间")
@Column(name = "label_time")
private Date labelTime;
@ApiModelProperty(value = "创建时间")
@Column(name = "create_time")
@CreationTimestamp
@ -84,5 +88,5 @@ public class BaseClueMiddle implements Serializable {
@ApiModelProperty(value = "线索来源 1-表单推送 2-个人上传 3-抖音 4-投流 5-拓客 6-拓客回流 7-投流回流")
@Column(name = "clue_type")
private Integer clueType=0;
private Integer clueType = 0;
}

@ -85,4 +85,8 @@ public class BaseTask implements Serializable {
@Column(name = "is_form")
@NotNull(groups = AddGroup.class, message = "任务状态不能为空")
private Integer isForm=0;
@ApiModelProperty(value = "是否开启了自动分配 0:关闭 1:开启")
@Column(name = "is_open")
private Integer isOpen = 0;
}

@ -144,6 +144,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/api/users/admin").permitAll()
.antMatchers("/api/task/query").permitAll()
.antMatchers("/api/task/sendErrMessage").permitAll()
.antMatchers("/api/task/findTaskDistribution").permitAll()
.antMatchers("/api/organize/queryAll").permitAll()
.antMatchers("/api/organize/findNameById").permitAll()
.antMatchers("/api/organize/findOrganizeIdByMember").permitAll()

@ -0,0 +1,48 @@
package com.baiye.modules.system.domain;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
/**
* @author yqy
*
*/
@Entity
@Data
@Table(name = "tb_task_user_distribution")
@EntityListeners(AuditingEntityListener.class)
public class TaskUserDistribution {
@Id
@Column(name = "id")
@ApiModelProperty(value = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "task_id")
@ApiModelProperty(value = "动态任务id")
@JsonSerialize(using = ToStringSerializer.class)
private Long taskId;
@Column(name = "user_id")
@ApiModelProperty(value = "用户id")
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
@Column(name = "ratio")
@ApiModelProperty(value = "分配比率")
private Integer ratio = 0;
@Transient
@ApiModelProperty(value = "用户名称")
private String userName;
@Transient
@ApiModelProperty(value = "是否开启了自动分配 0:关闭 1:开启")
private Integer isOpen;
}

@ -0,0 +1,20 @@
package com.baiye.modules.system.repository;
import com.baiye.modules.system.domain.TaskUserDistribution;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author YQY
* @date 2022-11-02
*/
@Repository
public interface TaskUserDistributionRepository extends JpaRepository<TaskUserDistribution, Long>, JpaSpecificationExecutor<TaskUserDistribution> {
List<TaskUserDistribution> findByTaskId(Long taskId);
void deleteByTaskId(Long taskId);
}

@ -165,8 +165,8 @@ public class OrganizeController {
@ApiOperation("查询所有组和未分配用户")
@GetMapping("/selectAllOrganizeUser")
public ResponseEntity<Map<String, Object>> selectAllOrganizeUser() {
return new ResponseEntity<>(organizeService.selectAllOrganizeUser(), HttpStatus.OK);
public ResponseEntity<Map<String, Object>> selectAllOrganizeUser(@RequestParam(value = "taskId", required = false) Long taskId) {
return new ResponseEntity<>(organizeService.selectAllOrganizeUser(taskId), HttpStatus.OK);
}
@PostMapping("/findNameById")

@ -3,9 +3,10 @@ package com.baiye.modules.system.rest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baiye.http.CommonResponse;
import com.baiye.http.ResponseCode;
import com.baiye.model.dto.DynamicTaskDistributionDTO;
import com.baiye.model.dto.TaskQueryCriteria;
import com.baiye.modules.system.domain.Task;
import com.baiye.modules.system.domain.TaskUserDistribution;
import com.baiye.modules.system.service.TaskService;
import com.baiye.modules.system.service.dto.TaskTagDto;
import com.baiye.socket.WebSocketServer;
@ -20,6 +21,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -54,6 +56,12 @@ public class TaskController {
return new ResponseEntity<>(taskService.query(taskQueryCriteria), HttpStatus.OK);
}
@ApiOperation("查询任务列表")
@GetMapping("/list")
public ResponseEntity<Object> list(TaskQueryCriteria taskQueryCriteria) {
return new ResponseEntity<>(taskService.list(taskQueryCriteria), HttpStatus.OK);
}
@ApiOperation("查询任务详情")
@GetMapping("/queryDetails")
public ResponseEntity<Task> queryDetails(@RequestParam("taskId") Long taskId) {
@ -69,16 +77,16 @@ public class TaskController {
@ApiOperation("未分配前删除任务")
@GetMapping("/del")
public ResponseEntity<Task> delTask(@RequestParam("taskId") Long taskId) {
public CommonResponse<Object> delTask(@RequestParam("taskId") Long taskId) {
taskService.delTask(taskId);
return new ResponseEntity<>(HttpStatus.OK);
return CommonResponse.createBySuccess();
}
@ApiOperation("删除动态任务")
@GetMapping("/delDynamic")
public ResponseEntity<Task> delDynamicTask(@RequestParam("taskId") Long taskId) {
public CommonResponse<Object> delDynamicTask(@RequestParam("taskId") Long taskId) {
taskService.delDynamicTask(taskId);
return new ResponseEntity<>(HttpStatus.OK);
return CommonResponse.createBySuccess();
}
@ApiOperation("websocket发送错误信息")
@ -111,4 +119,17 @@ public class TaskController {
taskService.saveAdBackTask(taskTagDto);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@ApiOperation("新增动态任务(自动)分配比率")
@PostMapping("/addTaskDistribution")
public CommonResponse<Object> addTaskDistribution(@RequestBody @Validated DynamicTaskDistributionDTO dynamicTaskDistributionDTO){
taskService.addTaskDistribution(dynamicTaskDistributionDTO);
return CommonResponse.createBySuccessMessage("操作成功");
}
@ApiOperation("查询动态任务(自动)分配比率")
@GetMapping("/findTaskDistribution")
public CommonResponse<DynamicTaskDistributionDTO> findTaskDistribution(@RequestParam("taskId") Long taskId){
return CommonResponse.createBySuccess(taskService.findTaskDistribution(taskId));
}
}

@ -174,10 +174,10 @@ public interface OrganizeService {
/**
*
*
* @param taskId
* @return
*/
Map<String, Object> selectAllOrganizeUser();
Map<String, Object> selectAllOrganizeUser(Long taskId);
/**
* id

@ -1,7 +1,9 @@
package com.baiye.modules.system.service;
import com.baiye.model.dto.DynamicTaskDistributionDTO;
import com.baiye.model.dto.TaskQueryCriteria;
import com.baiye.modules.system.domain.Task;
import com.baiye.modules.system.domain.TaskUserDistribution;
import com.baiye.modules.system.service.dto.TaskDto;
import com.baiye.modules.system.service.dto.TaskTagDto;
import org.springframework.data.domain.Pageable;
@ -39,6 +41,14 @@ public interface TaskService {
*/
List<TaskDto> query(TaskQueryCriteria taskQueryCriteria);
/**
*
*
* @param taskQueryCriteria
* @return
*/
Object list(TaskQueryCriteria taskQueryCriteria);
/**
*
*
@ -83,4 +93,16 @@ public interface TaskService {
* @param taskTagDto
*/
void saveAdBackTask(TaskTagDto taskTagDto);
/**
* ()
*/
void addTaskDistribution(DynamicTaskDistributionDTO dynamicTaskDistributionDTO);
/**
* ()
*
* @return
*/
DynamicTaskDistributionDTO findTaskDistribution(Long taskId);
}

@ -226,13 +226,21 @@ public interface UserService {
List<User> findUserByExpirationTime(DateTime date, Boolean flag);
/**
*
*
*
* @param userIds
* @return
*/
Map<Long, String> queryName(Set<Long> userIds);
/**
*
*
* @param userIds
* @return
*/
Map<Long, String> queryNickName(Set<Long> userIds);
/**
*
*

@ -48,6 +48,7 @@ public class TaskDto implements Serializable {
private String remark;
private Integer isForm;
private Integer isOpen;
/**
*
*/

@ -58,6 +58,7 @@ public class OrganizeServiceImpl implements OrganizeService {
private final CompanyRepository companyRepository;
private final LabelOrganizeService labelOrganizeService;
private final LabelService labelService;
private final TaskUserDistributionRepository taskUserDistributionRepository;
private final MessageNotificationRepository messageNotificationRepository;
@ -644,22 +645,53 @@ public class OrganizeServiceImpl implements OrganizeService {
}
@Override
public Map<String, Object> selectAllOrganizeUser() {
int i = 1;
Set<Organize> organizeAll = organizeRepository.findByCreateBy(SecurityUtils.getCurrentUserId());
public Map<String, Object> selectAllOrganizeUser(Long taskId) {
Map<String, Object> returnMap = new HashMap<>();
Set<Long> organizeUserAll = new HashSet<>();
// 查询动态任务的分配比率(一个任务下的用户分配比率,用户不会重复)
Map<Long, List<TaskUserDistribution>> userDistributionMap = new HashMap<>();
if (taskId != null) {
List<TaskUserDistribution> taskUserDistributions = taskUserDistributionRepository.findByTaskId(taskId);
if (CollUtil.isNotEmpty(taskUserDistributions)) {
userDistributionMap = taskUserDistributions.stream().collect(Collectors.groupingBy(TaskUserDistribution::getUserId));
}
}
// 查询管理员下所有组
Set<Organize> organizeAll = organizeRepository.findByCreateBy(SecurityUtils.getCurrentUserId());
// 查询组员的用户信息
Set<Long> organizeIds = organizeAll.stream().map(Organize::getId).collect(Collectors.toSet());
List<OrganizeUser> organizeUserList = organizeUserRepository.findByOrganizeIdIn(organizeIds);
Set<Long> userIdList = organizeUserList.stream().map(OrganizeUser::getUserId).collect(Collectors.toSet());
Map<Long, String> userNameMap = userService.queryNickName(userIdList);
// 组员信息根据组ID分类
Map<Long, List<OrganizeUser>> organizeUserMap = organizeUserList.stream().collect(Collectors.groupingBy(OrganizeUser::getOrganizeId));
// 小组组名重复加数字
int i = 1;
for (Organize organize : organizeAll) {
Set<Long> userIdList = organizeUserRepository.findByOrganizeId(organize.getId()).stream().map(OrganizeUser::getUserId).collect(Collectors.toSet());
List<Map<String, Object>> map = packageUser(userIdList);
boolean flag = returnMap.containsKey(organize.getOrganizeName());
String key = organize.getOrganizeName();
String organizeName = organize.getOrganizeName();
// 取出小组下所有的组员
Set<Long> userIds = organizeUserMap.get(organize.getId()).stream().map(OrganizeUser::getUserId).collect(Collectors.toSet());
List<Map<String, Object>> list = new ArrayList<>();
for (Long userId : userIds) {
Map<String, Object> map = new HashMap<>();
map.put("id", userId);
map.put("label", userNameMap.get(userId));
if (taskId != null) {
map.put("ratio", 0);
if (userDistributionMap.containsKey(userId)) {
Integer ratio = userDistributionMap.get(userId).get(0).getRatio();
map.put("ratio", ratio);
}
}
list.add(map);
}
// 如果小组名称重复
boolean flag = returnMap.containsKey(organizeName);
if (flag) {
key = organize.getOrganizeName() + i;
returnMap.put(organizeName + i, list);
i++;
} else {
returnMap.put(organizeName, list);
}
returnMap.put(key, map);
organizeUserAll.addAll(userIdList);
}
return returnMap;
}

@ -6,17 +6,13 @@ import com.baiye.constant.ClueTypeConstants;
import com.baiye.constant.DefaultNumberConstants;
import com.baiye.exception.BadRequestException;
import com.baiye.feign.SourceClueClient;
import com.baiye.model.dto.ClueQueryCriteria;
import com.baiye.model.dto.TaskQueryCriteria;
import com.baiye.model.dto.UserDto;
import com.baiye.modules.system.domain.Label;
import com.baiye.modules.system.domain.OrganizeUser;
import com.baiye.modules.system.domain.Task;
import com.baiye.modules.system.domain.TaskOrganize;
import com.baiye.model.dto.*;
import com.baiye.modules.system.domain.*;
import com.baiye.modules.system.httpRequest.AdBackRequestApi;
import com.baiye.modules.system.repository.OrganizeUserRepository;
import com.baiye.modules.system.repository.TaskOrganizeRepository;
import com.baiye.modules.system.repository.TaskRepository;
import com.baiye.modules.system.repository.TaskUserDistributionRepository;
import com.baiye.modules.system.service.LabelOrganizeService;
import com.baiye.modules.system.service.LabelService;
import com.baiye.modules.system.service.TaskService;
@ -57,6 +53,7 @@ public class TaskServiceImpl implements TaskService {
private final SourceClueClient sourceClueClient;
private final LabelOrganizeService labelOrganizeService;
private final LabelService labelService;
private final TaskUserDistributionRepository taskUserDistributionRepository;
private final AdBackRequestApi adBackRequestApi;
@Value("${snowflake.workerId}")
private int workerId;
@ -106,6 +103,68 @@ public class TaskServiceImpl implements TaskService {
adBackRequestApi.sendTag(taskId, taskTagDto.getUserId(), taskTagDto.getTagStr());
}
@Override
@Transactional(rollbackOn = Exception.class)
public void addTaskDistribution(DynamicTaskDistributionDTO dynamicTaskDistributionDTO) {
Long taskId = dynamicTaskDistributionDTO.getTaskId();
Integer isOpen = dynamicTaskDistributionDTO.getIsOpen();
List<DynamicTaskDistributionUserDTO> dynamicTaskDistributionUserDTOS = dynamicTaskDistributionDTO.getDynamicTaskDistributionUserDTOS();
Task task = taskRepository.findById(taskId).orElseGet(Task::new);
if (isOpen == 0) {
task.setIsOpen(0);
} else {
task.setIsOpen(1);
// 不更新,先删除在添加
taskUserDistributionRepository.deleteByTaskId(taskId);
}
taskRepository.save(task);
if (CollUtil.isNotEmpty(dynamicTaskDistributionUserDTOS)){
int num = dynamicTaskDistributionUserDTOS.stream().mapToInt(DynamicTaskDistributionUserDTO::getRatio).sum();
// 总和是'0'就是开启了平均分配
if (num == DefaultNumberConstants.ONE_HUNDRED || num == DefaultNumberConstants.ZERO_NUMBER){
// 如果0就设置一个平均比率
if (num == DefaultNumberConstants.ZERO_NUMBER){
averageRatio(dynamicTaskDistributionUserDTOS);
}
List<TaskUserDistribution> list = new ArrayList<>();
for (DynamicTaskDistributionUserDTO dynamicTaskDistributionUserDTO : dynamicTaskDistributionUserDTOS) {
TaskUserDistribution taskUserDistribution = new TaskUserDistribution();
taskUserDistribution.setTaskId(taskId);
taskUserDistribution.setUserId(dynamicTaskDistributionUserDTO.getId());
taskUserDistribution.setRatio(dynamicTaskDistributionUserDTO.getRatio());
list.add(taskUserDistribution);
}
taskUserDistributionRepository.saveAll(list);
}else {
throw new BadRequestException("错误请总比例和等于100%");
}
}else {
if (isOpen == 1) {
throw new BadRequestException("请勾选人员,分配比率");
}
}
}
@Override
public DynamicTaskDistributionDTO findTaskDistribution(Long taskId) {
Task task = taskRepository.findById(taskId).orElseGet(Task::new);
List<TaskUserDistribution> distributions = taskUserDistributionRepository.findByTaskId(taskId);
DynamicTaskDistributionDTO dynamicTaskDistributionDTO = new DynamicTaskDistributionDTO();
dynamicTaskDistributionDTO.setTaskId(task.getId());
dynamicTaskDistributionDTO.setIsOpen(task.getIsOpen());
if (CollUtil.isNotEmpty(distributions)) {
List<DynamicTaskDistributionUserDTO> list = new ArrayList<>();
for (TaskUserDistribution distribution : distributions) {
DynamicTaskDistributionUserDTO dynamicTaskDistributionUserDTO = new DynamicTaskDistributionUserDTO();
dynamicTaskDistributionUserDTO.setId(distribution.getUserId());
dynamicTaskDistributionUserDTO.setRatio(distribution.getRatio());
list.add(dynamicTaskDistributionUserDTO);
}
dynamicTaskDistributionDTO.setDynamicTaskDistributionUserDTOS(list);
}
return dynamicTaskDistributionDTO;
}
/**
*
*
@ -193,6 +252,13 @@ public class TaskServiceImpl implements TaskService {
return taskDtos;
}
@Override
public Object list(TaskQueryCriteria taskQueryCriteria) {
Sort sort = Sort.by(Sort.Direction.ASC, "createTime");
List<TaskDto> taskDtos = taskMapper.toDto(taskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, taskQueryCriteria, criteriaBuilder), sort));
return taskDtos;
}
@Override
public Task queryDetails(Long taskId) {
return taskRepository.findById(taskId).orElseGet(Task::new);
@ -290,4 +356,20 @@ public class TaskServiceImpl implements TaskService {
}
}
/**
*
*/
public void averageRatio(List<DynamicTaskDistributionUserDTO> dynamicTaskDistributionUserDTOS){
int size = dynamicTaskDistributionUserDTOS.size();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i % size);
}
Map<Integer, Integer> countMap = list.stream().collect(Collectors.toMap(key -> key, value -> 1, Integer::sum));
for (Integer key : countMap.keySet()) {
DynamicTaskDistributionUserDTO dynamicTaskDistributionUserDTO = dynamicTaskDistributionUserDTOS.get(key);
dynamicTaskDistributionUserDTO.setRatio(countMap.get(key));
}
}
}

@ -292,6 +292,18 @@ public class UserServiceImpl implements UserService {
return map;
}
@Override
public Map<Long, String> queryNickName(Set<Long> userIds) {
Map<Long, String> map = new HashMap<>();
List<User> userList = userRepository.findAllById(userIds);
if (CollUtil.isNotEmpty(userList)) {
for (User user : userList) {
map.put(user.getId(), user.getNickName());
}
}
return map;
}
@Override
public UserDto findUserInfo(Long userId) {
User user = userRepository.findById(userId).orElseGet(User::new);

@ -0,0 +1,29 @@
package com.baiye.feign;
import com.baiye.feign.fallback.AssignDataClientFallback;
import com.baiye.http.CommonResponse;
import com.baiye.model.dto.DistributeDTO;
import com.baiye.model.dto.DistributeResponseDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* @author yqy
* @date : 2022/11/03
*/
@FeignClient(name = "ad-platform-service", fallback = AssignDataClientFallback.class)
public interface AssignDataClient {
String API_PREFIX = "/engine";
/**
*
* @param distributeDTO
* @return
*/
@PostMapping(API_PREFIX + "/allocation")
CommonResponse<List<DistributeResponseDTO>> dataDistribution(@RequestBody DistributeDTO distributeDTO);
}

@ -2,6 +2,7 @@ package com.baiye.feign;
import com.baiye.feign.fallback.TaskClientFallback;
import com.baiye.http.CommonResponse;
import com.baiye.model.dto.DynamicTaskDistributionDTO;
import com.baiye.model.dto.TaskQueryCriteria;
import com.baiye.module.entity.Task;
import io.swagger.annotations.ApiOperation;
@ -39,4 +40,8 @@ public interface TaskClient {
@ApiOperation("修改任务信息")
@PostMapping(PAY_PREFIX + "/update")
CommonResponse<Object> updateTask(@RequestBody Task task);
@ApiOperation("查询动态任务(自动)分配比率")
@GetMapping(PAY_PREFIX + "/findTaskDistribution")
CommonResponse<DynamicTaskDistributionDTO> findTaskDistribution(@RequestParam("taskId") Long taskId);
}

@ -0,0 +1,23 @@
package com.baiye.feign.fallback;
import com.baiye.feign.AssignDataClient;
import com.baiye.http.CommonResponse;
import com.baiye.model.dto.DistributeDTO;
import com.baiye.model.dto.DistributeResponseDTO;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author yqy
* @date : 2022/11/03
*/
@Component
public class AssignDataClientFallback implements AssignDataClient {
@Override
public CommonResponse<List<DistributeResponseDTO>> dataDistribution(DistributeDTO distributeDTO) {
return null;
}
}

@ -2,6 +2,7 @@ package com.baiye.feign.fallback;
import com.baiye.feign.TaskClient;
import com.baiye.http.CommonResponse;
import com.baiye.model.dto.DynamicTaskDistributionDTO;
import com.baiye.model.dto.TaskQueryCriteria;
import com.baiye.module.entity.Task;
import org.springframework.http.ResponseEntity;
@ -33,4 +34,9 @@ public class TaskClientFallback implements TaskClient {
public CommonResponse<Object> updateTask(Task task) {
return null;
}
@Override
public CommonResponse<DynamicTaskDistributionDTO> findTaskDistribution(Long taskId) {
return null;
}
}

@ -208,4 +208,6 @@ public interface ClueMiddleRepository extends JpaRepository<ClueMiddle, Long>, J
*/
@Query(value = " select * from tb_clue_middle as t where t.label_time >= ?1 and t.label_time< ?2 and t.clue_stage in ?3", nativeQuery = true)
List<ClueMiddle> queryClueByClueType(String startTime, String endTime, List<Integer> clueType);
List<ClueMiddle> findByTaskIdAndMemberStatus(Long taskId, int memberStatus);
}

@ -29,10 +29,6 @@ public class Clue extends BaseClue {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ApiModelProperty(value = "此次线索是否加密手机号 0:不加密 1:加密")
@Transient
private Integer isEncryption = 0;
@Transient
@JsonSerialize(using = ToStringSerializer.class)
private Long taskId;

@ -41,7 +41,7 @@ public class ClueRecord implements Serializable {
@Column(name = "status")
private Boolean status;
@ApiModelProperty(value = "上传类型 0:自定义模板 1:UC 2:快手 3:抖音 4:百度 5:动态任务自定义模板")
@ApiModelProperty(value = "上传类型 0:自定义模板 1:UC 2:快手 3:抖音 4:百度 5:动态任务自定义模板 6:拓客任务模板")
@Column(name = "upload_type")
private Integer uploadType;

@ -67,8 +67,12 @@ public class DynamicTaskListener extends AnalysisEventListener<DynamicTaskListen
if (StringUtils.isNotBlank(row.getNid())) {
Clue clue = new Clue();
String nid = row.getNid();
if (nid.length() == 24) {
nid = DecryptPnoUtil.decryptPno(nid);
}
BeanUtils.copyProperties(row, clue);
clue.setNid(nid);
clue.setIsEncryption(DefaultNumberConstants.ZERO_NUMBER);
clue.setOrigin(baseExcelListenerDto.getOrigin());
clue.setRecordId(baseExcelListenerDto.getClueRecordId());
clue.setCreateBy(baseExcelListenerDto.getUserId());

@ -1,5 +1,7 @@
package com.baiye.module.listener;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baiye.constant.DefaultNumberConstants;
@ -8,9 +10,11 @@ import com.baiye.module.entity.Clue;
import com.baiye.module.listener.dto.BaseExcelListenerDto;
import com.baiye.module.listener.dto.TokerListenerDto;
import com.baiye.module.service.ClueService;
import com.baiye.module.service.dto.SecretResponseBean;
import com.baiye.util.DecryptPnoUtil;
import com.google.common.base.Splitter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
@ -19,6 +23,7 @@ import java.util.List;
public class TokerListener extends AnalysisEventListener<TokerListenerDto> {
public final List<TokerListenerDto> rows = new ArrayList<>();
public final List<String> nidList = new ArrayList<>();
private BaseExcelListenerDto baseExcelListenerDto;
/**
* springservice
@ -54,6 +59,7 @@ public class TokerListener extends AnalysisEventListener<TokerListenerDto> {
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
saveData();
rows.clear();
nidList.clear();
}
/**
@ -63,17 +69,47 @@ public class TokerListener extends AnalysisEventListener<TokerListenerDto> {
List<Clue> clues = new ArrayList<>();
for (TokerListenerDto row : rows) {
String nid = row.getNid();
if (StringUtils.isNotBlank(nid)) {
Clue clue = new Clue();
BeanUtils.copyProperties(row, clue);
clue.setOrigin(baseExcelListenerDto.getOrigin());
clue.setRecordId(baseExcelListenerDto.getClueRecordId());
clue.setCreateBy(baseExcelListenerDto.getUserId());
clues.add(clue);
// 批量解密拓客手机号
if (StringUtils.isNotBlank(nid) && nid.length() == DefaultNumberConstants.TWENTY_FOUR) {
nidList.add(nid);
if (nidList.size() == 200) {
cluePackage(clues, nidList);
nidList.clear();
}
}else {
addClue(clues, nid, 0);
}
}
if (clues.size() > 0) {
// 清空集合
if (CollUtil.isNotEmpty(nidList)) {
cluePackage(clues, nidList);
}
if (CollUtil.isNotEmpty(clues)) {
clueService.saveClue(clues, baseExcelListenerDto.getTaskId(), DefaultNumberConstants.FIVE_NUMBER);
}
}
private void cluePackage(List<Clue> clues, List<String> list) {
String join = String.join(",", list);
SecretResponseBean responseBean = DecryptPnoUtil.batchDecryptPno(Base64.encode(join));
String phoneStr = Base64.decodeStr(responseBean.getTels());
if (StringUtils.isNotEmpty(phoneStr)) {
List<String> phoneList = Splitter.on(",").trimResults().splitToList(phoneStr);
for (String phone : phoneList) {
if (StringUtils.isNotEmpty(phone)) {
addClue(clues, phone, 1);
}
}
}
}
private void addClue(List<Clue> clues, String nid, Integer isEncryption) {
Clue clue = new Clue();
clue.setNid(nid);
clue.setIsEncryption(isEncryption);
clue.setOrigin(baseExcelListenerDto.getOrigin());
clue.setRecordId(baseExcelListenerDto.getClueRecordId());
clue.setCreateBy(baseExcelListenerDto.getUserId());
clues.add(clue);
}
}

@ -65,6 +65,7 @@ public class ZdyListener extends AnalysisEventListener<ZdyListenerDto> {
if (StringUtils.isNotBlank(row.getNid())) {
Clue clue = new Clue();
BeanUtils.copyProperties(row, clue);
clue.setIsEncryption(DefaultNumberConstants.ZERO_NUMBER);
clue.setOrigin(baseExcelListenerDto.getOrigin());
clue.setRecordId(baseExcelListenerDto.getClueRecordId());
clue.setCreateBy(baseExcelListenerDto.getUserId());

@ -16,7 +16,7 @@ public class BaseExcelListenerDto {
@ApiModelProperty(value = "用户id")
private Long userId;
@ApiModelProperty(value = "数据来源类型")
@ApiModelProperty(value = "数据来源类型 0:自定义模板 1:UC 2:快手 3:抖音 4:百度 5:动态任务自定义模板 6:拓客任务模板")
private Integer origin;
@ApiModelProperty(value = "任务id")

@ -243,6 +243,7 @@ public interface ClueService {
/**
*
*
* @param taskId
* @return
*/
@ -267,4 +268,9 @@ public interface ClueService {
* @param clueType
*/
void clueBackFlow(Long taskId, Long clueId, Long userId, Integer clueType);
/**
*
*/
void dynamicTaskDistribution(Long taskId);
}

@ -91,7 +91,7 @@ public class ClueRecordServiceImpl implements ClueRecordService {
List<ClueRecord> clueRecords = clueRecordRepository.findByTaskIdAndIsPass(taskId, DefaultNumberConstants.ONE_NUMBER);
// 异步读取文件并更新任务
if (CollUtil.isNotEmpty(clueRecords)) {
fileAnalysisTask.runFileAnalysisTask(clueRecords, clueRecords.get(0).getOldFile());
fileAnalysisTask.runFileAnalysisTask(clueRecords, clueRecords.get(0).getOldFile(), false);
}
}
clueRecordRepository.updateIsPassByTaskIdIn(taskIdList, DefaultNumberConstants.ZERO_NUMBER);

@ -63,6 +63,7 @@ public class ClueServiceImpl implements ClueService {
private final WeChatAddFriendClient weChatAddFriendClient;
private final OceanEngineClueIdRepository oceanEngineClueIdRepository;
private final ClueFailRecordRepository clueFailRecordRepository;
private final AssignDataClient assignDataClient;
private static SimpleDateFormat timeOne = new SimpleDateFormat("yyyyMMddHHmmssSSS");
@ -75,14 +76,6 @@ public class ClueServiceImpl implements ClueService {
while (it.hasNext()) {
Clue clue = it.next();
if (StringUtils.isNotBlank(clue.getNid())) {
// 24位的nid解密,查询时要加*显示的线索
if (clue.getNid().length() == DefaultNumberConstants.TWENTY_FOUR) {
String str = DecryptPnoUtil.decryptPno(clue.getNid());
if (str != null) {
clue.setNid(str);
clue.setIsEncryption(DefaultNumberConstants.ONE_NUMBER);
}
}
boolean bool = MobileUtil.checkPhone(clue.getNid());
if (!bool) {
ClueFailRecord clueFailRecord = new ClueFailRecord();
@ -161,17 +154,16 @@ public class ClueServiceImpl implements ClueService {
public ResponseEntity<Object> queryOrganizeIdList(ClueQueryCriteria clueQueryCriteria) {
//查询此小组下的所有资源id
List<ClueMiddle> clueMiddleList = new ArrayList<>();
List<ClueMiddle> clueMiddleList;
//memberId不等空(组员替换重新分配替换资源下的资源)
if (clueQueryCriteria.getMemberId() != null) {
clueMiddleList = clueMiddleRepository.findByMemberId(clueQueryCriteria.getMemberId());
} else {
clueMiddleList = clueMiddleRepository.findByTaskIdAndOrganizeId(clueQueryCriteria.getTaskId(), clueQueryCriteria.getOrganizeId());
}
if (clueMiddleList.size() > 0) {
if (CollUtil.isNotEmpty(clueMiddleList)) {
// 所有的资源id
List<Long> clueIds = new ArrayList<>();
clueMiddleList.forEach(ct -> clueIds.add(ct.getClueId()));
List<Long> clueIds = clueMiddleList.stream().map(ClueMiddle::getClueId).collect(Collectors.toList());
//小组内资源分配
//Map<Long, List<Long>>用户id -> 资源ID集合
List<Long> userIdList = new ArrayList<>(clueQueryCriteria.getUserIds());
@ -491,6 +483,7 @@ public class ClueServiceImpl implements ClueService {
String oneFileName = baseExcelListenerDto.getOneFileName();
Long taskId = baseExcelListenerDto.getTaskId();
Long userId = baseExcelListenerDto.getUserId();
Integer origin = baseExcelListenerDto.getOrigin();
Integer taskNum = clueMiddleRepository.findTaskNum(taskId);
if (taskNum == null || taskNum == 0) {
try {
@ -509,7 +502,12 @@ public class ClueServiceImpl implements ClueService {
task.setCreateBy(userId);
task.setTaskName(taskName);
task.setTotalNumber(taskNum);
task.setTaskType(DefaultNumberConstants.ZERO_NUMBER);
if (origin == DefaultNumberConstants.SIX_NUMBER) {
task.setTaskType(DefaultNumberConstants.ONE_NUMBER);
task.setIsForm(DefaultNumberConstants.FIVE_NUMBER);
} else {
task.setTaskType(DefaultNumberConstants.ZERO_NUMBER);
}
try {
taskClient.saveTask(task);
} catch (Exception e) {
@ -628,6 +626,7 @@ public class ClueServiceImpl implements ClueService {
public void insertDynamicTask(DynamicTaskDto dynamicTaskDto) {
Long taskId = dynamicTaskDto.getTaskId();
String remark = dynamicTaskDto.getRemark();
boolean flag = false;
if (taskId == null) {
if (dynamicTaskDto.getWhichUserId() == null) {
@ -672,6 +671,7 @@ public class ClueServiceImpl implements ClueService {
clueMiddle.setClueStage(DefaultNumberConstants.ZERO_NUMBER);
clueMiddle.setClueCallStatus(DefaultNumberConstants.ZERO_NUMBER);
clueMiddle.setClueType(DefaultNumberConstants.TWO_NUMBER);
if (StringUtils.isNotBlank(remark)) clueMiddle.setRemark(remark);
clueMiddleRepository.save(clueMiddle);
//动态任务
if (dynamicTaskDto.getType() == FileConstant.FIVE_NUMBER) {
@ -731,6 +731,9 @@ public class ClueServiceImpl implements ClueService {
@Override
public void clueBackFlow(Long taskId, Long clueId, Long userId, Integer clueType) {
// 初始化线索加密字段
Clue clue = clueRepository.findById(clueId).orElseGet(Clue::new);
clue.setIsEncryption(DefaultNumberConstants.ZERO_NUMBER);
ClueMiddle clueMiddle = clueMiddleRepository.findById(clueId).orElseGet(ClueMiddle::new);
//查看crm任务
TaskQueryCriteria taskQueryCriteria = new TaskQueryCriteria();
@ -769,6 +772,49 @@ public class ClueServiceImpl implements ClueService {
taskClient.updateTask(task);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void dynamicTaskDistribution(Long taskId) {
List<ClueMiddle> clueAll = clueMiddleRepository.findByTaskIdAndMemberStatus(taskId, DefaultNumberConstants.ZERO_NUMBER);
List<Long> clueIds = clueAll.stream().map(ClueMiddle::getClueId).collect(Collectors.toList());
CommonResponse<DynamicTaskDistributionDTO> response = taskClient.findTaskDistribution(taskId);
if (response.getStatus() == DefaultNumberConstants.ZERO_NUMBER) {
DynamicTaskDistributionDTO dynamicTaskDistributionDTO = response.getData();
// 开启了自动分配
if (dynamicTaskDistributionDTO.getIsOpen() == 1) {
List<DynamicTaskDistributionUserDTO> dynamicTaskDistributionUserDTOS = dynamicTaskDistributionDTO.getDynamicTaskDistributionUserDTOS();
if (CollUtil.isNotEmpty(dynamicTaskDistributionUserDTOS)) {
DistributeDTO distributeDTO = new DistributeDTO();
// 获取用户分配的资源
List<Long> userIdList = new ArrayList<>();
List<Double> weights = new ArrayList<>();
for (DynamicTaskDistributionUserDTO dynamicTaskDistributionUserDTO : dynamicTaskDistributionUserDTOS) {
userIdList.add(dynamicTaskDistributionUserDTO.getId());
weights.add(Double.valueOf(dynamicTaskDistributionUserDTO.getRatio()));
}
int num = dynamicTaskDistributionUserDTOS.stream().mapToInt(DynamicTaskDistributionUserDTO::getRatio).sum();
// 比率分配数据
if (num == DefaultNumberConstants.ONE_HUNDRED){
distributeDTO.setIsWeight(true);
}
// 平均分配数据
if (num == DefaultNumberConstants.ZERO_NUMBER){
distributeDTO.setIsWeight(false);
}
distributeDTO.setDeptIds(userIdList);
distributeDTO.setWeights(weights);
distributeDTO.setResourceList(clueIds);
CommonResponse<List<DistributeResponseDTO>> distributeResponse = assignDataClient.dataDistribution(distributeDTO);
if (distributeResponse.getStatus() == DefaultNumberConstants.ZERO_NUMBER) {
for (DistributeResponseDTO data : distributeResponse.getData()) {
clueMiddleRepository.updateMemberIdByClueIdIn(data.getResponseList(), data.getDeptId());
}
}
}
}
}
}
private List<HashMap<String, Object>> getOrganizeInfo(String startTime, String endTime, List<Long> organizeIds) {
List<ClueMiddle> clueMiddles = clueMiddleRepository.queryAllByTimeAndorganizeIds(startTime, endTime, organizeIds);

@ -60,8 +60,13 @@ public class UploadFileServiceImpl implements UploadFileService {
List<ClueRecord> clueRecordList = new ArrayList<>();
String oneFileName = files[0].getOriginalFilename();
if (uploadType > 4 && taskId == null) {
throw new BadRequestException("上传错误,请联系管理员");
// 判断拓客任务上传是否新增任务
Boolean isCreateTask = false;
if (uploadType == 5 && taskId == null) {
throw new BadRequestException("上传动态任务表单错误,请联系管理员");
}
if (uploadType == 6 && taskId == null){
isCreateTask = true;
}
// 如果taskId是null就是小组任务动态任务都需要传taskId
if (taskId == null) taskId = IdUtil.getSnowflake(workerId, datacenterId).nextId();
@ -84,7 +89,7 @@ public class UploadFileServiceImpl implements UploadFileService {
}
if (!flag) {
//异步读取文件并创建任务
fileAnalysisTask.runFileAnalysisTask(clueRecordList, oneFileName);
fileAnalysisTask.runFileAnalysisTask(clueRecordList, oneFileName, isCreateTask);
}
return new ResponseEntity<>(CommonResponse.createBySuccess(ResponseCode.SUCCESS), HttpStatus.OK);
}

@ -50,11 +50,13 @@ public class FileAnalysisTask {
/**
*
*
* @param clueRecords
* @param clueRecords
* @param oneFileName
* @param isCreateTask
*/
@Transactional(rollbackFor = Exception.class)
@Async(value = "SendBigDataTaskExecutor")
public void runFileAnalysisTask(List<ClueRecord> clueRecords, String oneFileName) {
public void runFileAnalysisTask(List<ClueRecord> clueRecords, String oneFileName, Boolean isCreateTask) {
if (CollUtil.isNotEmpty(clueRecords)) {
try {
for (ClueRecord clueRecord : clueRecords) {
@ -90,9 +92,9 @@ public class FileAnalysisTask {
e.printStackTrace();
throw new BadRequestException("=========读取资源错误============");
}
//动态任务不需要创建任务,更新后结束方法
//动态任务不需要创建任务,更新后结束方法拓客任务不指定任务ID就也要新建任务
Integer uploadType = clueRecords.get(0).getUploadType();
if (uploadType == FileConstant.FIVE_NUMBER || uploadType == FileConstant.SIX_NUMBER) {
if (uploadType == FileConstant.FIVE_NUMBER || (uploadType == FileConstant.SIX_NUMBER && !isCreateTask)) {
Long taskId = clueRecords.get(0).getTaskId();
Integer taskNum = clueMiddleRepository.findTaskNum(taskId);
Task task = new Task();
@ -100,6 +102,8 @@ public class FileAnalysisTask {
task.setTotalNumber(taskNum);
task.setIsDistribution(1);
taskClient.updateTask(task);
// 查看此任务是否开启自动分配,开启了就分配掉
clueService.dynamicTaskDistribution(taskId);
return;
}
//创建任务
@ -113,6 +117,7 @@ public class FileAnalysisTask {
baseExcelListenerDto.setUserId(userId);
baseExcelListenerDto.setTaskId(taskId);
baseExcelListenerDto.setOneFileName(oneFileName);
baseExcelListenerDto.setOrigin(uploadType);
clueService.saveTask(baseExcelListenerDto);
}
}

@ -36,7 +36,6 @@ public class DecryptPnoUtil {
.form(paramMap)
.timeout(2_000)
.execute().body();
log.info("result======={}", JSONUtil.toJsonStr(result));
SecretResponseBean secretResponseBean = JSONUtil.toBean(result, SecretResponseBean.class);
String nid = Base64.decodeStr(secretResponseBean.getTels());

Loading…
Cancel
Save