Browse Source

增加确认名单短信通知

tags/24080901
WendyYang 1 year ago
parent
commit
202e90085c
6 changed files with 228 additions and 7 deletions
  1. +24
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/constant/MeetingMsgTemplateConst.java
  2. +147
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingMsgHelper.java
  3. +3
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java
  4. +3
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java
  5. +14
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/staging/service/INdWorkNoticeStagingService.java
  6. +37
    -4
      pmapi/src/main/java/com/ningdatech/pmapi/staging/service/impl/NdWorkNoticeStagingServiceImpl.java

+ 24
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/constant/MeetingMsgTemplateConst.java View File

@@ -0,0 +1,24 @@
package com.ningdatech.pmapi.meeting.constant;

/**
* <p>
* MeetingMsgConst
* </p>
*
* @author WendyYang
* @since 2023/4/20
**/
public interface MeetingMsgTemplateConst {

/**
* 已结束:自动抽取结束,结束时给会议发起人发送浙政钉工作通知、短信:“注意,xxx会议自动抽取已结束,请及时确认是否召开会议”。
*/
String INVITE_END = "注意,%s会议自动抽取已结束,请及时确认是否召开会议";

/**
* 尊敬的【姓名】专家您好,您于【确认时间】接受了信息化项目评审会议邀请,会议时间:【会议时间】,会议地点:【会议地点】。请准时参加评审会议。如有疑问请联系【联系人】(【联系方式】)。
*/
String CONFIRMED_ROSTER = "尊敬的%s专家您好,您于%s接受了信息化项目评审会议邀请,会议时间:%s,会议地点:%s。请准时参加评审会议。如有疑问请联系%s(%s)。";


}

+ 147
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingMsgHelper.java View File

@@ -0,0 +1,147 @@
package com.ningdatech.pmapi.meeting.helper;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.meeting.constant.MeetingMsgTemplateConst;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.organization.model.entity.DingEmployeeInfo;
import com.ningdatech.pmapi.organization.model.entity.DingOrganization;
import com.ningdatech.pmapi.organization.service.IDingEmployeeInfoService;
import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
import com.ningdatech.pmapi.staging.enums.MsgTypeEnum;
import com.ningdatech.pmapi.staging.service.INdWorkNoticeStagingService;
import com.ningdatech.pmapi.sys.model.entity.Notify;
import com.ningdatech.pmapi.sys.service.INotifyService;
import com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo;
import com.ningdatech.pmapi.user.entity.UserInfo;
import com.ningdatech.pmapi.user.service.IUserInfoService;
import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* <p>
* MeetingMsgHelper
* </p>
*
* @author WendyYang
* @since 2023/4/20
**/
@Component
@AllArgsConstructor
public class MeetingMsgHelper {

private final IUserInfoService userInfoService;
private final YxtCallOrSmsHelper yxtCallOrSmsHelper;
private final INdWorkNoticeStagingService workNoticeStagingService;
private final IDingEmployeeInfoService dingEmployeeInfoService;
private final IDingOrganizationService dingOrganizationService;
private final INotifyService notifyService;

private Notify getNotify(Long userId, String msg, Map<String, Object> extraPara) {
Notify notify = new Notify();
notify.setUserId(userId);
notify.setContent(msg);
notify.setReaded(Boolean.FALSE);
notify.setCreateTime(LocalDateTime.now());
String extraJson = JSON.toJSONString(extraPara);
notify.setExtraInfo(extraJson);
return notify;
}

private WorkNoticeInfo getSendWorkNoticeInfo(Long accountId) {
WorkNoticeInfo workNoticeInfo = new WorkNoticeInfo();
workNoticeInfo.setAccountId(accountId);
// 根据浙政钉用户ID获取部门code
DingEmployeeInfo employeeInfo = dingEmployeeInfoService.getOne(Wrappers.lambdaQuery(DingEmployeeInfo.class)
.eq(DingEmployeeInfo::getAccountId, accountId)
.eq(DingEmployeeInfo::getMainJob, String.valueOf(Boolean.TRUE))
.last("limit 1"));
String organizationCode = employeeInfo.getOrganizationCode();
workNoticeInfo.setOrganizationCode(organizationCode);
// 根据部门code获取部门名称
DingOrganization dingOrganization = dingOrganizationService.getOne(Wrappers.lambdaQuery(DingOrganization.class)
.eq(DingOrganization::getOrganizationCode, organizationCode));
String organizationName = dingOrganization.getOrganizationName();
workNoticeInfo.setOrganizationName(organizationName);
// 构建唯一的消息ID
String bizMsgId = "ZD_WORK_NOTICE_" + StrUtil.UNDERLINE + organizationCode + StrUtil.UNDERLINE
+ organizationName + accountId + StrUtil.UNDERLINE + System.currentTimeMillis();
workNoticeInfo.setBizMsgId(bizMsgId);
String receiverUserId = String.valueOf(accountId);
workNoticeInfo.setReceiverUserId(receiverUserId);
return workNoticeInfo;
}

@Transactional(rollbackFor = Exception.class)
public void sendInviteStopMsg(Long userId, Long meetingId, String meetingName) {
UserInfo info = userInfoService.getById(userId);
String msgContent = String.format(MeetingMsgTemplateConst.INVITE_END, meetingName);
// 音信通消息
SendSmsContext yxtContent = new SendSmsContext();
yxtContent.setContent(msgContent);
yxtContent.setReceiveNumber(info.getMobile());
yxtCallOrSmsHelper.sendSms(yxtContent);
// 发送工作通知
if (info.getAccountId() != null) {
WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
swn.setMsg(msgContent);
workNoticeStagingService.addByWorkNotice(swn, MsgTypeEnum.REVIEW_MEETING);
Map<String, Object> map = new HashMap<>();
map.put("meetingId", meetingId);
Notify notify = getNotify(userId, msgContent, map);
notifyService.save(notify);
}
}

@Transactional(rollbackFor = Exception.class)
public void sendConfirmedRosterMsg(List<MeetingExpert> experts, Meeting meeting) {
List<Long> userIds = CollUtils.fieldList(experts, MeetingExpert::getExpertId);
List<UserInfo> userInfos = userInfoService.listByIds(userIds);
Map<Long, UserInfo> userMap = CollUtils.listToMap(userInfos, UserInfo::getId);
String sTime = meeting.getStartTime().format(DatePattern.NORM_DATETIME_MINUTE_FORMATTER);
String eTime = meeting.getEndTime().format(DatePattern.NORM_DATETIME_MINUTE_FORMATTER);
String meetingTime = sTime + " - " + eTime;
List<SendSmsContext> yxtContents = new ArrayList<>();
List<Notify> notifies = new ArrayList<>();
List<WorkNoticeInfo> workingNotices = new ArrayList<>();
experts.forEach(w -> {
String msgContent = String.format(MeetingMsgTemplateConst.CONFIRMED_ROSTER,
w.getExpertName(), w.getCreateOn(), meetingTime, meeting.getMeetingAddress(),
meeting.getConnecter(), meeting.getContact());
// 音信通消息
SendSmsContext yxtContent = new SendSmsContext();
yxtContent.setContent(msgContent);
yxtContent.setReceiveNumber(w.getMobile());
yxtContents.add(yxtContent);
UserInfo info = userMap.get(w.getExpertId());
// 发送工作通知
if (info.getAccountId() != null) {
WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
swn.setMsg(msgContent);
workingNotices.add(swn);
Map<String, Object> map = new HashMap<>();
map.put("meetingId", meeting.getId());
Notify notify = getNotify(info.getId(), msgContent, map);
notifies.add(notify);
}
});
notifyService.saveBatch(notifies);
yxtCallOrSmsHelper.sendSms(yxtContents);
workNoticeStagingService.addByWorkNotice(workingNotices, MsgTypeEnum.EXPERT_REVIEW);
}


}

+ 3
- 1
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java View File

@@ -36,6 +36,7 @@ import com.ningdatech.pmapi.meeting.entity.req.*;
import com.ningdatech.pmapi.meeting.entity.vo.*;
import com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper;
import com.ningdatech.pmapi.meeting.helper.MeetingManageHelper;
import com.ningdatech.pmapi.meeting.helper.MeetingMsgHelper;
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper;
import com.ningdatech.pmapi.meeting.service.*;
import com.ningdatech.pmapi.meeting.task.ExpertInviteTask;
@@ -96,6 +97,7 @@ public class MeetingManage {
private final IDingOrganizationService dingOrganizationService;
private final IExpertReviewService expertReviewService;
private final ExpertInviteHelper expertInviteHelper;
private final MeetingMsgHelper meetingMsgHelper;
private static final String INVITED_RULE_CREATE = "INVITED_RULE_CREATE:";

private static final String MEETING_CREATE_KEY = "MEETING_CREATE:";
@@ -826,7 +828,7 @@ public class MeetingManage {
.in(MeetingExpert::getId, currConfirmedMeIds)
.set(MeetingExpert::getConfirmedRoster, Boolean.TRUE);
meetingExpertService.update(meUpdate);
// TODO 发送会议通知
meetingMsgHelper.sendConfirmedRosterMsg(expertNoticing, meeting);
} finally {
distributedLock.releaseLock(key);
}


+ 3
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java View File

@@ -16,6 +16,7 @@ import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO;
import com.ningdatech.pmapi.meeting.entity.dto.InviteCacheDTO;
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.helper.MeetingMsgHelper;
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper;
import com.ningdatech.pmapi.meeting.manage.ExpertInviteManage;
import com.ningdatech.pmapi.meeting.service.IExpertInviteAvoidRuleService;
@@ -74,6 +75,7 @@ public class ExpertInviteTask {
private final ExpertInviteManage expertInviteManage;
private final IExpertInviteAvoidRuleService inviteAvoidRuleService;
private final YxtCallOrSmsHelper yxtCallOrSmsHelper;
private final MeetingMsgHelper meetingMsgHelper;

/**
* 用来存入线程执行句柄, 停止定时任务时使用
@@ -273,6 +275,7 @@ public class ExpertInviteTask {
if (notIgnoreCnt.get() == 0 || notIgnoreCnt.get() == notSupportCnt.get()) {
log.info("停止会议随机邀请:{} 未完成抽取规则数量 {} 无可抽取专家规则数量 {}", meetingId, notIgnoreCnt, notSupportCnt);
currProxy().cancelByMeetingId(meetingId);
meetingMsgHelper.sendInviteStopMsg(meeting.getCreateBy(), meetingId, meeting.getName());
}
}



+ 14
- 2
pmapi/src/main/java/com/ningdatech/pmapi/staging/service/INdWorkNoticeStagingService.java View File

@@ -7,9 +7,11 @@ import com.ningdatech.pmapi.staging.model.entity.WorkNoticeStaging;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo;

import java.util.List;

/**
* <p>
* 服务类
* 服务类
* </p>
*
* @author CMM
@@ -19,5 +21,15 @@ public interface INdWorkNoticeStagingService extends IService<WorkNoticeStaging>

Boolean addRetryTimes(WorkNoticeStaging workNoticeStaging);

public Boolean addByWorkNotice(WorkNoticeInfo workNoticeInfo, MsgTypeEnum msgType) ;
Boolean addByWorkNotice(WorkNoticeInfo workNoticeInfo, MsgTypeEnum msgType);

/**
* 批量保存工作通知
*
* @param workNoticeInfos 工作通知内容
* @param msgType 通知类型
* @return 是否保存成功
*/
Boolean addByWorkNotice(List<WorkNoticeInfo> workNoticeInfos, MsgTypeEnum msgType);

}

+ 37
- 4
pmapi/src/main/java/com/ningdatech/pmapi/staging/service/impl/NdWorkNoticeStagingServiceImpl.java View File

@@ -13,10 +13,12 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
* <p>
* 服务实现类
* 服务实现类
* </p>
*
* @author CMM
@@ -33,6 +35,7 @@ public class NdWorkNoticeStagingServiceImpl extends ServiceImpl<NdWorkNoticeStag

/**
* 增加 重试次数 和下次扫描时间
*
* @param workNoticeStaging
* @return java.lang.Boolean
* @author CMM
@@ -41,22 +44,23 @@ public class NdWorkNoticeStagingServiceImpl extends ServiceImpl<NdWorkNoticeStag
@Override
public Boolean addRetryTimes(WorkNoticeStaging workNoticeStaging) {
Integer retryTimes = workNoticeStaging.getRetryTimes() + 1;
if(!workNoticeFlowMapUtil.intervalTimeMap.containsKey(retryTimes)){
if (!workNoticeFlowMapUtil.intervalTimeMap.containsKey(retryTimes)) {
log.info("没有对应重试间隔时间 添加重试信息失败");
return Boolean.FALSE;
}
Integer addSeconds = workNoticeFlowMapUtil.intervalTimeMap.get(retryTimes);
Boolean dead = Boolean.FALSE;
//超过重试最大次数 dead置为 true
if(retryTimes.compareTo(StagingContant.Retry.MAX_RETRY_TIMES) > 0){
if (retryTimes.compareTo(StagingContant.Retry.MAX_RETRY_TIMES) > 0) {
dead = Boolean.TRUE;
}
LocalDateTime nextRetryTime = LocalDateTime.now().plusSeconds(addSeconds);
return mapper.addRetryTimes(workNoticeStaging.getId(),retryTimes,nextRetryTime,dead);
return mapper.addRetryTimes(workNoticeStaging.getId(), retryTimes, nextRetryTime, dead);
}

/**
* 在对应的流程处理后,增加一个工作通知到暂存表中
*
* @param workNoticeInfo
* @param msgType
* @return java.lang.Boolean
@@ -80,4 +84,33 @@ public class NdWorkNoticeStagingServiceImpl extends ServiceImpl<NdWorkNoticeStag
.build();
return this.save(workNoticeStaging);
}

/**
* 在对应的流程处理后,增加一个工作通知到暂存表中
*
* @param workNoticeInfo
* @param msgType
* @return java.lang.Boolean
* @author CMM
* @since 2023/02/28 20:02
*/
@Override
public Boolean addByWorkNotice(List<WorkNoticeInfo> workNoticeInfos, MsgTypeEnum msgType) {
List<WorkNoticeStaging> workNoticeInfoList = workNoticeInfos.stream()
.map(workNoticeInfo -> WorkNoticeStaging.builder()
.accountId(workNoticeInfo.getAccountId())
.msg(workNoticeInfo.getMsg())
.bizMsgId(workNoticeInfo.getBizMsgId())
.organizationCode(workNoticeInfo.getOrganizationCode())
.organizationName(workNoticeInfo.getOrganizationName())
.receiverUserId(workNoticeInfo.getReceiverUserId())
.msgType(msgType)
.createOn(LocalDateTime.now())
.updateOn(LocalDateTime.now())
.nextTime(LocalDateTime.now())
.retryTimes(0)
.build()).collect(Collectors.toList());
return saveBatch(workNoticeInfoList);
}

}

Loading…
Cancel
Save