diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/performance/constant/BizConst.java b/pmapi/src/main/java/com/ningdatech/pmapi/performance/constant/BizConst.java index 8f25773..c59b17d 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/performance/constant/BizConst.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/performance/constant/BizConst.java @@ -9,13 +9,13 @@ package com.ningdatech.pmapi.performance.constant; public interface BizConst { /** - * 500万 + * 500万元 */ - Integer FIVE_MILLION = 5000000; + Integer FIVE_MILLION = 500; /** - * 2000万 + * 2000万元 */ - Integer TWENTY_MILLION = 20000000; + Integer TWENTY_MILLION = 2000; /** * 立项批复金额在500万以下 diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/performance/controller/ReAppraisalController.java b/pmapi/src/main/java/com/ningdatech/pmapi/performance/controller/ReAppraisalController.java new file mode 100644 index 0000000..fa0b0a0 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/performance/controller/ReAppraisalController.java @@ -0,0 +1,64 @@ +package com.ningdatech.pmapi.performance.controller; + +import javax.validation.Valid; + +import com.ningdatech.pmapi.performance.manage.ReAppraisalManage; +import org.springframework.web.bind.annotation.*; + +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.pmapi.performance.manage.OrgSelfAppraisalManage; +import com.ningdatech.pmapi.performance.model.dto.ProjectAppraisalDTO; +import com.ningdatech.pmapi.performance.model.req.PerformanceAppraisalListReq; +import com.ningdatech.pmapi.performance.model.vo.PerformanceAppraisalProjectVO; +import com.ningdatech.pmapi.performance.model.vo.PerformanceAppraisalVO; +import com.ningdatech.pmapi.performance.model.vo.ProjectAppraisalIndexDetailVO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; + +/** + * ReAppraisalController + * @return + * @author CMM + * @since 2023/08/10 8:54 + */ +@RestController +@RequiredArgsConstructor +@Api(tags = "绩效评价-人工复评") +@RequestMapping("/api/v1/re-appraisal") +public class ReAppraisalController { + + private final ReAppraisalManage reAppraisalManage; + + @GetMapping("/list") + @ApiOperation("当前复评用户的绩效评价计划列表") + public PageVo list(PerformanceAppraisalListReq req) { + return reAppraisalManage.list(req); + } + + //@GetMapping("/pending-list/{planId}") + //@ApiOperation("当前绩效评价待自评列表") + //public PageVo pendingList(@PathVariable Long planId, PerformanceAppraisalListReq req) { + // return selfAppraisalManage.pendingList(planId,req); + //} + // + //@GetMapping("/appraisaled-list/{planId}") + //@ApiOperation("当前绩效评价已自评列表") + //public PageVo appraisaledList(@PathVariable Long planId,PerformanceAppraisalListReq req) { + // return selfAppraisalManage.appraisaledList(planId,req); + //} + // + //@GetMapping("/get-appraisal-template-detail/{projectCode}") + //@ApiOperation("获取自评模版详情") + //public ProjectAppraisalIndexDetailVO getAppraisalTemplateDetail(@PathVariable String projectCode){ + // return selfAppraisalManage.getAppraisalTemplateDetail(projectCode); + //} + // + //@PostMapping("/submit-self-appraisal") + //@ApiOperation("提交自评") + //public String submitSelfAppraisal(@Valid @RequestBody ProjectAppraisalDTO param){ + // return selfAppraisalManage.submitSelfAppraisal(param); + //} + +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/performance/manage/ReAppraisalManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/performance/manage/ReAppraisalManage.java new file mode 100644 index 0000000..405cb35 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/performance/manage/ReAppraisalManage.java @@ -0,0 +1,373 @@ +package com.ningdatech.pmapi.performance.manage; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.function.VUtils; +import com.ningdatech.basic.model.PageVo; +import com.ningdatech.basic.util.StrPool; +import com.ningdatech.pmapi.performance.constant.BizConst; +import com.ningdatech.pmapi.performance.enumration.AppraisalTypeEnum; +import com.ningdatech.pmapi.performance.helper.TemplateDetailBuildHelper; +import com.ningdatech.pmapi.performance.model.dto.ProjectAppraisalDTO; +import com.ningdatech.pmapi.performance.model.dto.ProjectAppraisalInfoDTO; +import com.ningdatech.pmapi.performance.model.entity.*; +import com.ningdatech.pmapi.performance.model.req.PerformanceAppraisalListReq; +import com.ningdatech.pmapi.performance.model.vo.PerformanceAppraisalProjectVO; +import com.ningdatech.pmapi.performance.model.vo.PerformanceAppraisalVO; +import com.ningdatech.pmapi.performance.model.vo.ProjectAppraisalIndexDetailVO; +import com.ningdatech.pmapi.performance.model.vo.ProjectTemplateDetailVO; +import com.ningdatech.pmapi.performance.service.*; +import com.ningdatech.pmapi.portrait.model.entity.ProjectTag; +import com.ningdatech.pmapi.portrait.service.IProjectTagService; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectTypeEnum; +import com.ningdatech.pmapi.projectlib.model.entity.Project; +import com.ningdatech.pmapi.projectlib.service.IProjectService; +import com.ningdatech.pmapi.sys.model.entity.Role; +import com.ningdatech.pmapi.sys.service.IRoleService; +import com.ningdatech.pmapi.user.entity.enumeration.RoleEnum; +import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; +import com.ningdatech.pmapi.user.util.LoginUserUtil; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * ReAppraisalManage + * @return + * @author CMM + * @since 2023/08/10 8:55 + */ +@Component +@Slf4j +@AllArgsConstructor +public class ReAppraisalManage { + + private final IPerformanceAppraisalService performanceAppraisalService; + private final IPerformanceAppraisalProjectService performanceAppraisalProjectService; + private final IProjectService projectService; + private final IRoleService roleService; + private final IPerformanceIndicatorProjectTemplateService indicatorProjectTemplateService; + private final TemplateDetailBuildHelper templateDetailBuildHelper; + private final IPerformanceIndicatorProjectTemplateDetailService indicatorProjectTemplateDetailService; + private final IProjectTagService projectTagService; + private final IPerformanceAppraisalScoreInfoService performanceAppraisalScoreInfoService; + /** + * 绩效列表 + * @param req + * @return + */ + public PageVo list(PerformanceAppraisalListReq req) { + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + + //当前登录用户 单位code + String empPosUnitCode = user.getEmpPosUnitCode(); + // 获取当前登录用户的角色列表,只有绩效复评人员才能查看该列表 + List userRoleList = user.getUserRoleList(); + List roleIdList = userRoleList.stream().map(Role::getId).collect(Collectors.toList()); + Role role = roleService.getOne(Wrappers.lambdaQuery(Role.class) + .eq(Role::getName, BizConst.REAPPRAISAL_ROLE)); + if (Objects.isNull(role)){ + throw new BizException("登录用户没有复评员角色!"); + } + + // 登录用户不是复评员,不能查看复评计划列表 + if (!roleIdList.contains(role.getId())){ + return PageVo.empty(); + } + + // 获取登录用户所在单位的所有已终验项目信息 + List projectLists = projectService.list(Wrappers.lambdaQuery(Project.class) + .eq(Project::getStatus, ProjectStatusEnum.ACCEPTED.getCode()) + .eq(Project::getBuildOrgCode, empPosUnitCode)); + + if(CollUtil.isEmpty(projectLists)){ + return PageVo.empty(); + } + List projectIds = projectLists.stream().map(Project::getId).collect(Collectors.toList()); + // 获取添加过该单位项目的所有评价计划信息 + List paps = performanceAppraisalProjectService.list(Wrappers.lambdaQuery(PerformanceAppraisalProject.class) + .in(PerformanceAppraisalProject::getProjectId, projectIds)); + if(CollUtil.isEmpty(paps)){ + return PageVo.empty(); + } + Set paIds = paps.stream().map(PerformanceAppraisalProject::getAppraisalId).collect(Collectors.toSet()); + + // 获取评价计划关联的分组信息 + + // 获取评价计划列表 + Page page = req.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PerformanceAppraisal.class) + .in(PerformanceAppraisal::getId,paIds) + .orderByDesc(PerformanceAppraisal::getUpdateOn); + performanceAppraisalService.page(page,wrapper); + if(0L == page.getTotal()){ + return PageVo.empty(); + } + + List res = page.getRecords().stream() + .map(p -> BeanUtil.copyProperties(p, PerformanceAppraisalVO.class)) + .collect(Collectors.toList()); + return PageVo.of(res,page.getTotal()); + } + + public PageVo pendingList(Long planId, PerformanceAppraisalListReq req) { + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + + PerformanceAppraisal plan = performanceAppraisalService.getById(planId); + VUtils.isTrue(Objects.isNull(plan)).throwMessage("该评价计划不存在!"); + + // 获取评价计划内已添加的待评价项目信息 + List paps = performanceAppraisalProjectService.list(Wrappers.lambdaQuery(PerformanceAppraisalProject.class) + .eq(PerformanceAppraisalProject::getAppraisalId, plan.getId())).stream() + .filter(p -> Objects.isNull(p.getSelfAppraisalScoreTime())).collect(Collectors.toList()); + Map papsMap = paps.stream().collect(Collectors.toMap(PerformanceAppraisalProject::getProjectId, p -> p)); + + if(CollUtil.isEmpty(paps)){ + return PageVo.empty(); + } + + // 获取本单位在当前评价计划内的项目 + Set projectCodes = paps.stream().map(PerformanceAppraisalProject::getProjectCode).collect(Collectors.toSet()); + Page page = req.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Project.class) + .in(Project::getProjectCode, projectCodes) + .eq(Project::getNewest, Boolean.TRUE) + .eq(Project::getBuildOrgCode, user.getEmpPosUnitCode()) + .like(StringUtils.isNotBlank(req.getProjectName()),Project::getProjectName,req.getProjectName()); + projectService.page(page,wrapper); + + if(0L == page.getTotal()){ + return PageVo.empty(); + } + + List res = page.getRecords().stream() + .map(p -> { + PerformanceAppraisalProjectVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalProjectVO.class); + PerformanceAppraisalProject appraisalProject = papsMap.get(p.getId()); + BeanUtil.copyProperties(appraisalProject,vo); + vo.setProjectId(appraisalProject.getProjectId()); + vo.setProjectTypeName(ProjectTypeEnum.getDesc(p.getProjectType())); + vo.setCanSelfAppraisal(checkCanSelfAppraisal(appraisalProject)); + vo.setAppraisalId(planId); + return vo; + }) + .collect(Collectors.toList()); + + return PageVo.of(res,page.getTotal()); + } + + /** + * 已经自评表 + * + * @param planId + * @param req + * @return + */ + public PageVo appraisaledList(Long planId, PerformanceAppraisalListReq req) { + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + + PerformanceAppraisal plan = performanceAppraisalService.getById(planId); + VUtils.isTrue(Objects.isNull(plan)).throwMessage("该评价计划不存在!"); + + // 获取评价计划内已添加的已评价项目信息 + List paps = performanceAppraisalProjectService.list(Wrappers.lambdaQuery(PerformanceAppraisalProject.class) + .eq(PerformanceAppraisalProject::getAppraisalId, plan.getId())).stream() + .filter(p -> Objects.nonNull(p.getSelfAppraisalScoreTime())).collect(Collectors.toList()); + Map papsMap = paps.stream().collect(Collectors.toMap(PerformanceAppraisalProject::getProjectId, p -> p)); + + if(CollUtil.isEmpty(paps)){ + return PageVo.empty(); + } + + // 获取本单位在当前评价计划内的项目 + Set projectCodes = paps.stream().map(PerformanceAppraisalProject::getProjectCode).collect(Collectors.toSet()); + Page page = req.page(); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Project.class) + .in(Project::getProjectCode, projectCodes) + .eq(Project::getNewest, Boolean.TRUE) + .eq(Project::getBuildOrgCode, user.getEmpPosUnitCode()) + .like(StringUtils.isNotBlank(req.getProjectName()),Project::getProjectName,req.getProjectName()); + projectService.page(page,wrapper); + + if(0L == page.getTotal()){ + return PageVo.empty(); + } + List res = page.getRecords().stream() + .map(p -> { + PerformanceAppraisalProjectVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalProjectVO.class); + PerformanceAppraisalProject appraisalProject = papsMap.get(p.getId()); + BeanUtil.copyProperties(appraisalProject,vo); + vo.setProjectId(appraisalProject.getProjectId()); + vo.setProjectTypeName(ProjectTypeEnum.getDesc(p.getProjectType())); + vo.setCanSelfAppraisal(checkCanSelfAppraisal(appraisalProject)); + vo.setAppraisalId(planId); + return vo; + }) + .collect(Collectors.toList()); + + return PageVo.of(res,page.getTotal()); + } + + /** + * 是否可以自评 + * @param appraisalProject + * @return + */ + private Boolean checkCanSelfAppraisal(PerformanceAppraisalProject appraisalProject) { + // 在自评时间段内,且是首次自评(打分时间为空) + if(LocalDateTime.now().compareTo(appraisalProject.getSelfAppraisalStart()) > 0 && + LocalDateTime.now().compareTo(appraisalProject.getSelfAppraisalEnd()) < 0 && + Objects.isNull(appraisalProject.getSelfAppraisalScoreTime())){ + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + public ProjectAppraisalIndexDetailVO getAppraisalTemplateDetail(String projectCode) { + UserInfoDetails user = LoginUserUtil.loginUserDetail(); + String regionCode = user.getRegionCode(); + + ProjectAppraisalIndexDetailVO vo = new ProjectAppraisalIndexDetailVO(); + + // 根据项目编码获取最新版本的项目信息 + Project project = projectService.getProjectByCode(projectCode); + VUtils.isTrue(Objects.isNull(project)).throwMessage("项目不存在!"); + // 根据项目类型、预算年度、批复金额、项目标签匹配本区域指标模版 + Integer projectType = project.getProjectType(); + Integer projectYear = project.getProjectYear(); + BigDecimal approvalAmount = project.getApprovalAmount(); + VUtils.isTrue(Objects.isNull(approvalAmount)).throwMessage("未获取到该项目的立项批复金额"); + // 根据项目code获取项目标签ID列表 + List tagIdList = projectTagService.list(Wrappers.lambdaQuery(ProjectTag.class) + .eq(ProjectTag::getProjectCode, projectCode)).stream() + .map(ProjectTag::getTagId).collect(Collectors.toList()); + VUtils.isTrue(CollUtil.isEmpty(tagIdList)).throwMessage("当前项目未设置标签,匹配不到指标模板,请至项目库或评价计划编辑页面设置标签!"); + + List strIdList = tagIdList.stream().map(String::valueOf).collect(Collectors.toList()); + String projectTagIds = String.join(StrPool.COMMA, strIdList); + + Integer amountRange = null; + if (approvalAmount.compareTo(BigDecimal.valueOf(BizConst.FIVE_MILLION)) < 0){ + amountRange = BizConst.AMOUNT_RANGE_ONE; + } else if (approvalAmount.compareTo(BigDecimal.valueOf(BizConst.FIVE_MILLION)) >= 0 && + approvalAmount.compareTo(BigDecimal.valueOf(BizConst.TWENTY_MILLION)) < 0) { + amountRange = BizConst.AMOUNT_RANGE_TWO; + }else if (approvalAmount.compareTo(BigDecimal.valueOf(BizConst.TWENTY_MILLION)) >= 0){ + amountRange = BizConst.AMOUNT_RANGE_THREE; + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplate.class) + .eq(PerformanceIndicatorProjectTemplate::getRegionCode, regionCode) + .eq(PerformanceIndicatorProjectTemplate::getProjectType, projectType) + .eq(PerformanceIndicatorProjectTemplate::getProjectYear, projectYear) + .eq(PerformanceIndicatorProjectTemplate::getAmountRange, amountRange) + .eq(PerformanceIndicatorProjectTemplate::getProjectTagIds,projectTagIds) + .orderByDesc(PerformanceIndicatorProjectTemplate::getUpdateOn); + PerformanceIndicatorProjectTemplate projectTemplate = indicatorProjectTemplateService.getOne(wrapper); + + if (Objects.isNull(projectTemplate)){ + throw new BizException("该项目匹配不到指标模板,请返回上一页或者刷新重试。"); + } + // 装配项目指标详情及分数信息 + // 获取模版绩效指标详情 + List templateDetails = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class) + .eq(PerformanceIndicatorProjectTemplateDetail::getTemplateId, projectTemplate.getId())); + // 获取模版附加绩效指标详情 + List additionalTemplateDetails = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class) + .eq(PerformanceIndicatorProjectTemplateDetail::getTemplateId, projectTemplate.getId()) + .eq(PerformanceIndicatorProjectTemplateDetail::getIsAdditional,Boolean.TRUE)); + List templateDetailVos = templateDetailBuildHelper.buildTemplateDetail(templateDetails); + List additionalTemplateDetailVos = templateDetailBuildHelper.buildTemplateDetail(additionalTemplateDetails); + vo.setProjectName(project.getProjectName()); + vo.setBuildOrgName(project.getBuildOrgName()); + vo.setProjectStatus(project.getStatus()); + vo.setProjectYear(projectYear); + vo.setApprovalAmount(approvalAmount); + vo.setTemplateDetails(templateDetailVos); + vo.setAdditionalIndexDetails(additionalTemplateDetailVos); + return vo; + } + + @Transactional(rollbackFor = Exception.class) + public String submitSelfAppraisal(ProjectAppraisalDTO param) { + UserInfoDetails userDetail = LoginUserUtil.loginUserDetail(); + String employeeCode = userDetail.getEmployeeCode(); + String username = userDetail.getUsername(); + Long appraisalId = param.getAppraisalId(); + Long appraisalProjectId = param.getAppraisalProjectId(); + List appraisalInfoList = param.getAppraisalInfoList(); + // 判断该项目是否还存在于计划或分组中 + PerformanceAppraisalProject appraisalProject = performanceAppraisalProjectService.getOne(Wrappers.lambdaQuery(PerformanceAppraisalProject.class) + .eq(PerformanceAppraisalProject::getAppraisalId, appraisalId) + .eq(PerformanceAppraisalProject::getProjectId, appraisalProjectId)); + if (Objects.isNull(appraisalProject)){ + throw new BizException("该项目已被移除评价计划,请返回上一页或者刷新重试!"); + } + // 根据项目模板详情ID保存自评得分、打分时间 + if (CollUtil.isEmpty(appraisalInfoList)){ + throw new BizException("填写所有自评得分后才能提交!"); + } + List ids = appraisalInfoList.stream() + .map(ProjectAppraisalInfoDTO::getProjectTemplateDetailId) + .collect(Collectors.toList()); + // 查出项目模版详情信息 + List detailList = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class) + .in(PerformanceIndicatorProjectTemplateDetail::getId, ids)); + if (CollUtil.isEmpty(detailList)){ + throw new BizException("评价指标不存在!"); + } + Map detailMap = detailList.stream().collect(Collectors.toMap(PerformanceIndicatorProjectTemplateDetail::getId, d -> d)); + List scoreInfos = appraisalInfoList.stream().map(a -> { + PerformanceIndicatorProjectTemplateDetail templateDetail = detailMap.get(a.getProjectTemplateDetailId()); + BigDecimal score = a.getScore(); + BigDecimal indexScore = templateDetail.getIndexScore(); + if (score.compareTo(indexScore) > 0 || score.compareTo(BigDecimal.ZERO) < 0){ + throw new BizException("自评得分必须大于等于0且小于等于指标分值!"); + } + // 保存自评分数信息 + PerformanceAppraisalScoreInfo scoreInfo = new PerformanceAppraisalScoreInfo(); + scoreInfo.setAppraisalBasis(a.getAppraisalBasis()); + scoreInfo.setAppraisalScore(a.getScore()); + scoreInfo.setAppraisalBasisAppendix(a.getAppraisalBasisAppendix()); + scoreInfo.setAppraisalType(AppraisalTypeEnum.SELF_APPRAISAL.getCode()); + scoreInfo.setTemplateDetailId(templateDetail.getId()); + scoreInfo.setTemplateId(templateDetail.getTemplateId()); + scoreInfo.setAppraisalEmployeeCode(employeeCode); + scoreInfo.setAppraisalEmployeeName(username); + scoreInfo.setCreateOn(LocalDateTime.now()); + scoreInfo.setCreateBy(username); + return scoreInfo; + }).collect(Collectors.toList()); + + if (performanceAppraisalScoreInfoService.saveBatch(scoreInfos)){ + // 计算自评总分并保存 + BigDecimal selfAppraisalTotalScore = appraisalInfoList.stream() + .map(ProjectAppraisalInfoDTO::getScore) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + appraisalProject.setSelfAppraisalTotalScore(selfAppraisalTotalScore); + appraisalProject.setSelfAppraisalScoreTime(LocalDateTime.now()); + appraisalProject.setUpdateOn(LocalDateTime.now()); + appraisalProject.setUpdateBy(username); + performanceAppraisalProjectService.updateById(appraisalProject); + return "提交成功"; + } + return "提交失败"; + } +}