diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/common/util/BizUtils.java b/pmapi/src/main/java/com/ningdatech/pmapi/common/util/BizUtils.java index 15d5ec3..809dca5 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/common/util/BizUtils.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/common/util/BizUtils.java @@ -105,4 +105,8 @@ public class BizUtils { }))); } + public static String inSqlJoin(List strings) { + return strings.stream().map(w -> "'" + w + "'").collect(Collectors.joining(StrPool.COMMA, StrPool.LEFT_BRACKET, StrPool.RIGHT_BRACKET)); + } + } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/expert/service/IExpertUserFullInfoService.java b/pmapi/src/main/java/com/ningdatech/pmapi/expert/service/IExpertUserFullInfoService.java index a0a6c27..129e68b 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/expert/service/IExpertUserFullInfoService.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/expert/service/IExpertUserFullInfoService.java @@ -1,8 +1,13 @@ package com.ningdatech.pmapi.expert.service; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.IService; +import com.ningdatech.basic.util.CollUtils; import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo; +import java.util.Collection; import java.util.List; /** @@ -33,7 +38,6 @@ public interface IExpertUserFullInfoService extends IService List listByUserId(List userId); - /** * 批量查询专家用户信息 * @@ -42,4 +46,12 @@ public interface IExpertUserFullInfoService extends IService */ List listByUserIds(List userIds); + default List listCompanyUniqCodeByUserIds(Collection userIds) { + LambdaQueryWrapper query = Wrappers + .lambdaQuery(ExpertUserFullInfo.class) + .select(ExpertUserFullInfo::getCompanyUniqCode) + .in(ExpertUserFullInfo::getUserId, userIds); + return CollUtils.fieldList(list(query), ExpertUserFullInfo::getCompanyUniqCode); + } + } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/leave/entity/domain/ExpertLeave.java b/pmapi/src/main/java/com/ningdatech/pmapi/leave/entity/domain/ExpertLeave.java index 4aca8d3..12ed67f 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/leave/entity/domain/ExpertLeave.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/leave/entity/domain/ExpertLeave.java @@ -1,8 +1,6 @@ package com.ningdatech.pmapi.leave.entity.domain; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -48,15 +46,19 @@ public class ExpertLeave implements Serializable { private String creator; @ApiModelProperty("创建人") + @TableField(fill = FieldFill.INSERT_UPDATE) private Long createBy; @ApiModelProperty("创建时间") + @TableField(fill = FieldFill.INSERT) private LocalDateTime createOn; @ApiModelProperty("修改人") + @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateBy; @ApiModelProperty("修改时间") + @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateOn; @ApiModelProperty("请假开始时间") @@ -75,9 +77,4 @@ public class ExpertLeave implements Serializable { private Integer status; - public void setUpdateAndCreate(Long createBy, LocalDateTime createOn) { - this.updateBy = this.createBy = createBy; - this.updateOn = this.createOn = createOn; - } - } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/leave/manage/LeaveManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/leave/manage/LeaveManage.java index 8246530..76bd25e 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/leave/manage/LeaveManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/leave/manage/LeaveManage.java @@ -150,7 +150,7 @@ public class LeaveManage { leave.setType(po.getType()); leave.setRemark(po.getPostscript()); leave.setLeaveUserId(leaveUserId); - leave.setUpdateAndCreate(applyUserId, now); + leave.setCreator(LoginUserUtil.getUsername()); List> leaveDetailTimes = new ArrayList<>(); if (type.equals(LeaveTypeEnum.FIXED_TERM) || type.equals(LeaveTypeEnum.LONG_TERM)) { boolean fixedTerm = CollUtil.isNotEmpty(po.getFixedType()); diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java index 1cc38c1..cad0c9c 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java @@ -70,6 +70,9 @@ public class ExpertInviteManage { @Value("#{randomInviteProperties.recentMeetingCount}") private Integer recentMeetingCount; + @Value("#{randomInviteProperties.recentDays}") + private Integer recentDays; + private static final Predicate> COLL_EMPTY = (coll) -> coll != null && coll.isEmpty(); private LambdaQueryWrapper buildBaseExpertQuery() { @@ -83,6 +86,36 @@ public class ExpertInviteManage { .eq(ExpertUserFullInfo::getExpertAccountStatus, ExpertAccountStatusEnum.AVAILABLE.getKey()); } + private void buildAvoidCompanyAndBusinessStrip(LambdaQueryWrapper query, List units, List strips) { + if (CollUtil.isNotEmpty(units)) { + String unitStr = BizUtils.inSqlJoin(units); + query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" + + " and company_uniq_code in " + unitStr); + } + if (CollUtil.isNotEmpty(strips)) { + String orgStr = BizUtils.inSqlJoin(strips); + query.notExists("select 1 from expert_gov_business_strip egbs where egbs.expert_user_id = nd_expert_user_full_info.user_id" + + " and business_strip_code in " + orgStr); + } + } + + /** + * 获取一周内被抽中并同意参会的专家ID + * + * @param agreeCnt 一周内被抽中并同意参会次数 + * @param sTime 会议开始时间 + * @param days 天数 + * @return java.util.List + * @author WendyYang + **/ + private List listAgreedUserIdByRecentMeetings(int agreeCnt, int days, LocalDateTime sTime) { + if (agreeCnt == 0 || days == 0) { + return Collections.emptyList(); + } + LocalDateTime beginLimit = sTime.minusDays(days); + return meetingExpertService.listAgreeExpertIdByRecentDaysAndAgreeCount(agreeCnt, beginLimit, sTime); + } + /** * 增加专家层级限制 * @@ -249,13 +282,13 @@ public class ExpertInviteManage { * * @param avoidRule 回避信息 * @param randomRule 抽取规则 - * @param appointExpertIds 指定抽取专家ID + * @param invitedExpertIds 指定抽取专家ID * @return 满足抽取条件的专家 * @author WendyYang **/ public ExpertChooseDTO expertInviteByRandomRule(AvoidRuleDTO avoidRule, RandomInviteRuleDTO randomRule, - List appointExpertIds, + List invitedExpertIds, LocalDateTime sTime, LocalDateTime eTime) { ExpertChooseDTO result = new ExpertChooseDTO(new ArrayList<>(), 0); @@ -265,17 +298,19 @@ public class ExpertInviteManage { } boolean avoidExpert = CollUtil.isNotEmpty(avoidRule.getExpertIds()); boolean avoidCompany = CollUtil.isNotEmpty(avoidRule.getAvoidUnitIdList()); - Set tmpAvoidCompany = new HashSet<>(); + Set avoidCompanyUniqCodes = new HashSet<>(); if (avoidCompany) { - tmpAvoidCompany.addAll(avoidRule.getAvoidUnitIdList()); + avoidCompanyUniqCodes.addAll(avoidRule.getAvoidUnitIdList()); + } + if (CollUtil.isNotEmpty(invitedExpertIds)) { + List tmpCompanyUniqCodes = expertUserFullInfoService.listCompanyUniqCodeByUserIds(invitedExpertIds); + avoidCompanyUniqCodes.addAll(tmpCompanyUniqCodes); } // 回避信息 LambdaQueryWrapper query = buildBaseExpertQuery(); - query.notIn(!tmpAvoidCompany.isEmpty(), ExpertUserFullInfo::getCompanyUniqCode, tmpAvoidCompany); - if (avoidCompany) { - query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" + - " and company_uniq_code in ({0})", CollUtils.joinByComma(avoidRule.getAvoidUnitIdList())); - } + query.notIn(!avoidCompanyUniqCodes.isEmpty(), ExpertUserFullInfo::getCompanyUniqCode, avoidCompanyUniqCodes); + // 处理回避单位与回避条线 + buildAvoidCompanyAndBusinessStrip(query, avoidRule.getAvoidUnitIdList(), avoidRule.getAvoidOrgIdList()); Set expertIdsIn = new HashSet<>(); Set expertIdsNotIn = new HashSet<>(); if (CollUtil.isNotEmpty(merge.getExpertIdsIn())) { @@ -283,6 +318,12 @@ public class ExpertInviteManage { } else if (CollUtil.isNotEmpty(merge.getExpertIdsNotIn())) { expertIdsNotIn.addAll(merge.getExpertIdsNotIn()); } + // 处理回避专家次数 + if (avoidRule.getWeekInviteCount() != null) { + Integer weekInviteCount = avoidRule.getWeekInviteCount(); + List tmpExpertIdsNotIn = listAgreedUserIdByRecentMeetings(weekInviteCount, recentDays, sTime); + expertIdsNotIn.addAll(tmpExpertIdsNotIn); + } // 处理专家层级 addRegionLimit(query, randomRule); if (!expertIdsIn.isEmpty()) { @@ -293,8 +334,8 @@ public class ExpertInviteManage { return result; } } - if (CollUtil.isNotEmpty(appointExpertIds)) { - expertIdsIn.removeIf(appointExpertIds::contains); + if (CollUtil.isNotEmpty(invitedExpertIds)) { + expertIdsIn.removeIf(invitedExpertIds::contains); if (expertIdsIn.isEmpty()) { return result; } @@ -305,8 +346,8 @@ public class ExpertInviteManage { if (expertIdsIn.isEmpty()) { return result; } - } else if (avoidExpert || CollUtil.isNotEmpty(appointExpertIds)) { - Set tmpExpert = expertInviteHelper.getAvoidExpert(appointExpertIds, avoidRule, sTime, eTime); + } else if (avoidExpert || CollUtil.isNotEmpty(invitedExpertIds)) { + Set tmpExpert = expertInviteHelper.getAvoidExpert(invitedExpertIds, avoidRule, sTime, eTime); expertIdsNotIn.addAll(tmpExpert); } else { Set tmpNotInUserIds = expertInviteHelper.listExpertLeaveOrInvited(sTime, eTime); @@ -365,8 +406,14 @@ public class ExpertInviteManage { LambdaQueryWrapper query = buildBaseExpertQuery(); // 设置回避单位 Set notInCompanyUniqCodeList = new HashSet<>(avoidRule.getAvoidUnitIdList()); - query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" + - " and company_uniq_code in ({0})", CollUtils.joinByComma(avoidRule.getAvoidUnitIdList())); + // 处理回避单位与回避条线 + buildAvoidCompanyAndBusinessStrip(query, avoidRule.getAvoidUnitIdList(), avoidRule.getAvoidOrgIdList()); + // 处理回避专家次数 + if (avoidRule.getWeekInviteCount() != null) { + Integer weekInviteCount = avoidRule.getWeekInviteCount(); + List tmpExpertIdsNotIn = listAgreedUserIdByRecentMeetings(weekInviteCount, recentDays, msTime); + expertIdsNotIn.addAll(tmpExpertIdsNotIn); + } // 处理专家层级 addRegionLimit(query, randomRule); diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.java b/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.java index e6332e3..d13b407 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.java @@ -9,6 +9,7 @@ import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; import com.ningdatech.pmapi.meeting.entity.req.ReviewProjectListReq; import org.apache.ibatis.annotations.Param; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -62,6 +63,19 @@ public interface MeetingExpertMapper extends BaseMapper { @Param("meetingIds") Collection meetingIds); /** + * 查询时间窗口之内参与会议不超过{@code agreeCount}次的专家ID + * + * @param agreeCount 参与次数(包含) + * @param startTime 开始时间 + * @param endTime 结束时间 + * @return 专家ID集合 + * @author WendyYang + **/ + List listAgreeExpertIdByRecentDaysAndAgreeCount(@Param("agreeCount") Integer agreeCount, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + + /** * 根据会议ID与参与状态统计专家数量 * * @param status 会议状态 diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.xml b/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.xml index 4dc5475..dd1c32c 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.xml +++ b/pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.xml @@ -50,6 +50,15 @@ + +