luotaiqian 2026-07-21 18:19:36 +08:00
parent 96f5dfd184
commit 7a9a4656d6
12 changed files with 277 additions and 0 deletions

View File

@ -6,10 +6,13 @@ import io.swagger.annotations.ApiParam;
import org.qinan.safetyeval.client.api.institution.EvalProjectApi;
import org.qinan.safetyeval.client.co.institution.EvalProjectCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectEnumsCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressStatCO;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.EvalProjectAddCmd;
import org.qinan.safetyeval.client.dto.institution.EvalProjectPageQuery;
import org.qinan.safetyeval.client.dto.institution.EvalProjectProgressPageQuery;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -46,4 +49,16 @@ public class EvalProjectController {
public SingleResponse<EvalProjectEnumsCO> enums() {
return evalProjectApi.enums();
}
@ApiOperation("项目进度管理统计")
@GetMapping("/progress-stat")
public SingleResponse<EvalProjectProgressStatCO> progressStat() {
return evalProjectApi.progressStat();
}
@ApiOperation("项目进度管理分页")
@GetMapping("/progress-page")
public PageResponse<EvalProjectProgressCO> progressPage(@Validated EvalProjectProgressPageQuery query) {
return evalProjectApi.progressPage(query);
}
}

View File

@ -10,9 +10,12 @@ import org.qinan.safetyeval.client.co.institution.EnumOptionCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectEnumsCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectParticipantItemCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressCO;
import org.qinan.safetyeval.client.dto.institution.EvalProjectAddCmd;
import org.qinan.safetyeval.client.dto.institution.EvalProjectPageQuery;
import org.qinan.safetyeval.client.dto.institution.EvalProjectProgressPageQuery;
import org.qinan.safetyeval.domain.constant.ChongqingDistrictEnum;
import org.qinan.safetyeval.domain.constant.EvalProjectProgressStatEnum;
import org.qinan.safetyeval.domain.constant.EvalTypeEnum;
import org.qinan.safetyeval.domain.entity.EvalProjectEntity;
import org.qinan.safetyeval.domain.query.EvalProjectQuery;
@ -44,6 +47,12 @@ public interface EvalProjectCmdConvertor {
@Mapping(target = "projectIds", ignore = true)
EvalProjectQuery convertPageQueryToQ(EvalProjectPageQuery query);
@Mapping(target = "pageNum", source = "current")
@Mapping(target = "pageSize", source = "size")
@Mapping(target = "orgId", ignore = true)
@Mapping(target = "projectIds", ignore = true)
EvalProjectQuery convertProgressPageQueryToQ(EvalProjectProgressPageQuery query);
@Mapping(target = "id", expression = "java(entity.getId() == null ? null : String.valueOf(entity.getId()))")
@Mapping(target = "customerId", expression = "java(entity.getCustomerId() == null ? null : String.valueOf(entity.getCustomerId()))")
@Mapping(target = "evalTypeName", ignore = true)
@ -55,6 +64,14 @@ public interface EvalProjectCmdConvertor {
List<EvalProjectCO> convertEListToCOList(List<EvalProjectEntity> list);
@Mapping(target = "id", expression = "java(entity.getId() == null ? null : String.valueOf(entity.getId()))")
@Mapping(target = "evalTypeName", ignore = true)
@Mapping(target = "progressStatusCode", ignore = true)
@Mapping(target = "progressStatusName", ignore = true)
EvalProjectProgressCO convertEToProgressCO(EvalProjectEntity entity);
List<EvalProjectProgressCO> convertEListToProgressCOList(List<EvalProjectEntity> list);
@AfterMapping
default void fillDisplayFields(EvalProjectEntity entity, @MappingTarget EvalProjectCO co) {
if (entity == null || co == null) {
@ -86,6 +103,45 @@ public interface EvalProjectCmdConvertor {
}
}
@AfterMapping
default void fillProgressDisplayFields(EvalProjectEntity entity, @MappingTarget EvalProjectProgressCO co) {
if (entity == null || co == null) {
return;
}
EvalTypeEnum evalType = EvalTypeEnum.ofCode(entity.getEvalTypeCode());
if (evalType != null) {
co.setEvalTypeName(evalType.getValue());
}
String statusCode = computeProgressStatus(entity.getPlanEndDate());
co.setProgressStatusCode(statusCode);
co.setProgressStatusName(progressStatusNameOf(statusCode));
}
/**
*
* DELAY
* 33 NEAR
* 3 NORMAL
*/
default String computeProgressStatus(LocalDate planEndDate) {
if (planEndDate == null) {
return null;
}
LocalDate today = LocalDate.now();
if (today.isAfter(planEndDate)) {
return EvalProjectProgressStatEnum.DELAY.getCode();
}
if (planEndDate.isAfter(today.plusDays(3))) {
return EvalProjectProgressStatEnum.NORMAL.getCode();
}
return EvalProjectProgressStatEnum.NEAR.getCode();
}
default String progressStatusNameOf(String code) {
EvalProjectProgressStatEnum statEnum = EvalProjectProgressStatEnum.ofCode(code);
return statEnum == null ? null : statEnum.getValue();
}
default String toParticipantsJson(List<EvalProjectParticipantItemCO> participants) {
if (participants == null) {
return null;

View File

@ -4,16 +4,21 @@ import org.qinan.safetyeval.app.convertor.EvalProjectCmdConvertor;
import org.qinan.safetyeval.client.api.institution.EvalProjectApi;
import org.qinan.safetyeval.client.co.institution.EvalProjectCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectEnumsCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressStatCO;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.EvalProjectAddCmd;
import org.qinan.safetyeval.client.dto.institution.EvalProjectPageQuery;
import org.qinan.safetyeval.client.dto.institution.EvalProjectProgressPageQuery;
import org.qinan.safetyeval.domain.constant.EvalProjectProgressStatEnum;
import org.qinan.safetyeval.domain.entity.EvalProjectEntity;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.query.EvalProjectQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.service.EvalProjectDomainService;
import org.qinan.safetyeval.infrastructure.adapter.ThreadLocalUserInfoAdapter;
import org.qinan.safetyeval.infrastructure.support.InstitutionOrgSupport;
import org.qinan.safetyeval.infrastructure.support.ProjectNoGenerator;
import org.springframework.beans.factory.annotation.Autowired;
@ -70,6 +75,27 @@ public class EvalProjectExecutor implements EvalProjectApi {
return SingleResponse.success(evalProjectCmdConvertor.buildEnums());
}
@Override
public SingleResponse<EvalProjectProgressStatCO> progressStat() {
Long orgId = ThreadLocalUserInfoAdapter.getOrgId();
EvalProjectProgressStatCO co = new EvalProjectProgressStatCO();
co.setTotalCount((int) evalProjectDomainService.countByOrgIdAndProgressStatus(orgId, null));
co.setNormalCount((int) evalProjectDomainService.countByOrgIdAndProgressStatus(orgId, EvalProjectProgressStatEnum.NORMAL.getCode()));
co.setNearExpiryCount((int) evalProjectDomainService.countByOrgIdAndProgressStatus(orgId, EvalProjectProgressStatEnum.NEAR.getCode()));
co.setDelayedCount((int) evalProjectDomainService.countByOrgIdAndProgressStatus(orgId, EvalProjectProgressStatEnum.DELAY.getCode()));
return SingleResponse.success(co);
}
@Override
public PageResponse<EvalProjectProgressCO> progressPage(EvalProjectProgressPageQuery query) {
EvalProjectQuery domainQuery = evalProjectCmdConvertor.convertProgressPageQueryToQ(query);
domainQuery.setOrgId( ThreadLocalUserInfoAdapter.getOrgId());
PageResult<EvalProjectEntity> pageResult = evalProjectDomainService.page(domainQuery);
return PageResponse.of(
evalProjectCmdConvertor.convertEListToProgressCOList(pageResult.getRecords()),
pageResult.getTotal());
}
private EvalProjectEntity saveWithProjectNo(EvalProjectEntity entity, Long orgId) {
DuplicateKeyException lastEx = null;
for (int i = 0; i < projectNoGenerator.maxRetry(); i++) {

View File

@ -2,10 +2,13 @@ package org.qinan.safetyeval.client.api.institution;
import org.qinan.safetyeval.client.co.institution.EvalProjectCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectEnumsCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectProgressStatCO;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.EvalProjectAddCmd;
import org.qinan.safetyeval.client.dto.institution.EvalProjectPageQuery;
import org.qinan.safetyeval.client.dto.institution.EvalProjectProgressPageQuery;
public interface EvalProjectApi {
@ -16,4 +19,8 @@ public interface EvalProjectApi {
PageResponse<EvalProjectCO> page(EvalProjectPageQuery query);
SingleResponse<EvalProjectEnumsCO> enums();
SingleResponse<EvalProjectProgressStatCO> progressStat();
PageResponse<EvalProjectProgressCO> progressPage(EvalProjectProgressPageQuery query);
}

View File

@ -0,0 +1,40 @@
package org.qinan.safetyeval.client.co.institution;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
/**
*
*/
@Data
public class EvalProjectProgressCO {
@ApiModelProperty("项目ID")
private String id;
@ApiModelProperty("项目编号")
private String projectNo;
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty("客户负责人")
private String customerContactName;
@ApiModelProperty("评价类型名称")
private String evalTypeName;
@ApiModelProperty("项目负责人")
private String projectLeaderName;
@ApiModelProperty("项目结束日期")
private LocalDate planEndDate;
@ApiModelProperty("项目进度状态码NORMAL正常 NEAR临期 DELAY延期")
private String progressStatusCode;
@ApiModelProperty("项目进度状态名称:正常/项目临期/项目延期")
private String progressStatusName;
}

View File

@ -0,0 +1,23 @@
package org.qinan.safetyeval.client.co.institution;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
*
*/
@Data
public class EvalProjectProgressStatCO {
@ApiModelProperty("项目总数")
private Integer totalCount;
@ApiModelProperty("正常项目数距结束日期超过3天")
private Integer normalCount;
@ApiModelProperty("临期项目数距结束日期3天以内含3天")
private Integer nearExpiryCount;
@ApiModelProperty("延期项目数(已超过项目结束日期)")
private Integer delayedCount;
}

View File

@ -0,0 +1,20 @@
package org.qinan.safetyeval.client.dto.institution;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.qinan.safetyeval.client.dto.BasePageQuery;
/**
*
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class EvalProjectProgressPageQuery extends BasePageQuery {
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty("项目进度状态NORMAL正常 NEAR临期 DELAY延期")
private String progressStatus;
}

View File

@ -0,0 +1,45 @@
package org.qinan.safetyeval.domain.constant;
/**
*
* <p>
* DELAY
* 33 NEAR
* 3 NORMAL
* </p>
*/
public enum EvalProjectProgressStatEnum {
NORMAL("NORMAL", "正常"),
NEAR("NEAR", "项目临期"),
DELAY("DELAY", "项目延期"),
;
private final String code;
private final String value;
EvalProjectProgressStatEnum(String code, String value) {
this.code = code;
this.value = value;
}
public String getCode() {
return code;
}
public String getValue() {
return value;
}
public static EvalProjectProgressStatEnum ofCode(String code) {
if (code == null) {
return null;
}
for (EvalProjectProgressStatEnum item : values()) {
if (item.code.equals(code)) {
return item;
}
}
return null;
}
}

View File

@ -19,4 +19,6 @@ public interface EvalProjectGateway {
long countByCustomerId(Long customerId, Long orgId);
void updateLeader(Long projectId, String leaderName);
long countByOrgIdAndProgressStatus(Long orgId, String progressStatus);
}

View File

@ -25,4 +25,7 @@ public class EvalProjectQuery {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
private List<Long> projectIds;
@ApiModelProperty("项目进度状态NORMAL正常 NEAR临期 DELAY延期")
private String progressStatus;
}

View File

@ -40,6 +40,10 @@ public class EvalProjectDomainService {
return evalProjectGateway.page(query);
}
public long countByOrgIdAndProgressStatus(Long orgId, String progressStatus) {
return evalProjectGateway.countByOrgIdAndProgressStatus(orgId, progressStatus);
}
public void updateLeader(Long projectId, Long leaderPersonnelId, String leaderName) {
evalProjectGateway.updateLeader(projectId, leaderName);
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.qinan.safetyeval.domain.entity.EvalProjectEntity;
import org.qinan.safetyeval.domain.constant.EvalProjectProgressStatEnum;
import org.qinan.safetyeval.domain.gateway.EvalProjectGateway;
import org.qinan.safetyeval.domain.query.EvalProjectQuery;
import org.qinan.safetyeval.domain.query.PageResult;
@ -17,6 +18,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
@ -99,6 +101,17 @@ public class EvalProjectGatewayImpl implements EvalProjectGateway {
evalProjectMapper.updateById(dataObject);
}
@Override
public long countByOrgIdAndProgressStatus(Long orgId, String progressStatus) {
LambdaQueryWrapper<EvalProjectDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EvalProjectDO::getDeleteEnum, "false");
if (orgId != null) {
wrapper.eq(EvalProjectDO::getOrgId, orgId);
}
applyProgressStatusFilter(wrapper, progressStatus);
return evalProjectMapper.selectCount(wrapper);
}
private LambdaQueryWrapper<EvalProjectDO> buildQueryWrapper(EvalProjectQuery query) {
LambdaQueryWrapper<EvalProjectDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EvalProjectDO::getDeleteEnum, "false");
@ -124,7 +137,30 @@ public class EvalProjectGatewayImpl implements EvalProjectGateway {
if (!CollectionUtils.isEmpty(query.getProjectIds())) {
wrapper.in(EvalProjectDO::getId, query.getProjectIds());
}
applyProgressStatusFilter(wrapper, query.getProgressStatus());
wrapper.orderByDesc(EvalProjectDO::getId);
return wrapper;
}
/**
* planEndDate
* DELAYplanEndDate &lt;
* NEAR &lt;= planEndDate &lt;= +3
* NORMALplanEndDate &gt; +3
*/
private void applyProgressStatusFilter(LambdaQueryWrapper<EvalProjectDO> wrapper, String progressStatus) {
if (!StringUtils.hasText(progressStatus)) {
return;
}
LocalDate today = LocalDate.now();
LocalDate nearExpiryDeadline = today.plusDays(3);
if (EvalProjectProgressStatEnum.DELAY.getCode().equals(progressStatus)) {
wrapper.lt(EvalProjectDO::getPlanEndDate, today);
} else if (EvalProjectProgressStatEnum.NEAR.getCode().equals(progressStatus)) {
wrapper.ge(EvalProjectDO::getPlanEndDate, today);
wrapper.le(EvalProjectDO::getPlanEndDate, nearExpiryDeadline);
} else if (EvalProjectProgressStatEnum.NORMAL.getCode().equals(progressStatus)) {
wrapper.gt(EvalProjectDO::getPlanEndDate, nearExpiryDeadline);
}
}
}