@@ -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.req.*; | ||||
import com.ningdatech.pmapi.meeting.entity.vo.*; | import com.ningdatech.pmapi.meeting.entity.vo.*; | ||||
import com.ningdatech.pmapi.meeting.manage.MeetingManage; | import com.ningdatech.pmapi.meeting.manage.MeetingManage; | ||||
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO; | |||||
import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||
import lombok.Getter; | |||||
import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||
import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
@@ -165,7 +163,7 @@ public class MeetingController { | |||||
@ApiOperation("重发短信") | @ApiOperation("重发短信") | ||||
@PostMapping("/confirmedRoster") | @PostMapping("/confirmedRoster") | ||||
@WebLog(value = "重发短信") | @WebLog(value = "重发短信") | ||||
public void resendSms(MeetingCancelReq req) { | |||||
public void resendSms(@RequestBody MeetingCancelReq req) { | |||||
meetingManage.confirmedRoster(req.getMeetingId()); | meetingManage.confirmedRoster(req.getMeetingId()); | ||||
} | } | ||||
@@ -36,12 +36,12 @@ public class MeetingBasicDTO { | |||||
@NotNull(message = "开始时间不能为空") | @NotNull(message = "开始时间不能为空") | ||||
@ApiModelProperty("开始时间") | @ApiModelProperty("开始时间") | ||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") | |||||
private LocalDateTime startTime; | private LocalDateTime startTime; | ||||
@NotNull(message = "结束时间不能为空") | @NotNull(message = "结束时间不能为空") | ||||
@ApiModelProperty("结束时间") | @ApiModelProperty("结束时间") | ||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") | |||||
private LocalDateTime endTime; | private LocalDateTime endTime; | ||||
@NotNull(message = "评审耗时不能为空") | @NotNull(message = "评审耗时不能为空") | ||||
@@ -50,7 +50,7 @@ public class MeetingBasicDTO { | |||||
@NotNull(message = "评委出席时间不能为空") | @NotNull(message = "评委出席时间不能为空") | ||||
@ApiModelProperty("评委出席时间") | @ApiModelProperty("评委出席时间") | ||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") | |||||
private LocalDateTime judgesAttendanceTime; | private LocalDateTime judgesAttendanceTime; | ||||
@NotEmpty(message = "评审地点不能为空") | @NotEmpty(message = "评审地点不能为空") | ||||
@@ -26,11 +26,11 @@ public class MeetingListReq extends PagePo { | |||||
private String name; | private String name; | ||||
@ApiModelProperty("会议开始时间") | @ApiModelProperty("会议开始时间") | ||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") | |||||
private LocalDateTime startTime; | private LocalDateTime startTime; | ||||
@ApiModelProperty("会议结束时间") | @ApiModelProperty("会议结束时间") | ||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") | |||||
private LocalDateTime endTime; | private LocalDateTime endTime; | ||||
@ApiModelProperty("事务状态") | @ApiModelProperty("事务状态") | ||||
@@ -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.MeetingBasicDTO; | ||||
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.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; | ||||
import com.ningdatech.pmapi.meeting.entity.vo.MeetingByManagerVO; | 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 符合邀请规则的专家 | * @return 符合邀请规则的专家 | ||||
* @author WendyYang | * @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); | 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 -> { | 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()); | ExpertAccountStatusEnum accountStatus = ExpertAccountStatusEnum.of(expert.getExpertAccountStatus()); | ||||
@@ -1,13 +1,24 @@ | |||||
package com.ningdatech.pmapi.meeting.helper; | 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.Meeting; | ||||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | 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 lombok.AllArgsConstructor; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.List; | import java.util.List; | ||||
import static com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.SubmitTaskCallContext; | |||||
import static com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.of; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
* YxtCallOrSmsHelper | * YxtCallOrSmsHelper | ||||
@@ -20,24 +31,24 @@ import java.util.List; | |||||
@AllArgsConstructor | @AllArgsConstructor | ||||
public class YxtCallOrSmsHelper { | public class YxtCallOrSmsHelper { | ||||
// private final YinXinTongClient yinXinTongClient; | |||||
private final YxtClient yxtClient; | |||||
public void callByMeetingExperts(Meeting meeting, List<MeetingExpert> experts) { | 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 -> { | List<SubmitTaskCallContext> callContexts = CollUtils.convert(experts, w -> { | ||||
SubmitTaskCallContext context = new SubmitTaskCallContext(); | SubmitTaskCallContext context = new SubmitTaskCallContext(); | ||||
context.setContent(callContent); | context.setContent(callContent); | ||||
context.setReceiveNumber(w.getMobile()); | context.setReceiveNumber(w.getMobile()); | ||||
return context; | 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); | setContextList(smsList); | ||||
setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | ||||
}}); | }}); | ||||
@@ -45,6 +56,6 @@ public class YxtCallOrSmsHelper { | |||||
public void sendSms(SendSmsContext sms) { | public void sendSms(SendSmsContext sms) { | ||||
sendSms(Collections.singletonList(sms)); | sendSms(Collections.singletonList(sms)); | ||||
}*/ | |||||
} | |||||
} | } |
@@ -559,7 +559,7 @@ public class MeetingManage { | |||||
throw BizException.wrap("补充专家失败"); | throw BizException.wrap("补充专家失败"); | ||||
} | } | ||||
AppointInviteRuleDTO rule = inviteRuleService.appointRuleByMeetingId(meetingId); | 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 -> { | List<MeetingExpert> expertList = CollUtils.convert(userInfos, w -> { | ||||
MeetingExpert me = ExpertInviteBuilder.getExpertByAppoint(meetingId, w, rule.getId()); | MeetingExpert me = ExpertInviteBuilder.getExpertByAppoint(meetingId, w, rule.getId()); | ||||
me.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | me.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | ||||
@@ -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); | |||||
}); | |||||
} | |||||
}*/ | |||||
} | |||||
} |
@@ -11,7 +11,10 @@ import com.ningdatech.pmapi.organization.model.entity.DingOrganization; | |||||
import com.ningdatech.pmapi.organization.service.IDingOrganizationService; | import com.ningdatech.pmapi.organization.service.IDingOrganizationService; | ||||
import org.springframework.stereotype.Service; | 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; | import java.util.stream.Collectors; | ||||
/** | /** | ||||
@@ -58,7 +61,7 @@ public class DingOrganizationServiceImpl extends ServiceImpl<DingOrganizationMap | |||||
public List<String> listNameByCodes(Collection<String> codes) { | public List<String> listNameByCodes(Collection<String> codes) { | ||||
LambdaQueryWrapper<DingOrganization> query = Wrappers.lambdaQuery(DingOrganization.class) | LambdaQueryWrapper<DingOrganization> query = Wrappers.lambdaQuery(DingOrganization.class) | ||||
.select(DingOrganization::getOrganizationName) | .select(DingOrganization::getOrganizationName) | ||||
.eq(DingOrganization::getOrganizationCode, codes); | |||||
.in(DingOrganization::getOrganizationCode, codes); | |||||
return CollUtils.fieldList(list(query), DingOrganization::getOrganizationName); | return CollUtils.fieldList(list(query), DingOrganization::getOrganizationName); | ||||
} | } | ||||
@@ -76,7 +79,7 @@ public class DingOrganizationServiceImpl extends ServiceImpl<DingOrganizationMap | |||||
orgCodeList = orgCodeList.stream().distinct().collect(Collectors.toList()); | orgCodeList = orgCodeList.stream().distinct().collect(Collectors.toList()); | ||||
List<DingOrganization> dingOrganizationList = listByCodes(orgCodeList); | List<DingOrganization> dingOrganizationList = listByCodes(orgCodeList); | ||||
return dingOrganizationList.stream() | 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)); | |||||
} | } | ||||
} | } |
@@ -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 = ""; | |||||
} |
@@ -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分钟),请勿泄露给他人,如非本人操作,请忽略此信息。"; | |||||
} |
@@ -6,7 +6,7 @@ import com.ningdatech.basic.exception.BizException; | |||||
import com.ningdatech.cache.model.cache.CacheKey; | import com.ningdatech.cache.model.cache.CacheKey; | ||||
import com.ningdatech.cache.repository.CachePlusOps; | import com.ningdatech.cache.repository.CachePlusOps; | ||||
import com.ningdatech.pmapi.sms.constant.VerificationCodeType; | 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.dto.VerifyCodeCacheDTO; | ||||
import com.ningdatech.pmapi.sms.model.po.ReqVerificationCodePO; | import com.ningdatech.pmapi.sms.model.po.ReqVerificationCodePO; | ||||
import com.ningdatech.pmapi.sms.utils.DateUtil; | import com.ningdatech.pmapi.sms.utils.DateUtil; | ||||
@@ -69,7 +69,7 @@ public class SmsManage { | |||||
case LOGIN: | case LOGIN: | ||||
SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext(); | SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext(); | ||||
sendSmsContext.setReceiveNumber(request.getMobile()); | 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.setContextList(Collections.singletonList(sendSmsContext)); | ||||
sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | ||||
break; | break; | ||||
@@ -316,10 +316,6 @@ public class TodoCenterManage { | |||||
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery() | HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery() | ||||
.processInstanceId(processInstanceId) | .processInstanceId(processInstanceId) | ||||
.singleResult(); | .singleResult(); | ||||
// 获取流程发起人信息 | |||||
String startUserId = instance.getStartUserId(); | |||||
UserInfo startUserInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class) | |||||
.eq(UserInfo::getEmployeeCode, startUserId)); | |||||
// 获取流程定义名称 | // 获取流程定义名称 | ||||
String processDefinitionName = instance.getProcessDefinitionName(); | String processDefinitionName = instance.getProcessDefinitionName(); | ||||
@@ -339,15 +335,15 @@ public class TodoCenterManage { | |||||
// 获取流程通过后当前审核人信息,向其发送工作通知 | // 获取流程通过后当前审核人信息,向其发送工作通知 | ||||
List<ProgressNode> newProgressInfo = newInstanceDetail.getProgressInfo(); | List<ProgressNode> newProgressInfo = newInstanceDetail.getProgressInfo(); | ||||
ProgressNode currentNode = newProgressInfo.get(newProgressInfo.size() - 1); | ProgressNode currentNode = newProgressInfo.get(newProgressInfo.size() - 1); | ||||
UserInfo auditUserInfo; | |||||
String currentEmployeeCode; | |||||
// 说明当前节点是子流程节点 | // 说明当前节点是子流程节点 | ||||
if (currentNode.getNodeType().name().equals(NodeTypeEnum.SUB.name())) { | if (currentNode.getNodeType().name().equals(NodeTypeEnum.SUB.name())) { | ||||
List<ProgressNode> children = currentNode.getChildren(); | List<ProgressNode> children = currentNode.getChildren(); | ||||
// 获取子流程当前审核人节点 | // 获取子流程当前审核人节点 | ||||
ProgressNode subCurrentNode = children.get(children.size() - 1); | ProgressNode subCurrentNode = children.get(children.size() - 1); | ||||
auditUserInfo = userInfoService.getById(Long.valueOf(subCurrentNode.getUserId())); | |||||
currentEmployeeCode = subCurrentNode.getUserId(); | |||||
} else { | } else { | ||||
auditUserInfo = userInfoService.getById(Long.valueOf(currentNode.getUserId())); | |||||
currentEmployeeCode = currentNode.getUserId(); | |||||
} | } | ||||
// 流程通过后,判断当前登录用户是不是最后一个审核人 | // 流程通过后,判断当前登录用户是不是最后一个审核人 | ||||
@@ -376,7 +372,7 @@ public class TodoCenterManage { | |||||
throw new IllegalStateException("Unexpected value: " + projectStatus); | throw new IllegalStateException("Unexpected value: " + projectStatus); | ||||
} | } | ||||
// 获取发送浙政钉工作通知必要信息 | // 获取发送浙政钉工作通知必要信息 | ||||
WorkNoticeInfo passWorkNoticeInfo2 = getSendWorkNoticeInfo(startUserInfo); | |||||
WorkNoticeInfo passWorkNoticeInfo2 = getSendWorkNoticeInfo(currentEmployeeCode); | |||||
String passMsg2 = String.format(PASS_MSG_TEMPLATE2, projectName, processDefinitionName); | String passMsg2 = String.format(PASS_MSG_TEMPLATE2, projectName, processDefinitionName); | ||||
passWorkNoticeInfo2.setMsg(passMsg2); | passWorkNoticeInfo2.setMsg(passMsg2); | ||||
// 放入系统通知表中,保存记录 | // 放入系统通知表中,保存记录 | ||||
@@ -387,10 +383,10 @@ public class TodoCenterManage { | |||||
// 若有下一个审核人(当前节点的用户), | // 若有下一个审核人(当前节点的用户), | ||||
// 向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。 | // 向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。 | ||||
// 获取发送浙政钉工作通知必要信息 | // 获取发送浙政钉工作通知必要信息 | ||||
if (Objects.isNull(auditUserInfo)) { | |||||
if (Objects.isNull(currentEmployeeCode)) { | |||||
throw new BizException("审核人信息不存在!"); | throw new BizException("审核人信息不存在!"); | ||||
} | } | ||||
WorkNoticeInfo sendWorkNoticeInfo = getSendWorkNoticeInfo(auditUserInfo); | |||||
WorkNoticeInfo sendWorkNoticeInfo = getSendWorkNoticeInfo(currentEmployeeCode); | |||||
String msg = String.format(PASS_MSG_TEMPLATE, sendWorkNoticeInfo.getOrganizationName(), projectName); | String msg = String.format(PASS_MSG_TEMPLATE, sendWorkNoticeInfo.getOrganizationName(), projectName); | ||||
sendWorkNoticeInfo.setMsg(msg); | sendWorkNoticeInfo.setMsg(msg); | ||||
// 放入系统通知表中,保存记录 | // 放入系统通知表中,保存记录 | ||||
@@ -407,7 +403,7 @@ public class TodoCenterManage { | |||||
// 更新项目状态和流程状态 | // 更新项目状态和流程状态 | ||||
updateRejectProjectStatus(userId, declaredProject); | updateRejectProjectStatus(userId, declaredProject); | ||||
// 获取发送浙政钉工作通知必要信息 | // 获取发送浙政钉工作通知必要信息 | ||||
WorkNoticeInfo rejectWorkNoticeInfo = getSendWorkNoticeInfo(startUserInfo); | |||||
WorkNoticeInfo rejectWorkNoticeInfo = getSendWorkNoticeInfo(instance.getStartUserId()); | |||||
String rejectMsg = String.format(REJECT_MSG_TEMPLATE, projectName, processDefinitionName); | String rejectMsg = String.format(REJECT_MSG_TEMPLATE, projectName, processDefinitionName); | ||||
rejectWorkNoticeInfo.setMsg(rejectMsg); | rejectWorkNoticeInfo.setMsg(rejectMsg); | ||||
// 放入系统通知表中,保存记录 | // 放入系统通知表中,保存记录 | ||||
@@ -421,7 +417,7 @@ public class TodoCenterManage { | |||||
processTaskService.handleTask(param, employeeCode); | processTaskService.handleTask(param, employeeCode); | ||||
// 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。 | // 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。 | ||||
// 获取发送浙政钉工作通知必要信息 | // 获取发送浙政钉工作通知必要信息 | ||||
WorkNoticeInfo backWorkNoticeInfo = getSendWorkNoticeInfo(startUserInfo); | |||||
WorkNoticeInfo backWorkNoticeInfo = getSendWorkNoticeInfo(instance.getStartUserId()); | |||||
String backMsg = String.format(BACK_MSG_TEMPLATE, projectName, processDefinitionName); | String backMsg = String.format(BACK_MSG_TEMPLATE, projectName, processDefinitionName); | ||||
backWorkNoticeInfo.setMsg(backMsg); | backWorkNoticeInfo.setMsg(backMsg); | ||||
// 放入系统通知表中,保存记录 | // 放入系统通知表中,保存记录 | ||||
@@ -432,7 +428,7 @@ public class TodoCenterManage { | |||||
// 撤回(流程发起人和当前流程审核人的前一个审核人操作) | // 撤回(流程发起人和当前流程审核人的前一个审核人操作) | ||||
case WITHDRAW: | case WITHDRAW: | ||||
// 登录用户是流程发起人,且是流程发起人撤回 | // 登录用户是流程发起人,且是流程发起人撤回 | ||||
if (employeeCode.equals(startUserId) | |||||
if (employeeCode.equals(instance.getStartUserId()) | |||||
&& ProcessConstant.Field.ROOT.equals(param.getTaskId())) { | && ProcessConstant.Field.ROOT.equals(param.getTaskId())) { | ||||
processTaskService.handleTask(param, employeeCode); | processTaskService.handleTask(param, employeeCode); | ||||
// 若是流程发起人点击撤回,项目回到上一个状态,需调用状态机更新项目状态,流程状态更新为审核通过 | // 若是流程发起人点击撤回,项目回到上一个状态,需调用状态机更新项目状态,流程状态更新为审核通过 | ||||
@@ -589,12 +585,16 @@ public class TodoCenterManage { | |||||
/** | /** | ||||
* 获取发送浙政钉工作通知的信息 | * 获取发送浙政钉工作通知的信息 | ||||
* | * | ||||
* @param auditUserInfo | |||||
* @param currentEmployeeCode | |||||
* @return com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo | * @return com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo | ||||
* @author CMM | * @author CMM | ||||
* @since 2023/02/15 14:04 | * @since 2023/02/15 14:04 | ||||
*/ | */ | ||||
public WorkNoticeInfo getSendWorkNoticeInfo(UserInfo auditUserInfo) { | |||||
public WorkNoticeInfo getSendWorkNoticeInfo(String currentEmployeeCode) { | |||||
UserInfo auditUserInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getEmployeeCode,currentEmployeeCode).last("limit 1")); | |||||
if (Objects.isNull(auditUserInfo)) { | |||||
throw new BizException("该用户不存在!"); | |||||
} | |||||
WorkNoticeInfo workNoticeInfo = new WorkNoticeInfo(); | WorkNoticeInfo workNoticeInfo = new WorkNoticeInfo(); | ||||
Long accountId = auditUserInfo.getAccountId(); | Long accountId = auditUserInfo.getAccountId(); | ||||
if (Objects.isNull(accountId)) { | if (Objects.isNull(accountId)) { | ||||
@@ -1,5 +1,6 @@ | |||||
package com.ningdatech.pmapi.user.service.impl; | package com.ningdatech.pmapi.user.service.impl; | ||||
import cn.hutool.core.collection.CollUtil; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||
import com.ningdatech.basic.exception.BizException; | import com.ningdatech.basic.exception.BizException; | ||||
@@ -15,10 +16,7 @@ import lombok.RequiredArgsConstructor; | |||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.Objects; | |||||
import java.util.Set; | |||||
import java.util.*; | |||||
import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
/** | /** | ||||
@@ -68,10 +66,13 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||||
@Override | @Override | ||||
public Map<String, ProcessInstanceUserDto> getUserMapByEmployeeCode(Set<String> staterUsers) { | public Map<String, ProcessInstanceUserDto> getUserMapByEmployeeCode(Set<String> staterUsers) { | ||||
List<UserInfo> userInfos = userInfoMapper.selectList(Wrappers.lambdaQuery(UserInfo.class) | List<UserInfo> userInfos = userInfoMapper.selectList(Wrappers.lambdaQuery(UserInfo.class) | ||||
.eq(UserInfo::getEmployeeCode,staterUsers)); | |||||
.in(UserInfo::getEmployeeCode,staterUsers)); | |||||
if(CollUtil.isEmpty(userInfos)){ | |||||
return Collections.emptyMap(); | |||||
} | |||||
return userInfos.stream().map(u -> { | return userInfos.stream().map(u -> { | ||||
ProcessInstanceUserDto userInfo = new ProcessInstanceUserDto(); | ProcessInstanceUserDto userInfo = new ProcessInstanceUserDto(); | ||||
userInfo.setUserId(String.valueOf(u.getId())); | |||||
userInfo.setUserId(u.getEmployeeCode()); | |||||
userInfo.setUserName(u.getRealName()); | userInfo.setUserName(u.getRealName()); | ||||
Long accountId = u.getAccountId(); | Long accountId = u.getAccountId(); | ||||
if (Objects.isNull(accountId)) { | if (Objects.isNull(accountId)) { | ||||
@@ -85,10 +85,9 @@ public class TodoCenterTest extends AppTests { | |||||
////若没有指定属性名,则默认为方法名 | ////若没有指定属性名,则默认为方法名 | ||||
//TaskExecutor taskExecutor = (TaskExecutor) ac.getBean("executor"); | //TaskExecutor taskExecutor = (TaskExecutor) ac.getBean("executor"); | ||||
Long userId = 4L; | |||||
UserInfo auditUserInfo = userInfoService.getById(userId); | |||||
String userId = "4"; | |||||
// 获取发送浙政钉工作通知必要信息 | // 获取发送浙政钉工作通知必要信息 | ||||
WorkNoticeInfo workNoticeInfo = todoCenterManage.getSendWorkNoticeInfo(auditUserInfo); | |||||
WorkNoticeInfo workNoticeInfo = todoCenterManage.getSendWorkNoticeInfo(userId); | |||||
// workNoticeInfo.setBizMsgId("1"); | // workNoticeInfo.setBizMsgId("1"); | ||||
String msg = String.format(PASS_MSG_TEMPLATE, "发改委", "0223-02-测试项目"); | String msg = String.format(PASS_MSG_TEMPLATE, "发改委", "0223-02-测试项目"); | ||||
@@ -125,9 +124,9 @@ public class TodoCenterTest extends AppTests { | |||||
@Test | @Test | ||||
public void sendWorkNoticeTest2(){ | public void sendWorkNoticeTest2(){ | ||||
UserInfo userInfo = userInfoService.getById(4L); | |||||
String userId = "2"; | |||||
// 获取发送浙政钉工作通知必要信息 | // 获取发送浙政钉工作通知必要信息 | ||||
WorkNoticeInfo passWorkNoticeInfo = todoCenterManage.getSendWorkNoticeInfo(userInfo); | |||||
WorkNoticeInfo passWorkNoticeInfo = todoCenterManage.getSendWorkNoticeInfo(userId); | |||||
String passMsg = String.format(PASS_MSG_TEMPLATE, passWorkNoticeInfo.getOrganizationName(), "测试项目0301-1"); | String passMsg = String.format(PASS_MSG_TEMPLATE, passWorkNoticeInfo.getOrganizationName(), "测试项目0301-1"); | ||||
passWorkNoticeInfo.setMsg(passMsg); | passWorkNoticeInfo.setMsg(passMsg); | ||||
// 放入工作通知暂存表中,通过扫表异步发送 | // 放入工作通知暂存表中,通过扫表异步发送 | ||||