@@ -0,0 +1,109 @@ | |||
package com.ningdatech.pmapi.common.config; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.http.Header; | |||
import org.apache.http.client.HttpClient; | |||
import org.apache.http.client.config.RequestConfig; | |||
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; | |||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; | |||
import org.apache.http.impl.client.HttpClientBuilder; | |||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | |||
import org.apache.http.message.BasicHeader; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.http.MediaType; | |||
import org.springframework.http.client.ClientHttpRequestFactory; | |||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; | |||
import org.springframework.http.converter.HttpMessageConverter; | |||
import org.springframework.http.converter.StringHttpMessageConverter; | |||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | |||
import org.springframework.web.client.RestTemplate; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* @Classname BeanConfig | |||
* @Description | |||
* @Date 2023/3/2 9:42 | |||
* @Created by PoffyZhang | |||
*/ | |||
@Configuration | |||
@Slf4j | |||
public class BeanConfig { | |||
@Bean | |||
public RestTemplate restTemplate() { | |||
// 添加内容转换器,使用默认的内容转换器 | |||
RestTemplate restTemplate = new RestTemplate(httpRequestFactory()); | |||
// 设置编码格式为UTF-8,解决中文乱码问题 | |||
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters(); | |||
HttpMessageConverter<?> converterTarget = null; | |||
for (HttpMessageConverter<?> item : converterList) { | |||
if (item.getClass() == StringHttpMessageConverter.class) { | |||
converterTarget = item; | |||
break; | |||
} | |||
} | |||
if (converterTarget != null) { | |||
converterList.remove(converterTarget); | |||
} | |||
HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); | |||
converterList.add(1,converter); | |||
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); | |||
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList( | |||
MediaType.TEXT_HTML, | |||
MediaType.TEXT_PLAIN)); | |||
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter); | |||
log.info("-----restTemplate-----初始化完成"); | |||
return restTemplate; | |||
} | |||
@Bean | |||
public ClientHttpRequestFactory httpRequestFactory() { | |||
return new HttpComponentsClientHttpRequestFactory(httpClient()); | |||
} | |||
@Bean | |||
public HttpClient httpClient() { | |||
// 长连接保持30秒 | |||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS); | |||
//设置整个连接池最大连接数 根据自己的场景决定 | |||
connectionManager.setMaxTotal(500); | |||
//同路由的并发数,路由是对maxTotal的细分 | |||
connectionManager.setDefaultMaxPerRoute(500); | |||
//requestConfig | |||
RequestConfig requestConfig = RequestConfig.custom() | |||
//服务器返回数据(response)的时间,超过该时间抛出read timeout | |||
.setSocketTimeout(10000) | |||
//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout | |||
.setConnectTimeout(5000) | |||
//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool | |||
.setConnectionRequestTimeout(500) | |||
.build(); | |||
//headers | |||
List<Header> headers = new ArrayList<>(); | |||
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36")); | |||
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate")); | |||
headers.add(new BasicHeader("Accept-Language", "zh-CN")); | |||
headers.add(new BasicHeader("Connection", "Keep-Alive")); | |||
headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8")); | |||
return HttpClientBuilder.create() | |||
.setDefaultRequestConfig(requestConfig) | |||
.setConnectionManager(connectionManager) | |||
.setDefaultHeaders(headers) | |||
// 保持长连接配置,需要在头添加Keep-Alive | |||
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) | |||
//重试次数,默认是3次,没有开启 | |||
.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)) | |||
.build(); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package com.ningdatech.pmapi.common.config; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.context.annotation.Configuration; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* @author zpf | |||
* @date 2023/3/2 下午5:37 | |||
*/ | |||
@Data | |||
@Configuration | |||
@ConfigurationProperties(prefix = "provincial") | |||
public class ProvincialProperties { | |||
private String host; | |||
private String pushUrl; | |||
private String detailUrl; | |||
private String key; | |||
private String secret; | |||
} |
@@ -1,6 +1,10 @@ | |||
package com.ningdatech.pmapi.meeting.controller; | |||
import cn.hutool.core.io.FileUtil; | |||
import cn.hutool.json.JSON; | |||
import cn.hutool.json.JSONObject; | |||
import cn.hutool.json.JSONUtil; | |||
import com.ningdatech.basic.model.IdVo; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.log.annotation.WebLog; | |||
@@ -14,6 +18,9 @@ import org.springframework.validation.annotation.Validated; | |||
import org.springframework.web.bind.annotation.*; | |||
import javax.validation.Valid; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
/** | |||
* <p> | |||
@@ -67,17 +74,17 @@ public class MeetingController { | |||
} | |||
@ApiOperation("会议详情-基本信息") | |||
@GetMapping("detail/{meetingId}/basicInfo") | |||
@GetMapping("/basicInfo/{meetingId}") | |||
@WebLog(value = "会议详情-基本信息") | |||
public MeetingDetailBasicVO meetingBasic(@PathVariable Long meetingId) { | |||
return meetingManage.getMeetingDetail(meetingId); | |||
} | |||
@ApiOperation("邀请情况详情") | |||
@GetMapping("/detail/{meetingId}/inviteDetail") | |||
@ApiOperation("抽取情况") | |||
@GetMapping("/inviteExpertList/{meetingId}") | |||
@WebLog(value = "邀请情况详请") | |||
public ExpertInviteDetailVO inviteDetail(@PathVariable Long meetingId) { | |||
return meetingManage.inviteDetail(meetingId); | |||
public ExpertInviteDetailVO inviteExpertList(@PathVariable Long meetingId) { | |||
return meetingManage.inviteExpertList(meetingId); | |||
} | |||
@ApiOperation("会议基础信息修改") | |||
@@ -88,33 +95,17 @@ public class MeetingController { | |||
} | |||
@ApiOperation("会议详情-抽取规则") | |||
@GetMapping("/detail/inviteRule/{meetingId}") | |||
@GetMapping("/inviteRuleDetail/{meetingId}") | |||
@WebLog(value = "会议详情-抽取规则") | |||
public InviteRuleDetailVO inviteRuleDetail(@PathVariable Long meetingId) { | |||
return meetingManage.inviteRuleDetail(meetingId); | |||
} | |||
@ApiOperation("专家移除") | |||
@PostMapping("/expertRemove") | |||
@WebLog(value = "专家移除") | |||
public void expertRemove(@RequestBody ExpertRemoveReq po) { | |||
meetingManage.expertRemove(po); | |||
} | |||
@ApiOperation("专家替换") | |||
@PostMapping("/expertReplace") | |||
@WebLog(value = "专家替换") | |||
public void expertReplace(@RequestBody ExpertRemoveReq po) { | |||
meetingManage.expertReplace(po); | |||
} | |||
@ApiOperation("确认名单(下发会议通知)") | |||
@GetMapping("/sendMeetingNotice/{meetingId}") | |||
@WebLog(value = "确认名单(下发会议通知") | |||
public void sendMeetingNotice(@PathVariable Long meetingId) { | |||
meetingManage.sendMeetingNotice(meetingId); | |||
} | |||
@ApiOperation("停止抽取") | |||
@@ -122,21 +113,20 @@ public class MeetingController { | |||
@WebLog(value = "停止抽取") | |||
public void stopInvite(@PathVariable Long meetingId) { | |||
meetingManage.stopRandomInvite(meetingId); | |||
} | |||
@ApiOperation("取消会议") | |||
@PostMapping("/cancelMeeting") | |||
@PostMapping("/cancel") | |||
@WebLog(value = "取消会议") | |||
public void cancelMeeting(@Valid @RequestBody MeetingCancelReq po) { | |||
meetingManage.cancelMeeting(po); | |||
} | |||
@ApiOperation("邀请函信息") | |||
@GetMapping("/expertInvitationDetail") | |||
@GetMapping("/expertInviteDetail") | |||
@WebLog(value = "邀请函信息") | |||
public ExpertInvitationDetailVO expertInvitationDetail(@RequestParam("meetingId") Long meetingId, | |||
@RequestParam(required = false) Long expertId) { | |||
public ExpertInvitationDetailVO expertInvitationDetail(@RequestParam(required = false) Long expertId, | |||
@RequestParam Long meetingId) { | |||
return meetingManage.expertInvitationDetail(meetingId, expertId); | |||
} | |||
@@ -148,10 +138,32 @@ public class MeetingController { | |||
} | |||
@ApiOperation("确认参加") | |||
@PostMapping("/confirmAttendByManager") | |||
@PostMapping("/expert/confirm") | |||
@WebLog(value = "确认参加") | |||
public void confirmAttendByManager(@RequestBody ExpertRemoveReq po) { | |||
meetingManage.confirmAttendByManager(po); | |||
public void confirmAttendByManager(@RequestBody ExpertConfirmReq req) { | |||
meetingManage.confirmAttendByManager(req); | |||
} | |||
@ApiOperation("释放专家") | |||
@PostMapping("/expert/release") | |||
@WebLog(value = "释放专家") | |||
public void releaseExperts(@RequestBody MeetingCancelReq req) { | |||
meetingManage.releaseExperts(req); | |||
} | |||
@ApiOperation("设置专家组长") | |||
@PostMapping("setUpHeadman") | |||
@WebLog(value = "设置专家组长") | |||
public void setUpHeadman(@RequestBody ExpertConfirmReq req){ | |||
meetingManage.setUpHeadman(req); | |||
} | |||
@ApiOperation("重发短信") | |||
@PostMapping("/confirmedRoster") | |||
@WebLog(value = "重发短信") | |||
public void resendSms(MeetingCancelReq req){ | |||
meetingManage.confirmedRoster(req.getMeetingId()); | |||
} | |||
} |
@@ -1,20 +0,0 @@ | |||
package com.ningdatech.pmapi.meeting.controller; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.stereotype.Controller; | |||
/** | |||
* <p> | |||
* 会议评审内部项目表 前端控制器 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023-02-28 | |||
*/ | |||
@Controller | |||
@RequestMapping("/pmapi.meeting/meeting-inner-project") | |||
public class MeetingInnerProjectController { | |||
} |
@@ -1,20 +0,0 @@ | |||
package com.ningdatech.pmapi.meeting.controller; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.stereotype.Controller; | |||
/** | |||
* <p> | |||
* 会议评审外部项目 前端控制器 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023-02-28 | |||
*/ | |||
@Controller | |||
@RequestMapping("/pmapi.meeting/meeting-outer-project") | |||
public class MeetingOuterProjectController { | |||
} |
@@ -54,22 +54,6 @@ public class Meeting implements Serializable { | |||
@ApiModelProperty("联系方式") | |||
private String contact; | |||
@ApiModelProperty("创建人ID") | |||
@TableField(fill = FieldFill.INSERT) | |||
private Long createBy; | |||
@ApiModelProperty("创建时间") | |||
@TableField(fill = FieldFill.INSERT) | |||
private LocalDateTime createOn; | |||
@ApiModelProperty("修改人ID") | |||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||
private Long updateBy; | |||
@ApiModelProperty("修改时间") | |||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||
private LocalDateTime updateOn; | |||
@ApiModelProperty("创建人") | |||
private String creator; | |||
@@ -81,6 +65,9 @@ public class Meeting implements Serializable { | |||
@ApiModelProperty("是否停止随机邀请") | |||
private Boolean inviteStopped; | |||
@ApiModelProperty("是否确认名单") | |||
private Boolean confirmedRoster; | |||
@ApiModelProperty("举办单位") | |||
private String holdOrg; | |||
@@ -90,4 +77,23 @@ public class Meeting implements Serializable { | |||
@ApiModelProperty("是否为内部项目") | |||
private Boolean isInnerProject; | |||
@ApiModelProperty("抽取类型") | |||
private Integer inviteType; | |||
@ApiModelProperty("创建人ID") | |||
@TableField(fill = FieldFill.INSERT) | |||
private Long createBy; | |||
@ApiModelProperty("创建时间") | |||
@TableField(fill = FieldFill.INSERT) | |||
private LocalDateTime createOn; | |||
@ApiModelProperty("修改人ID") | |||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||
private Long updateBy; | |||
@ApiModelProperty("修改时间") | |||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||
private LocalDateTime updateOn; | |||
} |
@@ -47,9 +47,14 @@ public class MeetingExpert implements Serializable { | |||
private String mobile; | |||
private String expertName; | |||
@ApiModelProperty("当前状态") | |||
private Integer status; | |||
@ApiModelProperty("是否是专家组长") | |||
private Boolean isHeadman; | |||
@ApiModelProperty("前一个状态") | |||
private Integer preStatus; | |||
@@ -68,6 +73,5 @@ public class MeetingExpert implements Serializable { | |||
private String submitKey; | |||
private String expertName; | |||
} |
@@ -1,5 +1,6 @@ | |||
package com.ningdatech.pmapi.meeting.entity.enumeration; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
@@ -13,29 +14,26 @@ import java.util.Arrays; | |||
* @since 09:23 2022/8/9 | |||
*/ | |||
@Getter | |||
public enum ExpertAttendStatus { | |||
@AllArgsConstructor | |||
public enum ExpertAttendStatusEnum { | |||
NOTICING("通知中", 0), | |||
NOT_ANSWERED("未应答", 1), | |||
UNANSWERED("未应答", 1), | |||
REPLACED("已替换", 2), | |||
AGREED("同意参加", 3), | |||
REFUSED("拒绝参加", 4), | |||
CANCELED("已移除", 5), | |||
ON_LEAVE("已请假", 6); | |||
REMOVED("已移除", 5), | |||
ON_LEAVE("已请假", 6), | |||
RELEASED("已释放", 7); | |||
private final String value; | |||
private final Integer code; | |||
private final String desc; | |||
ExpertAttendStatus(String desc, Integer code) { | |||
this.code = code; | |||
this.desc = desc; | |||
} | |||
public boolean eq(Integer code) { | |||
return this.getCode().equals(code); | |||
} | |||
public static ExpertAttendStatus getByCode(Integer code) { | |||
public static ExpertAttendStatusEnum getByCode(Integer code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.eq(code)) | |||
.findFirst() |
@@ -0,0 +1,35 @@ | |||
package com.ningdatech.pmapi.meeting.entity.enumeration; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
/** | |||
* <p> | |||
* 专家参会状态 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 20:30 2023/3/2 | |||
*/ | |||
@Getter | |||
@AllArgsConstructor | |||
public enum MeetingAttendStatusEnum { | |||
TO_ATTEND("待参加", 1), | |||
ATTENDED("已参加", 2), | |||
ON_LEAVE("已请假", 3), | |||
UN_ATTEND("缺席", 4); | |||
private final String value; | |||
private final Integer code; | |||
public static MeetingAttendStatusEnum getByCode(Integer code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.getCode().equals(code)) | |||
.findFirst() | |||
.orElseThrow(() -> new IllegalArgumentException("专家参会状态编码无效")); | |||
} | |||
} |
@@ -1,32 +1,32 @@ | |||
package com.ningdatech.pmapi.meeting.entity.enumeration; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
/** | |||
* <p> | |||
* MeetingDateTermType-会议日期类型 | |||
* MeetingDateTermType | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 09:54 2022/8/15 | |||
*/ | |||
@Getter | |||
public enum MeetingDateTermType { | |||
@AllArgsConstructor | |||
public enum MeetingDateTermTypeEnum { | |||
/** | |||
* 会议日期类型 | |||
*/ | |||
ONE_DAY(1, "一天"), | |||
MORE_THAN_ONE(2, "两天及以上"); | |||
private final Integer code; | |||
private final String name; | |||
private final String value; | |||
MeetingDateTermType(Integer code, String name) { | |||
this.code = code; | |||
this.name = name; | |||
} | |||
public static MeetingDateTermType getByCode(Integer code) { | |||
public static MeetingDateTermTypeEnum getByCode(Integer code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.getCode().equals(code)) | |||
.findFirst() |
@@ -1,73 +0,0 @@ | |||
package com.ningdatech.pmapi.meeting.entity.enumeration; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
/** | |||
* <p> | |||
* MeetingStatus | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:14 2022/8/8 | |||
*/ | |||
public class MeetingStatus { | |||
/** | |||
* 管理员事务列表:事务状态 | |||
*/ | |||
@Getter | |||
public enum Manager { | |||
UNCOMPLETED("未完成", 1), | |||
COMPLETED("已完成", 2), | |||
CANCELED("已取消", 3); | |||
private final String desc; | |||
private final Integer code; | |||
Manager(String desc, Integer code) { | |||
this.desc = desc; | |||
this.code = code; | |||
} | |||
public boolean eq(Integer code) { | |||
return this.getCode().equals(code); | |||
} | |||
public static Manager getByCode(Integer code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.getCode().equals(code)) | |||
.findFirst() | |||
.orElseThrow(() -> new IllegalArgumentException("状态编码")); | |||
} | |||
} | |||
@Getter | |||
public enum Expert { | |||
TO_ATTEND("待参加", 1), | |||
ATTENDED("已参加", 2), | |||
ON_LEAVE("已请假", 3), | |||
UN_ATTEND("缺席", 4); | |||
private final String desc; | |||
private final Integer code; | |||
Expert(String desc, Integer code) { | |||
this.desc = desc; | |||
this.code = code; | |||
} | |||
public static Expert getByCode(Integer code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.getCode().equals(code)) | |||
.findFirst() | |||
.orElseThrow(() -> new IllegalArgumentException("状态编码")); | |||
} | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
package com.ningdatech.pmapi.meeting.entity.enumeration; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
/** | |||
* <p> | |||
* MeetingStatus | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:14 2022/8/8 | |||
*/ | |||
@Getter | |||
@AllArgsConstructor | |||
public enum MeetingStatusEnum { | |||
/** | |||
* 会议状态 | |||
*/ | |||
NORMAL("正常", 1), | |||
CANCELED("已取消", 3); | |||
private final String value; | |||
private final Integer code; | |||
public boolean eq(Integer code) { | |||
return this.getCode().equals(code); | |||
} | |||
public static MeetingStatusEnum getByCode(Integer code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.getCode().equals(code)) | |||
.findFirst() | |||
.orElseThrow(() -> new IllegalArgumentException("会议状态编码无效")); | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
package com.ningdatech.pmapi.meeting.entity.req; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotNull; | |||
/** | |||
* <p> | |||
* 确认参加参数类 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 08:59 2022/8/10 | |||
*/ | |||
@Data | |||
@ApiModel("确认参加") | |||
public class ExpertConfirmReq { | |||
@NotNull(message = "会议ID不能为空") | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@NotNull(message = "专家会议ID不能为空") | |||
@ApiModelProperty("专家会议ID") | |||
private Long expertMeetingId; | |||
} |
@@ -4,7 +4,6 @@ import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotBlank; | |||
import javax.validation.constraints.NotNull; | |||
/** | |||
@@ -23,8 +22,4 @@ public class MeetingCancelReq { | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@NotBlank(message = "取消说明不能为空") | |||
@ApiModelProperty("取消说明") | |||
private String cancelRemark; | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.ningdatech.pmapi.meeting.entity.req; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
/** | |||
* <p> | |||
* MeetingExpertIdReq | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 14:11 2023/3/3 | |||
*/ | |||
@Data | |||
public class MeetingExpertIdReq { | |||
@ApiModelProperty("专家会议ID") | |||
private Long expertMeetingId; | |||
} |
@@ -3,13 +3,12 @@ package com.ningdatech.pmapi.meeting.entity.vo; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import lombok.EqualsAndHashCode; | |||
import java.util.List; | |||
/** | |||
* <p> | |||
* ExpertInviteDetailVo | |||
* ExpertInviteDetailVO | |||
* </p> | |||
* | |||
* @author WendyYang | |||
@@ -19,73 +18,16 @@ import java.util.List; | |||
@ApiModel("专家邀请情况实体") | |||
public class ExpertInviteDetailVO { | |||
@Data | |||
@EqualsAndHashCode(callSuper = true) | |||
@ApiModel("最终参与名单实体") | |||
public static class ExpertAttendListItemVO extends ExpertBasicInfoVO { | |||
private Long meetingId; | |||
private Long expertMeetingId; | |||
@ApiModelProperty("邀请方式") | |||
private String inviteType; | |||
} | |||
@Data | |||
@EqualsAndHashCode(callSuper = true) | |||
@ApiModel("随机邀请名单实体") | |||
public static class RandomInviteListItemVO extends ExpertBasicInfoVO { | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@ApiModelProperty("专家会议ID") | |||
private Long expertMeetingId; | |||
@ApiModelProperty("电话通知状态") | |||
private String noticeStatus; | |||
@ApiModelProperty("邀请结果") | |||
private String confirmResult; | |||
@ApiModelProperty("邀请状态") | |||
private Integer status; | |||
} | |||
@ApiModelProperty("参与数量总计") | |||
private Integer attendTotal; | |||
@ApiModelProperty("随机邀请参与数量") | |||
private Integer randomAttend; | |||
@ApiModelProperty("指定邀请参与数量") | |||
private Integer appointAttend; | |||
@ApiModelProperty("是否已停止邀请") | |||
private Boolean invitedStopped; | |||
@ApiModelProperty("最终参与名单") | |||
private List<ExpertAttendListItemVO> attendList; | |||
@ApiModelProperty("随机邀请名单") | |||
private List<RandomInviteListItemVO> randomInviteList; | |||
@ApiModelProperty("指定邀请名单") | |||
private List<RandomInviteListItemVO> appointInviteList; | |||
public void addAttendList(ExpertAttendListItemVO attend) { | |||
this.attendList.add(attend); | |||
} | |||
@ApiModelProperty("是否已确认名单") | |||
private Boolean confirmedRoster; | |||
public void addRandomInviteList(RandomInviteListItemVO randomInvite) { | |||
this.randomInviteList.add(randomInvite); | |||
} | |||
@ApiModelProperty("邀请名单") | |||
private List<InviteExpertListItemVO> inviteExpertList; | |||
public void addAppointInviteList(RandomInviteListItemVO appointInvite) { | |||
this.appointInviteList.add(appointInvite); | |||
} | |||
@ApiModelProperty("抽取情况") | |||
private List<InviteStatisticsByRuleVO> inviteStatistics; | |||
} |
@@ -0,0 +1,41 @@ | |||
package com.ningdatech.pmapi.meeting.entity.vo; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import lombok.EqualsAndHashCode; | |||
import java.time.LocalDateTime; | |||
/** | |||
* <p> | |||
* RandomInviteListItemVO | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 16:48 2023/3/3 | |||
*/ | |||
@Data | |||
@ApiModel("邀请名单实体") | |||
@EqualsAndHashCode(callSuper = true) | |||
public class InviteExpertListItemVO extends ExpertBasicInfoVO { | |||
@ApiModelProperty("邀请规则ID") | |||
private Long ruleId; | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@ApiModelProperty("专家会议ID") | |||
private Long expertMeetingId; | |||
@ApiModelProperty("电话通知状态") | |||
private String noticeStatus; | |||
@ApiModelProperty("邀请状态") | |||
private Integer status; | |||
@ApiModelProperty("通知时间") | |||
private LocalDateTime noticeTime; | |||
} |
@@ -0,0 +1,50 @@ | |||
package com.ningdatech.pmapi.meeting.entity.vo; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
/** | |||
* <p> | |||
* InviteStatisticsVO | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 18:07 2023/3/4 | |||
*/ | |||
@Data | |||
public class InviteStatisticsByRuleVO { | |||
@ApiModelProperty("抽取规则ID") | |||
private Long ruleId; | |||
@ApiModelProperty("抽取人数") | |||
private Integer inviteCnt; | |||
@ApiModelProperty("同意人数") | |||
private Integer agreeCnt; | |||
@ApiModelProperty("实抽人数") | |||
private Integer noticedCnt; | |||
public static InviteStatisticsByRuleVO init(Long ruleId) { | |||
InviteStatisticsByRuleVO statistics = new InviteStatisticsByRuleVO(); | |||
statistics.setRuleId(ruleId); | |||
statistics.setNoticedCnt(0); | |||
statistics.setInviteCnt(0); | |||
statistics.setAgreeCnt(0); | |||
return statistics; | |||
} | |||
public void incrInviteCnt() { | |||
this.inviteCnt++; | |||
} | |||
public void incrAgreeCnt() { | |||
this.agreeCnt++; | |||
} | |||
public void incrNoticedCnt() { | |||
this.noticedCnt++; | |||
} | |||
} |
@@ -1,6 +1,5 @@ | |||
package com.ningdatech.pmapi.meeting.helper; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
@@ -13,15 +12,13 @@ import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.AbstractInviteRule; | |||
import com.ningdatech.pmapi.meeting.entity.dto.AppointInviteRuleDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum; | |||
import com.ningdatech.pmapi.meeting.service.IMeetingExpertService; | |||
import com.ningdatech.pmapi.meeting.service.IMeetingService; | |||
import lombok.AllArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.util.Assert; | |||
import java.time.LocalDateTime; | |||
import java.util.*; | |||
@@ -54,7 +51,6 @@ public class ExpertInviteHelper { | |||
public List<Long> listInvitedExpertByTime(LocalDateTime start, LocalDateTime end) { | |||
LambdaQueryWrapper<Meeting> meetingQuery = Wrappers.lambdaQuery(Meeting.class) | |||
.select(Meeting::getId) | |||
.eq(Meeting::getStatus, MeetingStatus.Manager.UNCOMPLETED.getCode()) | |||
.and(wrapper -> wrapper.between(Meeting::getStartTime, start, end) | |||
.or(wrapper1 -> wrapper1.between(Meeting::getEndTime, start, end))); | |||
List<Meeting> meetings = meetingService.list(meetingQuery); | |||
@@ -64,16 +60,14 @@ public class ExpertInviteHelper { | |||
List<Long> meetingIds = CollUtils.fieldList(meetings, Meeting::getId); | |||
LambdaQueryWrapper<MeetingExpert> meetingExpertQuery = Wrappers.lambdaQuery(MeetingExpert.class) | |||
.select(MeetingExpert::getExpertId) | |||
.in(MeetingExpert::getStatus, ExpertAttendStatus.AGREED.getCode(), ExpertAttendStatus.NOTICING.getCode()) | |||
.in(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode(), ExpertAttendStatusEnum.NOTICING.getCode()) | |||
.in(MeetingExpert::getMeetingId, meetingIds); | |||
List<MeetingExpert> meetingExperts = meetingExpertService.list(meetingExpertQuery); | |||
return CollUtils.fieldList(meetingExperts, MeetingExpert::getExpertId); | |||
} | |||
public Set<Long> listExpertLeaveOrInvited(LocalDateTime start, LocalDateTime end) { | |||
Set<Long> notInUserIds = new HashSet<>(); | |||
notInUserIds.addAll(listInvitedExpertByTime(start, end)); | |||
return notInUserIds; | |||
return new HashSet<>(listInvitedExpertByTime(start, end)); | |||
} | |||
public Set<Long> getAvoidExpert(List<Long> appoints, AvoidInfoDTO avoid, LocalDateTime start, LocalDateTime end) { | |||
@@ -16,8 +16,7 @@ import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.MeetingBasicDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.req.MeetingListReq; | |||
import com.ningdatech.pmapi.meeting.entity.vo.ExpertBasicInfoVO; | |||
import com.ningdatech.pmapi.meeting.entity.vo.MeetingByManagerVO; | |||
@@ -66,15 +65,8 @@ public class MeetingManageHelper { | |||
* @author WendyYang | |||
**/ | |||
public Integer getExpertAttendStatus(MeetingAndAttendStatusDTO info) { | |||
if (info.getAttended() == null && info.getStatus().equals(ExpertAttendStatus.AGREED.getCode())) { | |||
return MeetingStatus.Expert.TO_ATTEND.getCode(); | |||
} else if (info.getStatus().equals(ExpertAttendStatus.ON_LEAVE.getCode())) { | |||
return MeetingStatus.Expert.ON_LEAVE.getCode(); | |||
} else if (info.getAttended() != null && info.getAttended()) { | |||
return MeetingStatus.Expert.ATTENDED.getCode(); | |||
} else { | |||
return MeetingStatus.Expert.UN_ATTEND.getCode(); | |||
} | |||
// TODO | |||
return null; | |||
} | |||
public MeetingByManagerVO buildByMeeting(Meeting meeting) { | |||
@@ -188,16 +180,16 @@ public class MeetingManageHelper { | |||
ExpertUserFullInfo expertInfo = expertMap.get(w.getExpertId()); | |||
if (expertInfo != null) { | |||
String expertName = expertInfo.getExpertName(); | |||
switch (ExpertAttendStatus.getByCode(w.getStatus())) { | |||
switch (ExpertAttendStatusEnum.getByCode(w.getStatus())) { | |||
case REFUSED: | |||
throw BizException.wrap("专家%s已拒绝参加", expertName); | |||
case CANCELED: | |||
case REMOVED: | |||
throw BizException.wrap("专家%s已被移除", expertName); | |||
case REPLACED: | |||
switch (ExpertAttendStatus.getByCode(w.getPreStatus())) { | |||
switch (ExpertAttendStatusEnum.getByCode(w.getPreStatus())) { | |||
case REFUSED: | |||
throw BizException.wrap("专家%s已拒绝参加", expertName); | |||
case CANCELED: | |||
case REMOVED: | |||
throw BizException.wrap("专家%s已被移除", expertName); | |||
default: | |||
break; | |||
@@ -12,9 +12,9 @@ import com.ningdatech.pmapi.meeting.entity.domain.Meeting; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.CountConfirmByMeetingIdDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusByDashboard; | |||
import com.ningdatech.pmapi.meeting.entity.req.MeetingCalenderReq; | |||
import com.ningdatech.pmapi.meeting.entity.req.MeetingListReq; | |||
@@ -66,14 +66,14 @@ public class DashboardManage { | |||
meetingListPo.setEndTime(po.getEndDate().atTime(LocalTime.MAX)); | |||
PageVo<MeetingByManagerVO> meetingPage = meetingManage.meetingListByExpert(meetingListPo); | |||
Map<LocalDate, List<MeetingByManagerVO>> meetingByDate = meetingPage.getRecords().stream().map(w -> { | |||
List<Pair<LocalDate, MeetingByManagerVO>> pairs = new ArrayList<>(); | |||
LocalDateTime tempTime = w.getStartTime(); | |||
while (tempTime.isBefore(w.getEndTime())) { | |||
pairs.add(Pair.of(tempTime.toLocalDate(), w)); | |||
tempTime = tempTime.plusDays(1); | |||
} | |||
return pairs; | |||
}).flatMap(Collection::stream) | |||
List<Pair<LocalDate, MeetingByManagerVO>> pairs = new ArrayList<>(); | |||
LocalDateTime tempTime = w.getStartTime(); | |||
while (tempTime.isBefore(w.getEndTime())) { | |||
pairs.add(Pair.of(tempTime.toLocalDate(), w)); | |||
tempTime = tempTime.plusDays(1); | |||
} | |||
return pairs; | |||
}).flatMap(Collection::stream) | |||
.collect(Collectors.groupingBy(Pair::getLeft, | |||
Collectors.collectingAndThen(Collectors.mapping(Pair::getRight, Collectors.toList()), | |||
w -> { | |||
@@ -101,7 +101,7 @@ public class DashboardManage { | |||
// 查询所有未完成的项目 | |||
LambdaQueryWrapper<Meeting> query = Wrappers.lambdaQuery(Meeting.class) | |||
.select(Meeting::getId) | |||
.ne(Meeting::getStatus, MeetingStatus.Manager.CANCELED.getCode()) | |||
.ne(Meeting::getStatus, MeetingStatusEnum.CANCELED.getCode()) | |||
.eq(Meeting::getCreateBy, LoginUserUtil.getUserId()); | |||
List<Meeting> meetings = meetingService.list(query); | |||
if (meetings.isEmpty()) { | |||
@@ -110,7 +110,8 @@ public class DashboardManage { | |||
List<Long> meetingIds = CollUtils.fieldList(meetings, Meeting::getId); | |||
Page<MeetingExpert> page = meetingExpertEvaluationService.pageExpertEvaluationTodo(meetingIds, po); | |||
if (page.getTotal() > 0) { | |||
List<Long> expertIds = new ArrayList<>(), meetingIdsByPage = new ArrayList<>(); | |||
List<Long> expertIds = new ArrayList<>(); | |||
List<Long> meetingIdsByPage = new ArrayList<>(); | |||
page.getRecords().forEach(w -> { | |||
meetingIdsByPage.add(w.getMeetingId()); | |||
expertIds.add(w.getExpertId()); | |||
@@ -136,7 +137,6 @@ public class DashboardManage { | |||
public PageVo<MeetingConfirmToDoListItemVO> expertConfirmToDo(PagePo po) { | |||
// 查询所有未完成的项目 | |||
LambdaQueryWrapper<Meeting> query = Wrappers.lambdaQuery(Meeting.class) | |||
.eq(Meeting::getStatus, MeetingStatus.Manager.UNCOMPLETED.getCode()) | |||
.eq(Meeting::getCreateBy, LoginUserUtil.getUserId()) | |||
.orderByDesc(Meeting::getStartTime); | |||
List<Meeting> meetings = meetingService.list(query); | |||
@@ -179,7 +179,6 @@ public class DashboardManage { | |||
public PageVo<ExpertReplaceTodoListItemVO> expertReplaceTodoList(PagePo po) { | |||
// 查询所有未完成的项目 | |||
LambdaQueryWrapper<Meeting> query = Wrappers.lambdaQuery(Meeting.class) | |||
.eq(Meeting::getStatus, MeetingStatus.Manager.UNCOMPLETED.getCode()) | |||
.eq(Meeting::getCreateBy, LoginUserUtil.getUserId()) | |||
.orderByDesc(Meeting::getStartTime); | |||
List<Meeting> meetings = meetingService.list(query); | |||
@@ -188,7 +187,7 @@ public class DashboardManage { | |||
} | |||
List<Long> meetingIds = CollUtils.fieldList(meetings, Meeting::getId); | |||
Page<MeetingExpert> page = meetingExpertService.pageExpertByStatusAndMeetingIds(new Page<>(po.getPageNumber(), po.getPageSize()), | |||
meetingIds, ExpertAttendStatus.ON_LEAVE); | |||
meetingIds, ExpertAttendStatusEnum.ON_LEAVE); | |||
if (page.getTotal() == 0) { | |||
return PageVo.empty(); | |||
} | |||
@@ -225,7 +224,7 @@ public class DashboardManage { | |||
List<MeetingAndAttendStatusDTO> attendStatusList = meetingExpertService.listByExpertIdAndStatus(LoginUserUtil.getUserId(), null, null); | |||
MeetingCountByExpertVO result = MeetingCountByExpertVO.init(); | |||
attendStatusList.forEach(w -> { | |||
if (w.getStatus().equals(ExpertAttendStatus.ON_LEAVE.getCode())) { | |||
if (w.getStatus().equals(ExpertAttendStatusEnum.ON_LEAVE.getCode())) { | |||
result.incrLeaved(); | |||
} else if (w.getAttended() != null && w.getAttended()) { | |||
result.incrAttended(); | |||
@@ -19,7 +19,7 @@ import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.ExpertDictChooseDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper; | |||
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper; | |||
import com.ningdatech.pmapi.meeting.service.IExpertInviteRuleService; | |||
@@ -396,28 +396,28 @@ public class ExpertInviteManage { | |||
} | |||
Comparator<MeetingExpert> sort = Comparator.comparing(MeetingExpert::getUpdateOn).reversed(); | |||
Map<Long, MeetingExpert> tempExpertIdsMap = BizUtils.groupFirstMap(meetingExperts, MeetingExpert::getExpertId, sort); | |||
Map<ExpertAttendStatus, List<MeetingExpert>> expertIdGroupByStatus = tempExpertIdsMap.values().stream() | |||
.collect(Collectors.groupingBy(w -> ExpertAttendStatus.getByCode(w.getStatus()))); | |||
Map<ExpertAttendStatusEnum, List<MeetingExpert>> expertIdGroupByStatus = tempExpertIdsMap.values().stream() | |||
.collect(Collectors.groupingBy(w -> ExpertAttendStatusEnum.getByCode(w.getStatus()))); | |||
// 回避同单位其他专家 | |||
List<MeetingExpert> removeExpertByCompany = new ArrayList<>(); | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatus.AGREED), removeExpertByCompany::addAll); | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatus.NOTICING), removeExpertByCompany::addAll); | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.AGREED), removeExpertByCompany::addAll); | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.NOTICING), removeExpertByCompany::addAll); | |||
List<Long> removeExpertIds = new ArrayList<>(); | |||
// 拒绝参加的不可以被再次抽中 | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatus.REFUSED), w -> { | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.REFUSED), w -> { | |||
List<Long> tempRefused = CollUtils.fieldList(w, MeetingExpert::getExpertId); | |||
removeExpertIds.addAll(tempRefused); | |||
}); | |||
// 被取消的也不可以被再次抽中 | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatus.CANCELED), w -> { | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.REMOVED), w -> { | |||
List<Long> tempCanceled = CollUtils.fieldList(w, MeetingExpert::getExpertId); | |||
removeExpertIds.addAll(tempCanceled); | |||
}); | |||
// 被替换之前是上述两种状态的不可被再次抽中 | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatus.REPLACED), w -> { | |||
BizUtils.notEmpty(expertIdGroupByStatus.get(ExpertAttendStatusEnum.REPLACED), w -> { | |||
for (MeetingExpert me : w) { | |||
BizUtils.notNull(me.getPreStatus(), preStatus -> { | |||
if (ExpertAttendStatus.REFUSED.eq(preStatus) || ExpertAttendStatus.CANCELED.eq(preStatus)) { | |||
if (ExpertAttendStatusEnum.REFUSED.eq(preStatus) || ExpertAttendStatusEnum.REMOVED.eq(preStatus)) { | |||
removeExpertIds.add(me.getExpertId()); | |||
} | |||
}); | |||
@@ -572,7 +572,7 @@ public class ExpertInviteManage { | |||
Long ruleId = randoms.get(i).getId(); | |||
expertsByRandom.get(i).getExperts().forEach(w -> { | |||
MeetingExpert expert = ExpertInviteBuilder.getExpertByRandom(meeting.getId(), w, ruleId); | |||
expert.setStatus(ExpertAttendStatus.NOTICING.getCode()); | |||
expert.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | |||
expertInserts.add(expert); | |||
}); | |||
} | |||
@@ -16,7 +16,6 @@ import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.basic.util.ValidUtil; | |||
import com.ningdatech.cache.lock.DistributedLock; | |||
import com.ningdatech.file.service.FileService; | |||
import com.ningdatech.pmapi.common.helper.RegionCacheHelper; | |||
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo; | |||
import com.ningdatech.pmapi.expert.helper.PermissionCheckHelper; | |||
@@ -24,13 +23,11 @@ import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService; | |||
import com.ningdatech.pmapi.meeting.builder.ExpertInviteBuilder; | |||
import com.ningdatech.pmapi.meeting.entity.domain.*; | |||
import com.ningdatech.pmapi.meeting.entity.dto.*; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatus.Manager; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.req.*; | |||
import com.ningdatech.pmapi.meeting.entity.vo.*; | |||
import com.ningdatech.pmapi.meeting.entity.vo.ExpertInviteDetailVO.ExpertAttendListItemVO; | |||
import com.ningdatech.pmapi.meeting.entity.vo.ExpertInviteDetailVO.RandomInviteListItemVO; | |||
import com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper; | |||
import com.ningdatech.pmapi.meeting.helper.MeetingManageHelper; | |||
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper; | |||
@@ -42,7 +39,6 @@ import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
@@ -73,7 +69,6 @@ public class MeetingManage { | |||
private final IExpertInviteAvoidRuleService inviteAvoidRuleService; | |||
private final IExpertInviteRuleService inviteRuleService; | |||
private final IExpertUserFullInfoService expertUserFullInfoService; | |||
private final FileService fileService; | |||
private final TagCache tagCache; | |||
private final DictionaryCache dictionaryCache; | |||
private final IMeetingExpertService meetingExpertService; | |||
@@ -83,7 +78,6 @@ public class MeetingManage { | |||
private final YxtCallOrSmsHelper yxtCallOrSmsHelper; | |||
private final DistributedLock distributedLock; | |||
private final PermissionCheckHelper permissionCheckHelper; | |||
private final IUserInfoService userInfoService; | |||
private final IProjectService projectService; | |||
private final IMeetingInnerProjectService meetingInnerProjectService; | |||
private final IMeetingOuterProjectService meetingOuterProjectService; | |||
@@ -110,13 +104,14 @@ public class MeetingManage { | |||
try { | |||
// 保存会议基本信息 | |||
Meeting meeting = BeanUtil.copyProperties(meetingBasic, Meeting.class); | |||
meeting.setStatus(Manager.UNCOMPLETED.getCode()); | |||
meeting.setStatus(MeetingStatusEnum.NORMAL.getCode()); | |||
UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); | |||
meeting.setHoldOrg(userDetail.getOrganizationName()); | |||
meeting.setHoldOrgCode(userDetail.getOrganizationCode()); | |||
meeting.setRegionCode(userDetail.getRegionCode()); | |||
meeting.setCreator(userDetail.getUsername()); | |||
meeting.setInviteStopped(true); | |||
meeting.setInviteStopped(Boolean.FALSE); | |||
meeting.setConfirmedRoster(Boolean.FALSE); | |||
meetingService.save(meeting); | |||
if (meetingBasic.getIsInnerProject()) { | |||
List<MeetingInnerProject> projects = meetingBasic.getProjectIdList().stream().map(w -> { | |||
@@ -195,7 +190,7 @@ public class MeetingManage { | |||
List<MeetingExpert> experts = appointRule.getExpertIds().stream().map(w -> { | |||
ExpertUserFullInfo info = usersMap.get(w); | |||
MeetingExpert expert = ExpertInviteBuilder.getExpertByAppoint(meeting.getId(), info, ruleId); | |||
expert.setStatus(ExpertAttendStatus.NOTICING.getCode()); | |||
expert.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | |||
return expert; | |||
}).collect(Collectors.toList()); | |||
meetingExpertService.saveBatch(experts); | |||
@@ -253,7 +248,7 @@ public class MeetingManage { | |||
LambdaQueryWrapper<Meeting> query = new LambdaQueryWrapper<Meeting>() | |||
.orderByDesc(Meeting::getCreateOn) | |||
.in(Meeting::getId, mapByMeetingId.keySet()) | |||
.ne(Meeting::getStatus, Manager.CANCELED.getCode()); | |||
.ne(Meeting::getStatus, MeetingStatusEnum.CANCELED.getCode()); | |||
if (req.getExpertId() == null) { | |||
meetingManageHelper.buildMeetingQuery(query, req); | |||
} | |||
@@ -351,80 +346,60 @@ public class MeetingManage { | |||
return detail; | |||
} | |||
public ExpertInviteDetailVO inviteDetail(Long meetingId) { | |||
ExpertInviteDetailVO result = new ExpertInviteDetailVO(); | |||
public ExpertInviteDetailVO inviteExpertList(Long meetingId) { | |||
Meeting meeting = meetingService.getById(meetingId); | |||
if (Objects.isNull(meeting)) { | |||
throw new BizException("该会议信息不存在"); | |||
if (meeting == null) { | |||
throw BizException.wrap("该会议信息不存在"); | |||
} | |||
ExpertInviteDetailVO result = new ExpertInviteDetailVO(); | |||
result.setInvitedStopped(meeting.getInviteStopped()); | |||
result.setConfirmedRoster(meeting.getConfirmedRoster()); | |||
List<MeetingExpert> experts = meetingExpertService.listByMeetingId(meetingId); | |||
if (experts.isEmpty()) { | |||
return result; | |||
} | |||
List<MeetingExpert> randomList = new ArrayList<>(); | |||
List<MeetingExpert> appointList = new ArrayList<>(); | |||
List<MeetingExpert> attendList = new ArrayList<>(); | |||
List<Long> expertIds = new ArrayList<>(); | |||
experts.forEach(w -> { | |||
boolean randomInvite = w.getInviteType().equals(ExpertInviteTypeEnum.RANDOM.getCode()); | |||
if (randomInvite) { | |||
randomList.add(w); | |||
} else { | |||
appointList.add(w); | |||
} | |||
if (w.getStatus().equals(ExpertAttendStatus.AGREED.getCode())) { | |||
attendList.add(w); | |||
if (randomInvite) { | |||
result.setRandomAttend(result.getRandomAttend() + 1); | |||
} else { | |||
result.setAppointAttend(result.getAppointAttend() + 1); | |||
} | |||
} | |||
expertIds.add(w.getExpertId()); | |||
}); | |||
result.setAttendTotal(attendList.size()); | |||
Map<Long, ExpertBasicInfoVO> expertBasicInfoVoMap = meetingManageHelper.getExpertBasicInfo(expertIds); | |||
Function<MeetingExpert, RandomInviteListItemVO> mapping = sme -> { | |||
ExpertBasicInfoVO basicInfoVo = expertBasicInfoVoMap.get(sme.getExpertId()); | |||
RandomInviteListItemVO item = BeanUtil.copyProperties(basicInfoVo, RandomInviteListItemVO.class); | |||
item.setStatus(sme.getStatus()); | |||
item.setMeetingId(sme.getMeetingId()); | |||
List<Long> expertIds = CollUtils.fieldList(experts, MeetingExpert::getExpertId); | |||
Map<Long, ExpertBasicInfoVO> expertMap = meetingManageHelper.getExpertBasicInfo(expertIds); | |||
Function<MeetingExpert, InviteExpertListItemVO> mapping = sme -> { | |||
ExpertBasicInfoVO expert = expertMap.get(sme.getExpertId()); | |||
InviteExpertListItemVO item = BeanUtil.copyProperties(expert, InviteExpertListItemVO.class); | |||
item.setExpertMeetingId(sme.getId()); | |||
ExpertAttendStatus status = ExpertAttendStatus.getByCode(sme.getStatus()); | |||
if (status.equals(ExpertAttendStatus.NOTICING)) { | |||
item.setNoticeStatus(status.getDesc()); | |||
item.setConfirmResult(StrUtil.EMPTY); | |||
item.setMeetingId(sme.getMeetingId()); | |||
item.setStatus(sme.getStatus()); | |||
item.setNoticeTime(sme.getCreateOn()); | |||
item.setRuleId(sme.getRuleId()); | |||
if (ExpertAttendStatusEnum.NOTICING.eq(sme.getStatus())) { | |||
item.setNoticeStatus("通知中"); | |||
} else { | |||
item.setNoticeStatus("已通知"); | |||
item.setConfirmResult(status.getDesc()); | |||
} | |||
return item; | |||
}; | |||
// 随机邀请列表 | |||
randomList.forEach(w -> result.addRandomInviteList(mapping.apply(w))); | |||
// 指定抽取列表 | |||
appointList.forEach(w -> result.addAppointInviteList(mapping.apply(w))); | |||
boolean isRandom = ExpertInviteTypeEnum.RANDOM.eq(meeting.getInviteType()); | |||
if (!isRandom) { | |||
result.setInviteStatistics(new ArrayList<>()); | |||
Map<Long, List<MeetingExpert>> groupByRule = CollUtils.group(experts, MeetingExpert::getRuleId); | |||
List<ExpertInviteRule> inviteRules = inviteRuleService.listByIds(groupByRule.keySet()); | |||
Map<Long, ExpertInviteRule> ruleMap = CollUtils.listToMap(inviteRules, ExpertInviteRule::getId); | |||
groupByRule.forEach((ruleId, expertList) -> { | |||
InviteStatisticsByRuleVO statistics = InviteStatisticsByRuleVO.init(ruleId); | |||
expertList.forEach((expert) -> { | |||
Integer status = expert.getStatus(); | |||
if (ExpertAttendStatusEnum.AGREED.eq(status)) { | |||
statistics.incrAgreeCnt(); | |||
} | |||
statistics.setInviteCnt(ruleMap.get(ruleId).getInviteCount()); | |||
statistics.incrNoticedCnt(); | |||
}); | |||
result.getInviteStatistics().add(statistics); | |||
}); | |||
} | |||
List<InviteExpertListItemVO> converts = CollUtils.convert(experts, mapping); | |||
result.setInviteExpertList(converts); | |||
// 确定参加列表 | |||
attendList.forEach(w -> { | |||
ExpertBasicInfoVO expertBasicInfoVo = expertBasicInfoVoMap.get(w.getExpertId()); | |||
ExpertAttendListItemVO item = BeanUtil.copyProperties(expertBasicInfoVo, ExpertAttendListItemVO.class); | |||
item.setInviteType(ExpertInviteTypeEnum.getByCode(w.getInviteType()).getName()); | |||
result.addAttendList(item); | |||
}); | |||
return result; | |||
} | |||
private boolean meetingInfoChange(Meeting old, Meeting current) { | |||
if (!old.getStartTime().equals(current.getStartTime())) { | |||
return Boolean.TRUE; | |||
} | |||
if (!old.getRegionCode().equals(current.getRegionCode())) { | |||
return Boolean.TRUE; | |||
} | |||
return Boolean.FALSE; | |||
} | |||
/** | |||
* 会议基本信息修改 | |||
* | |||
@@ -435,14 +410,12 @@ public class MeetingManage { | |||
BeanUtil.copyProperties(po, meeting); | |||
LocalDateTime now = LocalDateTime.now(); | |||
Meeting old = meetingService.getById(po.getId()); | |||
if (Manager.UNCOMPLETED.eq(old.getStatus()) && meetingInfoChange(old, meeting)) { | |||
List<MeetingExpert> meList = meetingExpertService.listExpertByAgreeAttend(Collections.singletonList(po.getId())); | |||
if (!meList.isEmpty() && old.getStartTime().isAfter(now)) { | |||
// TODO | |||
/*String meetingType = dictionaryCache.getByCode(old.getType()).getName(); | |||
List<SendSmsContext> contexts = YxtSmsContextBuilder.smsToExpertByMeetingChange(old, meeting, meList, meetingType); | |||
yxtCallOrSmsHelper.sendSms(contexts);*/ | |||
} | |||
List<MeetingExpert> meList = meetingExpertService.listAgreedExperts(Collections.singletonList(po.getId())); | |||
if (!meList.isEmpty() && old.getStartTime().isAfter(now)) { | |||
// TODO | |||
/*String meetingType = dictionaryCache.getByCode(old.getType()).getName(); | |||
List<SendSmsContext> contexts = YxtSmsContextBuilder.smsToExpertByMeetingChange(old, meeting, meList, meetingType); | |||
yxtCallOrSmsHelper.sendSms(contexts);*/ | |||
} | |||
meetingService.updateById(meeting); | |||
} | |||
@@ -508,7 +481,7 @@ public class MeetingManage { | |||
public void expertRemove(ExpertRemoveReq po) { | |||
LambdaUpdateWrapper<MeetingExpert> update = Wrappers.lambdaUpdate(MeetingExpert.class) | |||
.eq(MeetingExpert::getId, po.getExpertMeetingId()) | |||
.set(MeetingExpert::getStatus, ExpertAttendStatus.CANCELED.getCode()); | |||
.set(MeetingExpert::getStatus, ExpertAttendStatusEnum.REMOVED.getCode()); | |||
meetingExpertService.update(update); | |||
} | |||
@@ -556,7 +529,7 @@ public class MeetingManage { | |||
.eq(MeetingExpert::getId, po.getExpertMeetingId()) | |||
.set(MeetingExpert::getUpdateOn, LocalDateTime.now()) | |||
.set(MeetingExpert::getPreStatus, meetingExpert.getStatus()) | |||
.set(MeetingExpert::getStatus, ExpertAttendStatus.REPLACED.getCode()); | |||
.set(MeetingExpert::getStatus, ExpertAttendStatusEnum.REPLACED.getCode()); | |||
meetingExpertService.update(update); | |||
MeetingExpert me; | |||
if (po.getExpertId() == null) { | |||
@@ -564,7 +537,7 @@ public class MeetingManage { | |||
} else { | |||
me = ExpertInviteBuilder.getExpertByAppoint(po.getMeetingId(), expertFullInfo, ruleId); | |||
} | |||
me.setStatus(ExpertAttendStatus.NOTICING.getCode()); | |||
me.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | |||
me.setPreId(po.getExpertMeetingId()); | |||
yxtCallOrSmsHelper.callByMeetingExperts(meeting, Collections.singletonList(me)); | |||
meetingExpertService.save(me); | |||
@@ -578,64 +551,40 @@ public class MeetingManage { | |||
List<ExpertUserFullInfo> userInfos = meetingManageHelper.appointExpertCheck(po.getMeetingId(), po.getExpertIds()); | |||
List<MeetingExpert> expertList = CollUtils.convert(userInfos, w -> { | |||
MeetingExpert me = ExpertInviteBuilder.getExpertByAppoint(po.getMeetingId(), w, 0L); | |||
me.setStatus(ExpertAttendStatus.NOTICING.getCode()); | |||
me.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | |||
return me; | |||
}); | |||
meetingExpertService.saveBatch(expertList); | |||
} | |||
public void sendMeetingNotice(Long meetingId) { | |||
String key = "SEND_MEETING_NOTICE:" + meetingId; | |||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||
throw BizException.wrap("正在下发会议通知"); | |||
} | |||
try { | |||
Meeting meeting = meetingService.getById(meetingId); | |||
Assert.isTrue(Manager.UNCOMPLETED.eq(meeting.getStatus()), "非未完成会议无法发送会议通知"); | |||
Assert.isTrue(meeting.getInviteStopped(), "随机邀请未结束"); | |||
int noticeCount = meetingExpertService.countExpertByStatusAndMeetingId(ExpertAttendStatus.NOTICING, meetingId, null); | |||
Assert.isTrue(noticeCount == 0, "存在未确认完成的专家,暂无法下发会议通知"); | |||
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class) | |||
.eq(Meeting::getId, meetingId); | |||
meetingService.update(update); | |||
// 发送会议通知 | |||
List<MeetingExpert> experts = meetingExpertService.listExpertByAgreeAttend(Collections.singletonList(meetingId)); | |||
if (!experts.isEmpty()) { | |||
// TODO | |||
// String meetingType = dictionaryCache.getByCode(meeting.getType()).getName(); | |||
// List<SendSmsContext> contexts = YxtSmsContextBuilder.smsToExpertBySendNotice(meeting, experts, meetingType); | |||
// yxtCallOrSmsHelper.sendSms(contexts); | |||
} | |||
} finally { | |||
distributedLock.releaseLock(key); | |||
} | |||
} | |||
public void stopRandomInvite(Long meetingId) { | |||
expertInviteTask.cancelByMeetingId(meetingId); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public void cancelMeeting(MeetingCancelReq po) { | |||
String key = "CANCEL_MEETING:" + po.getMeetingId(); | |||
public void cancelMeeting(MeetingCancelReq req) { | |||
Long meetingId = req.getMeetingId(); | |||
String key = "CANCEL_MEETING:" + meetingId; | |||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||
throw BizException.wrap("正在取消会议,请刷新后重试"); | |||
} | |||
try { | |||
Meeting meeting = meetingService.getById(po.getMeetingId()); | |||
Assert.isTrue(!Manager.CANCELED.eq(meeting.getStatus()), "会议已取消"); | |||
Assert.isTrue(meeting.getStartTime().isAfter(LocalDateTime.now()), "会议已开始,暂时无法取消"); | |||
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class) | |||
.set(Meeting::getStatus, Manager.CANCELED.getCode()) | |||
.set(Meeting::getUpdateBy, LoginUserUtil.getUserId()) | |||
.set(Meeting::getUpdateOn, LocalDateTime.now()) | |||
.eq(Meeting::getId, po.getMeetingId()); | |||
meetingService.update(update); | |||
expertInviteTask.cancelByMeetingId(po.getMeetingId()); | |||
Meeting meeting = meetingService.getById(meetingId); | |||
if (MeetingStatusEnum.CANCELED.eq(meeting.getStatus())) { | |||
throw BizException.wrap("会议已取消"); | |||
} | |||
if (meeting.getStartTime().isBefore(LocalDateTime.now())) { | |||
throw BizException.wrap("会议已开始,暂时无法取消"); | |||
} | |||
LambdaUpdateWrapper<Meeting> meetingUpdate = Wrappers.lambdaUpdate(Meeting.class) | |||
.set(Meeting::getStatus, MeetingStatusEnum.CANCELED.getCode()) | |||
.eq(Meeting::getId, meetingId); | |||
meetingService.update(meetingUpdate); | |||
expertInviteTask.cancelByMeetingId(meetingId); | |||
// 发送通知给专家 | |||
List<MeetingExpert> experts = meetingExpertService.listExpertByAgreeAttend(Collections.singletonList(po.getMeetingId())); | |||
List<MeetingExpert> experts = meetingExpertService.listAgreedExperts(meetingId); | |||
if (!experts.isEmpty()) { | |||
// TODO | |||
// TODO 取消会议后发送短信通知 | |||
// meeting.setCancelRemark(po.getCancelRemark()); | |||
// String meetingType = dictionaryCache.getByCode(meeting.getType()).getName(); | |||
// List<SendSmsContext> contexts = YxtSmsContextBuilder.smsToExpertByCancelMeeting(meeting, experts, meetingType); | |||
@@ -649,12 +598,16 @@ public class MeetingManage { | |||
public ExpertInvitationDetailVO expertInvitationDetail(Long meetingId, Long expertId) { | |||
Long userId = expertId == null ? LoginUserUtil.getUserId() : expertId; | |||
MeetingExpert me = meetingExpertService.getByMeetingIdAndExpertId(meetingId, userId); | |||
Assert.notNull(me, "未被邀请参加"); | |||
Assert.isTrue(ExpertAttendStatus.AGREED.eq(me.getStatus()), "未确认参加"); | |||
ExpertUserFullInfo expertInfo = expertUserFullInfoService.getByUserId(userId); | |||
if (me == null) { | |||
throw BizException.wrap("未被邀请参加此会议"); | |||
} | |||
if (ExpertAttendStatusEnum.AGREED.eq(me.getStatus())) { | |||
throw BizException.wrap("未确认参加此会议"); | |||
} | |||
ExpertUserFullInfo userInfo = expertUserFullInfoService.getByUserId(userId); | |||
Meeting meeting = meetingService.getById(meetingId); | |||
return ExpertInvitationDetailVO.builder() | |||
.expertName(expertInfo.getExpertName()) | |||
.expertName(userInfo.getExpertName()) | |||
.holdOrg(meeting.getHoldOrg()) | |||
.meetingName(meeting.getName()) | |||
.startTime(meeting.getStartTime()) | |||
@@ -665,18 +618,95 @@ public class MeetingManage { | |||
.build(); | |||
} | |||
public void confirmAttendByManager(ExpertRemoveReq po) { | |||
MeetingExpert meetingExpert = meetingExpertService.getById(po.getExpertMeetingId()); | |||
if (meetingExpert.getStatus().equals(ExpertAttendStatus.NOTICING.getCode())) { | |||
public void confirmAttendByManager(ExpertConfirmReq req) { | |||
String key = "CONFIRM_ATTEND:" + req.getExpertMeetingId(); | |||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||
throw BizException.wrap("确认参加失败,请重试!"); | |||
} | |||
try { | |||
MeetingExpert me = meetingExpertService.getById(req.getExpertMeetingId()); | |||
if (!ExpertAttendStatusEnum.NOTICING.eq(me.getStatus())) { | |||
throw BizException.wrap("确认参加失败,请重试!"); | |||
} | |||
LambdaUpdateWrapper<MeetingExpert> update = Wrappers.lambdaUpdate(MeetingExpert.class) | |||
.set(MeetingExpert::getStatus, ExpertAttendStatus.AGREED.getCode()) | |||
.set(MeetingExpert::getUpdateOn, LocalDateTime.now()) | |||
.set(MeetingExpert::getUpdateBy, LoginUserUtil.getUserId()) | |||
.eq(MeetingExpert::getId, po.getExpertMeetingId()); | |||
.set(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode()) | |||
.eq(MeetingExpert::getId, req.getExpertMeetingId()); | |||
meetingExpertService.update(update); | |||
} else { | |||
ExpertAttendStatus status = ExpertAttendStatus.getByCode(meetingExpert.getStatus()); | |||
throw BizException.wrap("该专家" + status.getDesc()); | |||
} finally { | |||
distributedLock.releaseLock(key); | |||
} | |||
} | |||
public void releaseExperts(MeetingCancelReq req) { | |||
String key = "EXPERT_RELEASE:" + req.getMeetingId(); | |||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||
throw BizException.wrap("释放专家失败,请重试!"); | |||
} | |||
try { | |||
Meeting meeting = meetingService.getById(req.getMeetingId()); | |||
if (MeetingStatusEnum.CANCELED.eq(meeting.getStatus())) { | |||
throw BizException.wrap("会议已取消"); | |||
} | |||
LambdaUpdateWrapper<MeetingExpert> update = Wrappers.lambdaUpdate(MeetingExpert.class) | |||
.set(MeetingExpert::getStatus, ExpertAttendStatusEnum.RELEASED.getCode()) | |||
.eq(MeetingExpert::getMeetingId, req.getMeetingId()); | |||
meetingExpertService.update(update); | |||
} finally { | |||
distributedLock.releaseLock(key); | |||
} | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public void setUpHeadman(ExpertConfirmReq req) { | |||
String key = "SETUP_HEADMAN:" + req.getMeetingId(); | |||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||
throw BizException.wrap("设置专家组长失败,请重试!"); | |||
} | |||
try { | |||
Meeting meeting = meetingService.getById(req.getMeetingId()); | |||
if (MeetingStatusEnum.CANCELED.eq(meeting.getStatus())) { | |||
throw BizException.wrap("会议已取消"); | |||
} | |||
LambdaUpdateWrapper<MeetingExpert> cancel = Wrappers.lambdaUpdate(MeetingExpert.class) | |||
.set(MeetingExpert::getIsHeadman, Boolean.FALSE) | |||
.eq(MeetingExpert::getIsHeadman, Boolean.TRUE) | |||
.eq(MeetingExpert::getMeetingId, req.getMeetingId()); | |||
meetingExpertService.update(cancel); | |||
MeetingExpert headman = meetingExpertService.getById(req.getExpertMeetingId()); | |||
if (!ExpertAttendStatusEnum.AGREED.eq(headman.getStatus())) { | |||
ExpertAttendStatusEnum status = ExpertAttendStatusEnum.getByCode(headman.getStatus()); | |||
throw BizException.wrap("该专家处于:%s状态,不能被设置为专家组长!", status.getValue()); | |||
} | |||
LambdaUpdateWrapper<MeetingExpert> setup = Wrappers.lambdaUpdate(MeetingExpert.class) | |||
.set(MeetingExpert::getIsHeadman, Boolean.TRUE) | |||
.eq(MeetingExpert::getId, req.getExpertMeetingId()); | |||
meetingExpertService.update(setup); | |||
} finally { | |||
distributedLock.releaseLock(key); | |||
} | |||
} | |||
public void confirmedRoster(Long meetingId) { | |||
String key = "MEETING_RESEND_SMS:" + meetingId; | |||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||
throw BizException.wrap("请刷新后重试!"); | |||
} | |||
try { | |||
Meeting meeting = meetingService.getById(meetingId); | |||
if (!MeetingStatusEnum.NORMAL.eq(meeting.getStatus())) { | |||
throw BizException.wrap("请刷新后重试!"); | |||
} | |||
if (!meeting.getConfirmedRoster()) { | |||
// 首次确认的 | |||
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class); | |||
update.set(Meeting::getConfirmedRoster, Boolean.TRUE); | |||
update.eq(Meeting::getId, meetingId); | |||
meetingService.update(update); | |||
} | |||
List<MeetingExpert> experts = meetingExpertService.listAgreedExperts(meetingId); | |||
// TODO 发送会议通知 | |||
} finally { | |||
distributedLock.releaseLock(key); | |||
} | |||
} | |||
@@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import org.apache.ibatis.annotations.Param; | |||
import java.util.Collection; | |||
@@ -37,7 +37,7 @@ public interface MeetingExpertMapper extends BaseMapper<MeetingExpert> { | |||
* 分页查询专家列表 | |||
* | |||
* @param page 分页数据 | |||
* @param status 状态{@link ExpertAttendStatus} | |||
* @param status 状态{@link ExpertAttendStatusEnum} | |||
* @param meetingId 会议ID | |||
* @param inviteType 邀请类型 | |||
* @return Page<MeetingExpert> | |||
@@ -51,7 +51,7 @@ public interface MeetingExpertMapper extends BaseMapper<MeetingExpert> { | |||
* 分页查询专家列表 | |||
* | |||
* @param page 分页数据 | |||
* @param status 状态{@link ExpertAttendStatus} | |||
* @param status 状态{@link ExpertAttendStatusEnum} | |||
* @param meetingIds 会议ID | |||
* @return Page<MeetingExpert> | |||
* @author WendyYang | |||
@@ -5,10 +5,11 @@ import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.CountConfirmByMeetingIdDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Map; | |||
@@ -78,7 +79,7 @@ public interface IMeetingExpertService extends IService<MeetingExpert> { | |||
* @return Page<MeetingExpert> | |||
* @author WendyYang | |||
**/ | |||
Page<MeetingExpert> pageExpertByStatusAndMeetingId(Page<MeetingExpert> page, Long meetingId, ExpertAttendStatus status, Integer inviteType); | |||
Page<MeetingExpert> pageExpertByStatusAndMeetingId(Page<MeetingExpert> page, Long meetingId, ExpertAttendStatusEnum status, Integer inviteType); | |||
/** | |||
* 批量查询某个状态的专家邀请记录 | |||
@@ -89,7 +90,7 @@ public interface IMeetingExpertService extends IService<MeetingExpert> { | |||
* @return 专家邀请记录 | |||
* @author WendyYang | |||
**/ | |||
Page<MeetingExpert> pageExpertByStatusAndMeetingIds(Page<MeetingExpert> page, List<Long> meetingIds, ExpertAttendStatus status); | |||
Page<MeetingExpert> pageExpertByStatusAndMeetingIds(Page<MeetingExpert> page, List<Long> meetingIds, ExpertAttendStatusEnum status); | |||
/** | |||
* 根据邀请类型统计会议下某个状态的专家数量 | |||
@@ -100,16 +101,27 @@ public interface IMeetingExpertService extends IService<MeetingExpert> { | |||
* @return int | |||
* @author WendyYang | |||
**/ | |||
int countExpertByStatusAndMeetingId(ExpertAttendStatus status, Long meetingId, ExpertInviteTypeEnum inviteType); | |||
int countExpertByStatusAndMeetingId(ExpertAttendStatusEnum status, Long meetingId, ExpertInviteTypeEnum inviteType); | |||
/** | |||
* 查询所有同意参加的专家记录 | |||
* 查询所有同意参加的专家记录(批量会议) | |||
* | |||
* @param meetingIds 会议ID | |||
* @return List<MeetingExpert> | |||
* @return 同意参加的专家 | |||
* @author WendyYang | |||
**/ | |||
List<MeetingExpert> listExpertByAgreeAttend(Collection<Long> meetingIds); | |||
List<MeetingExpert> listAgreedExperts(Collection<Long> meetingIds); | |||
/** | |||
* 查询所有同意参加的专家记录(单个会议) | |||
* | |||
* @param meetingId 会议ID | |||
* @return 同意参加的专家 | |||
* @author WendyYang | |||
**/ | |||
default List<MeetingExpert> listAgreedExperts(Long meetingId) { | |||
return listAgreedExperts(Collections.singletonList(meetingId)); | |||
} | |||
/** | |||
* 查询会议的所有被抽取人最后一条记录 | |||
@@ -9,7 +9,7 @@ import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.CountConfirmByMeetingIdDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum; | |||
import com.ningdatech.pmapi.meeting.mapper.ExpertInviteRuleMapper; | |||
import com.ningdatech.pmapi.meeting.mapper.MeetingExpertMapper; | |||
@@ -58,17 +58,17 @@ public class MeetingExpertServiceImpl extends ServiceImpl<MeetingExpertMapper, M | |||
.meetingId(meetingId) | |||
.build(); | |||
w.forEach(item -> { | |||
ExpertAttendStatus attendStatus = ExpertAttendStatus.getByCode(item.getStatus()); | |||
ExpertAttendStatusEnum attendStatus = ExpertAttendStatusEnum.getByCode(item.getStatus()); | |||
if (item.getInviteType().equals(ExpertInviteTypeEnum.APPOINT.getCode())) { | |||
// 被替换和已取消的不计数 | |||
if (attendStatus.equals(ExpertAttendStatus.CANCELED) | |||
|| attendStatus.equals(ExpertAttendStatus.REPLACED)) { | |||
if (attendStatus.equals(ExpertAttendStatusEnum.REMOVED) | |||
|| attendStatus.equals(ExpertAttendStatusEnum.REPLACED)) { | |||
return; | |||
} | |||
confirm.setTotal(confirm.getTotal() + 1); | |||
} | |||
// 除通知中的均为已确认 | |||
if (attendStatus.equals(ExpertAttendStatus.AGREED)) { | |||
if (attendStatus.equals(ExpertAttendStatusEnum.AGREED)) { | |||
confirm.setConfirmed(confirm.getConfirmed() + 1); | |||
} | |||
}); | |||
@@ -103,26 +103,26 @@ public class MeetingExpertServiceImpl extends ServiceImpl<MeetingExpertMapper, M | |||
} | |||
@Override | |||
public Page<MeetingExpert> pageExpertByStatusAndMeetingId(Page<MeetingExpert> page, Long meetingId, ExpertAttendStatus status, Integer inviteType) { | |||
public Page<MeetingExpert> pageExpertByStatusAndMeetingId(Page<MeetingExpert> page, Long meetingId, ExpertAttendStatusEnum status, Integer inviteType) { | |||
return baseMapper.selectExpertByStatusAndMeetingId(page, status.getCode(), meetingId, inviteType); | |||
} | |||
@Override | |||
public Page<MeetingExpert> pageExpertByStatusAndMeetingIds(Page<MeetingExpert> page, List<Long> meetingIds, ExpertAttendStatus status) { | |||
public Page<MeetingExpert> pageExpertByStatusAndMeetingIds(Page<MeetingExpert> page, List<Long> meetingIds, ExpertAttendStatusEnum status) { | |||
return baseMapper.selectExpertByStatusAndMeetingIds(page, status == null ? null : status.getCode(), meetingIds); | |||
} | |||
@Override | |||
public int countExpertByStatusAndMeetingId(ExpertAttendStatus status, Long meetingId, ExpertInviteTypeEnum inviteType) { | |||
public int countExpertByStatusAndMeetingId(ExpertAttendStatusEnum status, Long meetingId, ExpertInviteTypeEnum inviteType) { | |||
Integer tempStatus = status == null ? null : status.getCode(); | |||
Integer tempInviteType = inviteType == null ? null : inviteType.getCode(); | |||
return baseMapper.countExpertByStatusAndMeetingId(tempStatus, meetingId, tempInviteType); | |||
} | |||
@Override | |||
public List<MeetingExpert> listExpertByAgreeAttend(Collection<Long> meetingIds) { | |||
public List<MeetingExpert> listAgreedExperts(Collection<Long> meetingIds) { | |||
LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class) | |||
.eq(MeetingExpert::getStatus, ExpertAttendStatus.AGREED.getCode()) | |||
.eq(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode()) | |||
.in(MeetingExpert::getMeetingId, meetingIds); | |||
return baseMapper.selectList(query); | |||
} | |||
@@ -16,7 +16,7 @@ import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.dto.AvoidInfoDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.ExpertChooseDTO; | |||
import com.ningdatech.pmapi.meeting.entity.dto.RandomInviteRuleDTO; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatus; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum; | |||
import com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper; | |||
import com.ningdatech.pmapi.meeting.helper.YxtCallOrSmsHelper; | |||
@@ -134,7 +134,7 @@ public class ExpertInviteTask { | |||
Map<Long, ExpertInviteRule> ruleMap = CollUtils.listToMap(randomRules, ExpertInviteRule::getId); | |||
LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class) | |||
.in(MeetingExpert::getRuleId, ruleMap.keySet()) | |||
.in(MeetingExpert::getStatus, ExpertAttendStatus.AGREED.getCode()); | |||
.in(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode()); | |||
List<MeetingExpert> meetingExperts = meetingExpertService.list(query); | |||
int totalCount = CollUtils.sum(randomRules, ExpertInviteRule::getInviteCount); | |||
boolean needed = totalCount > meetingExperts.size(); | |||
@@ -235,8 +235,8 @@ public class ExpertInviteTask { | |||
if (expertChoose.getTotal() > 0) { | |||
List<MeetingExpert> expertMeetings = CollUtils.convert(expertChoose.getExperts(), w -> { | |||
MeetingExpert expert = ExpertInviteBuilder.getExpertByRandom(meetingId, w, ruleId); | |||
expert.setPreStatus(ExpertAttendStatus.NOTICING.getCode()); | |||
expert.setStatus(ExpertAttendStatus.NOTICING.getCode()); | |||
expert.setPreStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | |||
expert.setStatus(ExpertAttendStatusEnum.NOTICING.getCode()); | |||
return expert; | |||
}); | |||
yxtCallOrSmsHelper.callByMeetingExperts(meeting, expertMeetings); | |||
@@ -282,13 +282,13 @@ public class ExpertInviteTask { | |||
Collectors.collectingAndThen(Collectors.mapping(Map.Entry::getValue, Collectors.toList()), w -> { | |||
ExpertCntBO cnt = ExpertCntBO.zeroInit(); | |||
for (MeetingExpert expert : w) { | |||
if (ExpertAttendStatus.AGREED.eq(expert.getStatus())) { | |||
if (ExpertAttendStatusEnum.AGREED.eq(expert.getStatus())) { | |||
cnt.incrAgreeCnt(); | |||
} else if (ExpertAttendStatus.NOTICING.eq(expert.getStatus())) { | |||
} else if (ExpertAttendStatusEnum.NOTICING.eq(expert.getStatus())) { | |||
cnt.incrNoticeCnt(); | |||
} else if (ExpertAttendStatus.REPLACED.eq(expert.getStatus())) { | |||
} else if (ExpertAttendStatusEnum.REPLACED.eq(expert.getStatus())) { | |||
MeetingExpert replacedExpert = replacedMap.get(expert.getId()); | |||
if (replacedExpert != null && ExpertAttendStatus.AGREED.eq(replacedExpert.getStatus())) { | |||
if (replacedExpert != null && ExpertAttendStatusEnum.AGREED.eq(replacedExpert.getStatus())) { | |||
cnt.incrAgreeCnt(); | |||
} | |||
} | |||
@@ -66,7 +66,7 @@ public class ProcDefController { | |||
@ApiOperation(value = "单位流程配置部署", notes = "单位流程配置部署") | |||
@PostMapping("/deploy/{processDefId}") | |||
public String deploy(@Validated @PathVariable String processDefId) { | |||
return orgProcessModelService.deployProcess(processDefId); | |||
return orgProcessModelService.deployProcess(processDefId,null); | |||
} | |||
@ApiOperation(value = "单位流程配置删除", notes = "单位流程配置删除") | |||
@@ -1,6 +1,7 @@ | |||
package com.ningdatech.pmapi.projectdeclared.controller; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.pmapi.projectdeclared.manage.DefaultDeclaredProjectManage; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DeclaredProjectListParamDTO; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.ProjectDraftSaveDTO; | |||
@@ -24,6 +24,7 @@ import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.exception.BusinessException; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.vo.ProcessStartParamsVo; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
import com.wflow.workflow.service.ProcessModelService; | |||
@@ -65,6 +66,7 @@ public class ConstructionPlanManage { | |||
private final UserInfoHelper userInfoHelper; | |||
private final DefaultDeclaredProjectManage declaredProjectManage; | |||
private final DefaultDeclaredProjectManage defaultDeclaredProjectManage; | |||
/** | |||
* 建设方案 | |||
@@ -111,7 +113,9 @@ public class ConstructionPlanManage { | |||
}) | |||
); | |||
params.setFormData(dto.getFormData()); | |||
String instanceId = processService.startProcess(model.getProcessDefId(), params); | |||
// 获取发起单位、发起单位主管单位信息 | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId, model); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("建设方案项目申报成功 【{}】", instanceId); | |||
//保存建设项目 | |||
@@ -10,11 +10,10 @@ import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.pmapi.common.enumeration.ProjectProcessStageEnum; | |||
import com.ningdatech.pmapi.common.helper.UserInfoHelper; | |||
import com.ningdatech.pmapi.organization.model.entity.DingOrganization; | |||
import com.ningdatech.pmapi.organization.service.IDingOrganizationService; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.*; | |||
import com.ningdatech.pmapi.projectdeclared.model.entity.ProjectDraft; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DeclaredProjectListParamDTO; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.ProjectConditionDTO; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.ProjectDraftSaveDTO; | |||
import com.ningdatech.pmapi.projectdeclared.model.vo.ProjectDraftVO; | |||
import com.ningdatech.pmapi.projectdeclared.service.IProjectDraftService; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
@@ -31,7 +30,12 @@ import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.bean.entity.WflowOrgModels; | |||
import com.wflow.enums.OrgTypeEnum; | |||
import com.wflow.enums.ProcessDefTypeEnum; | |||
import com.wflow.exception.BusinessException; | |||
import com.wflow.service.OrgProcdefService; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.vo.ProcessStartParamsVo; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
import com.wflow.workflow.service.ProcessModelService; | |||
@@ -43,10 +47,7 @@ import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.time.LocalDateTime; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
/** | |||
@@ -131,7 +132,9 @@ public class DeclaredProjectManage { | |||
); | |||
params.setFormData(dto.getFormData()); | |||
//开始申报 | |||
String instanceId = processService.startProcess(model.getProcessDefId(), params); | |||
// 获取发起单位、发起单位主管单位流程信息map | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId, model); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("申报项目成功 【{}】", instanceId); | |||
//如果是重新提交的话 判断下 项目是否存在 | |||
@@ -140,6 +143,7 @@ public class DeclaredProjectManage { | |||
return instanceId; | |||
} | |||
/** | |||
* 重新提交 启动实例 | |||
* | |||
@@ -183,7 +187,9 @@ public class DeclaredProjectManage { | |||
}) | |||
); | |||
params.setFormData(dto.getFormData()); | |||
String instanceId = processService.startProcess(model.getProcessDefId(), params); | |||
// 获取发起单位、发起单位主管单位流程信息map | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId, model); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("重新申报项目成功 【{}】", instanceId); | |||
//保存项目 | |||
@@ -3,15 +3,28 @@ package com.ningdatech.pmapi.projectdeclared.manage; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.pmapi.common.helper.UserInfoHelper; | |||
import com.ningdatech.pmapi.organization.model.entity.DingOrganization; | |||
import com.ningdatech.pmapi.organization.service.IDingOrganizationService; | |||
import com.ningdatech.pmapi.projectlib.model.dto.ProjectDTO; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.bean.entity.WflowOrgModels; | |||
import com.wflow.enums.OrgTypeEnum; | |||
import com.wflow.enums.ProcessDefTypeEnum; | |||
import com.wflow.service.OrgProcdefService; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.stereotype.Component; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @Classname DefaultDeclaredProjectManage | |||
@@ -29,6 +42,9 @@ public class DefaultDeclaredProjectManage { | |||
private final UserInfoHelper userInfoHelper; | |||
private final IDingOrganizationService dingOrganizationService; | |||
private final OrgProcdefService orgProcdefService; | |||
//项目名称去重 | |||
public void checkDuplication(ProjectDTO project){ | |||
VUtils.isTrue(projectService.count(Wrappers.lambdaQuery(Project.class) | |||
@@ -50,4 +66,50 @@ public class DefaultDeclaredProjectManage { | |||
.orgName(userFullInfo.getOrganizationName()) | |||
.build(); | |||
} | |||
public Map<String, OrgInfoDTO> getOrgModelInfo(Long userId, WflowModels model) { | |||
Map<String, OrgInfoDTO> orgMap = new HashMap<>(); | |||
// 查出所有的单位流程配置 | |||
List<WflowOrgModels> orgModelsList = orgProcdefService.list(); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
DingOrganization startOrg = dingOrganizationService.getOne(Wrappers.lambdaQuery(DingOrganization.class) | |||
.eq(DingOrganization::getOrganizationCode, userFullInfo.getOrganizationCode())); | |||
String startOrgCode = startOrg.getOrganizationCode(); | |||
String startOrgName = startOrg.getOrganizationName(); | |||
String startOrgParentCode = startOrg.getParentCode(); | |||
String startOrgParentName = startOrg.getParentName(); | |||
//查询 当前发起人及主管单位所在区域的 单位流程配置 | |||
OrgInfoDTO startOrgInfoDto = new OrgInfoDTO(); | |||
startOrgInfoDto.setOrganizationCode(startOrgCode); | |||
startOrgInfoDto.setOrganizationName(startOrgName); | |||
startOrgInfoDto.setOrgModelMap(orgModelsList.stream() | |||
.filter(v -> v.getOrgCode().equals(startOrgCode) | |||
&& Boolean.FALSE.equals(v.getIsDelete()) | |||
&& (ProcessDefTypeEnum.SEAL.name().equals(v.getType()) || | |||
ProcessDefTypeEnum.DEFAULT.name().equals(v.getType()))) | |||
.collect(Collectors.toMap(WflowOrgModels::getType, v -> v))); | |||
OrgInfoDTO parentOrgInfoDto = new OrgInfoDTO(); | |||
parentOrgInfoDto.setOrganizationCode(startOrgParentCode); | |||
parentOrgInfoDto.setOrganizationName(startOrgParentName); | |||
parentOrgInfoDto.setOrgModelMap(orgModelsList.stream() | |||
.filter(v -> v.getOrgCode().equals(startOrgParentCode) | |||
&& Boolean.FALSE.equals(v.getIsDelete()) | |||
&& (ProcessDefTypeEnum.SEAL.name().equals(v.getType()) || | |||
ProcessDefTypeEnum.DEFAULT.name().equals(v.getType()))) | |||
.collect(Collectors.toMap(WflowOrgModels::getType, v -> v))); | |||
orgMap.put(OrgTypeEnum.TARGET_OWNER.name(),startOrgInfoDto); | |||
orgMap.put(OrgTypeEnum.TARGET_MANAGEMENT.name(),parentOrgInfoDto); | |||
// 如果是指定单位,直接根据流程定义ID放入map | |||
OrgInfoDTO orgInfoDTO = new OrgInfoDTO(); | |||
orgInfoDTO.setOrgModelMap(orgModelsList.stream() | |||
.collect(Collectors.toMap(WflowOrgModels::getProcessDefId, v -> v))); | |||
orgMap.put(OrgTypeEnum.TARGET_LABEL.name(),orgInfoDTO); | |||
return orgMap; | |||
} | |||
} |
@@ -25,6 +25,7 @@ import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.exception.BusinessException; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.vo.ProcessStartParamsVo; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
import com.wflow.workflow.service.ProcessModelService; | |||
@@ -68,6 +69,8 @@ public class PrequalificationDeclaredProjectManage { | |||
private final DefaultDeclaredProjectManage declaredProjectManage; | |||
private final DefaultDeclaredProjectManage defaultDeclaredProjectManage; | |||
/** | |||
* 提交预审 | |||
* | |||
@@ -135,7 +138,10 @@ public class PrequalificationDeclaredProjectManage { | |||
}) | |||
); | |||
params.setFormData(dto.getFormData()); | |||
instanceId = processService.startProcess(model.getProcessDefId(), params); | |||
// 获取发起单位、发起单位主管单位信息 | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId, model); | |||
instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("提交预审项目成功 【{}】", instanceId); | |||
//保存预审项目 | |||
@@ -17,6 +17,7 @@ import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.exception.BusinessException; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import com.wflow.workflow.bean.vo.ProcessStartParamsVo; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
@@ -52,8 +53,8 @@ public class ReviewByDeptJointManage { | |||
private final IProjectInstService projectInstService; | |||
private final UserInfoHelper userInfoHelper; | |||
private final DefaultDeclaredProjectManage declaredProjectManage; | |||
private final DefaultDeclaredProjectManage defaultDeclaredProjectManage; | |||
/** | |||
* 部门联审 | |||
@@ -102,7 +103,10 @@ public class ReviewByDeptJointManage { | |||
}) | |||
); | |||
params.setFormData(formData); | |||
String instanceId = processService.startProcess(model.getProcessDefId(), params); | |||
// 获取发起单位、发起单位主管单位信息 | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId, model); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("部门联审申报成功 【{}】", instanceId); | |||
//保存项目信息 | |||
@@ -6,10 +6,8 @@ import com.ningdatech.pmapi.projectdeclared.manage.DeclaredProjectManage; | |||
import com.ningdatech.pmapi.projectdeclared.manage.PrequalificationDeclaredProjectManage; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Component; | |||
import javax.annotation.PostConstruct; | |||
import java.util.Map; | |||
import java.util.function.Function; | |||
@@ -20,21 +18,22 @@ import java.util.function.Function; | |||
* @Author PoffyZhang | |||
*/ | |||
@Component | |||
@RequiredArgsConstructor | |||
public class ReStartProcessMapUtil { | |||
private final DeclaredProjectManage declaredProjectManage; | |||
@Autowired | |||
private DeclaredProjectManage declaredProjectManage; | |||
private final ConstructionPlanManage constructionPlanManage; | |||
@Autowired | |||
private ConstructionPlanManage constructionPlanManage; | |||
private final PrequalificationDeclaredProjectManage prequalificationDeclaredProjectManage; | |||
@Autowired | |||
private PrequalificationDeclaredProjectManage prequalificationDeclaredProjectManage; | |||
public Map<Integer, Function<DefaultDeclaredDTO,String>> reStartProcessMap = Maps.newHashMap(); | |||
/** | |||
* 初始化业务分派逻辑,代替了if-else部分 | |||
* key: 枚举 状态值 | |||
* value: lambda表达式,最终会获取发起实例的函数 | |||
*/ | |||
@PostConstruct | |||
public void reStartProcessInit(){ | |||
public ReStartProcessMapUtil(){ | |||
//重新项目申报 | |||
reStartProcessMap.put(ProjectStatusEnum.UNDER_INTERNAL_AUDIT_NOT_PASS.getCode(), | |||
dto->declaredProjectManage.reStartTheProcess(dto)); | |||
@@ -0,0 +1,38 @@ | |||
package com.ningdatech.pmapi.provincial.controller; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import io.swagger.annotations.Api; | |||
import io.swagger.annotations.ApiOperation; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.validation.annotation.Validated; | |||
import org.springframework.web.bind.annotation.*; | |||
import javax.validation.Valid; | |||
/** | |||
* @Classname TestController | |||
* @Description | |||
* @Date 2023/3/2 15:08 | |||
* @Author PoffyZhang | |||
*/ | |||
@RestController | |||
@RequestMapping("/api/v1/test") | |||
@Api(tags = "测试省局接口") | |||
public class TestController { | |||
@Autowired | |||
private IJoinReviewProvincialBureauService joinReviewProvincialBureauService; | |||
@PostMapping("/push") | |||
@ApiOperation("测试推送") | |||
private String push(@Valid @RequestBody ProvincialProjectDTO project){ | |||
return joinReviewProvincialBureauService.pushImportProject(project); | |||
} | |||
@GetMapping("/detail") | |||
@ApiOperation("测试推送") | |||
private String detail(@RequestParam String projectId){ | |||
return joinReviewProvincialBureauService.processInfo(projectId); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
package com.ningdatech.pmapi.provincial.model.dto; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
/** | |||
* @Classname ProcessCommentDTO | |||
* @Description | |||
* @Date 2023/3/2 15:25 | |||
* @Author PoffyZhang | |||
*/ | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProcessCommentDTO", description = "省局返回流程审核详情") | |||
public class ProcessCommentDTO { | |||
@ApiModelProperty("任务id") | |||
private String taskId; | |||
@ApiModelProperty("comment") | |||
private String comment; | |||
@ApiModelProperty("流程步骤") | |||
private String stepName; | |||
@ApiModelProperty("审批状态") | |||
private String status; | |||
@ApiModelProperty("审批人") | |||
private String label; | |||
@ApiModelProperty("时间") | |||
private String approverTime; | |||
} |
@@ -0,0 +1,98 @@ | |||
package com.ningdatech.pmapi.provincial.model.dto; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.util.List; | |||
/** | |||
* @Classname ProvincialApplicationDTO | |||
* @Description | |||
* @Date 2023/3/2 10:06 | |||
* @Author PoffyZhang | |||
*/ | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProvincialApplicationDTO", description = "") | |||
public class ProvincialApplicationDTO { | |||
//云 信息 | |||
private List<Cloud> clouds; | |||
//是否初次建设 1是 2不是 | |||
private Integer isFirst; | |||
//应用名称 | |||
private String applicationName; | |||
//关联 关联的IRS应用code | |||
private String applicationCode; | |||
//关联的IRS应用name | |||
private String relatedExistsApplication; | |||
//1: '办公类系统',2: '业务应用类系统',3: '门户网站',4: '宣传微博/微信公众号',5: '硬件类系统',6: '工具类系统',99: '其他' | |||
private Integer applicationType; | |||
//建设层级 1:国家 2:省级 3:市级 4:县(市、区) | |||
private Integer buildLevel; | |||
//是否统建 0:否 1:是 | |||
private Integer isUniteBuild; | |||
//统建类型 1:全省统建 2:全市统建 | |||
private Integer unionBuildKind; | |||
//应用简介 | |||
private String applicationSummary; | |||
//应用备注 | |||
private String applicationRemark; | |||
//应用总投资测算明细 | |||
private String applicationEstimateFile; | |||
//是否数改系统 0:否 1:是 | |||
private Integer isFiveDomain; | |||
//1: '党政机关整体智治',2: '数字政府',3: '数字经济',4: '数字社会',7: '数字文化',5: '数字法治',6: '一体化智能化公共数据平台', 8: '基层智治' 多个用英文,分隔 | |||
private String fiveDomain; | |||
//业务领域 | |||
private String bizDomain; | |||
//否涉及业务协同 0:否 1:是 | |||
private Integer isBizCooperate; | |||
//协同单位111111 | |||
private String cooperativeUnit; | |||
//用户范围 0: '机关事业单位人员','0-1': '跨部门跨系统','0-2': '系统内地方各级','0-3': '本部门本级','0-4': '处室内部','0-6': '主管处室内部','0-5': '其他',1: '企业', 2: '社会公众',3: '其他' 多个用英文,分隔 | |||
private String userRange; | |||
//是否使用政务云资源 1使用 | |||
private Integer useGovCloud; | |||
//是否符合国家信息技术应用创新相关规范 0:否 1:是 | |||
private Integer nationalITSpec; | |||
//网络环境 1:政务内网 2:政务外网 3:互联网 4:业务专网 5:单机 | |||
private String netEnv; | |||
//等保级别 1:一级 2:二级 3:三级 4:四级 5:五级 | |||
private Integer secrecyGrade; | |||
//密码测评级别 1:一级 2:二级 3:三级 4:四级 5:五级 | |||
private Integer passwordGrade; | |||
//是否是S2 0:否 1:是 | |||
private Integer isS2; | |||
//一本账应用名称 | |||
private String accountAppName; | |||
//领域”大脑”一本帐名称 | |||
private String brainAccountAppName; | |||
//是否使用公共数据 | |||
private Integer useCommonData; | |||
//使用的公共数据名称 | |||
private String dataName; | |||
//使用公共组件的名称 | |||
private String commonComponents; | |||
//是否使用公共组件 | |||
private Integer useCommonComponent; | |||
//是否产生公共组件 | |||
private Integer isProduceCommonComponent; | |||
//产生的组件名称 | |||
private String produceCommonComponent; | |||
//发布端 '浙里办','浙政钉','数字化改革门户','支付宝','微信','网页','PC客户端','APP端' | |||
private String publishSide; | |||
public static class Cloud { | |||
//云资源台数 11 | |||
private Integer cloudNums; | |||
//云资源类型 云服务器(ECS) | |||
private String cloudType; | |||
//云资源规格 1核8G | |||
private String cloudBasicSpec; | |||
//云资源描述 | |||
private String cloudUseDescription; | |||
} | |||
} |
@@ -0,0 +1,125 @@ | |||
package com.ningdatech.pmapi.provincial.model.dto; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.math.BigDecimal; | |||
import java.util.List; | |||
/** | |||
* @Classname ProvincialProjectDTO | |||
* @Description | |||
* @Date 2023/3/2 10:06 | |||
* @Author PoffyZhang | |||
*/ | |||
@Data | |||
@Builder | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@ApiModel(value = "ProvincialProjectDTO", description = "") | |||
public class ProvincialProjectDTO { | |||
@ApiModelProperty("区域code") | |||
private String regionCode; | |||
@ApiModelProperty("区域名称") | |||
private String regionName; | |||
@ApiModelProperty("重大项目名称") | |||
private String projectName; | |||
@ApiModelProperty("重大项目code 21位") | |||
private String projectId; | |||
@ApiModelProperty("项目类型 1新建 2续建") | |||
private Integer projectType; | |||
@ApiModelProperty("项目总投资(万元)") | |||
private BigDecimal totalMoney; | |||
@ApiModelProperty("项目年度预算(万元)") | |||
private BigDecimal yearBudget; | |||
@ApiModelProperty("自有资金,政府投资-本级财政资金,政府投资-上级补助资金") | |||
private String budgetFrom; | |||
@ApiModelProperty("预算年度 2023") | |||
private String year; | |||
@ApiModelProperty("财政code 32") | |||
private String financialCode; | |||
@ApiModelProperty("发改code 23") | |||
private String developCode; | |||
@ApiModelProperty("开始时间 比如2022-11-18") | |||
private String beginTime; | |||
@ApiModelProperty("结束时间 比如2022-12-13") | |||
private String endTime; | |||
@ApiModelProperty("立项依据1111") | |||
private String buildBasis; | |||
@ApiModelProperty("立项依据材料 [{\"fileId\":\"\"}]") | |||
private String buildBasisFile; | |||
@ApiModelProperty("项目概述") | |||
private String projectSummary; | |||
@ApiModelProperty("负责人") | |||
private String responsibleMan; | |||
@ApiModelProperty("联系人联系方式") | |||
private String responsibleManPhone; | |||
@ApiModelProperty("联系人") | |||
private String contactName; | |||
@ApiModelProperty("联系人联系方式") | |||
private String contactPhone; | |||
@ApiModelProperty("建设单位 比如财政局") | |||
private String buildUnit; | |||
@ApiModelProperty("建设单位浙政钉code") | |||
private String buildUnitCode; | |||
@ApiModelProperty("主管单位") | |||
private String superUnit; | |||
@ApiModelProperty("主管单位浙政钉code") | |||
private String superUnitCode; | |||
@ApiModelProperty("可研报告文件") | |||
private String researchReport; | |||
@ApiModelProperty("项目申报书") | |||
private String projectApplyFile; | |||
@ApiModelProperty("项目总投资测算明细") | |||
private String projectEstimateFile; | |||
@ApiModelProperty("申报单位主要职责") | |||
private String unitThreePlan; | |||
@ApiModelProperty("其他附件") | |||
private String otherFile; | |||
@ApiModelProperty("项目备注111") | |||
private String projectRemark; | |||
@ApiModelProperty("是否有效 1有效 2无效 3撤回") | |||
private String isEffective; | |||
@ApiModelProperty("是否包含应用 1包含") | |||
private String includeApplication; | |||
@ApiModelProperty("app信息") | |||
private List<ProvincialApplicationDTO> applicationInfo; | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.ningdatech.pmapi.provincial.service; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
/** | |||
* @Classname JointReviewProvincialBureauService | |||
* @Description 省局联审接口 | |||
* @Date 2023/3/2 9:29 | |||
* @Author PoffyZhang | |||
*/ | |||
public interface IJoinReviewProvincialBureauService { | |||
/** | |||
* 推送/保存 重大接口到 省局联审 | |||
* @return | |||
*/ | |||
String pushImportProject(ProvincialProjectDTO project); | |||
/** | |||
* 查看 本区域 省局联审 的项目审核详情 | |||
* @return | |||
*/ | |||
String processInfo(String projectId); | |||
} |
@@ -0,0 +1,114 @@ | |||
package com.ningdatech.pmapi.provincial.service.impl; | |||
import cn.hutool.core.util.StrUtil; | |||
import cn.hutool.crypto.SecureUtil; | |||
import com.ningdatech.pmapi.common.config.ProvincialProperties; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.http.HttpMethod; | |||
import org.springframework.http.MediaType; | |||
import org.springframework.http.RequestEntity; | |||
import org.springframework.http.ResponseEntity; | |||
import org.springframework.stereotype.Service; | |||
import org.springframework.web.client.RestTemplate; | |||
/** | |||
* @Classname JointReviewProvincialBureauService | |||
* @Description 省局联审接口 | |||
* @Date 2023/3/2 9:29 | |||
* @Author PoffyZhang | |||
*/ | |||
@Service | |||
@Slf4j | |||
public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvincialBureauService { | |||
@Autowired | |||
private ProvincialProperties provincialProperties; | |||
@Autowired | |||
private RestTemplate restTemplate; | |||
/** | |||
* 推送/保存 重大接口到 省局联审 | |||
* @return | |||
*/ | |||
@Override | |||
public String pushImportProject(ProvincialProjectDTO project){ | |||
Long timeStamp = System.currentTimeMillis()/1000; | |||
String url = provincialProperties.getHost() + provincialProperties.getPushUrl() | |||
+ "?timestamp=" + timeStamp; | |||
log.info("省局推送联审url {}",url); | |||
ResponseEntity<String> responseEntity = null; | |||
String signature = getSha256(timeStamp,provincialProperties.getPushUrl(), | |||
HttpMethod.POST.name()); | |||
//发送post请求 | |||
RequestEntity<ProvincialProjectDTO> requestEntity = RequestEntity | |||
.post(url) | |||
.header("Accept", MediaType.APPLICATION_JSON.toString()) | |||
.header("X-Hmac-Auth-Key",provincialProperties.getKey()) | |||
.header("X-Hmac-Auth-Signature",signature) | |||
.contentType(MediaType.APPLICATION_JSON) | |||
.accept(MediaType.APPLICATION_JSON) | |||
.body(project); | |||
try { | |||
responseEntity = restTemplate.exchange(requestEntity,String.class); | |||
log.info("省局联审 响应 :{}",responseEntity); | |||
} catch (Exception e) { | |||
log.error("[省局联审] http request error", e); | |||
} | |||
return responseEntity.getBody(); | |||
} | |||
/** | |||
* 获取流程审批详情 | |||
* @param projectId | |||
* @return | |||
*/ | |||
@Override | |||
public String processInfo(String projectId) { | |||
Long timeStamp = System.currentTimeMillis()/1000; | |||
String url = provincialProperties.getHost() + provincialProperties.getDetailUrl() | |||
+ "?timestamp=" + timeStamp; | |||
log.info("省局获取审核详情 url {}",url); | |||
ResponseEntity<String> responseEntity = null; | |||
String signature = getSha256(timeStamp,provincialProperties.getDetailUrl(), | |||
HttpMethod.POST.name()); | |||
//发送post请求 | |||
RequestEntity<String> requestEntity = RequestEntity | |||
.post(url) | |||
.header("Accept", MediaType.APPLICATION_JSON.toString()) | |||
.header("X-Hmac-Auth-Key",provincialProperties.getKey()) | |||
.header("X-Hmac-Auth-Signature",signature) | |||
.contentType(MediaType.APPLICATION_JSON) | |||
.accept(MediaType.APPLICATION_JSON) | |||
.body(projectId); //也可以是DTO | |||
try { | |||
responseEntity = restTemplate.exchange(requestEntity,String.class); | |||
log.info("获取审批详情 响应 :{}",responseEntity); | |||
} catch (Exception e) { | |||
log.error("[省局获取审核详情] http request error", e); | |||
} | |||
return responseEntity.getBody(); | |||
} | |||
private String getSha256(Long timeStamp,String url,String method){ | |||
String secret = provincialProperties.getSecret(); | |||
String key = provincialProperties.getKey(); | |||
String bytesToSign = method + StrUtil.LF + url + StrUtil.LF + timeStamp + StrUtil.LF + key; | |||
log.info("加密message :{}",bytesToSign); | |||
String res = SecureUtil.hmacSha256(secret).digestBase64(bytesToSign,false); | |||
log.info("加密结果 :{}",res); | |||
return res; | |||
} | |||
} |
@@ -14,6 +14,7 @@ import com.ningdatech.pmapi.sys.service.IRegionService; | |||
import com.wflow.bean.dto.WflowModelHistorysDto; | |||
import com.wflow.bean.entity.WflowForms; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.process.ProcessNode; | |||
import com.wflow.workflow.service.ProcessModelService; | |||
import com.wflow.workflow.service.WflowFormsService; | |||
@@ -122,7 +123,7 @@ public class InitProcessTask { | |||
if(StringUtils.isNotBlank(processModelService.saveProcess(models))){ | |||
//初始的流程在部署表也存一份,用来查询 | |||
if(StringUtils.isNotBlank(processModelService.deployProcess(models.getFormId()))){ | |||
if(StringUtils.isNotBlank(processModelService.deployProcess(models.getFormId(),null))){ | |||
log.info("当前区域 【{}】 流程名[{}] 流程数据已经保存成功",region.getName(),formName); | |||
}else{ | |||
log.info("当前区域 【{}】 流程名[{}] 流程数据保存失败",region.getName(),formName); | |||
@@ -46,7 +46,7 @@ public class WorkNoticeFlowTask { | |||
private final INdWorkNoticeStagingService workNoticeStagingService; | |||
private final ZwddClient zwddClient; | |||
@Scheduled(cron = "0 */1 * * * ?") | |||
// @Scheduled(cron = "0 */1 * * * ?") | |||
public void statusFlow() throws UnknownHostException { | |||
//测试暂时用自己电脑HOST | |||
if (TaskContant.Host.HOST_CMM.equals(InetAddress.getLocalHost().getHostName())) { | |||
@@ -7,6 +7,7 @@ import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.staging.model.entity.ProjectStaging; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Component; | |||
import javax.annotation.PostConstruct; | |||
@@ -20,11 +21,12 @@ import java.util.function.Function; | |||
* @Author PoffyZhang | |||
*/ | |||
@Component | |||
@RequiredArgsConstructor | |||
public class ProjectStatusFlowMapUtil { | |||
private final ReviewByProvincialDeptManage provincialDeptManage; | |||
@Autowired | |||
private ReviewByProvincialDeptManage provincialDeptManage; | |||
private final ReviewByDeptJointManage reviewByDeptJointManage; | |||
@Autowired | |||
private ReviewByDeptJointManage reviewByDeptJointManage; | |||
public Map<Integer, Function<Project,Boolean>> statusFlowFunctionMap = Maps.newHashMap(); | |||
/** | |||
@@ -37,8 +39,7 @@ public class ProjectStatusFlowMapUtil { | |||
* key: 枚举 状态值 | |||
* value: lambda表达式,最终会获取发起实例的函数 | |||
*/ | |||
@PostConstruct | |||
public void statusFlowFunctionInit(){ | |||
public ProjectStatusFlowMapUtil(){ | |||
//省级部门联审 | |||
statusFlowFunctionMap.put(ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS.getCode(), | |||
project->provincialDeptManage.startTheProcess(project)); | |||
@@ -47,6 +48,7 @@ public class ProjectStatusFlowMapUtil { | |||
project->reviewByDeptJointManage.startTheProcess(project)); | |||
} | |||
/** | |||
* 扫描的间隔越来越长 秒数 | |||
*/ | |||
@@ -1,6 +1,8 @@ | |||
package com.ningdatech.pmapi.sys.controller; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.pmapi.projectdeclared.manage.DefaultDeclaredProjectManage; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import com.wflow.bean.dto.WflowModelHistorysDto; | |||
import com.wflow.bean.vo.WflowModelVo; | |||
import com.wflow.service.ModelGroupService; | |||
@@ -30,6 +32,8 @@ public class SysProcDefController { | |||
private final ProcessModelService processModelService; | |||
private final DefaultDeclaredProjectManage defaultDeclaredProjectManage; | |||
@ApiOperation(value = "系统流程配置列表", notes = "系统流程配置列表") | |||
@GetMapping("/list") | |||
public PageVo<WflowModelVo> list(@RequestParam String regionCode, @RequestParam(defaultValue = "1") Integer pageNumber, | |||
@@ -60,6 +64,6 @@ public class SysProcDefController { | |||
@ApiOperation(value = "系统流程配置发布", notes = "系统流程配置发布") | |||
@PostMapping("/deploy/{formId}") | |||
public String deploy(@Validated @PathVariable String formId) { | |||
return processModelService.deployProcess(formId); | |||
return processModelService.deployProcess(formId,null); | |||
} | |||
} |
@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.google.common.collect.Sets; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.common.constant.CommonConst; | |||
@@ -201,11 +202,13 @@ public class TodoCenterManage { | |||
// 获取入参 | |||
String processInstanceId = param.getInstanceId(); | |||
Long projectId = param.getProjectId(); | |||
VUtils.isTrue(Objects.isNull(processInstanceId)).throwMessage("获取流程实例ID失败!"); | |||
VUtils.isTrue(Objects.isNull(projectId)).throwMessage("获取项目ID失败!"); | |||
// 获取当前申报项目 | |||
Project declaredProject = projectService.getOne(Wrappers.lambdaQuery(Project.class) | |||
.eq(Project::getInstCode, processInstanceId) | |||
.eq(Project::getId,projectId)); | |||
VUtils.isTrue(Objects.isNull(projectId)).throwMessage("获取项目ID失败!"); | |||
// 获取当前项目名称 | |||
String projectName = declaredProject.getProjectName(); | |||
// 获取当前项目状态 | |||
@@ -253,11 +256,6 @@ public class TodoCenterManage { | |||
// 如果流程状态是被退回状态,流程通过后,进入下一个审核人, | |||
// 当前通过审核人一定不是最后一个审核人(下一个审核人至多是最后一个),更新流程状态为审核中 | |||
if (ProcessStatusEnum.BE_BACKED.getDesc().equals(currentProcessStatus)) { | |||
// 更新流程状态为审核中 | |||
declaredProject.setProcessStatus(ProcessStatusEnum.UNDER_REVIEW.getCode()); | |||
declaredProject.setUpdateOn(LocalDateTime.now()); | |||
declaredProject.setUpdateBy(userId); | |||
projectService.updateById(declaredProject); | |||
// 获取发送浙政钉工作通知必要信息 | |||
WorkNoticeInfo passWorkNoticeInfo = getSendWorkNoticeInfo(auditUserInfo); | |||
String passMsg = String.format(PASS_MSG_TEMPLATE, passWorkNoticeInfo.getOrganizationName(), projectName); | |||
@@ -296,6 +294,9 @@ public class TodoCenterManage { | |||
// 若有下一个审核人(当前节点的用户), | |||
// 向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。 | |||
// 获取发送浙政钉工作通知必要信息 | |||
if (Objects.isNull(auditUserInfo)){ | |||
throw new BizException("审核人信息不存在!"); | |||
} | |||
WorkNoticeInfo sendWorkNoticeInfo = getSendWorkNoticeInfo(auditUserInfo); | |||
String msg = String.format(PASS_MSG_TEMPLATE, sendWorkNoticeInfo.getOrganizationName(), projectName); | |||
sendWorkNoticeInfo.setMsg(msg); | |||
@@ -327,11 +328,6 @@ public class TodoCenterManage { | |||
case BACK: | |||
// 退回该任务 | |||
processTaskService.handleTask(param, userId); | |||
// 更新申报项目表中的流程状态为被退回 | |||
declaredProject.setProcessStatus(ProcessStatusEnum.BE_BACKED.getCode()); | |||
declaredProject.setUpdateOn(LocalDateTime.now()); | |||
declaredProject.setUpdateBy(userId); | |||
projectService.updateById(declaredProject); | |||
// 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。 | |||
// 获取发送浙政钉工作通知必要信息 | |||
WorkNoticeInfo backWorkNoticeInfo = getSendWorkNoticeInfo(startUserInfo); | |||
@@ -410,10 +406,6 @@ public class TodoCenterManage { | |||
} catch (Exception e) { | |||
throw new BizException("状态机执行失败!"); | |||
} | |||
// 更新流程状态、项目状态到下一个状态 | |||
declaredProject.setProcessStatus(ProcessStatusEnum.BE_REJECTED.getCode()); | |||
declaredProject.setUpdateOn(LocalDateTime.now()); | |||
declaredProject.setUpdateBy(userId); | |||
projectService.updateById(declaredProject); | |||
} | |||
@@ -471,10 +463,6 @@ public class TodoCenterManage { | |||
} catch (Exception e) { | |||
throw new BizException("状态机执行失败!"); | |||
} | |||
// 更新流程状态、项目状态到下一个状态 | |||
declaredProject.setProcessStatus(ProcessStatusEnum.APPROVED.getCode()); | |||
declaredProject.setUpdateOn(LocalDateTime.now()); | |||
declaredProject.setUpdateBy(userId); | |||
projectService.updateById(declaredProject); | |||
} | |||
@@ -565,11 +553,6 @@ public class TodoCenterManage { | |||
} catch (Exception e) { | |||
throw new BizException("状态机执行失败!"); | |||
} | |||
// 更新项目状态 | |||
declaredProject.setProcessStatus(ProcessStatusEnum.APPROVED.getCode()); | |||
declaredProject.setUpdateOn(LocalDateTime.now()); | |||
declaredProject.setUpdateBy(userId); | |||
projectService.updateById(declaredProject); | |||
} | |||
/** | |||
@@ -724,6 +707,8 @@ public class TodoCenterManage { | |||
Long startUserId = LoginUserUtil.getUserId(); | |||
// 查出登录用户已提交工作流 | |||
List<ProcessInstanceVo> userSubmittedList = processInstanceService.getUserSubmittedList(String.valueOf(startUserId), param.getProcessDefId(), null); | |||
Map<String, ProcessInstanceVo> instanceVoMap = userSubmittedList.stream() | |||
.collect(Collectors.toMap(ProcessInstanceVo::getInstanceId, v -> v)); | |||
if(CollUtil.isEmpty(userSubmittedList)){ | |||
return PageVo.empty(); | |||
} | |||
@@ -743,7 +728,8 @@ public class TodoCenterManage { | |||
ResToBeProcessedVO res = new ResToBeProcessedVO(); | |||
BeanUtils.copyProperties(d, res); | |||
res.setProjectId(d.getId()); | |||
res.setProcessStatusName(ProcessStatusEnum.getDescByCode(d.getProcessStatus())); | |||
ProcessInstanceVo instanceVo = instanceVoMap.get(d.getInstCode()); | |||
res.setProcessStatusName(instanceVo.getStatus()); | |||
res.setProcessLaunchTime(d.getCreateOn()); | |||
return res; | |||
}).collect(Collectors.toList()); | |||
@@ -840,7 +826,7 @@ public class TodoCenterManage { | |||
ProcessInstanceVo instanceVo = instanceVoMap.get(d.getInstCode()); | |||
res.setNodeId(instanceVo.getNodeId()); | |||
res.setProjectId(d.getId()); | |||
res.setProcessStatusName(ProcessStatusEnum.getDescByCode(d.getProcessStatus())); | |||
res.setProcessStatusName(instanceVo.getStatus()); | |||
res.setProcessLaunchTime(d.getCreateOn()); | |||
return res; | |||
}).collect(Collectors.toList()); | |||
@@ -184,4 +184,12 @@ yxt: | |||
password: hzndkj@2021 | |||
#音信通开关 | |||
sms-enable: true | |||
tel-enable: true | |||
tel-enable: true | |||
#省局联审 请求信息 | |||
provincial: | |||
host: http://zj.ningdatech.com/prometheus-zhejiang_foreign | |||
pushUrl: /api/v1/foreign/importantPro | |||
detailUrl: /api/v1/foreign/importantProView | |||
key: 7196317343a64e67895dc0375c098fe7 | |||
secret: 75152a97f20e4c4c854dc6301cf72ad4 |
@@ -0,0 +1,37 @@ | |||
package com.ningdatech.pmapi.provincial; | |||
import cn.hutool.crypto.SecureUtil; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.codec.binary.Base64; | |||
import javax.crypto.Mac; | |||
import javax.crypto.spec.SecretKeySpec; | |||
import java.io.UnsupportedEncodingException; | |||
import java.security.InvalidKeyException; | |||
import java.security.NoSuchAlgorithmException; | |||
/** | |||
* @Classname Test | |||
* @Description | |||
* @Date 2023/3/2 16:14 | |||
* @Author PoffyZhang | |||
*/ | |||
@Slf4j | |||
public class Test { | |||
@org.junit.Test | |||
public void test() throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { | |||
// Long timeStamp = System.currentTimeMillis()/1000; | |||
Long timeStamp = 1677750055L; | |||
String key = "7196317343a64e67895dc0375c098fe7"; | |||
String url = "/api/v1/foreign/importantProView"; | |||
String methed = "POST"; | |||
String bytesToSign = methed + "\n" + url + "\n" + timeStamp + "\n" + key; | |||
log.info("" + bytesToSign); | |||
String secret = "75152a97f20e4c4c854dc6301cf72ad4"; | |||
String str = SecureUtil.hmacSha256(secret).digestBase64(bytesToSign,false); | |||
log.info("" + str); | |||
} | |||
} |