diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/common/helper/MsgCallHelper.java b/hz-pm-api/src/main/java/com/hz/pm/api/common/helper/MsgCallHelper.java index cb577ae..a982b88 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/common/helper/MsgCallHelper.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/common/helper/MsgCallHelper.java @@ -97,6 +97,7 @@ public class MsgCallHelper { if (SendStatus.SUCCESS.equals(mcr.getSendStatus())) { switch (bizType) { case EXPERT_INVITE: + case MEETING_ROSTER_CONFIRM: mcr.setNeedReply(Boolean.TRUE); mcr.setReplyStatus(ReplyStatus.WAITING); break; diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/Meeting.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/Meeting.java index 17e8689..c16e835 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/Meeting.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/Meeting.java @@ -52,6 +52,9 @@ public class Meeting implements Serializable { @ApiModelProperty("会议地址") private String meetingAddress; + @ApiModelProperty("会议详细地址") + private String meetingAddressDetail; + @ApiModelProperty("评审地点经度") private Double addressLongitude; diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java index de74edb..5e26628 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java @@ -92,4 +92,7 @@ public class MeetingExpert implements Serializable { @ApiModelProperty("专家签到地点") private String signAddress; + @ApiModelProperty("确认名单短信通知标识") + private String confirmedRosterMsgSubmitKey; + } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/dto/MeetingBasicDTO.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/dto/MeetingBasicDTO.java index 9c56148..401c0e5 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/dto/MeetingBasicDTO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/dto/MeetingBasicDTO.java @@ -53,6 +53,10 @@ public class MeetingBasicDTO { @ApiModelProperty("评审地点") private String meetingAddress; + @Length(max = 200, message = "评审详细地址超出限制") + @ApiModelProperty("评审详细地址") + private String meetingAddressDetail; + @ApiModelProperty("评审地点经度") private Double addressLongitude; diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/InviteExpertListItemVO.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/InviteExpertListItemVO.java index 3458121..1f7ded1 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/InviteExpertListItemVO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/InviteExpertListItemVO.java @@ -62,6 +62,10 @@ public class InviteExpertListItemVO extends ExpertBasicInfoVO { @ApiModelProperty("专家签到地点") private String signAddress; + @ApiModelProperty("是否已确认名单") + private Boolean confirmedRoster; + @ApiModelProperty("确认名单短信回复内容") + private String confirmedRosterReplyContent; } \ No newline at end of file diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingByManagerVO.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingByManagerVO.java index 480b24f..56e4022 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingByManagerVO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingByManagerVO.java @@ -42,6 +42,9 @@ public class MeetingByManagerVO { @ApiModelProperty("评审地点") private String meetingAddress; + @ApiModelProperty("评审详细地址") + private String meetingAddressDetail; + @ApiModelProperty("会议状态") private Integer status; diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingDetailBasicVO.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingDetailBasicVO.java index dda5d1d..9c57a40 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingDetailBasicVO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/vo/MeetingDetailBasicVO.java @@ -59,6 +59,9 @@ public class MeetingDetailBasicVO { @ApiModelProperty("评审地点") private String meetingAddress; + @ApiModelProperty("评审详细地址") + private String meetingAddressDetail; + @ApiModelProperty("联系方式") private String contact; diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingManageHelper.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingManageHelper.java index 9e64d12..8c87e15 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingManageHelper.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingManageHelper.java @@ -112,6 +112,7 @@ public class MeetingManageHelper { result.setConnecter(meeting.getConnecter()); result.setContact(meeting.getContact()); result.setMeetingAddress(meeting.getMeetingAddress()); + result.setMeetingAddressDetail(meeting.getMeetingAddressDetail()); result.setIsInnerProject(meeting.getIsInnerProject()); result.setHasMeetingResult(StrUtil.isNotBlank(meeting.getResultDescription())); result.setSignQrCodeUrl(meeting.getSignQrCodeUrl()); diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java index 86eaa13..602d725 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java @@ -27,6 +27,7 @@ import com.hz.pm.api.user.model.entity.UserInfo; import com.hz.pm.api.user.service.IUserInfoService; import com.ningdatech.basic.util.CollUtils; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -43,6 +44,7 @@ import java.util.*; * @author WendyYang * @since 2023/4/20 **/ +@Slf4j @Component @RequiredArgsConstructor public class MeetingNotifyHelper { @@ -130,12 +132,18 @@ public class MeetingNotifyHelper { String meetingTime = sTime + "至" + eTime; List notifies = new ArrayList<>(); List workingNotices = new ArrayList<>(); + String meetingAddress = meeting.getMeetingAddress() + " " + meeting.getMeetingAddressDetail(); experts.forEach(w -> { String msgContent = String.format(MeetingMsgTemplateConst.CONFIRMED_ROSTER, - w.getExpertName(), officialTime(w.getCreateOn()), meetingTime, meeting.getMeetingAddress(), + w.getExpertName(), officialTime(w.getCreateOn()), meetingTime, meetingAddress, meeting.getConnecter(), meeting.getContact()); // 音信通消息 - msgCallHelper.sendMsg(w.getMobile(), msgContent, BizTypeEnum.MEETING_ROSTER_CONFIRM); + try { + String submitKey = msgCallHelper.sendMsg(w.getMobile(), msgContent, BizTypeEnum.MEETING_ROSTER_CONFIRM); + w.setConfirmedRosterMsgSubmitKey(submitKey); + } catch (Exception e) { + log.error("确认名单失败:{}", w.getMobile(), e); + } UserInfo info = userMap.get(w.getExpertId()); // 发送工作通知 if (info.getAccountId() != null) { diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java index 581ef97..6a3bc39 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java @@ -49,6 +49,9 @@ import com.hz.pm.api.projectlib.model.entity.Project; import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus; import com.hz.pm.api.projectlib.service.IProjectService; import com.hz.pm.api.sys.model.dto.RegionDTO; +import com.hz.pm.api.sys.model.entity.MsgCallRecord; +import com.hz.pm.api.sys.model.enumeration.SubmitTypeEnum; +import com.hz.pm.api.sys.service.IMsgCallRecordService; import com.hz.pm.api.user.helper.MhUnitCache; import com.hz.pm.api.user.model.entity.UserInfo; import com.hz.pm.api.user.model.enumeration.RoleEnum; @@ -112,6 +115,7 @@ public class MeetingManage { private final EnvironmentUtil environmentUtil; private final MhUnitCache mhUnitCache; private final ProjectStateMachineUtil projectStateMachineUtil; + private final IMsgCallRecordService msgCallRecordService; private static final String INVITED_RULE_CREATE = "INVITED_RULE_CREATE:"; @@ -494,6 +498,7 @@ public class MeetingManage { .meetingName(meeting.getName()) .meetingType(meeting.getType()) .meetingAddress(meeting.getMeetingAddress()) + .meetingAddressDetail(meeting.getMeetingAddressDetail()) .typeName(getDictName(meeting.getType())) .startTime(meeting.getStartTime()) .endTime(meeting.getEndTime()) @@ -543,12 +548,31 @@ public class MeetingManage { if (experts.isEmpty()) { return result; } - List expertIds = CollUtils.fieldList(experts, MeetingExpert::getExpertId); + List confirmedRosterSubmitKeys = new ArrayList<>(); + List expertIds = CollUtils.fieldList(experts, w -> { + if (StrUtil.isNotBlank(w.getConfirmedRosterMsgSubmitKey())) { + confirmedRosterSubmitKeys.add(w.getConfirmedRosterMsgSubmitKey()); + } + return w.getExpertId(); + }); + Map confirmedRosterReplyMap = new HashMap<>(); + if (!confirmedRosterSubmitKeys.isEmpty()) { + Wrapper query = Wrappers.lambdaQuery(MsgCallRecord.class) + .select(MsgCallRecord::getSubmitKey, MsgCallRecord::getReplyContent) + .eq(MsgCallRecord::getSubmitType, SubmitTypeEnum.SMS) + .in(MsgCallRecord::getSubmitKey, confirmedRosterSubmitKeys); + List msgCallRecords = msgCallRecordService.list(query); + for (MsgCallRecord msgCallRecord : msgCallRecords) { + confirmedRosterReplyMap.put(msgCallRecord.getSubmitKey(), msgCallRecord.getReplyContent()); + } + } Map expertMap = meetingManageHelper.getExpertBasicInfo(expertIds); BiFunction, InviteExpertListItemVO> mapping = (me, ruleMap) -> { ExpertBasicInfoVO expert = expertMap.get(me.getExpertId()); InviteExpertListItemVO item = BeanUtil.copyProperties(expert, InviteExpertListItemVO.class); item.setExpertMeetingId(me.getId()); + item.setConfirmedRoster(me.getConfirmedRoster()); + item.setConfirmedRosterReplyContent(confirmedRosterReplyMap.get(me.getConfirmedRosterMsgSubmitKey())); item.setMeetingId(me.getMeetingId()); item.setStatus(me.getStatus()); item.setStatusName(ExpertAttendStatusEnum.getValByCode(me.getStatus())); @@ -910,13 +934,21 @@ public class MeetingManage { return; } List currConfirmedMeIds = CollUtils.fieldList(expertNoticing, MeetingExpert::getId); - Wrapper meUpdate = Wrappers.lambdaUpdate(MeetingExpert.class) - .in(MeetingExpert::getId, currConfirmedMeIds) + LambdaUpdateWrapper meUpdate = Wrappers.lambdaUpdate(MeetingExpert.class) .set(MeetingExpert::getConfirmedRoster, Boolean.TRUE); - meetingExpertService.update(meUpdate); if (environmentUtil.isProdEnv()) { meetingNotifyHelper.sendConfirmedRosterMsg(expertNoticing, meeting); + for (MeetingExpert expert : expertNoticing) { + if (StrUtil.isBlank(expert.getConfirmedRosterMsgSubmitKey())) { + currConfirmedMeIds.remove(expert.getId()); + } + } + if (currConfirmedMeIds.isEmpty()) { + throw ReturnException.wrap("参会通知短信发送失败,请重试!"); + } } + meUpdate.in(MeetingExpert::getId, currConfirmedMeIds); + meetingExpertService.update(meUpdate); } finally { distributedLock.releaseLock(key); } @@ -930,6 +962,7 @@ public class MeetingManage { data.setEndTime(meeting.getEndTime()); data.setMeetingName(meeting.getName()); data.setMeetingAddress(meeting.getMeetingAddress()); + data.setMeetingAddressDetail(meeting.getMeetingAddressDetail()); data.setConnecter(meeting.getConnecter()); data.setContact(meeting.getContact()); data.setLongitude(meeting.getAddressLongitude()); @@ -1113,10 +1146,6 @@ public class MeetingManage { if (meeting == null || MeetingStatusEnum.CANCEL.eq(meeting.getStatus())) { throw ReturnException.wrap("会议不存在或已取消"); } - LocalDateTime now = LocalDateTime.now(); - if (meeting.getEndTime().isAfter(now)) { - throw ReturnException.wrap("会议未结束"); - } if (!Boolean.TRUE.equals(meeting.getIsInnerProject())) { throw ReturnException.wrap("此会议未关联项目"); } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/MeetingExpertToMhDTO.java b/hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/MeetingExpertToMhDTO.java index 5c12cb1..274af14 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/MeetingExpertToMhDTO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/MeetingExpertToMhDTO.java @@ -34,6 +34,9 @@ public class MeetingExpertToMhDTO { @ApiModelProperty("会议地址") private String meetingAddress; + @ApiModelProperty("会议地址详情") + private String meetingAddressDetail; + @ApiModelProperty("会议地址经度") private Double longitude; diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/entity/ProjectChangeHistory.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/entity/ProjectChangeHistory.java index 10f663d..f94fe97 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/entity/ProjectChangeHistory.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/entity/ProjectChangeHistory.java @@ -2,6 +2,7 @@ package com.hz.pm.api.projectdeclared.model.entity; import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -43,4 +44,7 @@ public class ProjectChangeHistory implements Serializable { private Integer status; + @ApiModelProperty("是否允许重新发起") + private Boolean canResubmit; + } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectChangeManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectChangeManage.java index d836370..88c4f61 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectChangeManage.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectChangeManage.java @@ -176,6 +176,7 @@ public class ProjectChangeManage { projectChangeHistory.setProjectId(project.getId()); projectChangeHistory.setProjectCode(project.getProjectCode()); projectChangeHistory.setStatus(ProjectChangeStatus.ON_CHANGE_APPLY.getCode()); + projectChangeHistory.setCanResubmit(Boolean.TRUE); projectChangeHistory.setInstCode(instId); projectChangeHistory.setId(req.getId()); projectChangeHistoryService.saveOrUpdate(projectChangeHistory); diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.xml b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.xml index 49644e5..9da37d5 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.xml +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.xml @@ -500,7 +500,8 @@ npch.status as changeStatus, npch.create_on as change_apply_time, npch.id as changeId, - npch.inst_code as instCode + npch.inst_code as instCode, + npch.can_resubmit as canResubmit from (select * from nd_project ${ew.customSqlSegment}) np inner join nd_project_change_history npch on np.id = npch.project_id diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectChangeListDTO.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectChangeListDTO.java index b88e665..a8f6d83 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectChangeListDTO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectChangeListDTO.java @@ -59,4 +59,7 @@ public class ProjectChangeListDTO { @ApiModelProperty("变更ID") private Long changeId; + @ApiModelProperty("是否可重新提交") + private Boolean canResubmit; + } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeListVO.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeListVO.java index e8ccabd..5894806 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeListVO.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeListVO.java @@ -62,4 +62,7 @@ public class ProjectChangeListVO { @ApiModelProperty("流程实例ID") private String instCode; + @ApiModelProperty("是否可重新提交") + private Boolean canResubmit; + } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/user/manage/UserInfoManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/user/manage/UserInfoManage.java index d1da415..9e6ee76 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/user/manage/UserInfoManage.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/user/manage/UserInfoManage.java @@ -15,7 +15,6 @@ import com.hz.pm.api.sys.model.entity.UserRole; import com.hz.pm.api.sys.service.IRoleService; import com.hz.pm.api.sys.service.IUserRoleService; import com.hz.pm.api.user.helper.MhUnitCache; -import com.hz.pm.api.user.model.dto.UnitDTO; import com.hz.pm.api.user.model.entity.UserInfo; import com.hz.pm.api.user.model.enumeration.UserAvailableEnum; import com.hz.pm.api.user.model.po.ReqUserDetailEditPO; @@ -75,6 +74,8 @@ public class UserInfoManage { if (page.getTotal() == 0) { return PageVo.empty(); } + List userIds = CollUtils.fieldList(page.getRecords(), UserInfo::getId); + Map> userRoleMap = getUserRoleMap(userIds); List result = new ArrayList<>(); page.getRecords().forEach(r -> { UserInfoListVO item = new UserInfoListVO(); @@ -82,7 +83,7 @@ public class UserInfoManage { userStatusBuilder(item, r); item.setUpdateTime(r.getUpdateOn()); item.setEmployeeCode(r.getEmployeeCode()); - item.setUserRoleList(getUserRole(item.getUserId())); + item.setUserRoleList(userRoleMap.get(r.getId())); item.setUserId(r.getId()); item.setPhoneNo(r.getMobile()); item.setMhUnitId(r.getMhUnitId()); @@ -154,6 +155,36 @@ public class UserInfoManage { return userRoleInfoList; } + private Map> getUserRoleMap(Collection userIds) { + if (CollUtil.isEmpty(userIds)) { + return Collections.emptyMap(); + } + List userRoleList = userRoleService.list(Wrappers.lambdaQuery(UserRole.class) + .in(UserRole::getUserId, userIds) + .orderByAsc(UserRole::getCreateOn)); + if (CollUtil.isNotEmpty(userRoleList)) { + List roleIds = CollUtils.fieldList(userRoleList, UserRole::getRoleId); + List roleList = roleService.listByIds(roleIds); + Map roleMap = CollUtils.listToMap(roleList, Role::getId); + Map> userRoleMap = userRoleList.stream() + .filter(r -> roleMap.containsKey(r.getRoleId())) + .collect(Collectors.groupingBy(UserRole::getUserId, + Collectors.mapping(w -> { + Role role = roleMap.get(w.getRoleId()); + UserRoleVO userRoleVO = new UserRoleVO(); + userRoleVO.setId(role.getId()); + userRoleVO.setName(role.getName()); + userRoleVO.setCreateOn(role.getCreateOn()); + return userRoleVO; + }, Collectors.toList()))); + for (List value : userRoleMap.values()) { + value.sort(Comparator.comparing(UserRoleVO::getCreateOn)); + } + return userRoleMap; + } + return Collections.emptyMap(); + } + @Transactional(rollbackFor = Exception.class) public void disableOrEnable(ReqUserDisableOrEnablePO req) { Long userId;