Browse Source

Merge remote-tracking branch 'origin/master'

master
CMM 1 year ago
parent
commit
a7294a4767
15 changed files with 280 additions and 265 deletions
  1. +7
    -7
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java
  2. +0
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/domain/MeetingExpert.java
  3. +1
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/AvoidRuleDTO.java
  4. +27
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/MeetingInviteCacheDTO.java
  5. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/ExpertInviteReq.java
  6. +20
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingIdReq.java
  7. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/ExpertInviteHelper.java
  8. +41
    -16
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingManageHelper.java
  9. +61
    -74
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java
  10. +34
    -82
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java
  11. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/IExpertInviteAvoidRuleService.java
  12. +13
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/IMeetingExpertService.java
  13. +3
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/impl/ExpertInviteAvoidRuleServiceImpl.java
  14. +66
    -67
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java
  15. +1
    -1
      pmapi/src/main/resources/application-dev.yml

+ 7
- 7
pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java View File

@@ -39,6 +39,13 @@ public class MeetingController {
return meetingManage.meetingCreateAndInviteExpert(req); return meetingManage.meetingCreateAndInviteExpert(req);
} }


@PostMapping("/continueInvite")
@ApiOperation(value = "续抽专家")
@WebLog(value = "续抽专家")
public void continueInvite(@Valid @RequestBody MeetingIdReq req) {
meetingManage.continueInvite(req.getMeetingId());
}

@PostMapping("/expertInviteByCreate") @PostMapping("/expertInviteByCreate")
@ApiOperation(value = "新建会议-专家抽取", hidden = true) @ApiOperation(value = "新建会议-专家抽取", hidden = true)
@WebLog(value = "新建会议-专家抽取") @WebLog(value = "新建会议-专家抽取")
@@ -94,13 +101,6 @@ public class MeetingController {
return meetingManage.inviteRuleDetail(meetingId); return meetingManage.inviteRuleDetail(meetingId);
} }


@ApiOperation("专家替换")
@PostMapping("/expertReplace")
@WebLog(value = "专家替换")
public void expertReplace(@RequestBody ExpertRemoveReq po) {
meetingManage.expertReplace(po);
}

@ApiOperation("停止抽取") @ApiOperation("停止抽取")
@GetMapping("/stopInvite/{meetingId}") @GetMapping("/stopInvite/{meetingId}")
@WebLog(value = "停止抽取") @WebLog(value = "停止抽取")


+ 0
- 5
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/domain/MeetingExpert.java View File

@@ -55,11 +55,6 @@ public class MeetingExpert implements Serializable {
@ApiModelProperty("是否是专家组长") @ApiModelProperty("是否是专家组长")
private Boolean isHeadman; private Boolean isHeadman;


@ApiModelProperty("前一个状态")
private Integer preStatus;

private Long preId;

@ApiModelProperty("邀请类型") @ApiModelProperty("邀请类型")
private Integer inviteType; private Integer inviteType;




pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/AvoidInfoDTO.java → pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/AvoidRuleDTO.java View File

@@ -5,7 +5,6 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;


import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;


/** /**
@@ -18,7 +17,7 @@ import java.util.List;
*/ */
@Data @Data
@ApiModel("回避信息") @ApiModel("回避信息")
public class AvoidInfoDTO {
public class AvoidRuleDTO {


@ApiModelProperty("回避单位") @ApiModelProperty("回避单位")
@NotEmpty(message = "回避单位不能为空", groups = {AbstractInviteRule.RuleSave.class}) @NotEmpty(message = "回避单位不能为空", groups = {AbstractInviteRule.RuleSave.class})

+ 27
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/MeetingInviteCacheDTO.java View File

@@ -0,0 +1,27 @@
package com.ningdatech.pmapi.meeting.entity.dto;

import lombok.Data;

/**
* <p>
* MeetingInviteDTO
* </p>
*
* @author WendyYang
* @since 19:21 2023/3/7
*/
@Data
public final class MeetingInviteCacheDTO {

private Long meetingId;

private Boolean invitedRefused;

public static MeetingInviteCacheDTO of(Long meetingId, Boolean invitedRefused) {
MeetingInviteCacheDTO bo = new MeetingInviteCacheDTO();
bo.setMeetingId(meetingId);
bo.setInvitedRefused(invitedRefused);
return bo;
}

}

+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/ExpertInviteReq.java View File

@@ -1,7 +1,7 @@
package com.ningdatech.pmapi.meeting.entity.req; package com.ningdatech.pmapi.meeting.entity.req;


import com.ningdatech.pmapi.meeting.entity.dto.AppointInviteRuleDTO; import com.ningdatech.pmapi.meeting.entity.dto.AppointInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO; import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
@@ -33,7 +33,7 @@ public class ExpertInviteReq {
@Valid @Valid
@NotNull(message = "回避信息不能为空") @NotNull(message = "回避信息不能为空")
@ApiModelProperty("回避信息") @ApiModelProperty("回避信息")
private AvoidInfoDTO avoidRule;
private AvoidRuleDTO avoidRule;


@Valid @Valid
@ApiModelProperty("随机抽取规则") @ApiModelProperty("随机抽取规则")


+ 20
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingIdReq.java View File

@@ -0,0 +1,20 @@
package com.ningdatech.pmapi.meeting.entity.req;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* <p>
* MeetingIdReq
* </p>
*
* @author WendyYang
* @since 17:10 2023/3/7
*/
@Data
public class MeetingIdReq {

@ApiModelProperty("会议ID")
private Long meetingId;

}

+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/ExpertInviteHelper.java View File

@@ -11,7 +11,7 @@ import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.AbstractInviteRule; import com.ningdatech.pmapi.meeting.entity.dto.AbstractInviteRule;
import com.ningdatech.pmapi.meeting.entity.dto.AppointInviteRuleDTO; import com.ningdatech.pmapi.meeting.entity.dto.AppointInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.service.IMeetingExpertService; import com.ningdatech.pmapi.meeting.service.IMeetingExpertService;
import com.ningdatech.pmapi.meeting.service.IMeetingService; import com.ningdatech.pmapi.meeting.service.IMeetingService;
@@ -69,7 +69,7 @@ public class ExpertInviteHelper {
return new HashSet<>(listInvitedExpertByTime(start, end)); return new HashSet<>(listInvitedExpertByTime(start, end));
} }


public Set<Long> getAvoidExpert(List<Long> appoints, AvoidInfoDTO avoid, LocalDateTime start, LocalDateTime end) {
public Set<Long> getAvoidExpert(List<Long> appoints, AvoidRuleDTO avoid, LocalDateTime start, LocalDateTime end) {
Set<Long> expertIds = new HashSet<>(); Set<Long> expertIds = new HashSet<>();
Optional.ofNullable(appoints).ifPresent(expertIds::addAll); Optional.ofNullable(appoints).ifPresent(expertIds::addAll);
Optional.ofNullable(avoid) Optional.ofNullable(avoid)


+ 41
- 16
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingManageHelper.java View File

@@ -1,5 +1,6 @@
package com.ningdatech.pmapi.meeting.helper; package com.ningdatech.pmapi.meeting.helper;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -14,9 +15,10 @@ import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteAvoidRule; import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteAvoidRule;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting; import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO; import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO;
import com.ningdatech.pmapi.meeting.entity.dto.MeetingBasicDTO; import com.ningdatech.pmapi.meeting.entity.dto.MeetingBasicDTO;
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.entity.req.MeetingListReq; import com.ningdatech.pmapi.meeting.entity.req.MeetingListReq;
import com.ningdatech.pmapi.meeting.entity.vo.ExpertBasicInfoVO; import com.ningdatech.pmapi.meeting.entity.vo.ExpertBasicInfoVO;
@@ -30,7 +32,10 @@ import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;


import java.util.*;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;


/** /**
* <p> * <p>
@@ -60,6 +65,36 @@ public class MeetingManageHelper {
} }


/** /**
* 校验会议是否还可继续抽取
*/
public boolean checkCouldBeInvitedContinue(Long meetingId) {
Map<Long, RandomInviteRuleDTO> ruleMap = inviteRuleService.randomRuleByMeetingId(meetingId);
List<MeetingExpert> experts = meetingExpertService.listExpertLastByMeetingId(meetingId);
if (experts.isEmpty()) {
return Boolean.TRUE;
}
Map<Long, List<MeetingExpert>> expertMap = CollUtils.group(experts, MeetingExpert::getRuleId);
for (Map.Entry<Long, RandomInviteRuleDTO> entry : ruleMap.entrySet()) {
List<MeetingExpert> tmpExperts = expertMap.get(entry.getKey());
if (CollUtil.isEmpty(tmpExperts)) {
return Boolean.TRUE;
}
int count = 0;
for (MeetingExpert w : tmpExperts) {
boolean status = ExpertAttendStatusEnum.AGREED.eq(w.getStatus()) ||
ExpertAttendStatusEnum.NOTICING.eq(w.getStatus());
if (status) {
count++;
}
}
if (count < entry.getValue().getCount()) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}

/**
* 获取专家出席会议的状态 * 获取专家出席会议的状态
* *
* @param info 会议状态及评价信息 * @param info 会议状态及评价信息
@@ -104,7 +139,7 @@ public class MeetingManageHelper {
query.and(q1 -> q1.exists("select 1 from nd_project np inner join meeting_inner_project mip on mip.project_id = np.id" + query.and(q1 -> q1.exists("select 1 from nd_project np inner join meeting_inner_project mip on mip.project_id = np.id" +
" where mip.meeting_id = meeting.id and np.project_name like {0}", projectName) " where mip.meeting_id = meeting.id and np.project_name like {0}", projectName)
.or(q2 -> q2.exists("select 1 from meeting_outer_project mop where mop.meeting_id = meeting.id" + .or(q2 -> q2.exists("select 1 from meeting_outer_project mop where mop.meeting_id = meeting.id" +
"and mop.project_name like {0}", projectName)));
" and mop.project_name like {0}", projectName)));
} }
} }


@@ -140,9 +175,9 @@ public class MeetingManageHelper {
return null; return null;
} }


public AvoidInfoDTO getAvoidInfoDto(Long meetingId) {
public AvoidRuleDTO getAvoidInfoDto(Long meetingId) {
ExpertInviteAvoidRule avoidRule = inviteAvoidRuleService.getByMeetingId(meetingId); ExpertInviteAvoidRule avoidRule = inviteAvoidRuleService.getByMeetingId(meetingId);
AvoidInfoDTO result = new AvoidInfoDTO();
AvoidRuleDTO result = new AvoidRuleDTO();
result.setAvoidOrgIdList(StrUtil.split(avoidRule.getAvoidOrgIds(), ",")); result.setAvoidOrgIdList(StrUtil.split(avoidRule.getAvoidOrgIds(), ","));
result.setExpertIds(BizUtils.splitToLong(avoidRule.getAvoidExpertIds())); result.setExpertIds(BizUtils.splitToLong(avoidRule.getAvoidExpertIds()));
result.setAvoidUnitIdList(StrUtil.split(avoidRule.getAvoidUnitIds(), ",")); result.setAvoidUnitIdList(StrUtil.split(avoidRule.getAvoidUnitIds(), ","));
@@ -165,7 +200,7 @@ public class MeetingManageHelper {
**/ **/
public List<ExpertUserFullInfo> appointExpertCheck(Long meetingId, List<Long> expertIds) { public List<ExpertUserFullInfo> appointExpertCheck(Long meetingId, List<Long> expertIds) {
List<ExpertUserFullInfo> experts = expertUserFullInfoService.listByUserId(expertIds); List<ExpertUserFullInfo> experts = expertUserFullInfoService.listByUserId(expertIds);
AvoidInfoDTO avoidRule = getAvoidInfoDto(meetingId);
AvoidRuleDTO avoidRule = getAvoidInfoDto(meetingId);
experts.forEach(expert -> { experts.forEach(expert -> {
if (avoidRule.getAvoidUnitIdList().contains(expert.getCompany())) { if (avoidRule.getAvoidUnitIdList().contains(expert.getCompany())) {
throw BizException.wrap("请移除已回避单位的专家"); throw BizException.wrap("请移除已回避单位的专家");
@@ -193,16 +228,6 @@ public class MeetingManageHelper {
throw BizException.wrap("专家%s已拒绝参加", expertName); throw BizException.wrap("专家%s已拒绝参加", expertName);
case REMOVED: case REMOVED:
throw BizException.wrap("专家%s已被移除", expertName); throw BizException.wrap("专家%s已被移除", expertName);
case REPLACED:
switch (ExpertAttendStatusEnum.getByCode(w.getPreStatus())) {
case REFUSED:
throw BizException.wrap("专家%s已拒绝参加", expertName);
case REMOVED:
throw BizException.wrap("专家%s已被移除", expertName);
default:
break;
}
break;
case AGREED: case AGREED:
throw BizException.wrap("专家%s已同意参加", expertName); throw BizException.wrap("专家%s已同意参加", expertName);
case NOTICING: case NOTICING:


+ 61
- 74
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.CollUtils; import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.common.util.BizUtils; import com.ningdatech.pmapi.common.util.BizUtils;
import com.ningdatech.pmapi.common.util.StrUtils;
import com.ningdatech.pmapi.expert.constant.ExpertAccountStatusEnum; import com.ningdatech.pmapi.expert.constant.ExpertAccountStatusEnum;
import com.ningdatech.pmapi.expert.entity.ExpertAvoidCompany; import com.ningdatech.pmapi.expert.entity.ExpertAvoidCompany;
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo; import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
@@ -15,7 +16,7 @@ import com.ningdatech.pmapi.meeting.builder.ExpertInviteBuilder;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule; import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting; import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO; import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO;
import com.ningdatech.pmapi.meeting.entity.dto.ExpertDictChooseDTO; import com.ningdatech.pmapi.meeting.entity.dto.ExpertDictChooseDTO;
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO; import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
@@ -135,7 +136,7 @@ public class ExpertInviteManage {
return expertAvoidCompanyList.stream().map(ExpertAvoidCompany::getUserId).distinct().collect(Collectors.toList()); return expertAvoidCompanyList.stream().map(ExpertAvoidCompany::getUserId).distinct().collect(Collectors.toList());
} }


private List<Long> mergeExpertIdsByCondition(RandomInviteRuleDTO rule, AvoidInfoDTO avoidInfo) {
private List<Long> mergeExpertIdsByCondition(RandomInviteRuleDTO rule, AvoidRuleDTO avoidInfo) {
// 处理履职意向地 // 处理履职意向地
List<Long> expertIdsByIntentionRegion = expertIdsByRegion(rule); List<Long> expertIdsByIntentionRegion = expertIdsByRegion(rule);
if (COLL_EMPTY.evaluate(expertIdsByIntentionRegion)) { if (COLL_EMPTY.evaluate(expertIdsByIntentionRegion)) {
@@ -246,34 +247,31 @@ public class ExpertInviteManage {
/** /**
* 专家抽取(随机) * 专家抽取(随机)
* *
* @param avoidInfo 回避信息
* @param avoidRule 回避信息
* @param randomRule 抽取规则 * @param randomRule 抽取规则
* @param appointExpertIds 指定抽取专家ID * @param appointExpertIds 指定抽取专家ID
* @return 满足抽取条件的专家 * @return 满足抽取条件的专家
* @author WendyYang * @author WendyYang
**/ **/
public ExpertChooseDTO expertInviteByRandomRule(AvoidInfoDTO avoidInfo,
public ExpertChooseDTO expertInviteByRandomRule(AvoidRuleDTO avoidRule,
RandomInviteRuleDTO randomRule, RandomInviteRuleDTO randomRule,
List<Long> appointExpertIds, List<Long> appointExpertIds,
LocalDateTime start, LocalDateTime start,
LocalDateTime end) { LocalDateTime end) {
ExpertChooseDTO result = new ExpertChooseDTO(new ArrayList<>(), 0); ExpertChooseDTO result = new ExpertChooseDTO(new ArrayList<>(), 0);
List<Long> expertIdsIn = mergeExpertIdsByCondition(randomRule, avoidInfo);
List<Long> expertIdsIn = mergeExpertIdsByCondition(randomRule, avoidRule);
if (expertIdsIn == null) { if (expertIdsIn == null) {
return result; return result;
} }
boolean avoid = avoidInfo != null;
boolean avoidExpert = avoid && CollUtil.isNotEmpty(avoidInfo.getExpertIds());
boolean avoidCompany = avoid && CollUtil.isNotEmpty(avoidInfo.getAvoidUnitIdList());
boolean avoidExpert = CollUtil.isNotEmpty(avoidRule.getExpertIds());
boolean avoidCompany = CollUtil.isNotEmpty(avoidRule.getAvoidUnitIdList());
Set<String> tmpAvoidCompany = new HashSet<>(); Set<String> tmpAvoidCompany = new HashSet<>();
if (avoidCompany) { if (avoidCompany) {
List<String> companyIds = avoidInfo.getAvoidUnitIdList();
List<String> companyIds = avoidRule.getAvoidUnitIdList();
for (String companyId : companyIds) { for (String companyId : companyIds) {
if (companyId.contains(",")) { if (companyId.contains(",")) {
String[] splitCompanyIds = companyId.split(","); String[] splitCompanyIds = companyId.split(",");
for (String splitCompanyId : splitCompanyIds) {
tmpAvoidCompany.add(splitCompanyId);
}
Collections.addAll(tmpAvoidCompany, splitCompanyIds);
} else { } else {
tmpAvoidCompany.add(companyId); tmpAvoidCompany.add(companyId);
} }
@@ -284,14 +282,13 @@ public class ExpertInviteManage {
query.notIn(!tmpAvoidCompany.isEmpty(), ExpertUserFullInfo::getCompany, tmpAvoidCompany); query.notIn(!tmpAvoidCompany.isEmpty(), ExpertUserFullInfo::getCompany, tmpAvoidCompany);
if (avoidCompany) { if (avoidCompany) {
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" + query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" +
" and company_name in ({0})", CollUtils.joinByComma(avoidInfo.getAvoidUnitIdList()));
" and company_name in ({0})", CollUtils.joinByComma(avoidRule.getAvoidUnitIdList()));
} }
// 处理专家层级 // 处理专家层级
addRegionLimit(query, randomRule); addRegionLimit(query, randomRule);

if (!expertIdsIn.isEmpty()) { if (!expertIdsIn.isEmpty()) {
if (avoidExpert) { if (avoidExpert) {
expertIdsIn.removeIf(w -> avoidInfo.getExpertIds().contains(w));
expertIdsIn.removeIf(w -> avoidRule.getExpertIds().contains(w));
if (expertIdsIn.isEmpty()) { if (expertIdsIn.isEmpty()) {
// 字典、标签、履职意向地筛选出的专家ID移除需要回避的专家ID // 字典、标签、履职意向地筛选出的专家ID移除需要回避的专家ID
// 如果为空则说明没有符合条件的 // 如果为空则说明没有符合条件的
@@ -312,7 +309,7 @@ public class ExpertInviteManage {
} }
query.in(ExpertUserFullInfo::getUserId, expertIdsIn); query.in(ExpertUserFullInfo::getUserId, expertIdsIn);
} else if (avoidExpert || CollUtil.isNotEmpty(appointExpertIds)) { } else if (avoidExpert || CollUtil.isNotEmpty(appointExpertIds)) {
Set<Long> tempExperts = expertInviteHelper.getAvoidExpert(appointExpertIds, avoidInfo, start, end);
Set<Long> tempExperts = expertInviteHelper.getAvoidExpert(appointExpertIds, avoidRule, start, end);
query.notIn(ExpertUserFullInfo::getUserId, tempExperts); query.notIn(ExpertUserFullInfo::getUserId, tempExperts);
} else { } else {
Set<Long> notInUserIds = expertInviteHelper.listExpertLeaveOrInvited(start, end); Set<Long> notInUserIds = expertInviteHelper.listExpertLeaveOrInvited(start, end);
@@ -320,15 +317,15 @@ public class ExpertInviteManage {
query.notIn(ExpertUserFullInfo::getUserId, notInUserIds); query.notIn(ExpertUserFullInfo::getUserId, notInUserIds);
} }
} }
List<ExpertUserFullInfo> userFullInfos = expertUserFullInfoService.list(query);
if (userFullInfos.isEmpty()) {
List<ExpertUserFullInfo> userInfoList = expertUserFullInfoService.list(query);
if (userInfoList.isEmpty()) {
return result; return result;
} }
result.setTotal(userFullInfos.size());
Map<String, List<ExpertUserFullInfo>> userGroupByUnit = CollUtils.group(userInfoList, ExpertUserFullInfo::getCompany);
result.setTotal(userInfoList.size());
// count为空表示数量校验 // count为空表示数量校验
if (randomRule.getCount() == null || result.getTotal() >= randomRule.getCount()) { if (randomRule.getCount() == null || result.getTotal() >= randomRule.getCount()) {
List<ExpertUserFullInfo> userFullInfoList = inviteWithoutCompany(userFullInfos, randomRule.getCount());
result.setExperts(userFullInfoList);
result.setExperts(inviteGroupByCompany(userGroupByUnit, randomRule.getCount()));
} }
return result; return result;
} }
@@ -336,39 +333,41 @@ public class ExpertInviteManage {
/** /**
* 专家替换、补充 * 专家替换、补充
* *
* @param avoidInfo 回避信息
* @param avoidRule 回避信息
* @param randomRule 随机抽取 * @param randomRule 随机抽取
* @param meetingExperts 已抽取人员
* @param invitedExperts 已抽取人员
* @param count 抽取数量 * @param count 抽取数量
* @return com.ningdatech.emapi.meeting.entity.dto.ExpertChooseDto
* @param start 会议开始时间
* @param end 会议结束时间
* @return {@link ExpertChooseDTO}
* @author WendyYang * @author WendyYang
**/ **/
public ExpertChooseDTO expertReplaceByRandomRule(AvoidInfoDTO avoidInfo,
public ExpertChooseDTO expertReplaceByRandomRule(AvoidRuleDTO avoidRule,
RandomInviteRuleDTO randomRule, RandomInviteRuleDTO randomRule,
Collection<MeetingExpert> meetingExperts,
Collection<MeetingExpert> invitedExperts,
Integer count, Integer count,
LocalDateTime start, LocalDateTime start,
LocalDateTime end, LocalDateTime end,
Long replacedExpertId) {
boolean invitedRefused) {
ExpertChooseDTO result = new ExpertChooseDTO(new ArrayList<>(), 0); ExpertChooseDTO result = new ExpertChooseDTO(new ArrayList<>(), 0);
// 合并标签、字典 // 合并标签、字典
List<Long> expertIdsIn = mergeExpertIdsByCondition(randomRule, avoidInfo);
List<Long> expertIdsIn = mergeExpertIdsByCondition(randomRule, avoidRule);
if (expertIdsIn == null) { if (expertIdsIn == null) {
return result; return result;
} }
LambdaQueryWrapper<ExpertUserFullInfo> query = buildBaseExpertQuery(); LambdaQueryWrapper<ExpertUserFullInfo> query = buildBaseExpertQuery();
query.notIn(ExpertUserFullInfo::getCompany, avoidInfo.getAvoidUnitIdList());
query.notIn(ExpertUserFullInfo::getCompany, avoidRule.getAvoidUnitIdList());
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" + query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" +
" and company_name in ({0})", CollUtils.joinByComma(avoidInfo.getAvoidOrgIdList()));
" and company_name in ({0})", CollUtils.joinByComma(avoidRule.getAvoidOrgIdList()));


// 处理专家层级 // 处理专家层级
if (ObjectUtils.allNotNull(randomRule.getExpertRegionCode(), randomRule.getExpertRegionLevel())) {
if (StrUtils.isNotBlank(randomRule.getExpertRegionCode())) {
query.eq(ExpertUserFullInfo::getRegionCode, randomRule.getExpertRegionCode()); query.eq(ExpertUserFullInfo::getRegionCode, randomRule.getExpertRegionCode());
query.eq(ExpertUserFullInfo::getRegionLevel, randomRule.getExpertRegionLevel()); query.eq(ExpertUserFullInfo::getRegionLevel, randomRule.getExpertRegionLevel());
} }
if (expertIdsIn.size() > 0) { if (expertIdsIn.size() > 0) {
if (CollectionUtils.isNotEmpty(avoidInfo.getExpertIds())) {
expertIdsIn.removeIf(w -> avoidInfo.getExpertIds().contains(w));
if (CollectionUtils.isNotEmpty(avoidRule.getExpertIds())) {
expertIdsIn.removeIf(w -> avoidRule.getExpertIds().contains(w));
if (expertIdsIn.isEmpty()) { if (expertIdsIn.isEmpty()) {
// 字典、标签、履职意向地筛选出的专家ID移除需要回避的专家ID // 字典、标签、履职意向地筛选出的专家ID移除需要回避的专家ID
// 如果为空则说明没有符合条件的 // 如果为空则说明没有符合条件的
@@ -381,8 +380,8 @@ public class ExpertInviteManage {
return result; return result;
} }
query.in(ExpertUserFullInfo::getUserId, expertIdsIn); query.in(ExpertUserFullInfo::getUserId, expertIdsIn);
} else if (CollectionUtils.isNotEmpty(avoidInfo.getExpertIds())) {
Set<Long> notInExpertIds = expertInviteHelper.getAvoidExpert(avoidInfo.getExpertIds(), null, start, end);
} else if (CollUtil.isNotEmpty(avoidRule.getExpertIds())) {
Set<Long> notInExpertIds = expertInviteHelper.getAvoidExpert(avoidRule.getExpertIds(), null, start, end);
query.notIn(ExpertUserFullInfo::getUserId, notInExpertIds); query.notIn(ExpertUserFullInfo::getUserId, notInExpertIds);
} else { } else {
Set<Long> notInUserIds = expertInviteHelper.listExpertLeaveOrInvited(start, end); Set<Long> notInUserIds = expertInviteHelper.listExpertLeaveOrInvited(start, end);
@@ -394,44 +393,31 @@ public class ExpertInviteManage {
if (userFullInfos.size() == 0) { if (userFullInfos.size() == 0) {
return result; return result;
} }
Comparator<MeetingExpert> sort = Comparator.comparing(MeetingExpert::getUpdateOn).reversed();
Map<Long, MeetingExpert> tempExpertIdsMap = BizUtils.groupFirstMap(meetingExperts, MeetingExpert::getExpertId, sort);
Map<ExpertAttendStatusEnum, List<MeetingExpert>> expertIdGroupByStatus = tempExpertIdsMap.values().stream()
Map<ExpertAttendStatusEnum, List<MeetingExpert>> expertGroupByStatus = invitedExperts.stream()
.collect(Collectors.groupingBy(w -> ExpertAttendStatusEnum.getByCode(w.getStatus()))); .collect(Collectors.groupingBy(w -> ExpertAttendStatusEnum.getByCode(w.getStatus())));
// 回避同单位其他专家 // 回避同单位其他专家
List<MeetingExpert> removeExpertByCompany = new ArrayList<>(); List<MeetingExpert> removeExpertByCompany = new ArrayList<>();
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.AGREED), removeExpertByCompany::addAll);
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.NOTICING), removeExpertByCompany::addAll);
BizUtils.notEmpty(expertGroupByStatus.get(ExpertAttendStatusEnum.AGREED), removeExpertByCompany::addAll);
BizUtils.notEmpty(expertGroupByStatus.get(ExpertAttendStatusEnum.NOTICING), removeExpertByCompany::addAll);
List<Long> removeExpertIds = new ArrayList<>(); List<Long> removeExpertIds = new ArrayList<>();
// 拒绝参加的不可以被再次抽中
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.REFUSED), w -> {
List<Long> tempRefused = CollUtils.fieldList(w, MeetingExpert::getExpertId);
removeExpertIds.addAll(tempRefused);
});
if (invitedRefused) {
// 拒绝参加的不可以被再次抽中
BizUtils.notEmpty(expertGroupByStatus.get(ExpertAttendStatusEnum.REFUSED), w -> {
List<Long> tempRefused = CollUtils.fieldList(w, MeetingExpert::getExpertId);
removeExpertIds.addAll(tempRefused);
});
}
// 被取消的也不可以被再次抽中 // 被取消的也不可以被再次抽中
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.REMOVED), w -> {
BizUtils.notEmpty(expertGroupByStatus.get(ExpertAttendStatusEnum.REMOVED), w -> {
List<Long> tempCanceled = CollUtils.fieldList(w, MeetingExpert::getExpertId); List<Long> tempCanceled = CollUtils.fieldList(w, MeetingExpert::getExpertId);
removeExpertIds.addAll(tempCanceled); removeExpertIds.addAll(tempCanceled);
}); });
// 被替换之前是上述两种状态的不可被再次抽中
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.REPLACED), w -> {
for (MeetingExpert me : w) {
BizUtils.notNull(me.getPreStatus(), preStatus -> {
if (ExpertAttendStatusEnum.REFUSED.eq(preStatus) || ExpertAttendStatusEnum.REMOVED.eq(preStatus)) {
removeExpertIds.add(me.getExpertId());
}
});
}
});
// 不为空时表示单个专家替换否则为专家补抽
if (replacedExpertId != null) {
removeExpertIds.add(replacedExpertId);
}
List<Long> tempExpertIds = CollUtils.fieldList(removeExpertByCompany, MeetingExpert::getExpertId); List<Long> tempExpertIds = CollUtils.fieldList(removeExpertByCompany, MeetingExpert::getExpertId);
// 移除确认参加、通知中的、拒绝参加、已取消 // 移除确认参加、通知中的、拒绝参加、已取消
userFullInfos.removeIf(w -> tempExpertIds.contains(w.getUserId()) || removeExpertIds.contains(w.getUserId())); userFullInfos.removeIf(w -> tempExpertIds.contains(w.getUserId()) || removeExpertIds.contains(w.getUserId()));
result.setTotal(userFullInfos.size());
result.setExperts(inviteWithoutCompany(userFullInfos, count));
Map<String, List<ExpertUserFullInfo>> userGroupByUnit = CollUtils.group(userFullInfos, ExpertUserFullInfo::getCompany);
result.setTotal(userGroupByUnit.size());
result.setExperts(inviteGroupByCompany(userGroupByUnit, count));
return result; return result;
} }


@@ -455,26 +441,26 @@ public class ExpertInviteManage {
/** /**
* 每个单位只抽取一人 * 每个单位只抽取一人
* *
* @param expertGroupByCompany 需要抽取的人
* @param count 抽取数量
* @param expertGroupByUnit 需要抽取的人
* @param count 抽取数量
* @return java.util.List<com.ningdatech.emapi.expert.entity.domain.ExpertUserFullInfo> * @return java.util.List<com.ningdatech.emapi.expert.entity.domain.ExpertUserFullInfo>
* @author WendyYang * @author WendyYang
**/ **/
private List<ExpertUserFullInfo> inviteGroupByCompany(Map<String, List<ExpertUserFullInfo>> expertGroupByCompany, Integer count) {
if (MapUtils.isEmpty(expertGroupByCompany)) {
private List<ExpertUserFullInfo> inviteGroupByCompany(Map<String, List<ExpertUserFullInfo>> expertGroupByUnit, Integer count) {
if (MapUtils.isEmpty(expertGroupByUnit)) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<List<MeetingExpert>> meetingExperts = selectMeetingExpertByCount(); List<List<MeetingExpert>> meetingExperts = selectMeetingExpertByCount();
if (meetingExperts.isEmpty()) { if (meetingExperts.isEmpty()) {
return expertGroupByCompany.values().stream()
return expertGroupByUnit.values().stream()
.map(expertUsers -> expertUsers.get(RandomUtils.nextInt(0, expertUsers.size()))) .map(expertUsers -> expertUsers.get(RandomUtils.nextInt(0, expertUsers.size())))
.limit(count).collect(Collectors.toList()); .limit(count).collect(Collectors.toList());
} else { } else {
List<ExpertUserFullInfo> result = new ArrayList<>(); List<ExpertUserFullInfo> result = new ArrayList<>();
List<String> keySet = new ArrayList<>(expertGroupByCompany.keySet());
List<String> keySet = new ArrayList<>(expertGroupByUnit.keySet());
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
String key = keySet.get(RandomUtils.nextInt(0, keySet.size())); String key = keySet.get(RandomUtils.nextInt(0, keySet.size()));
List<ExpertUserFullInfo> expertUserFullInfos = expertGroupByCompany.get(key);
List<ExpertUserFullInfo> expertUserFullInfos = expertGroupByUnit.get(key);
for (List<MeetingExpert> expertList : meetingExperts) { for (List<MeetingExpert> expertList : meetingExperts) {
List<ExpertUserFullInfo> tempList = expertUserFullInfos.stream() List<ExpertUserFullInfo> tempList = expertUserFullInfos.stream()
.filter(w -> expertList.stream().noneMatch(expert -> expert.getExpertId().equals(w.getUserId()))) .filter(w -> expertList.stream().noneMatch(expert -> expert.getExpertId().equals(w.getUserId())))
@@ -547,12 +533,13 @@ public class ExpertInviteManage {
* 专家抽取(会议创建时抽取) * 专家抽取(会议创建时抽取)
* *
* @param randomRules 随机抽取规则 * @param randomRules 随机抽取规则
* @param avoid 回避信息
* @param avoidRuled 回避信息
* @param meeting 会议信息
* @author WendyYang * @author WendyYang
**/ **/
public void expertRandomInviteByMeetingCreate(Meeting meeting,
List<RandomInviteRuleDTO> randomRules,
AvoidInfoDTO avoid) {
public void expertInviteByMeetingCreate(Meeting meeting,
List<RandomInviteRuleDTO> randomRules,
AvoidRuleDTO avoidRuled) {
List<MeetingExpert> expertInserts = new ArrayList<>(); List<MeetingExpert> expertInserts = new ArrayList<>();
// 处理随机抽取规则 // 处理随机抽取规则
if (CollectionUtils.isNotEmpty(randomRules)) { if (CollectionUtils.isNotEmpty(randomRules)) {
@@ -562,7 +549,7 @@ public class ExpertInviteManage {
LocalDateTime startTime = meeting.getStartTime(); LocalDateTime startTime = meeting.getStartTime();
LocalDateTime endTime = meeting.getEndTime(); LocalDateTime endTime = meeting.getEndTime();
randomRules.forEach(rule -> { randomRules.forEach(rule -> {
ExpertChooseDTO tempExperts = expertInviteByRandomRule(avoid, rule, choosedExpertIds, startTime, endTime);
ExpertChooseDTO tempExperts = expertInviteByRandomRule(avoidRuled, rule, choosedExpertIds, startTime, endTime);
expertsByRandom.add(tempExperts); expertsByRandom.add(tempExperts);
choosedExpertIds.addAll(CollUtils.fieldList(tempExperts.getExperts(), ExpertUserFullInfo::getUserId)); choosedExpertIds.addAll(CollUtils.fieldList(tempExperts.getExperts(), ExpertUserFullInfo::getUserId));
randoms.add(getExpertInviteRule(rule, meeting.getId())); randoms.add(getExpertInviteRule(rule, meeting.getId()));


+ 34
- 82
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java View File

@@ -140,6 +140,29 @@ public class MeetingManage {
} }
} }


public void continueInvite(Long meetingId) {
String key = "CONTINUE_INVITE:" + meetingId;
if (!distributedLock.lock(key, RETRY_TIMES)) {
throw BizException.wrap("已进行续抽,请勿重复点击");
}
try {
Meeting meeting = meetingService.getById(meetingId);
if (!meeting.getInviteStatus()) {
throw BizException.wrap("该会议正在抽取专家,暂无法续抽");
}
if (!MeetingStatusEnum.NORMAL.eq(meeting.getStatus())) {
throw BizException.wrap("续抽失败,请刷新后重试");
}
boolean invitedContinue = meetingManageHelper.checkCouldBeInvitedContinue(meetingId);
if (!invitedContinue) {
throw BizException.wrap("抽取人员数量已满足抽取规则");
}

} finally {
distributedLock.releaseLock(key);
}
}

@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void expertInviteByCreate(ExpertInviteReq req) { public void expertInviteByCreate(ExpertInviteReq req) {
String key = INVITED_RULE_CREATE + req.getMeetingId(); String key = INVITED_RULE_CREATE + req.getMeetingId();
@@ -151,7 +174,7 @@ public class MeetingManage {
if (ExpertInviteTypeEnum.RANDOM.eq(req.getInviteType())) { if (ExpertInviteTypeEnum.RANDOM.eq(req.getInviteType())) {
List<RandomInviteRuleDTO> randomRules = req.getRandomRules(); List<RandomInviteRuleDTO> randomRules = req.getRandomRules();
Assert.notEmpty(randomRules, "随机抽取规则不能为空"); Assert.notEmpty(randomRules, "随机抽取规则不能为空");
AvoidInfoDTO avoidInfo = req.getAvoidRule();
AvoidRuleDTO avoidInfo = req.getAvoidRule();
Assert.notNull(avoidInfo, "回避信息不能为空"); Assert.notNull(avoidInfo, "回避信息不能为空");
// 随机抽取的话则需进行抽取数量校验 // 随机抽取的话则需进行抽取数量校验
ExpertCountOnChangeVO countOnChange = expertCountOnChange(req); ExpertCountOnChangeVO countOnChange = expertCountOnChange(req);
@@ -163,23 +186,21 @@ public class MeetingManage {
Integer inviteCount = randomRules.get(i).getCount(); Integer inviteCount = randomRules.get(i).getCount();
Assert.isTrue(checkCount >= inviteCount, "可供抽取的专家数量不足"); Assert.isTrue(checkCount >= inviteCount, "可供抽取的专家数量不足");
} }
expertInviteManage.expertRandomInviteByMeetingCreate(meeting, randomRules, avoidInfo);
expertInviteManage.expertInviteByMeetingCreate(meeting, randomRules, avoidInfo);
expertInviteTask.addInviteExpertTaskByMeetingCreate(meeting.getId(), 5); expertInviteTask.addInviteExpertTaskByMeetingCreate(meeting.getId(), 5);
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class); LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class);
update.set(Meeting::getInviteStatus, false); update.set(Meeting::getInviteStatus, false);
update.eq(Meeting::getId, meeting.getId()); update.eq(Meeting::getId, meeting.getId());
meetingService.update(update); meetingService.update(update);
// 回避规则 // 回避规则
if (avoidInfo != null) {
ExpertInviteAvoidRule avoidRule = new ExpertInviteAvoidRule();
avoidRule.setMeetingId(meeting.getId());
// 未传值时设置为0 表示不限制周参与次数
avoidRule.setWeekInviteCount(ObjectUtil.defaultIfNull(avoidRule.getWeekInviteCount(), 0));
avoidRule.setAvoidOrgIds(CollUtils.joinByComma(avoidInfo.getAvoidOrgIdList()));
avoidRule.setAvoidUnitIds(CollUtils.joinByComma(avoidInfo.getAvoidUnitIdList()));
avoidRule.setAvoidExpertIds(CollUtils.joinByComma(avoidInfo.getExpertIds()));
inviteAvoidRuleService.save(avoidRule);
}
ExpertInviteAvoidRule avoidRule = new ExpertInviteAvoidRule();
avoidRule.setMeetingId(meeting.getId());
// 未传值时设置为0 表示不限制周参与次数
avoidRule.setWeekInviteCount(ObjectUtil.defaultIfNull(avoidRule.getWeekInviteCount(), 0));
avoidRule.setAvoidOrgIds(CollUtils.joinByComma(avoidInfo.getAvoidOrgIdList()));
avoidRule.setAvoidUnitIds(CollUtils.joinByComma(avoidInfo.getAvoidUnitIdList()));
avoidRule.setAvoidExpertIds(CollUtils.joinByComma(avoidInfo.getExpertIds()));
inviteAvoidRuleService.save(avoidRule);
} else { } else {
// 指定邀请 // 指定邀请
AppointInviteRuleDTO appointRule = req.getAppointRule(); AppointInviteRuleDTO appointRule = req.getAppointRule();
@@ -449,7 +470,7 @@ public class MeetingManage {
} }
result.getRandomRules().add(randomRule); result.getRandomRules().add(randomRule);
}); });
AvoidInfoDTO avoidInfo = inviteAvoidRuleService.getAvoidInfoDto(meetingId);
AvoidRuleDTO avoidInfo = inviteAvoidRuleService.getAvoidInfoDto(meetingId);
AvoidInfoVO vo = new AvoidInfoVO(); AvoidInfoVO vo = new AvoidInfoVO();
vo.setAvoidOrgIds(avoidInfo.getAvoidOrgIdList()); vo.setAvoidOrgIds(avoidInfo.getAvoidOrgIdList());
vo.setAvoidUnitIds(avoidInfo.getAvoidUnitIdList()); vo.setAvoidUnitIds(avoidInfo.getAvoidUnitIdList());
@@ -469,75 +490,6 @@ public class MeetingManage {
return result; return result;
} }


public void expertRemove(ExpertRemoveReq po) {
LambdaUpdateWrapper<MeetingExpert> update = Wrappers.lambdaUpdate(MeetingExpert.class)
.eq(MeetingExpert::getId, po.getExpertMeetingId())
.set(MeetingExpert::getStatus, ExpertAttendStatusEnum.REMOVED.getCode());
meetingExpertService.update(update);
}

@Transactional(rollbackFor = Exception.class)
public void expertReplace(ExpertRemoveReq po) {
MeetingExpert meetingExpert = meetingExpertService.getById(po.getExpertMeetingId());
ExpertUserFullInfo expertFullInfo;
Long ruleId = 0L;
Meeting meeting = meetingService.getById(po.getMeetingId());
if (po.getExpertId() != null) {
// 指定邀请替换
List<ExpertUserFullInfo> userInfos = meetingManageHelper.appointExpertCheck(po.getMeetingId(), Collections.singletonList(po.getExpertId()));
expertFullInfo = userInfos.get(0);
} else {
List<ExpertInviteRule> inviteRules = inviteRuleService.listByMeetingId(po.getMeetingId());
// 邀请规则
RandomInviteRuleDTO randomInviteRuleDto = null;
for (ExpertInviteRule rule : inviteRules) {
if (rule.getInviteType().equals(ExpertInviteTypeEnum.RANDOM.getCode()) &&
rule.getId().equals(meetingExpert.getRuleId())) {
randomInviteRuleDto = JSON.parseObject(rule.getInviteRule(), RandomInviteRuleDTO.class);
ruleId = rule.getId();
break;
}
}
// 回避规则
AvoidInfoDTO avoidInfoDto = meetingManageHelper.getAvoidInfoDto(po.getMeetingId());
// 添加回避该替换的专家
List<Long> expertIds = avoidInfoDto.getExpertIds();
if (CollUtil.isEmpty(expertIds)) {
expertIds = new ArrayList<>();
}
expertIds.add(meetingExpert.getExpertId());
avoidInfoDto.setExpertIds(expertIds);
meetingManageHelper.saveAvoidInfo(po.getMeetingId(), avoidInfoDto.getExpertIds());

List<MeetingExpert> meetingExperts = meetingExpertService.listByMeetingId(po.getMeetingId());
ExpertChooseDTO expertChooseDto = expertInviteManage.expertReplaceByRandomRule(avoidInfoDto, randomInviteRuleDto,
meetingExperts, 1, meeting.getStartTime(), meeting.getEndTime(), meetingExpert.getExpertId());
Assert.isTrue(expertChooseDto.getTotal() > 0, "暂无专家可供替换");
expertFullInfo = expertChooseDto.getExperts().get(0);
expertInviteTask.addInviteExpertTask(po.getMeetingId());
}
LambdaUpdateWrapper<MeetingExpert> update = Wrappers.lambdaUpdate(MeetingExpert.class)
.eq(MeetingExpert::getId, po.getExpertMeetingId())
.set(MeetingExpert::getUpdateOn, LocalDateTime.now())
.set(MeetingExpert::getPreStatus, meetingExpert.getStatus())
.set(MeetingExpert::getStatus, ExpertAttendStatusEnum.REPLACED.getCode());
meetingExpertService.update(update);
MeetingExpert me;
if (po.getExpertId() == null) {
me = ExpertInviteBuilder.getExpertByRandom(po.getMeetingId(), expertFullInfo, ruleId);
} else {
me = ExpertInviteBuilder.getExpertByAppoint(po.getMeetingId(), expertFullInfo, ruleId);
}
me.setStatus(ExpertAttendStatusEnum.NOTICING.getCode());
me.setPreId(po.getExpertMeetingId());
yxtCallOrSmsHelper.callByMeetingExperts(meeting, Collections.singletonList(me));
meetingExpertService.save(me);
// 发送专家替换短信 TODO
// String meetingType = dictionaryCache.getByCode(meeting.getType()).getName();
// SendSmsContext context = YxtSmsContextBuilder.smsToExpertByReplace(meeting, meetingExpert, meetingType);
// yxtCallOrSmsHelper.sendSms(context);
}

public void batchAppointExperts(BatchAppointExpertsReq req) { public void batchAppointExperts(BatchAppointExpertsReq req) {
Long meetingId = req.getMeetingId(); Long meetingId = req.getMeetingId();
String key = "BATCH_APPOINT_EXPERT:" + meetingId; String key = "BATCH_APPOINT_EXPERT:" + meetingId;


+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/IExpertInviteAvoidRuleService.java View File

@@ -2,7 +2,7 @@ package com.ningdatech.pmapi.meeting.service;


import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteAvoidRule; import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteAvoidRule;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;


/** /**
* <p> * <p>
@@ -23,6 +23,6 @@ public interface IExpertInviteAvoidRuleService extends IService<ExpertInviteAvoi
* @return com.ningdatech.emapi.meeting.entity.dto.AvoidInfoDto * @return com.ningdatech.emapi.meeting.entity.dto.AvoidInfoDto
* @author WendyYang * @author WendyYang
**/ **/
AvoidInfoDTO getAvoidInfoDto(Long meetingId);
AvoidRuleDTO getAvoidInfoDto(Long meetingId);


} }

+ 13
- 2
pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/IMeetingExpertService.java View File

@@ -27,7 +27,7 @@ public interface IMeetingExpertService extends IService<MeetingExpert> {
* 查询专家的参与状态 * 查询专家的参与状态
* *
* @param expertId 专家ID * @param expertId 专家ID
* @param status 状态{@link MeetingStatus.Expert}
* @param status 状态
* @param meetingIds 会议ID * @param meetingIds 会议ID
* @return 会议参加状态统计 * @return 会议参加状态统计
* @author WendyYang * @author WendyYang
@@ -35,7 +35,7 @@ public interface IMeetingExpertService extends IService<MeetingExpert> {
List<MeetingAndAttendStatusDTO> listByExpertIdAndStatus(Long expertId, Integer status, List<Long> meetingIds); List<MeetingAndAttendStatusDTO> listByExpertIdAndStatus(Long expertId, Integer status, List<Long> meetingIds);


/** /**
* 查询每个事物的确认进度
* 查询每个会议的确认进度
* *
* @param meetingIds 事务ID * @param meetingIds 事务ID
* @return 确认进度 * @return 确认进度
@@ -132,4 +132,15 @@ public interface IMeetingExpertService extends IService<MeetingExpert> {
**/ **/
List<MeetingExpert> listExpertLastByMeetingIds(Collection<Long> meetingIds); List<MeetingExpert> listExpertLastByMeetingIds(Collection<Long> meetingIds);


/**
* 查询会议的所有被抽取人最后一条记录
*
* @param meetingId 会议ID
* @return 抽取记录
* @author WendyYang
**/
default List<MeetingExpert> listExpertLastByMeetingId(Long meetingId) {
return listExpertLastByMeetingIds(Collections.singletonList(meetingId));
}

} }

+ 3
- 3
pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/impl/ExpertInviteAvoidRuleServiceImpl.java View File

@@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ningdatech.pmapi.common.util.BizUtils; import com.ningdatech.pmapi.common.util.BizUtils;
import com.ningdatech.pmapi.common.util.StrUtils; import com.ningdatech.pmapi.common.util.StrUtils;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteAvoidRule; import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteAvoidRule;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.mapper.ExpertInviteAvoidRuleMapper; import com.ningdatech.pmapi.meeting.mapper.ExpertInviteAvoidRuleMapper;
import com.ningdatech.pmapi.meeting.service.IExpertInviteAvoidRuleService; import com.ningdatech.pmapi.meeting.service.IExpertInviteAvoidRuleService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -30,12 +30,12 @@ public class ExpertInviteAvoidRuleServiceImpl extends ServiceImpl<ExpertInviteAv
} }


@Override @Override
public AvoidInfoDTO getAvoidInfoDto(Long meetingId) {
public AvoidRuleDTO getAvoidInfoDto(Long meetingId) {
ExpertInviteAvoidRule avoidRule = getByMeetingId(meetingId); ExpertInviteAvoidRule avoidRule = getByMeetingId(meetingId);
if (avoidRule == null) { if (avoidRule == null) {
return null; return null;
} }
AvoidInfoDTO avoidInfo = new AvoidInfoDTO();
AvoidRuleDTO avoidInfo = new AvoidRuleDTO();
avoidInfo.setAvoidOrgIdList(StrUtils.split(avoidRule.getAvoidOrgIds())); avoidInfo.setAvoidOrgIdList(StrUtils.split(avoidRule.getAvoidOrgIds()));
avoidInfo.setAvoidUnitIdList(StrUtils.split(avoidRule.getAvoidUnitIds())); avoidInfo.setAvoidUnitIdList(StrUtils.split(avoidRule.getAvoidUnitIds()));
avoidInfo.setExpertIds(BizUtils.splitToLong(avoidRule.getAvoidExpertIds())); avoidInfo.setExpertIds(BizUtils.splitToLong(avoidRule.getAvoidExpertIds()));


+ 66
- 67
pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java View File

@@ -1,23 +1,20 @@
package com.ningdatech.pmapi.meeting.task; package com.ningdatech.pmapi.meeting.task;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.CollUtils; import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.cache.model.cache.CacheKey;
import com.ningdatech.cache.model.cache.CacheHashKey;
import com.ningdatech.cache.repository.CachePlusOps; import com.ningdatech.cache.repository.CachePlusOps;
import com.ningdatech.pmapi.common.util.SpringContextHolder; import com.ningdatech.pmapi.common.util.SpringContextHolder;
import com.ningdatech.pmapi.meeting.builder.ExpertInviteBuilder; import com.ningdatech.pmapi.meeting.builder.ExpertInviteBuilder;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting; import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO; import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO;
import com.ningdatech.pmapi.meeting.entity.dto.MeetingInviteCacheDTO;
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO; import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper; import com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper;
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper; import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper;
import com.ningdatech.pmapi.meeting.manage.ExpertInviteManage; import com.ningdatech.pmapi.meeting.manage.ExpertInviteManage;
@@ -29,6 +26,7 @@ import com.ningdatech.pmapi.user.util.LoginUserUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.aop.framework.AopContext; import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -42,15 +40,12 @@ import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;




@@ -69,9 +64,13 @@ public class ExpertInviteTask {


private final ExpertInviteHelper expertInviteHelper; private final ExpertInviteHelper expertInviteHelper;
private final RandomInviteProperties properties; private final RandomInviteProperties properties;

private static final String MEETING_ID_INVITE_RANDOM = "MEETING_ID_INVITE_RANDOM"; private static final String MEETING_ID_INVITE_RANDOM = "MEETING_ID_INVITE_RANDOM";
private static final CacheKey CACHE_KEY = new CacheKey(MEETING_ID_INVITE_RANDOM);
private static final CacheHashKey CACHE_KEY = new CacheHashKey();

static {
CACHE_KEY.setKey(MEETING_ID_INVITE_RANDOM);
CACHE_KEY.setExpire(Duration.ofDays(100));
}


private final CachePlusOps cachePlusOps; private final CachePlusOps cachePlusOps;
@Qualifier("expertInviteScheduler") @Qualifier("expertInviteScheduler")
@@ -81,38 +80,38 @@ public class ExpertInviteTask {
private final IExpertInviteRuleService inviteRuleService; private final IExpertInviteRuleService inviteRuleService;
private final IMeetingService meetingService; private final IMeetingService meetingService;
private final ExpertInviteManage expertInviteManage; private final ExpertInviteManage expertInviteManage;
private final IExpertInviteAvoidRuleService expertInviteAvoidRuleService;

private final IExpertInviteAvoidRuleService inviteAvoidRuleService;
private final YxtCallOrSmsHelper yxtCallOrSmsHelper; private final YxtCallOrSmsHelper yxtCallOrSmsHelper;


public ExpertInviteTask currProxy() {
return (ExpertInviteTask) AopContext.currentProxy();
}

/** /**
* 用来存入线程执行情况, 方便于停止定时任务时使用 * 用来存入线程执行情况, 方便于停止定时任务时使用
*/ */
protected static final ConcurrentMap<Long, ScheduledFuture<?>> INVITE_MAP = new ConcurrentHashMap<>(); protected static final ConcurrentMap<Long, ScheduledFuture<?>> INVITE_MAP = new ConcurrentHashMap<>();


public ExpertInviteTask currProxy() {
return (ExpertInviteTask) AopContext.currentProxy();
}

@PostConstruct @PostConstruct
public void initTask() { public void initTask() {
if (!properties.getEnable()) { if (!properties.getEnable()) {
log.warn("随机邀请已关闭……"); log.warn("随机邀请已关闭……");
return; return;
} }
// initInviteTaskByStart();
initInviteTaskAfterAppStarted();
} }


/** /**
* 项目重启之后重新初始化邀请任务 * 项目重启之后重新初始化邀请任务
*/ */
private void initInviteTaskByStart() {
Set<Object> meetingIds = cachePlusOps.sMembers(CACHE_KEY);
if (meetingIds == null || meetingIds.isEmpty()) {
private void initInviteTaskAfterAppStarted() {
Map<Long, MeetingInviteCacheDTO> meetingIdMap = cachePlusOps.hGetAll(CACHE_KEY);
if (MapUtils.isEmpty(meetingIdMap)) {
log.info("暂无需要初始化的抽取会议信息");
return; return;
} }
for (Object meetingId : meetingIds) {
addInviteExpertTask(Convert.toLong(meetingId), true, properties.getInviteDelay());
for (MeetingInviteCacheDTO cache : meetingIdMap.values()) {
addInviteExpertTask(cache.getMeetingId(), true, properties.getInviteDelay(), cache.getInvitedRefused());
} }
} }


@@ -123,25 +122,27 @@ public class ExpertInviteTask {
* @return boolean * @return boolean
* @author WendyYang * @author WendyYang
**/ **/
private boolean inviteCheck(Long meetingId) {
List<ExpertInviteRule> expertInviteRules = inviteRuleService.listByMeetingId(meetingId);
Function<ExpertInviteRule, ExpertInviteTypeEnum> groupKey = w -> ExpertInviteTypeEnum.getByCode(w.getInviteType());
Map<ExpertInviteTypeEnum, List<ExpertInviteRule>> groupByType = CollUtils.group(expertInviteRules, groupKey);
List<ExpertInviteRule> randomRules = groupByType.get(ExpertInviteTypeEnum.RANDOM);
if (CollUtil.isEmpty(randomRules)) {
return false;
private boolean inviteCountCheck(Long meetingId) {
Map<Long, RandomInviteRuleDTO> ruleMap = inviteRuleService.randomRuleByMeetingId(meetingId);
if (ruleMap.isEmpty()) {
return Boolean.FALSE;
} }
Map<Long, ExpertInviteRule> ruleMap = CollUtils.listToMap(randomRules, ExpertInviteRule::getId);
LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class) LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class)
.select(MeetingExpert::getRuleId, MeetingExpert::getStatus)
.in(MeetingExpert::getRuleId, ruleMap.keySet()) .in(MeetingExpert::getRuleId, ruleMap.keySet())
.in(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode()); .in(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode());
List<MeetingExpert> meetingExperts = meetingExpertService.list(query);
int totalCount = CollUtils.sum(randomRules, ExpertInviteRule::getInviteCount);
boolean needed = totalCount > meetingExperts.size();
if (!needed) {
cancelByMeetingId(meetingId);
List<MeetingExpert> experts = meetingExpertService.list(query);
if (experts.isEmpty()) {
return Boolean.FALSE;
}
Map<Long, Long> cntMap = CollUtils.groupCount(experts, MeetingExpert::getRuleId);
for (Map.Entry<Long, RandomInviteRuleDTO> entry : ruleMap.entrySet()) {
Long agreeCnt = cntMap.getOrDefault(entry.getKey(), 0L);
if (agreeCnt < entry.getValue().getCount()) {
return Boolean.FALSE;
}
} }
return needed;
return Boolean.TRUE;
} }


/** /**
@@ -151,9 +152,8 @@ public class ExpertInviteTask {
* @author WendyYang * @author WendyYang
**/ **/
public void addInviteExpertTask(Long meetingId) { public void addInviteExpertTask(Long meetingId) {
boolean contains = INVITE_MAP.containsKey(meetingId);
if (!contains) {
addInviteExpertTask(meetingId, false, properties.getInviteDelay());
if (!INVITE_MAP.containsKey(meetingId)) {
addInviteExpertTask(meetingId, false, properties.getInviteDelay(), false);
log.info("重置会议的随机抽取状态:{}", meetingId); log.info("重置会议的随机抽取状态:{}", meetingId);
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class); LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class);
update.set(Meeting::getInviteStatus, false); update.set(Meeting::getInviteStatus, false);
@@ -170,17 +170,19 @@ public class ExpertInviteTask {
* @param meetingId 会议ID * @param meetingId 会议ID
* @param checked 是否前置校验 * @param checked 是否前置校验
* @param delayedMinutes 延迟执行时间 * @param delayedMinutes 延迟执行时间
* @param invitedRefused 是否可以邀请被拒绝的专家
* @author WendyYang * @author WendyYang
**/ **/
public void addInviteExpertTask(Long meetingId, boolean checked, int delayedMinutes) {
if (checked && !inviteCheck(meetingId)) {
public void addInviteExpertTask(Long meetingId, boolean checked, int delayedMinutes, boolean invitedRefused) {
if (checked && !inviteCountCheck(meetingId)) {
// 如果抽取数量满足直接返回
return; return;
} }
Instant startTime = LocalDateTime.now().plusMinutes(delayedMinutes).atZone(ZoneId.systemDefault()).toInstant(); Instant startTime = LocalDateTime.now().plusMinutes(delayedMinutes).atZone(ZoneId.systemDefault()).toInstant();
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(() -> { ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(() -> {
ExpertInviteTask bean = SpringContextHolder.getBean(ExpertInviteTask.class); ExpertInviteTask bean = SpringContextHolder.getBean(ExpertInviteTask.class);
try { try {
bean.invite(meetingId);
bean.invite(meetingId, invitedRefused);
} catch (Exception e) { } catch (Exception e) {
log.error("执行专家邀请任务异常:{}", meetingId, e); log.error("执行专家邀请任务异常:{}", meetingId, e);
} }
@@ -189,53 +191,55 @@ public class ExpertInviteTask {
log.info("添加专家抽取后台任务:{}", meetingId); log.info("添加专家抽取后台任务:{}", meetingId);
} }


/**
* 创建会议时添加抽取任务
*
* @param meetingId 会议ID
* @param delayedMinutes 延迟时间
* @author WendyYang
**/
public void addInviteExpertTaskByMeetingCreate(Long meetingId, int delayedMinutes) { public void addInviteExpertTaskByMeetingCreate(Long meetingId, int delayedMinutes) {
Assert.isTrue(properties.getEnable(), "随机邀请已关闭"); Assert.isTrue(properties.getEnable(), "随机邀请已关闭");
addInviteExpertTask(meetingId, false, delayedMinutes);
addInviteExpertTask(meetingId, false, delayedMinutes, false);
cachePlusOps.sAdd(CACHE_KEY, meetingId); cachePlusOps.sAdd(CACHE_KEY, meetingId);
} }


@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void invite(Long meetingId) {
public void invite(Long meetingId, Boolean invitedRefused) {
log.info("开始进行专家后台抽取:{}", meetingId); log.info("开始进行专家后台抽取:{}", meetingId);
Meeting meeting = meetingService.getById(meetingId); Meeting meeting = meetingService.getById(meetingId);
if (meeting.getStartTime().isBefore(LocalDateTime.now())) { if (meeting.getStartTime().isBefore(LocalDateTime.now())) {
// 会议开始结束随机抽取
cancelByMeetingId(meetingId);
log.info("会议已开始停止抽取:{}", meeting); log.info("会议已开始停止抽取:{}", meeting);
cancelByMeetingId(meetingId);
return; return;
} }
// 随机邀请规则 // 随机邀请规则
Map<Long, RandomInviteRuleDTO> ruleMap = inviteRuleService.randomRuleByMeetingId(meetingId); Map<Long, RandomInviteRuleDTO> ruleMap = inviteRuleService.randomRuleByMeetingId(meetingId);
// 回避规则 // 回避规则
AvoidInfoDTO avoidInfoDto = expertInviteAvoidRuleService.getAvoidInfoDto(meetingId);
AvoidRuleDTO avoidRule = inviteAvoidRuleService.getAvoidInfoDto(meetingId);
// 还需要抽取的规则数量 // 还需要抽取的规则数量
AtomicInteger notIgnoreCnt = new AtomicInteger(ruleMap.size()); AtomicInteger notIgnoreCnt = new AtomicInteger(ruleMap.size());
AtomicInteger notSupportCnt = new AtomicInteger(0); AtomicInteger notSupportCnt = new AtomicInteger(0);
ruleMap.forEach((ruleId, value) -> { ruleMap.forEach((ruleId, value) -> {
List<Long> singletonList = Collections.singletonList(meetingId);
List<MeetingExpert> tempExperts = meetingExpertService.listExpertLastByMeetingIds(singletonList);
Map<Long, MeetingExpert> expertMap = CollUtils.listToMap(tempExperts, MeetingExpert::getExpertId);
Map<Long, MeetingExpert> replacedMap = expertMap.values().stream().filter(w -> w.getPreId() > 0)
.collect(Collectors.toMap(MeetingExpert::getPreId, w -> w));
Map<Long, ExpertCntBO> countMap = countByAgree(expertMap, replacedMap);
// 已确认参加、通话中数量
List<MeetingExpert> tmpExperts = meetingExpertService.listExpertLastByMeetingId(meetingId);
Map<Long, MeetingExpert> expertMap = CollUtils.listToMap(tmpExperts, MeetingExpert::getExpertId);
// 统计通知中与同意参加专家数量
Map<Long, ExpertCntBO> countMap = countByAgree(expertMap);
ExpertCntBO cnt = countMap.getOrDefault(ruleId, ExpertCntBO.zeroInit()); ExpertCntBO cnt = countMap.getOrDefault(ruleId, ExpertCntBO.zeroInit());
int tempCurrent = cnt.getAgreeCnt() + cnt.getNoticeCnt();
if (tempCurrent == value.getCount()) {
int wouldAttendCnt = cnt.getAgreeCnt() + cnt.getNoticeCnt();
if (wouldAttendCnt == value.getCount()) {
if (cnt.getAgreeCnt().equals(value.getCount())) { if (cnt.getAgreeCnt().equals(value.getCount())) {
notIgnoreCnt.decrementAndGet(); notIgnoreCnt.decrementAndGet();
} }
return; return;
} }
int currInviteCnt = value.getCount() - tempCurrent;
ExpertChooseDTO expertChoose = expertInviteManage.expertReplaceByRandomRule(avoidInfoDto, value,
expertMap.values(), currInviteCnt, meeting.getStartTime(), meeting.getEndTime(), null);
int needInviteCnt = value.getCount() - wouldAttendCnt;
ExpertChooseDTO expertChoose = expertInviteManage.expertReplaceByRandomRule(avoidRule, value,
tmpExperts, needInviteCnt, meeting.getStartTime(), meeting.getEndTime(), invitedRefused);


if (expertChoose.getTotal() > 0) { if (expertChoose.getTotal() > 0) {
List<MeetingExpert> expertMeetings = CollUtils.convert(expertChoose.getExperts(), w -> { List<MeetingExpert> expertMeetings = CollUtils.convert(expertChoose.getExperts(), w -> {
MeetingExpert expert = ExpertInviteBuilder.getExpertByRandom(meetingId, w, ruleId); MeetingExpert expert = ExpertInviteBuilder.getExpertByRandom(meetingId, w, ruleId);
expert.setPreStatus(ExpertAttendStatusEnum.NOTICING.getCode());
expert.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); expert.setStatus(ExpertAttendStatusEnum.NOTICING.getCode());
return expert; return expert;
}); });
@@ -276,7 +280,7 @@ public class ExpertInviteTask {


//================================================================================================================== //==================================================================================================================


private Map<Long, ExpertCntBO> countByAgree(Map<Long, MeetingExpert> expertMap, Map<Long, MeetingExpert> replacedMap) {
private Map<Long, ExpertCntBO> countByAgree(Map<Long, MeetingExpert> expertMap) {
return expertMap.entrySet().stream() return expertMap.entrySet().stream()
.collect(Collectors.groupingBy(w -> w.getValue().getRuleId(), .collect(Collectors.groupingBy(w -> w.getValue().getRuleId(),
Collectors.collectingAndThen(Collectors.mapping(Map.Entry::getValue, Collectors.toList()), w -> { Collectors.collectingAndThen(Collectors.mapping(Map.Entry::getValue, Collectors.toList()), w -> {
@@ -286,11 +290,6 @@ public class ExpertInviteTask {
cnt.incrAgreeCnt(); cnt.incrAgreeCnt();
} else if (ExpertAttendStatusEnum.NOTICING.eq(expert.getStatus())) { } else if (ExpertAttendStatusEnum.NOTICING.eq(expert.getStatus())) {
cnt.incrNoticeCnt(); cnt.incrNoticeCnt();
} else if (ExpertAttendStatusEnum.REPLACED.eq(expert.getStatus())) {
MeetingExpert replacedExpert = replacedMap.get(expert.getId());
if (replacedExpert != null && ExpertAttendStatusEnum.AGREED.eq(replacedExpert.getStatus())) {
cnt.incrAgreeCnt();
}
} }
} }
return cnt; return cnt;


+ 1
- 1
pmapi/src/main/resources/application-dev.yml View File

@@ -15,7 +15,7 @@ spring:
timeout: 5000 timeout: 5000
host: 47.98.125.47 host: 47.98.125.47
port: 26379 port: 26379
database: 0
database: 4
password: Ndkj1234 password: Ndkj1234
jedis: jedis:
pool: pool:


Loading…
Cancel
Save