dev
luotaiqian 2026-07-23 08:45:06 +08:00
parent ab042d1a67
commit 5291d1241f
6 changed files with 241 additions and 0 deletions

View File

@ -5,7 +5,9 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.qinan.safetyeval.client.api.institution.EvalTechReviewApi;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewCO;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewDetailCO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewConfirmCmd;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewSaveCmd;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -31,4 +33,16 @@ public class EvalTechReviewController {
public SingleResponse<EvalTechReviewCO> get(@ApiParam("项目ID") @RequestParam String projectId) {
return evalTechReviewApi.getByProject(projectId);
} */
@ApiOperation("技审确认")
@PostMapping("/confirm")
public SingleResponse<Void> confirm(@Validated @RequestBody EvalTechReviewConfirmCmd cmd) {
return evalTechReviewApi.confirm(cmd);
}
@ApiOperation("按项目查询详情(技审人成员+审核项)")
@GetMapping("/detail")
public SingleResponse<EvalTechReviewDetailCO> detail(@ApiParam("项目ID") @RequestParam Long projectId) {
return evalTechReviewApi.getDetailByProject(projectId);
}
}

View File

@ -1,21 +1,46 @@
package org.qinan.safetyeval.app.executor.institution;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.qinan.safetyeval.app.executor.institution.support.EvalCmdCopy;
import org.qinan.safetyeval.app.executor.institution.support.EvalNodeCoConverter;
import org.qinan.safetyeval.app.executor.institution.support.EvalProjectNodeSupport;
import org.qinan.safetyeval.app.item.convertor.EvalReviewItemCmdConvertor;
import org.qinan.safetyeval.client.api.institution.EvalTechReviewApi;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewCO;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewDetailCO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewConfirmCmd;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewSaveCmd;
import org.qinan.safetyeval.client.item.request.EvalReviewItemAddCmd;
import org.qinan.safetyeval.client.item.response.EvalReviewItemCo;
import org.qinan.safetyeval.domain.constant.ProjectStageEnum;
import org.qinan.safetyeval.domain.constant.ReviewDimensionEnum;
import org.qinan.safetyeval.domain.entity.EvalProjectEntity;
import org.qinan.safetyeval.domain.entity.EvalProjectMemberEntity;
import org.qinan.safetyeval.domain.entity.EvalTechReviewEntity;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.gateway.EvalProjectMemberGateway;
import org.qinan.safetyeval.domain.gateway.EvalTechReviewGateway;
import org.qinan.safetyeval.domain.item.gateway.EvalReviewItemGateway;
import org.qinan.safetyeval.domain.item.model.EvalReviewItemE;
import org.qinan.safetyeval.domain.service.ProjectStageSyncService;
import org.qinan.safetyeval.domain.support.EvalNodeCodes;
import org.qinan.safetyeval.infrastructure.convertor.EvalTechReviewConvertor;
import org.qinan.safetyeval.infrastructure.dataobject.EvalTechReviewDO;
import org.qinan.safetyeval.infrastructure.mapper.EvalTechReviewMapper;
import org.qinan.safetyeval.infrastructure.persistence.queryservice.EvalReviewItemQueryService;
import org.qinan.safetyeval.infrastructure.support.NodeWriteAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import static org.qinan.safetyeval.domain.exception.ErrorCode.ASSIGN_SIGN_TASK;
import static org.qinan.safetyeval.domain.exception.ErrorCode.SIGN_TASK_NOT_COMPLETE;
@Service
public class EvalTechReviewExecutor implements EvalTechReviewApi {
@ -24,6 +49,20 @@ public class EvalTechReviewExecutor implements EvalTechReviewApi {
private EvalTechReviewGateway evalTechReviewGateway;
@Resource
private EvalProjectNodeSupport evalProjectNodeSupport;
@Resource
private EvalProjectMemberGateway evalProjectMemberGateway;
@Resource
private EvalReviewItemQueryService evalReviewItemQueryService;
@Resource
private EvalTechReviewConvertor evalTechReviewConvertor;
@Resource
private EvalReviewItemGateway evalReviewItemGateway;
@Resource
private EvalReviewItemCmdConvertor evalReviewItemCmdConvertor;
@Resource
private ProjectStageSyncService projectStageSyncService;
@Resource
private EvalTechReviewMapper evalTechReviewMapper;
@Override
public SingleResponse<EvalTechReviewCO> getOrSave(EvalTechReviewSaveCmd cmd) {
@ -57,4 +96,88 @@ public class EvalTechReviewExecutor implements EvalTechReviewApi {
}
return SingleResponse.success(EvalNodeCoConverter.toTechCO(entity));
}
@Override
@Transactional(rollbackFor = Exception.class)
public SingleResponse<Void> confirm(EvalTechReviewConfirmCmd cmd) {
Long projectId = cmd.getProjectId();
EvalProjectEntity project = evalProjectNodeSupport.requireProject(projectId);
// 判断项目是否归档
if (project.getArchiveFlag() != null && project.getArchiveFlag() == 1) {
throw new BizException(ErrorCode.EVAL_PROJECT_ARCHIVED);
}
EvalTechReviewEntity entity = evalTechReviewConvertor.applyConfirmCmd(cmd);
EvalTechReviewDO evalTechReviewDO = null;
if (cmd.getId() != null) {
evalTechReviewDO = evalTechReviewMapper.selectOne(new LambdaQueryWrapper<EvalTechReviewDO>()
.eq(EvalTechReviewDO::getId, cmd.getId())
.select(EvalTechReviewDO::getId, EvalTechReviewDO::getReviewerSignatureUrl));
if (evalTechReviewDO == null) {
throw new BizException(ErrorCode.EVAL_TECH_REVIEW_NOT_FOUND);
}
}
// 审核结果编码1通过 2退回修改
if (cmd.getResultCode() != null && cmd.getResultCode() == 1) {
if (evalTechReviewDO == null) {
throw new BizException(ASSIGN_SIGN_TASK);
}
if (StringUtils.isBlank(evalTechReviewDO.getReviewerSignatureUrl())) {
throw new BizException(SIGN_TASK_NOT_COMPLETE);
}
projectStageSyncService.onNodeCompleted(projectId, ProjectStageEnum.TECHNICAL_REVIEW.getNode());
}
if (cmd.getId() != null) {
entity = evalTechReviewGateway.modify(entity);
} else {
// id为空新增数据
entity.setOrgId(project.getOrgId());
entity = evalTechReviewGateway.save(entity);
}
// 审核项根据bizId和bizType先删后增
String bizType = ReviewDimensionEnum.TypeEnum.EVAL_TECH_REVIEW.getCode();
evalReviewItemGateway.deletedEvalReviewItemByBizIdAndBizType(entity.getId(), bizType);
for (EvalReviewItemAddCmd itemCmd : cmd.getReviewItems()) {
EvalReviewItemE itemE = evalReviewItemCmdConvertor.convertCmdToE(itemCmd);
itemE.setBizId(entity.getId());
itemE.setBizType(bizType);
evalReviewItemGateway.add(itemE);
}
return SingleResponse.success();
}
@Override
public SingleResponse<EvalTechReviewDetailCO> getDetailByProject(Long projectId) {
// 1. 查询项目成员中的技审人信息
List<EvalProjectMemberEntity> members = evalProjectMemberGateway
.listByProjectIdAndRoleCode(projectId, NodeWriteAuthority.ROLE_TECH_REVIEWER);
// 2. 查询技审记录,未查询到则技审记录字段为空
EvalTechReviewEntity entity = evalTechReviewGateway.getByProjectId(projectId, null);
EvalTechReviewDetailCO detailCO = new EvalTechReviewDetailCO();
detailCO.setReviewers(evalTechReviewConvertor.toMemberCOs(members));
if (entity != null) {
detailCO.setTechReview(evalTechReviewConvertor.toTechCO(entity));
// 3. 通过技审记录id查询审核项列表
detailCO.setReviewItems(evalReviewItemQueryService.listByBizIdAndBizType(
entity.getId(), ReviewDimensionEnum.TypeEnum.EVAL_TECH_REVIEW.getCode()));
} else {
// 未查询到技审记录,按审核维度枚举构建默认审核项
detailCO.setReviewItems(ReviewDimensionEnum.getListByType(ReviewDimensionEnum.TypeEnum.EVAL_TECH_REVIEW)
.stream()
.map(dimension -> {
EvalReviewItemCo item = new EvalReviewItemCo();
item.setBizType(ReviewDimensionEnum.TypeEnum.EVAL_TECH_REVIEW.getCode());
item.setReviewDimensionCode(dimension.getCode());
item.setReviewDimensionName(dimension.getLabel());
item.setReviewFocus(dimension.getReviewFocus());
return item;
})
.collect(Collectors.toList()));
}
return SingleResponse.success(detailCO);
}
}

View File

@ -1,10 +1,14 @@
package org.qinan.safetyeval.client.api.institution;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewCO;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewDetailCO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewConfirmCmd;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewSaveCmd;
public interface EvalTechReviewApi {
SingleResponse<EvalTechReviewCO> getOrSave(EvalTechReviewSaveCmd cmd);
SingleResponse<EvalTechReviewCO> getByProject(String projectId);
SingleResponse<Void> confirm(EvalTechReviewConfirmCmd cmd);
SingleResponse<EvalTechReviewDetailCO> getDetailByProject(Long projectId);
}

View File

@ -0,0 +1,23 @@
package org.qinan.safetyeval.client.co.institution;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.qinan.safetyeval.client.item.response.EvalReviewItemCo;
import java.util.List;
/**
* CO
*/
@Data
public class EvalTechReviewDetailCO {
@ApiModelProperty("技审记录信息")
private EvalTechReviewCO techReview;
@ApiModelProperty("技审人成员信息")
private List<EvalProjectMemberCO> reviewers;
@ApiModelProperty("审核项列表")
private List<EvalReviewItemCo> reviewItems;
}

View File

@ -0,0 +1,49 @@
package org.qinan.safetyeval.client.dto.institution;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.qinan.safetyeval.client.item.request.EvalReviewItemAddCmd;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class EvalTechReviewConfirmCmd {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("项目id")
private Long projectId;
@ApiModelProperty(value = "节点状态编码1未开始 2进行中 3已完成 4退回", example = "2")
private Integer statusCode;
@ApiModelProperty(value = "技审人人员id")
private Long reviewerPersonnelId;
@ApiModelProperty(value = "技审人姓名", example = "2")
private String reviewerName;
@ApiModelProperty(value = "审核签字任务状态 dispatched 下发non_dispatched 未下发", example = "non_dispatched")
private String reviewerSignatureTaskStatus;
@ApiModelProperty(value = "审核结果编码1通过 2退回修改", example = "1")
private Integer resultCode;
@ApiModelProperty(value = "总体审核意见")
@Size(max = 2000)
private String opinionContent;
@ApiModelProperty(value = "审核时间", hidden = true)
private LocalDateTime reviewTime;
@ApiModelProperty("审核项列表")
@NotNull
@Size(min = 1, max = 16)
@Valid
private List<EvalReviewItemAddCmd> reviewItems;
}

View File

@ -0,0 +1,28 @@
package org.qinan.safetyeval.infrastructure.convertor;
import org.mapstruct.Mapper;
import org.qinan.safetyeval.client.co.institution.EvalProjectMemberCO;
import org.qinan.safetyeval.client.co.institution.EvalTechReviewCO;
import org.qinan.safetyeval.client.dto.institution.EvalTechReviewConfirmCmd;
import org.qinan.safetyeval.domain.entity.EvalProjectMemberEntity;
import org.qinan.safetyeval.domain.entity.EvalTechReviewEntity;
import java.util.List;
/**
*
*/
@Mapper(componentModel = "spring")
public interface EvalTechReviewConvertor {
EvalTechReviewCO toTechCO(EvalTechReviewEntity entity);
EvalProjectMemberCO toMemberCO(EvalProjectMemberEntity entity);
List<EvalProjectMemberCO> toMemberCOs(List<EvalProjectMemberEntity> entities);
/**
* ConfirmCmd entity
*/
EvalTechReviewEntity applyConfirmCmd(EvalTechReviewConfirmCmd cmd);
}