소스 검색

feat:

1. 增加会议添加项目、移除项目接口;
tags/24121201
WendyYang 1 개월 전
부모
커밋
dae6bdf29b
8개의 변경된 파일155개의 추가작업 그리고 16개의 파일을 삭제
  1. +6
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/action/ProjectStateChangeAction.java
  2. +5
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/builder/impl/ProjectStateMachineBuilderImpl.java
  3. +5
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/event/ProjectStateChangeEvent.java
  4. +6
    -2
      hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/util/AbstractStateMachineUtil.java
  5. +14
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/meeting/controller/MeetingController.java
  6. +29
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/req/MeetingAppendProjectReq.java
  7. +4
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/req/MeetingOptionProjectReq.java
  8. +86
    -14
      hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java

+ 6
- 0
hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/action/ProjectStateChangeAction.java 파일 보기

@@ -73,6 +73,12 @@ public class ProjectStateChangeAction {
project.setStatus(ProjectStatus.WITHOUT_EXPERT_REVIEW.getCode());
}

@OnTransition(source = "ON_EXPERT_REVIEW", target = "WITHOUT_EXPERT_REVIEW")
public void EXPERT_REVIEW_WITHDRAW(Message<ProjectStateChangeEvent> message) {
Project project = getProject(message);
project.setStatus(ProjectStatus.WITHOUT_EXPERT_REVIEW.getCode());
}

@OnTransition(source = "ON_EXPERT_REVIEW", target = "EXPERT_REVIEW_FAILED")
public void EXPERT_REVIEW_FAILED(Message<ProjectStateChangeEvent> message) {
Project project = getProject(message);


+ 5
- 0
hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/builder/impl/ProjectStateMachineBuilderImpl.java 파일 보기

@@ -104,6 +104,11 @@ public class ProjectStateMachineBuilderImpl implements BaseStateMachineBuilder<P
.source(ProjectStatus.WITHOUT_EXPERT_REVIEW)
.target(ProjectStatus.ON_EXPERT_REVIEW)
.event(ProjectStateChangeEvent.EXPERT_REVIEW_SUBMIT).and()
// 专家评审撤回
.withExternal()
.source(ProjectStatus.ON_EXPERT_REVIEW)
.target(ProjectStatus.WITHOUT_EXPERT_REVIEW)
.event(ProjectStateChangeEvent.EXPERT_REVIEW_WITHDRAW).and()
// 重新提交专家评审
.withExternal()
.source(ProjectStatus.EXPERT_REVIEW_AFTER_MODIFY)


+ 5
- 0
hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/event/ProjectStateChangeEvent.java 파일 보기

@@ -54,6 +54,11 @@ public enum ProjectStateChangeEvent implements AbstractStateChangeEvent {
EXPERT_REVIEW_FAILED(null, ProjectStatus.ON_EXPERT_REVIEW.getCode(), null),

/**
* @see ProjectStateChangeAction#EXPERT_REVIEW_WITHDRAW(Message)
*/
EXPERT_REVIEW_WITHDRAW(null, null, ProjectStatus.ON_EXPERT_REVIEW.getCode()),

/**
* @see ProjectStateChangeAction#EXPERT_REVIEW_PASS(Message)
*/
EXPERT_REVIEW_PASS(ProjectStatus.ON_EXPERT_REVIEW.getCode(), null, null),


+ 6
- 2
hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/util/AbstractStateMachineUtil.java 파일 보기

@@ -67,11 +67,15 @@ public interface AbstractStateMachineUtil<O, E extends Enum<E> & AbstractStateCh
}
}

//撤回
default void withDraw(O obj) {
withDraw(obj, null);
}

//撤回
default <T> void withDraw(O obj, T extraArgs) {
try {
synchronized (getLockClass()) {
execute(obj, AbstractStateChangeEvent.getWithdrawEvent(eventClass(), statusFunction().apply(obj)));
execute(obj, AbstractStateChangeEvent.getWithdrawEvent(eventClass(), statusFunction().apply(obj)), extraArgs);
}
} catch (Exception e) {
LOG.error("状态机撤回失败", e);


+ 14
- 0
hz-pm-api/src/main/java/com/hz/pm/api/meeting/controller/MeetingController.java 파일 보기

@@ -192,6 +192,20 @@ public class MeetingController {
return meetingManage.optionProject(req);
}

@PostMapping("/project/append")
@WebLog("添加项目")
@ApiOperation("添加项目")
public void appendProject(@RequestBody @Valid MeetingAppendProjectReq req) {
meetingManage.appendProject(req);
}

@PostMapping("/project/remove")
@WebLog("移除项目")
@ApiOperation("移除项目")
public void removeProject(@RequestBody @Valid MeetingAppendProjectReq req) {
meetingManage.removeProject(req);
}

@GetMapping("/{meetingId}/projects")
@ApiOperation("会议关联项目列表")
public List<MeetingReviewProjectVO> projectsByMeetingId(@PathVariable Long meetingId) {


+ 29
- 0
hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/req/MeetingAppendProjectReq.java 파일 보기

@@ -0,0 +1,29 @@
package com.hz.pm.api.meeting.entity.req;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

/**
* <p>
* MeetingAppendProjectReq
* </p>
*
* @author WendyYang
* @since 17:36 2024/12/5
*/
@Data
public class MeetingAppendProjectReq {

@NotNull(message = "会议ID不能为空")
@ApiModelProperty("会议ID")
private Long meetingId;

@NotEmpty(message = "项目编码列表不能为空")
@ApiModelProperty("项目编码列表")
private List<String> projectCodes;

}

+ 4
- 0
hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/req/MeetingOptionProjectReq.java 파일 보기

@@ -1,6 +1,7 @@
package com.hz.pm.api.meeting.entity.req;

import com.ningdatech.basic.model.PagePo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

@@ -18,4 +19,7 @@ public class MeetingOptionProjectReq extends PagePo {

private String meetingType;

@ApiModelProperty("会议ID")
private Long meetingId;

}

+ 86
- 14
hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java 파일 보기

@@ -31,10 +31,7 @@ import com.hz.pm.api.meeting.builder.MeetingReviewProjectBuilder;
import com.hz.pm.api.meeting.builder.ProjectReviewResultBuilder;
import com.hz.pm.api.meeting.entity.domain.*;
import com.hz.pm.api.meeting.entity.dto.*;
import com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.hz.pm.api.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.hz.pm.api.meeting.entity.enumeration.MeetingReviewTypeEnum;
import com.hz.pm.api.meeting.entity.enumeration.MeetingStatusEnum;
import com.hz.pm.api.meeting.entity.enumeration.*;
import com.hz.pm.api.meeting.entity.req.*;
import com.hz.pm.api.meeting.entity.vo.*;
import com.hz.pm.api.meeting.helper.ExpertInviteHelper;
@@ -164,21 +161,19 @@ public class MeetingManage {
meetingService.save(meeting);
if (Boolean.TRUE.equals(meetingBasic.getIsInnerProject())) {
List<Long> projectIds = new ArrayList<>();
List<MeetingInnerProject> meetingInnerProjects = meetingBasic.getInnerProjects().stream().map(w -> {
List<MeetingInnerProject> mips = meetingBasic.getInnerProjects().stream().map(w -> {
MeetingInnerProject project = BeanUtil.copyProperties(w, MeetingInnerProject.class);
project.setMeetingId(meeting.getId());
projectIds.add(w.getProjectId());
return project;
}).collect(Collectors.toList());
List<Project> projects = projectService.listByIds(projectIds);
boolean allMatch = projects.stream().allMatch(w -> ProjectStatus.EXPERT_REVIEW_FAILED.eq(w.getStatus())
|| ProjectStatus.WITHOUT_EXPERT_REVIEW.eq(w.getStatus()));
if (!allMatch) {
if (CollUtil.anyMatch(projects, w -> !ProjectStatus.WITHOUT_EXPERT_REVIEW.eq(w.getStatus()))) {
throw ReturnException.wrap("当前关联项目包含暂不可评审项目");
}
projects.forEach(projectStateMachineUtil::pass);
projectService.updateBatchById(projects);
meetingInnerProjectService.saveBatch(meetingInnerProjects);
meetingInnerProjectService.saveBatch(mips);
}
// 抽取专家
inviteRule.setMeetingId(meeting.getId());
@@ -1009,6 +1004,79 @@ public class MeetingManage {
return PageVo.of(page.getRecords(), page.getTotal());
}

@Transactional(rollbackFor = Exception.class)
public synchronized void appendProject(MeetingAppendProjectReq req) {
Meeting meeting = meetingService.getById(req.getMeetingId());
Assert.notNull(meeting, "会议不存在");
Assert.isTrue(MeetingStatusEnum.NORMAL.eq(meeting.getStatus()), "当前会议无法添加项目");
List<String> projectCodes = req.getProjectCodes();
Wrapper<MeetingInnerProject> query = Wrappers.lambdaQuery(MeetingInnerProject.class)
.select(MeetingInnerProject::getMeetingId, MeetingInnerProject::getProjectCode,
MeetingInnerProject::getId, MeetingInnerProject::getReviewResult)
.in(MeetingInnerProject::getProjectCode, projectCodes);
Collection<MeetingInnerProject> linkedProjList = BizUtils.groupFirst(meetingInnerProjectService.list(query),
MeetingInnerProject::getProjectId, Comparator.comparing(MeetingInnerProject::getId).reversed());
// 移除已关联当前会议的项目
projectCodes.removeIf(w -> CollUtil.anyMatch(linkedProjList,
x -> x.getProjectCode().equals(w) && x.getMeetingId().equals(meeting.getId())));
if (projectCodes.isEmpty()) {
return;
}
linkedProjList.removeIf(w -> w.getMeetingId().equals(meeting.getId()));
if (CollUtil.isNotEmpty(linkedProjList)) {
Set<Long> linkedMeetingIds = CollUtils.fieldSet(linkedProjList, MeetingInnerProject::getMeetingId);
if (!linkedMeetingIds.isEmpty()) {
List<Meeting> meetings = meetingService.listByIds(linkedMeetingIds);
Map<Long, Meeting> meetingMap = CollUtils.listToMap(meetings, Meeting::getId);
if (CollUtil.anyMatch(linkedProjList, w -> {
Meeting linkedMeeting = meetingMap.get(w.getMeetingId());
return MeetingStatusEnum.NORMAL.eq(linkedMeeting.getStatus())
&& ExpertReviewResultEnum.PASS.eq(w.getReviewResult());
})) {
throw ReturnException.wrap("所选项目包含已评审通过的项目");
}
}
}
List<Project> projects = projectService.listNewestByProjectCodes(projectCodes);
if (CollUtil.anyMatch(projects, w -> !ProjectStatus.WITHOUT_EXPERT_REVIEW.eq(w.getStatus()))) {
throw ReturnException.wrap("所选项目必须为待专家评审状态");
}
List<MeetingInnerProject> mips = CollUtils.convert(projects, w -> {
projectStateMachineUtil.pass(w);
MeetingInnerProject mip = new MeetingInnerProject();
mip.setProjectId(w.getId());
mip.setMeetingId(req.getMeetingId());
mip.setProjectCode(w.getProjectCode());
return mip;
});
projectService.updateBatchById(projects);
meetingInnerProjectService.saveBatch(mips);
}

@Transactional(rollbackFor = Exception.class)
public synchronized void removeProject(MeetingAppendProjectReq req) {
Meeting meeting = meetingService.getById(req.getMeetingId());
Assert.notNull(meeting, "会议不存在");
Assert.isTrue(MeetingStatusEnum.NORMAL.eq(meeting.getStatus()), "当前会议无法移除项目");
List<String> projectCodes = req.getProjectCodes();
Wrapper<MeetingInnerProject> query = Wrappers.lambdaQuery(MeetingInnerProject.class)
.select(MeetingInnerProject::getId, MeetingInnerProject::getProjectCode, MeetingInnerProject::getReviewResult)
.in(MeetingInnerProject::getProjectCode, projectCodes)
.eq(MeetingInnerProject::getMeetingId, meeting.getId());
List<MeetingInnerProject> linkedProjList = meetingInnerProjectService.list(query);
if (projectCodes.size() != linkedProjList.size()) {
throw ReturnException.wrap("所选项目与当前会议未关联");
}
if (CollUtil.anyMatch(linkedProjList, w -> w.getReviewResult() != null)) {
throw ReturnException.wrap("已上传评审结果的项目不能移除");
}
Set<Long> mipIds = CollUtils.fieldSet(linkedProjList, MeetingInnerProject::getId);
meetingInnerProjectService.removeByIds(mipIds);
List<Project> projects = projectService.listNewestByProjectCodes(projectCodes);
projects.forEach(projectStateMachineUtil::withDraw);
projectService.updateBatchById(projects);
}

public PageVo<MeetingReviewProjectVO> optionProject(MeetingOptionProjectReq req) {
String meetingType = req.getMeetingType();
LambdaQueryWrapper<Project> query = Wrappers.lambdaQuery(Project.class)
@@ -1035,8 +1103,8 @@ public class MeetingManage {
case PRELIMINARY_SCHEME_REVIEW:
case CONSTRUCTION_SCHEME_REVIEW:
case DEPT_JOIN_REVIEW:
buildOptionProjectQuery(query, meetingType, null);
buildOptionProjectQuery(query, meetingType, null);
buildOptionProjectQuery(query, meetingType);
buildOptionProjectQuery(query, meetingType);
break;
case ACCEPTANCE_SCHEME_REVIEW:
buildOptionProjectQuery(query, meetingType, ProjectStatus.ON_FINALLY_INSPECTED);
@@ -1046,11 +1114,15 @@ public class MeetingManage {
case PROJECT_REVIEW:
case EXPERT_REVIEW:
query.isNotNull(Project::getConstructionPlanSealFile);
buildOptionProjectQuery(query, meetingType, ProjectStatus.WITHOUT_EXPERT_REVIEW, ProjectStatus.EXPERT_REVIEW_FAILED);
buildOptionProjectQuery(query, meetingType, ProjectStatus.WITHOUT_EXPERT_REVIEW);
break;
default:
return PageVo.empty();
}
if (req.getMeetingId() != null) {
query.notExists("select 1 from meeting_inner_project mip on mip.project_code = nd_project.project_code" +
" and nd_project.newest = 1 and mip.meeting_id = {0}", req.getMeetingId());
}
ProjectManageUtil.projectBaseQuery(query);
Page<Project> page = projectService.page(req.page(), query);
PageVo<MeetingReviewProjectVO> result = PageVo.of(null, page.getTotal());
@@ -1099,9 +1171,9 @@ public class MeetingManage {
query.in(Project::getStatus, statusCodeList);
}
String sql = String.format("select 1 from meeting m inner join meeting_inner_project mip on" +
" m.is_inner_project = 1 and m.id = mip.meeting_id and nd_project.id = mip.project_id" +
" m.is_inner_project = 1 and m.id = mip.meeting_id and nd_project.project_code = mip.project_code" +
" and m.type = %s and m.status != 3", meetingType);
String sql2 = String.format("1 = (select case when review_result in (0,2) then 1 else 0 end from " +
String sql2 = String.format("1 = (select case when review_result in (2) then 1 else 0 end from " +
" (select ner.review_result from meeting m inner join meeting_inner_project mip on" +
" m.is_inner_project = 1 and m.id = mip.meeting_id and nd_project.id = mip.project_id" +
" and m.type = %s and m.status != 3 left join nd_expert_review ner on ner.meeting_id = m.id " +


불러오는 중...
취소
저장