Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

master
PoffyZhang 1 rok temu
rodzic
commit
2d588a941f
11 zmienionych plików z 334 dodań i 287 usunięć
  1. +1
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java
  2. +3
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/MeetingBasicDTO.java
  3. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingListReq.java
  4. +18
    -9
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingManageHelper.java
  5. +20
    -9
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/YxtCallOrSmsHelper.java
  6. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java
  7. +252
    -241
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertCallResultRewriteTask.java
  8. +7
    -4
      pmapi/src/main/java/com/ningdatech/pmapi/organization/service/impl/DingOrganizationServiceImpl.java
  9. +28
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/sms/constant/VoiceSmsTemplateConst.java
  10. +0
    -13
      pmapi/src/main/java/com/ningdatech/pmapi/sms/constant/YxtSmsTemplateConst.java
  11. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/sms/manage/SmsManage.java

+ 1
- 3
pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java Wyświetl plik

@@ -8,11 +8,9 @@ import com.ningdatech.pmapi.meeting.entity.dto.ReviewProjectDTO;
import com.ningdatech.pmapi.meeting.entity.req.*;
import com.ningdatech.pmapi.meeting.entity.vo.*;
import com.ningdatech.pmapi.meeting.manage.MeetingManage;
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@@ -165,7 +163,7 @@ public class MeetingController {
@ApiOperation("重发短信")
@PostMapping("/confirmedRoster")
@WebLog(value = "重发短信")
public void resendSms(MeetingCancelReq req) {
public void resendSms(@RequestBody MeetingCancelReq req) {
meetingManage.confirmedRoster(req.getMeetingId());
}



+ 3
- 3
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/dto/MeetingBasicDTO.java Wyświetl plik

@@ -36,12 +36,12 @@ public class MeetingBasicDTO {

@NotNull(message = "开始时间不能为空")
@ApiModelProperty("开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime startTime;

@NotNull(message = "结束时间不能为空")
@ApiModelProperty("结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime endTime;

@NotNull(message = "评审耗时不能为空")
@@ -50,7 +50,7 @@ public class MeetingBasicDTO {

@NotNull(message = "评委出席时间不能为空")
@ApiModelProperty("评委出席时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime judgesAttendanceTime;

@NotEmpty(message = "评审地点不能为空")


+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingListReq.java Wyświetl plik

@@ -26,11 +26,11 @@ public class MeetingListReq extends PagePo {
private String name;

@ApiModelProperty("会议开始时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime startTime;

@ApiModelProperty("会议结束时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime endTime;

@ApiModelProperty("事务状态")


+ 18
- 9
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingManageHelper.java Wyświetl plik

@@ -23,6 +23,7 @@ import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO;
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.ExpertInviteTypeEnum;
import com.ningdatech.pmapi.meeting.entity.req.MeetingListReq;
import com.ningdatech.pmapi.meeting.entity.vo.ExpertBasicInfoVO;
import com.ningdatech.pmapi.meeting.entity.vo.MeetingByManagerVO;
@@ -194,20 +195,28 @@ public class MeetingManageHelper {
/**
* 校验是否能够进行指定邀请
*
* @param meetingId 会议ID
* @param expertIds 专家ID
* @param meetingId 会议ID
* @param expertIds 专家ID
* @param inviteType 邀请类型
* @return 符合邀请规则的专家
* @author WendyYang
**/
public List<ExpertUserFullInfo> appointExpertCheck(Long meetingId, List<Long> expertIds) {
public List<ExpertUserFullInfo> appointExpertCheck(Long meetingId, Integer inviteType, List<Long> expertIds) {
List<ExpertUserFullInfo> experts = expertUserFullInfoService.listByUserId(expertIds);
AvoidRuleDTO avoidRule = getAvoidInfoDto(meetingId);
AvoidRuleDTO avoidRule;
if (ExpertInviteTypeEnum.RANDOM.eq(inviteType)) {
avoidRule = getAvoidInfoDto(meetingId);
} else {
avoidRule = null;
}
experts.forEach(expert -> {
if (avoidRule.getAvoidUnitIdList().contains(expert.getCompany())) {
throw BizException.wrap("请移除已回避单位的专家");
}
if (CollectionUtils.isNotEmpty(avoidRule.getExpertIds()) && avoidRule.getExpertIds().contains(expert.getUserId())) {
throw BizException.wrap("请移除已回避的专家");
if (avoidRule != null) {
if (avoidRule.getAvoidUnitIdList().contains(expert.getCompany())) {
throw BizException.wrap("请移除已回避单位的专家");
}
if (CollectionUtils.isNotEmpty(avoidRule.getExpertIds()) && avoidRule.getExpertIds().contains(expert.getUserId())) {
throw BizException.wrap("请移除已回避的专家");
}
}
// 校验专家状态
ExpertAccountStatusEnum accountStatus = ExpertAccountStatusEnum.of(expert.getExpertAccountStatus());


+ 20
- 9
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/YxtCallOrSmsHelper.java Wyświetl plik

@@ -1,13 +1,24 @@
package com.ningdatech.pmapi.meeting.helper;

import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.sms.constant.VoiceSmsTemplateConst;
import com.ningdatech.pmapi.sms.utils.DateUtil;
import com.ningdatech.yxt.client.YxtClient;
import com.ningdatech.yxt.constants.YxtSmsSignEnum;
import com.ningdatech.yxt.model.cmd.SendSmsCmd;
import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import com.ningdatech.yxt.model.cmd.SubmitTaskCallResponse;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;

import static com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.SubmitTaskCallContext;
import static com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.of;

/**
* <p>
* YxtCallOrSmsHelper
@@ -20,24 +31,24 @@ import java.util.List;
@AllArgsConstructor
public class YxtCallOrSmsHelper {

// private final YinXinTongClient yinXinTongClient;
private final YxtClient yxtClient;

public void callByMeetingExperts(Meeting meeting, List<MeetingExpert> experts) {
/*String callContent = String.format(YxtCallTemplateConst.OFFLINE_TEMPLATE,
meeting.getHoldCompany(), meeting.getName(),
meeting.getStartTime().format(DateUtil.DTF_YMD_HM), meeting.getRegionDetail());
String callContent = String.format(VoiceSmsTemplateConst.OFFLINE_TEMPLATE,
meeting.getHoldOrg(), meeting.getName(),
meeting.getStartTime().format(DateUtil.DTF_YMD_HM), meeting.getMeetingAddress());
List<SubmitTaskCallContext> callContexts = CollUtils.convert(experts, w -> {
SubmitTaskCallContext context = new SubmitTaskCallContext();
context.setContent(callContent);
context.setReceiveNumber(w.getMobile());
return context;
});
SubmitTaskCallResponse callResponse = yinXinTongClient.submitTaskCall(SubmitTaskCallCmd.of(callContexts));
experts.forEach(w -> w.setSubmitKey(callResponse.getSubmitKey()));*/
SubmitTaskCallResponse callResponse = yxtClient.submitTaskCall(of(callContexts));
experts.forEach(w -> w.setSubmitKey(callResponse.getSubmitKey()));
}

/*public void sendSms(List<SendSmsContext> smsList) {
yinXinTongClient.submitSmsTask(new SendSmsCmd() {{
public void sendSms(List<SendSmsContext> smsList) {
yxtClient.submitSmsTask(new SendSmsCmd() {{
setContextList(smsList);
setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB);
}});
@@ -45,6 +56,6 @@ public class YxtCallOrSmsHelper {

public void sendSms(SendSmsContext sms) {
sendSms(Collections.singletonList(sms));
}*/
}

}

+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java Wyświetl plik

@@ -559,7 +559,7 @@ public class MeetingManage {
throw BizException.wrap("补充专家失败");
}
AppointInviteRuleDTO rule = inviteRuleService.appointRuleByMeetingId(meetingId);
List<ExpertUserFullInfo> userInfos = meetingManageHelper.appointExpertCheck(meetingId, req.getExpertIdList());
List<ExpertUserFullInfo> userInfos = meetingManageHelper.appointExpertCheck(meetingId, meeting.getInviteType(), req.getExpertIdList());
List<MeetingExpert> expertList = CollUtils.convert(userInfos, w -> {
MeetingExpert me = ExpertInviteBuilder.getExpertByAppoint(meetingId, w, rule.getId());
me.setStatus(ExpertAttendStatusEnum.NOTICING.getCode());


+ 252
- 241
pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertCallResultRewriteTask.java Wyświetl plik

@@ -1,241 +1,252 @@
//package com.ningdatech.pmapi.meeting.task;
//
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
//import com.ningdatech.basic.util.StrPool;
//import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
//import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService;
//import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule;
//import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
//import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
//import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
//import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteType;
//import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper;
//import com.ningdatech.pmapi.meeting.service.IExpertInviteRuleService;
//import com.ningdatech.pmapi.meeting.service.IMeetingExpertService;
//import com.ningdatech.pmapi.meeting.service.IMeetingService;
//import com.ningdatech.pmapi.meta.helper.DictionaryCache;
//import com.ningdatech.pmapi.sms.utils.DateUtil;
//import lombok.AllArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//import java.time.Duration;
//import java.time.Instant;
//import java.time.LocalDateTime;
//import java.time.temporal.ChronoUnit;
//import java.util.*;
//import java.util.stream.Collectors;
//
//import static com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus.AGREED;
//import static com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus.NOTICING;
//
//
///**
// * <p>
// * ExpertCallResultRewriteTask
// * <br>
// * 专家电话结果回填
// * </p>
// *
// * @author WendyYang
// * @since 14:15 2022/8/18
// */
//@Slf4j
//@Component
//@AllArgsConstructor
//public class ExpertCallResultRewriteTask {
//
// private final RandomInviteProperties randomInviteProperties;
//
// private final ThreadPoolTaskScheduler scheduler;
// private final IMeetingExpertService meetingExpertService;
// private final IExpertInviteRuleService inviteRuleService;
// private final IMeetingService meetingService;
// private final ISysMsgRecordDetailService msgRecordDetailService;
// private final DictionaryCache dictionaryCache;
// private final YxtCallOrSmsHelper yxtCallOrSmsHelper;
// private final IExpertUserFullInfoService iExpertUserFullInfoService;
//
// @PostConstruct
// public void initTask() {
// if (!randomInviteProperties.getEnable()) {
// log.warn("随机邀请已关闭……");
// return;
// }
// Instant startTime = Instant.now().plus(randomInviteProperties.getResultRewriteFixedRate(), ChronoUnit.MINUTES);
// // 处理电话结果回填
// scheduler.scheduleAtFixedRate(this::rewritePhoneCallResult, startTime, Duration.ofMinutes(randomInviteProperties.getResultRewriteFixedRate()));
// }
//
//
// public void rewritePhoneCallResult() {
// log.info("开始执行电话结果回填任务:{}", Thread.currentThread().getName());
// // 查询所有邀请的专家信息 状态为通话中的
// LambdaQueryWrapper<MeetingExpert> meQuery = Wrappers.lambdaQuery(MeetingExpert.class)
// .eq(MeetingExpert::getStatus, NOTICING.getCode())
// .eq(MeetingExpert::getInviteType, ExpertInviteType.RANDOM.getCode());
// List<MeetingExpert> experts = meetingExpertService.list(meQuery);
// if (experts.isEmpty()) {
// log.info("暂无电话结果回填任务执行");
// return;
// }
// // 所有随机邀请的规则ID
// Map<Long, String> submitKeys = new HashMap<>(experts.size());
// Set<Long> randomRuleIds = experts.stream().peek(w -> submitKeys.put(w.getId(), w.getSubmitKey()))
// .map(MeetingExpert::getRuleId).collect(Collectors.toSet());
// // 查询随机邀请回调等待时间
// Map<Long, Integer> callbackMinutes = new HashMap<>(randomRuleIds.size());
// if (!randomRuleIds.isEmpty()) {
// List<ExpertInviteRule> inviteRules = inviteRuleService.listByIds(randomRuleIds);
// inviteRules.forEach(w -> {
// RandomInviteRuleDTO rule = JSON.parseObject(w.getInviteRule(), RandomInviteRuleDTO.class);
// callbackMinutes.put(w.getId(), rule.getWaitForCallbackMinutes());
// });
// }
// LambdaQueryWrapper<SysMsgRecordDetail> msgRecordDetailQuery = Wrappers.lambdaQuery(SysMsgRecordDetail.class)
// .in(SysMsgRecordDetail::getSubmitKey, submitKeys.values());
// List<SysMsgRecordDetail> recordDetailList = msgRecordDetailService.list(msgRecordDetailQuery);
// if (recordDetailList.isEmpty()) {
// return;
// }
// Map<String, SysMsgRecordDetail> recordDetailMap = recordDetailList.stream()
// .collect(Collectors.toMap(w -> w.getSubmitKey() + StrPool.UNDERSCORE + w.getReceiveNumber(), w -> w));
// List<MeetingExpert> updates = new ArrayList<>(), agrees = new ArrayList<>();
// for (MeetingExpert expert : experts) {
// String key = expert.getSubmitKey() + StrPool.UNDERSCORE + expert.getMobile();
// SysMsgRecordDetail msgRecordDetail = recordDetailMap.get(key);
// if (msgRecordDetail == null) {
// // 极端情况下获取不到submitKey异常情况
// continue;
// }
// Integer minutes = callbackMinutes.get(expert.getRuleId());
// Optional<Integer> status = getStatusByMsgRecordDetail(msgRecordDetail, minutes, expert.getCreateOn());
// if (status.isPresent()) {
// MeetingExpert update = new MeetingExpert();
// update.setUpdateBy(0L);
// update.setUpdateOn(LocalDateTime.now());
// update.setId(expert.getId());
// update.setPreStatus(expert.getStatus());
// update.setStatus(status.get());
// if (AGREED.eq(update.getStatus())) {
// sendAgreeNotice(expert);
// agrees.add(expert);
// }
// updates.add(update);
// }
// }
// meetingExpertService.updateBatchById(updates);
// if (agrees.size() > 0) {
// obtainCallBackAfterMeetingCanceled(agrees);
// }
// }
//
// private void sendAgreeNotice(MeetingExpert expert) {
// try {
// Meeting meeting = meetingService.getById(expert.getMeetingId());
// if (Objects.isNull(meeting)) {
// return;
// }
// ExpertUserFullInfo expertUserFullInfo = iExpertUserFullInfoService.getByUserId(expert.getExpertId());
// String expertName = null;
// if (Objects.nonNull(expertUserFullInfo)) {
// expertName = expertUserFullInfo.getExpertName();
// }
// String smsContent = String.format(YxtSmsTemplateConst.EXPERT_AGREE_NOTICE, meeting.getHoldCompany(), expertName, meeting.getName()
// , meeting.getStartTime().format(DateUtil.DTF_YMD_HM), meeting.getRegionDetail(), meeting.getConnecter(), meeting.getContact(), WebProperties.webUrl);
// SendSmsContext context = new SendSmsContext();
// context.setContent(smsContent);
// context.setReceiveNumber(expert.getMobile());
//
// yxtCallOrSmsHelper.sendSms(context);
// } catch (Exception e) {
// log.info("发送专家会议接受通知短信失败:{}", JSONObject.toJSONString(expert));
// }
// }
//
// private static Optional<Integer> getStatusByMsgRecordDetail(SysMsgRecordDetail msgRecordDetail, int minutes, LocalDateTime createOn) {
// LocalDateTime time = LocalDateTime.now().minusMinutes(minutes);
// String callBackJson = msgRecordDetail.getCallBackJson();
// if (StrUtils.isBlank(callBackJson) && time.isBefore(createOn)) {
// return Optional.empty();
// }
// ExpertAttendStatus status;
// if (StrUtils.isNotBlank(callBackJson)) {
// try {
// JSONObject callbackObject = JSON.parseObject(callBackJson);
// Date dialBeginTime = callbackObject.getDate("dialBeginTime");
// if (dialBeginTime == null) {
// return Optional.empty();
// }
// Integer resultCode = callbackObject.getInteger("resultCode");
// if (resultCode != null && resultCode == 0) {
// String pressKeyStr = callbackObject.getString("pressKey");
// if (Objects.nonNull(pressKeyStr)) {
// pressKeyStr = pressKeyStr.replaceAll("\\*", "").trim();
// }
// Integer pressKey = null;
// if (StringUtils.isNotBlank(pressKeyStr)) {
// pressKey = Integer.parseInt(pressKeyStr);
// }
// if (pressKey == null) {
// if (time.isBefore(createOn)) {
// return Optional.empty();
// }
// status = REFUSED;
// } else {
// if (pressKey == 1) {
// status = AGREED;
// } else {
// status = REFUSED;
// }
// }
// } else {
// status = NOT_ANSWERED;
// }
// } catch (Exception e) {
// log.error("获取电话回调结果异常", e);
// status = NOT_ANSWERED;
// }
// } else {
// // 超时未回复设置为拒绝参加
// status = REFUSED;
// }
// return Optional.of(status.getCode());
// }
//
// /**
// * 会议取消之后拿到回调结果的话需要发送取消短信
// **/
// private void obtainCallBackAfterMeetingCanceled(List<MeetingExpert> experts) {
// /*List<Long> meetingIds = CollUtils.fieldList(experts, MeetingExpert::getMeetingId);
// LambdaQueryWrapper<Meeting> mQuery = Wrappers.lambdaQuery(Meeting.class)
// .eq(Meeting::getStatus, Manager.CANCELED.getCode())
// .in(Meeting::getId, meetingIds);
// Map<Long, Meeting> meetingMap = CollUtils.listToMap(meetingService.list(mQuery), Meeting::getId);
// if (meetingMap.size() > 0) {
// Map<Meeting, List<MeetingExpert>> expertList = new HashMap<>(16);
// experts.forEach(w -> {
// Meeting meeting = meetingMap.get(w.getMeetingId());
// if (meeting == null) {
// return;
// }
// List<MeetingExpert> list = expertList.computeIfAbsent(meeting, k -> new ArrayList<>());
// list.add(w);
// });
// if (!expertList.isEmpty()) {
// expertList.forEach((m, mes) -> {
// String meetingType = dictionaryCache.getByCode(m.getType()).getName();
// List<SendSmsContext> contexts = YxtSmsContextBuilder.smsToExpertByCancelMeeting(m, mes, meetingType);
// yxtCallOrSmsHelper.sendSms(contexts);
// });
// }
// }*/
// }
//
//}
package com.ningdatech.pmapi.meeting.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.pmapi.common.util.StrUtils;
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService;
import com.ningdatech.pmapi.meeting.entity.config.WebProperties;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper;
import com.ningdatech.pmapi.meeting.service.IExpertInviteRuleService;
import com.ningdatech.pmapi.meeting.service.IMeetingExpertService;
import com.ningdatech.pmapi.meeting.service.IMeetingService;
import com.ningdatech.pmapi.meta.helper.DictionaryCache;
import com.ningdatech.pmapi.sms.constant.VoiceSmsTemplateConst;
import com.ningdatech.pmapi.sms.utils.DateUtil;
import com.ningdatech.yxt.entity.SysMsgRecordDetail;
import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import com.ningdatech.yxt.service.ISysMsgRecordDetailService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import static com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum.*;

/**
* <p>
* ExpertCallResultRewriteTask
* <br>
* 专家电话结果回填
* </p>
*
* @author WendyYang
* @since 14:15 2022/8/18
*/
@Slf4j
@Component
@AllArgsConstructor
public class ExpertCallResultRewriteTask {

private final RandomInviteProperties randomInviteProperties;

private final ThreadPoolTaskScheduler scheduler;
private final IMeetingExpertService meetingExpertService;
private final IExpertInviteRuleService inviteRuleService;
private final IMeetingService meetingService;
private final ISysMsgRecordDetailService msgRecordDetailService;
private final DictionaryCache dictionaryCache;
private final YxtCallOrSmsHelper yxtCallOrSmsHelper;
private final IExpertUserFullInfoService userFullInfoService;

@PostConstruct
public void initTask() {
if (!randomInviteProperties.getEnable()) {
log.warn("随机邀请已关闭……");
return;
}
Instant startTime = Instant.now().plus(randomInviteProperties.getResultRewriteFixedRate(), ChronoUnit.MINUTES);
// 处理电话结果回填
scheduler.scheduleAtFixedRate(this::rewritePhoneCallResult, startTime, Duration.ofMinutes(randomInviteProperties.getResultRewriteFixedRate()));
}


public void rewritePhoneCallResult() {
log.info("开始执行电话结果回填任务:{}", Thread.currentThread().getName());
// 查询所有邀请的专家信息 状态为通话中的
LambdaQueryWrapper<MeetingExpert> meQuery = Wrappers.lambdaQuery(MeetingExpert.class)
.eq(MeetingExpert::getStatus, NOTICING.getCode())
.eq(MeetingExpert::getInviteType, ExpertInviteTypeEnum.RANDOM.getCode());
List<MeetingExpert> experts = meetingExpertService.list(meQuery);
if (experts.isEmpty()) {
log.info("暂无电话结果回填任务执行");
return;
}
// 所有随机邀请的规则ID
Map<Long, String> submitKeys = new HashMap<>(experts.size());
Set<Long> randomRuleIds = experts.stream().peek(w -> submitKeys.put(w.getId(), w.getSubmitKey()))
.map(MeetingExpert::getRuleId).collect(Collectors.toSet());
// 查询随机邀请回调等待时间
Map<Long, Integer> callbackMinutes = new HashMap<>(randomRuleIds.size());
if (!randomRuleIds.isEmpty()) {
List<ExpertInviteRule> inviteRules = inviteRuleService.listByIds(randomRuleIds);
inviteRules.forEach(w -> {
RandomInviteRuleDTO rule = JSON.parseObject(w.getInviteRule(), RandomInviteRuleDTO.class);
callbackMinutes.put(w.getId(), rule.getWaitForCallbackMinutes());
});
}
LambdaQueryWrapper<SysMsgRecordDetail> msgRecordDetailQuery = Wrappers.lambdaQuery(SysMsgRecordDetail.class)
.in(SysMsgRecordDetail::getSubmitKey, submitKeys.values());
List<SysMsgRecordDetail> recordDetailList = msgRecordDetailService.list(msgRecordDetailQuery);
if (recordDetailList.isEmpty()) {
return;
}
Map<String, SysMsgRecordDetail> recordDetailMap = recordDetailList.stream()
.collect(Collectors.toMap(w -> w.getSubmitKey() + StrPool.UNDERSCORE + w.getReceiveNumber(), w -> w));
List<MeetingExpert> updates = new ArrayList<>(), agrees = new ArrayList<>();
for (MeetingExpert expert : experts) {
String key = expert.getSubmitKey() + StrPool.UNDERSCORE + expert.getMobile();
SysMsgRecordDetail msgRecordDetail = recordDetailMap.get(key);
if (msgRecordDetail == null) {
// 极端情况下获取不到submitKey异常情况
continue;
}
Integer minutes = callbackMinutes.get(expert.getRuleId());
Optional<Integer> status = getStatusByMsgRecordDetail(msgRecordDetail, minutes, expert.getCreateOn());
if (status.isPresent()) {
MeetingExpert update = new MeetingExpert();
update.setUpdateBy(0L);
update.setUpdateOn(LocalDateTime.now());
update.setId(expert.getId());
update.setStatus(status.get());
if (AGREED.eq(update.getStatus())) {
// 发送专家确认参加的短信通知
// sendAgreeNotice(expert);
agrees.add(expert);
}
updates.add(update);
}
}
meetingExpertService.updateBatchById(updates);
if (agrees.size() > 0) {
obtainCallBackAfterMeetingCanceled(agrees);
}
}

private void sendAgreeNotice(MeetingExpert expert) {
try {
Meeting meeting = meetingService.getById(expert.getMeetingId());
if (Objects.isNull(meeting)) {
return;
}
ExpertUserFullInfo expertUserFullInfo = userFullInfoService.getByUserId(expert.getExpertId());
String expertName = null;
if (Objects.nonNull(expertUserFullInfo)) {
expertName = expertUserFullInfo.getExpertName();
}
String smsContent = String.format(VoiceSmsTemplateConst.EXPERT_AGREE_ATTEND_TEMPLATE,
meeting.getHoldOrg(),
expertName,
meeting.getName(),
meeting.getStartTime().format(DateUtil.DTF_YMD_HM),
meeting.getMeetingAddress(),
meeting.getConnecter(),
meeting.getContact(),
WebProperties.webUrl);
SendSmsContext context = new SendSmsContext();
context.setContent(smsContent);
context.setReceiveNumber(expert.getMobile());
yxtCallOrSmsHelper.sendSms(context);
} catch (Exception e) {
log.info("发送专家会议接受通知短信失败:{}", JSONObject.toJSONString(expert));
}
}

private static Optional<Integer> getStatusByMsgRecordDetail(SysMsgRecordDetail msgRecordDetail, int minutes, LocalDateTime createOn) {
LocalDateTime time = LocalDateTime.now().minusMinutes(minutes);
String callBackJson = msgRecordDetail.getCallBackJson();
if (StrUtils.isBlank(callBackJson) && time.isBefore(createOn)) {
return Optional.empty();
}
ExpertAttendStatusEnum status;
if (StrUtils.isNotBlank(callBackJson)) {
try {
JSONObject callbackObject = JSON.parseObject(callBackJson);
Date dialBeginTime = callbackObject.getDate("dialBeginTime");
if (dialBeginTime == null) {
return Optional.empty();
}
Integer resultCode = callbackObject.getInteger("resultCode");
if (resultCode != null && resultCode == 0) {
String pressKeyStr = callbackObject.getString("pressKey");
if (Objects.nonNull(pressKeyStr)) {
pressKeyStr = pressKeyStr.replaceAll("\\*", "").trim();
}
Integer pressKey = null;
if (StringUtils.isNotBlank(pressKeyStr)) {
pressKey = Integer.parseInt(pressKeyStr);
}
if (pressKey == null) {
if (time.isBefore(createOn)) {
return Optional.empty();
}
status = REFUSED;
} else {
if (pressKey == 1) {
status = AGREED;
} else {
status = REFUSED;
}
}
} else {
status = UNANSWERED;
}
} catch (Exception e) {
log.error("获取电话回调结果异常", e);
status = UNANSWERED;
}
} else {
// 超时未回复设置为拒绝参加
status = REFUSED;
}
return Optional.of(status.getCode());
}

/**
* 会议取消之后拿到回调结果的话需要发送取消短信
**/
private void obtainCallBackAfterMeetingCanceled(List<MeetingExpert> experts) {
/*List<Long> meetingIds = CollUtils.fieldList(experts, MeetingExpert::getMeetingId);
LambdaQueryWrapper<Meeting> mQuery = Wrappers.lambdaQuery(Meeting.class)
.eq(Meeting::getStatus, Manager.CANCELED.getCode())
.in(Meeting::getId, meetingIds);
Map<Long, Meeting> meetingMap = CollUtils.listToMap(meetingService.list(mQuery), Meeting::getId);
if (meetingMap.size() > 0) {
Map<Meeting, List<MeetingExpert>> expertList = new HashMap<>(16);
experts.forEach(w -> {
Meeting meeting = meetingMap.get(w.getMeetingId());
if (meeting == null) {
return;
}
List<MeetingExpert> list = expertList.computeIfAbsent(meeting, k -> new ArrayList<>());
list.add(w);
});
if (!expertList.isEmpty()) {
expertList.forEach((m, mes) -> {
String meetingType = dictionaryCache.getByCode(m.getType()).getName();
List<SendSmsContext> contexts = YxtSmsContextBuilder.smsToExpertByCancelMeeting(m, mes, meetingType);
yxtCallOrSmsHelper.sendSms(contexts);
});
}
}*/
}

}

+ 7
- 4
pmapi/src/main/java/com/ningdatech/pmapi/organization/service/impl/DingOrganizationServiceImpl.java Wyświetl plik

@@ -11,7 +11,10 @@ import com.ningdatech.pmapi.organization.model.entity.DingOrganization;
import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
@@ -58,7 +61,7 @@ public class DingOrganizationServiceImpl extends ServiceImpl<DingOrganizationMap
public List<String> listNameByCodes(Collection<String> codes) {
LambdaQueryWrapper<DingOrganization> query = Wrappers.lambdaQuery(DingOrganization.class)
.select(DingOrganization::getOrganizationName)
.eq(DingOrganization::getOrganizationCode, codes);
.in(DingOrganization::getOrganizationCode, codes);
return CollUtils.fieldList(list(query), DingOrganization::getOrganizationName);
}

@@ -76,7 +79,7 @@ public class DingOrganizationServiceImpl extends ServiceImpl<DingOrganizationMap
orgCodeList = orgCodeList.stream().distinct().collect(Collectors.toList());
List<DingOrganization> dingOrganizationList = listByCodes(orgCodeList);
return dingOrganizationList.stream()
.filter(r -> StringUtils.isNotBlank(r.getOrganizationCode()) && Objects.nonNull(r))
.collect(Collectors.toMap(DingOrganization::getOrganizationCode, r->r));
.filter(r -> StringUtils.isNotBlank(r.getOrganizationCode()))
.collect(Collectors.toMap(DingOrganization::getOrganizationCode, r -> r));
}
}

+ 28
- 0
pmapi/src/main/java/com/ningdatech/pmapi/sms/constant/VoiceSmsTemplateConst.java Wyświetl plik

@@ -0,0 +1,28 @@
package com.ningdatech.pmapi.sms.constant;

/**
* <p>
* VoiceSmsTemplateConst
* </p>
*
* @author WendyYang
* @since 15:10 2023/3/30
*/
public interface VoiceSmsTemplateConst {

/**
* 短信登陆验证码
*/
String SMS_LOGIN_TEMPLATE = "验证码:%s(有效期为%s分钟),请勿泄露给他人,如非本人操作,请忽略此信息。";

/**
* 专家电话通知语音模版
*/
String OFFLINE_TEMPLATE = "尊敬的专家您好,%s现邀请您作为专家参加%s会议,会议时间:%s,会议地点:%s。 确认参加请按 1,拒绝参加请按 2。请您选择";

/**
* 专家同意参加短信通知模板
*/
String EXPERT_AGREE_ATTEND_TEMPLATE = "";

}

+ 0
- 13
pmapi/src/main/java/com/ningdatech/pmapi/sms/constant/YxtSmsTemplateConst.java Wyświetl plik

@@ -1,13 +0,0 @@
package com.ningdatech.pmapi.sms.constant;

/**
* @author liuxinxin
* @date 2022/8/8 下午5:05
*/
public interface YxtSmsTemplateConst {

/**
* 短信登陆验证码
*/
String SMS_LOGIN_TEMPLATE = "验证码:%s(有效期为%s分钟),请勿泄露给他人,如非本人操作,请忽略此信息。";
}

+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/sms/manage/SmsManage.java Wyświetl plik

@@ -6,7 +6,7 @@ import com.ningdatech.basic.exception.BizException;
import com.ningdatech.cache.model.cache.CacheKey;
import com.ningdatech.cache.repository.CachePlusOps;
import com.ningdatech.pmapi.sms.constant.VerificationCodeType;
import com.ningdatech.pmapi.sms.constant.YxtSmsTemplateConst;
import com.ningdatech.pmapi.sms.constant.VoiceSmsTemplateConst;
import com.ningdatech.pmapi.sms.model.dto.VerifyCodeCacheDTO;
import com.ningdatech.pmapi.sms.model.po.ReqVerificationCodePO;
import com.ningdatech.pmapi.sms.utils.DateUtil;
@@ -69,7 +69,7 @@ public class SmsManage {
case LOGIN:
SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext();
sendSmsContext.setReceiveNumber(request.getMobile());
sendSmsContext.setContent(String.format(YxtSmsTemplateConst.SMS_LOGIN_TEMPLATE, code, verificationCodeTypeEnum.getExpireTime()));
sendSmsContext.setContent(String.format(VoiceSmsTemplateConst.SMS_LOGIN_TEMPLATE, code, verificationCodeTypeEnum.getExpireTime()));
sendSmsCmd.setContextList(Collections.singletonList(sendSmsContext));
sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB);
break;


Ładowanie…
Anuluj
Zapisz