Browse Source

Merge remote-tracking branch 'origin/master'

tags/24080901
liuxinxin 1 year ago
parent
commit
6981a5cb14
48 changed files with 1302 additions and 524 deletions
  1. +109
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/config/BeanConfig.java
  2. +27
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/config/ProvincialProperties.java
  3. +42
    -30
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java
  4. +0
    -20
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingInnerProjectController.java
  5. +0
    -20
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingOuterProjectController.java
  6. +22
    -16
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/domain/Meeting.java
  7. +5
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/domain/MeetingExpert.java
  8. +9
    -11
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/ExpertAttendStatusEnum.java
  9. +35
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingAttendStatusEnum.java
  10. +9
    -9
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingDateTermTypeEnum.java
  11. +0
    -73
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingStatus.java
  12. +40
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingStatusEnum.java
  13. +29
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/ExpertConfirmReq.java
  14. +0
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingCancelReq.java
  15. +20
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingExpertIdReq.java
  16. +7
    -65
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/vo/ExpertInviteDetailVO.java
  17. +41
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/vo/InviteExpertListItemVO.java
  18. +50
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/vo/InviteStatisticsByRuleVO.java
  19. +4
    -10
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/ExpertInviteHelper.java
  20. +7
    -15
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingManageHelper.java
  21. +15
    -16
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/DashboardManage.java
  22. +10
    -10
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java
  23. +166
    -136
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java
  24. +3
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.java
  25. +19
    -7
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/IMeetingExpertService.java
  26. +10
    -10
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/impl/MeetingExpertServiceImpl.java
  27. +8
    -8
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java
  28. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/organization/controller/ProcDefController.java
  29. +1
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/controller/DeclaredProjectController.java
  30. +5
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ConstructionPlanManage.java
  31. +16
    -10
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DeclaredProjectManage.java
  32. +62
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DefaultDeclaredProjectManage.java
  33. +7
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PrequalificationDeclaredProjectManage.java
  34. +6
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ReviewByDeptJointManage.java
  35. +8
    -9
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/utils/ReStartProcessMapUtil.java
  36. +38
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/provincial/controller/TestController.java
  37. +36
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/dto/ProcessCommentDTO.java
  38. +98
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/dto/ProvincialApplicationDTO.java
  39. +125
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/dto/ProvincialProjectDTO.java
  40. +25
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/provincial/service/IJoinReviewProvincialBureauService.java
  41. +114
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/provincial/service/impl/JoinReviewProvincialBureauServiceImpl.java
  42. +2
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/scheduler/task/InitProcessTask.java
  43. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/scheduler/task/WorkNoticeFlowTask.java
  44. +7
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/staging/utils/ProjectStatusFlowMapUtil.java
  45. +5
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/SysProcDefController.java
  46. +12
    -26
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java
  47. +9
    -1
      pmapi/src/main/resources/application-dev.yml
  48. +37
    -0
      pmapi/src/test/java/com/ningdatech/pmapi/provincial/Test.java

+ 109
- 0
pmapi/src/main/java/com/ningdatech/pmapi/common/config/BeanConfig.java View File

@@ -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();
}
}

+ 27
- 0
pmapi/src/main/java/com/ningdatech/pmapi/common/config/ProvincialProperties.java View File

@@ -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;
}

+ 42
- 30
pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java View File

@@ -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());
}


}

+ 0
- 20
pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingInnerProjectController.java View File

@@ -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 {

}

+ 0
- 20
pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingOuterProjectController.java View File

@@ -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 {

}

+ 22
- 16
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/domain/Meeting.java View File

@@ -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;

}

+ 5
- 1
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/domain/MeetingExpert.java View File

@@ -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;

}

pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/ExpertAttendStatus.java → pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/ExpertAttendStatusEnum.java View File

@@ -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()

+ 35
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingAttendStatusEnum.java View File

@@ -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("专家参会状态编码无效"));
}

}

pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingDateTermType.java → pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingDateTermTypeEnum.java View File

@@ -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()

+ 0
- 73
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingStatus.java View File

@@ -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("状态编码"));
}

}

}

+ 40
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/enumeration/MeetingStatusEnum.java View File

@@ -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("会议状态编码无效"));
}

}

+ 29
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/ExpertConfirmReq.java View File

@@ -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;

}

+ 0
- 5
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingCancelReq.java View File

@@ -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;

}

+ 20
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingExpertIdReq.java View File

@@ -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;

}

+ 7
- 65
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/vo/ExpertInviteDetailVO.java View File

@@ -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;

}

+ 41
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/vo/InviteExpertListItemVO.java View File

@@ -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;

}

+ 50
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/vo/InviteStatisticsByRuleVO.java View File

@@ -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++;
}

}

+ 4
- 10
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/ExpertInviteHelper.java View File

@@ -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) {


+ 7
- 15
pmapi/src/main/java/com/ningdatech/pmapi/meeting/helper/MeetingManageHelper.java View File

@@ -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;


+ 15
- 16
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/DashboardManage.java View File

@@ -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();


+ 10
- 10
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java View File

@@ -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);
});
}


+ 166
- 136
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java View File

@@ -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);
}
}



+ 3
- 3
pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.java View File

@@ -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


+ 19
- 7
pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/IMeetingExpertService.java View File

@@ -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));
}

/**
* 查询会议的所有被抽取人最后一条记录


+ 10
- 10
pmapi/src/main/java/com/ningdatech/pmapi/meeting/service/impl/MeetingExpertServiceImpl.java View File

@@ -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);
}


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

@@ -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();
}
}


+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/organization/controller/ProcDefController.java View File

@@ -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
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/controller/DeclaredProjectController.java View File

@@ -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;


+ 5
- 1
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ConstructionPlanManage.java View File

@@ -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);

//保存建设项目


+ 16
- 10
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DeclaredProjectManage.java View File

@@ -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);

//保存项目


+ 62
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DefaultDeclaredProjectManage.java View File

@@ -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;
}
}

+ 7
- 1
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PrequalificationDeclaredProjectManage.java View File

@@ -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);

//保存预审项目


+ 6
- 2
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ReviewByDeptJointManage.java View File

@@ -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);

//保存项目信息


+ 8
- 9
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/utils/ReStartProcessMapUtil.java View File

@@ -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));


+ 38
- 0
pmapi/src/main/java/com/ningdatech/pmapi/provincial/controller/TestController.java View File

@@ -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);
}
}

+ 36
- 0
pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/dto/ProcessCommentDTO.java View File

@@ -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;
}

+ 98
- 0
pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/dto/ProvincialApplicationDTO.java View File

@@ -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;
}
}

+ 125
- 0
pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/dto/ProvincialProjectDTO.java View File

@@ -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;

}

+ 25
- 0
pmapi/src/main/java/com/ningdatech/pmapi/provincial/service/IJoinReviewProvincialBureauService.java View File

@@ -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);
}

+ 114
- 0
pmapi/src/main/java/com/ningdatech/pmapi/provincial/service/impl/JoinReviewProvincialBureauServiceImpl.java View File

@@ -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;
}
}

+ 2
- 1
pmapi/src/main/java/com/ningdatech/pmapi/scheduler/task/InitProcessTask.java View File

@@ -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);


+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/scheduler/task/WorkNoticeFlowTask.java View File

@@ -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
- 5
pmapi/src/main/java/com/ningdatech/pmapi/staging/utils/ProjectStatusFlowMapUtil.java View File

@@ -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));
}


/**
* 扫描的间隔越来越长 秒数
*/


+ 5
- 1
pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/SysProcDefController.java View File

@@ -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);
}
}

+ 12
- 26
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java View File

@@ -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());


+ 9
- 1
pmapi/src/main/resources/application-dev.yml View File

@@ -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

+ 37
- 0
pmapi/src/test/java/com/ningdatech/pmapi/provincial/Test.java View File

@@ -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);
}
}

Loading…
Cancel
Save