0509新功能优化

This commit is contained in:
lzm
2026-05-08 17:39:39 +08:00
parent e278ca59bd
commit 1d26048bc1
23 changed files with 154 additions and 58 deletions

View File

@@ -21,7 +21,7 @@ public class ProjectOutputSplitRespVO {
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "规划内容")
@Schema(description = "项目任务包")
private String planningContent;
@Schema(description = "年度")
@@ -33,16 +33,16 @@ public class ProjectOutputSplitRespVO {
@Schema(description = "项目经理")
private String projectManagerName;
@Schema(description = "项目负责人")
@Schema(description = "工程负责人")
private String engineeringLeaderName;
@Schema(description = "项目经理/项目负责人")
@Schema(description = "项目经理/工程负责人")
private String projectLeadName;
@Schema(description = "项目经理/项目负责人合并比例")
@Schema(description = "项目经理/工程负责人合并比例")
private BigDecimal projectLeadRatio;
@Schema(description = "项目经理/项目负责人合并金额")
@Schema(description = "项目经理/工程负责人合并金额")
private BigDecimal projectLeadAmount;
@Schema(description = "专业所比例")

View File

@@ -16,8 +16,8 @@ public class ProjectOutputSplitSaveReqVO {
@NotNull(message = "合约规划 ID 不能为空")
private Long planningId;
@Schema(description = "项目经理/项目负责人合并比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0550")
@NotNull(message = "项目经理/项目负责人合并比例不能为空")
@Schema(description = "项目经理/工程负责人合并比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0550")
@NotNull(message = "项目经理/工程负责人合并比例不能为空")
@DecimalMin(value = "0.0000", message = "projectLeadRatio must be >= 0")
@DecimalMax(value = "1.0000", message = "projectLeadRatio must be <= 1")
private BigDecimal projectLeadRatio;

View File

@@ -24,7 +24,7 @@ public class ProjectPlanningPageReqVO extends PageParam {
@Schema(description = "产值计算方式", example = "指导价法")
private String calculationMethod;
@Schema(description = "规划内容,模糊匹配", example = "建筑")
@Schema(description = "项目任务包,模糊匹配", example = "建筑")
private String planningContent;
@Schema(description = "开始年度", example = "2026")

View File

@@ -16,25 +16,43 @@ public class ProjectPlanningRespVO {
@Schema(description = "项目 ID", example = "1")
private Long projectId;
@Schema(description = "排序")
private Integer sortNo;
@Schema(description = "归属类型")
private String ownershipType;
@Schema(description = "产值计算方式")
private String calculationMethod;
@Schema(description = "规划内容")
@Schema(description = "项目任务包")
private String planningContent;
@Schema(description = "规划金额")
@Schema(description = "分项合同产值")
private BigDecimal planningAmount;
@Schema(description = "合同产值数量")
private BigDecimal contractValueQuantity;
@Schema(description = "合同产值单价")
private BigDecimal contractValueUnitPrice;
@Schema(description = "管理费率")
private BigDecimal managementFeeRate;
@Schema(description = "管理费")
private BigDecimal managementFee;
@Schema(description = "实施团队")
@Schema(description = "增值税率")
private BigDecimal vatRate;
@Schema(description = "增值税")
private BigDecimal vatAmount;
@Schema(description = "项目预算产值")
private BigDecimal projectBudgetOutputValue;
@Schema(description = "意向实施团队")
private String implementationTeam;
@Schema(description = "开始年度")

View File

@@ -21,6 +21,9 @@ public class ProjectPlanningSaveReqVO {
@NotNull(message = "项目 ID 不能为空")
private Long projectId;
@Schema(description = "排序", example = "0")
private Integer sortNo;
@Schema(description = "归属类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "专业所")
@NotBlank(message = "归属类型不能为空")
@Size(max = 20, message = "归属类型长度不能超过 20 个字符")
@@ -30,23 +33,38 @@ public class ProjectPlanningSaveReqVO {
@Size(max = 30, message = "产值计算方式长度不能超过 30 个字符")
private String calculationMethod;
@Schema(description = "规划内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "建筑设计")
@NotBlank(message = "规划内容不能为空")
@Size(max = 255, message = "规划内容长度不能超过 255 个字符")
@Schema(description = "项目任务包", requiredMode = Schema.RequiredMode.REQUIRED, example = "建筑设计")
@NotBlank(message = "项目任务包不能为空")
@Size(max = 255, message = "项目任务包长度不能超过 255 个字符")
private String planningContent;
@Schema(description = "规划金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "500000")
@NotNull(message = "规划金额不能为空")
@Schema(description = "分项合同产值,系统根据合同产值数量和合同产值单价自动计算", example = "500000")
private BigDecimal planningAmount;
@Schema(description = "合同产值数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "合同产值数量不能为空")
@DecimalMin(value = "0.0000", message = "contractValueQuantity must be >= 0")
private BigDecimal contractValueQuantity;
@Schema(description = "合同产值单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "500000")
@NotNull(message = "合同产值单价不能为空")
@DecimalMin(value = "0.0000", message = "contractValueUnitPrice must be >= 0")
private BigDecimal contractValueUnitPrice;
@Schema(description = "管理费率", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0500")
@NotNull(message = "管理费率不能为空")
@DecimalMin(value = "0.0000", message = "managementFeeRate must be >= 0")
@DecimalMax(value = "1.0000", message = "managementFeeRate must be <= 1")
private BigDecimal managementFeeRate;
@Schema(description = "实施团队", example = "建筑一所")
@Size(max = 100, message = "实施团队长度不能超过 100 个字符")
@Schema(description = "增值税率", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0600")
@NotNull(message = "增值税率不能为空")
@DecimalMin(value = "0.0000", message = "vatRate must be >= 0")
@DecimalMax(value = "1.0000", message = "vatRate must be <= 1")
private BigDecimal vatRate;
@Schema(description = "意向实施团队", example = "建筑一所")
@Size(max = 100, message = "意向实施团队长度不能超过 100 个字符")
private String implementationTeam;
@Schema(description = "开始年度", example = "2026")

View File

@@ -15,7 +15,7 @@ import static cn.iocoder.lyzsys.framework.common.util.date.DateUtils.FORMAT_YEAR
@EqualsAndHashCode(callSuper = true)
public class ProjectProfitPageReqVO extends PageParam {
@Schema(description = "工程名称,模糊匹配", example = "设计")
@Schema(description = "项目名称,模糊匹配", example = "设计")
private String projectName;
@Schema(description = "是否签订合同", example = "true")

View File

@@ -13,13 +13,16 @@ public class ProjectProfitRespVO {
@Schema(description = "项目 ID", example = "1")
private Long projectId;
@Schema(description = "工程名称")
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "排序")
private Integer sortNo;
@Schema(description = "是否签订合同")
private Boolean contractSignedFlag;
@Schema(description = "合同金额")
@Schema(description = "合同产值")
private BigDecimal contractAmount;
@Schema(description = "最终结算金额")

View File

@@ -15,7 +15,7 @@ import static cn.iocoder.lyzsys.framework.common.util.date.DateUtils.FORMAT_YEAR
@EqualsAndHashCode(callSuper = true)
public class ProjectPageReqVO extends PageParam {
@Schema(description = "工程名称,模糊匹配", example = "设计")
@Schema(description = "项目名称,模糊匹配", example = "设计")
private String projectName;
@Schema(description = "是否签订合同", example = "true")

View File

@@ -22,16 +22,20 @@ public class ProjectRespVO {
@ExcelProperty("项目ID")
private Long id;
@Schema(description = "工程名称", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("工程名称")
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("项目名称")
private String projectName;
@Schema(description = "排序")
@ExcelProperty("排序")
private Integer sortNo;
@Schema(description = "是否签订合同", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("是否签订合同")
private Boolean contractSignedFlag;
@Schema(description = "合同金额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("合同金额")
@Schema(description = "合同产值", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("合同产值")
private BigDecimal contractAmount;
@Schema(description = "工程总面积", requiredMode = Schema.RequiredMode.REQUIRED)
@@ -42,12 +46,12 @@ public class ProjectRespVO {
@ExcelProperty("建设单位")
private String constructionUnitName;
@Schema(description = "联系人")
@ExcelProperty("联系人")
@Schema(description = "建设单位联系人")
@ExcelProperty("建设单位联系人")
private String contactName;
@Schema(description = "联系方式")
@ExcelProperty("联系方式")
@Schema(description = "建设单位联系电话")
@ExcelProperty("建设单位联系电话")
private String contactPhone;
@Schema(description = "合同签订日期")

View File

@@ -23,17 +23,20 @@ public class ProjectSaveReqVO {
@Schema(description = "项目 ID", example = "1")
private Long id;
@Schema(description = "工程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX 设计项目")
@NotBlank(message = "工程名称不能为空")
@Size(max = 200, message = "工程名称长度不能超过 200 个字符")
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX 设计项目")
@NotBlank(message = "项目名称不能为空")
@Size(max = 200, message = "项目名称长度不能超过 200 个字符")
private String projectName;
@Schema(description = "排序", example = "0")
private Integer sortNo;
@Schema(description = "是否签订合同", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否签订合同不能为空")
private Boolean contractSignedFlag;
@Schema(description = "合同金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000000")
@NotNull(message = "合同金额不能为空")
@Schema(description = "合同产值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000000")
@NotNull(message = "合同产值不能为空")
private BigDecimal contractAmount;
@Schema(description = "工程总面积", requiredMode = Schema.RequiredMode.REQUIRED, example = "30000")
@@ -44,12 +47,12 @@ public class ProjectSaveReqVO {
@Size(max = 200, message = "建设单位长度不能超过 200 个字符")
private String constructionUnitName;
@Schema(description = "联系人", example = "张三")
@Size(max = 64, message = "联系人长度不能超过 64 个字符")
@Schema(description = "建设单位联系人", example = "张三")
@Size(max = 64, message = "建设单位联系人长度不能超过 64 个字符")
private String contactName;
@Schema(description = "联系方式", example = "13800000000")
@Size(max = 32, message = "联系方式长度不能超过 32 个字符")
@Schema(description = "建设单位联系电话", example = "13800000000")
@Size(max = 32, message = "建设单位联系电话长度不能超过 32 个字符")
private String contactPhone;
@Schema(description = "合同签订日期", example = "2026-04-14")

View File

@@ -51,7 +51,7 @@ public class ProjectOutputReportController {
}
@GetMapping("/project-lead-quarter-output/export-excel")
@Operation(summary = "导出项目负责人年度季度计取表")
@Operation(summary = "导出工程负责人年度季度计取表")
@PreAuthorize("@ss.hasPermission('tjt:report-project-quarter:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportProjectLeadQuarterOutputExcel(HttpServletResponse response,

View File

@@ -5,7 +5,7 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 项目负责人年度季度计取表导出 Request VO")
@Schema(description = "管理后台 - 工程负责人年度季度计取表导出 Request VO")
@Data
public class ProjectLeadQuarterOutputExportReqVO {

View File

@@ -18,7 +18,7 @@ public class ProjectOverviewExcelRespVO {
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("规划内容")
@ExcelProperty("项目任务包")
private String planningContent;
@ExcelProperty("工程进度情况及其它说明")

View File

@@ -22,7 +22,7 @@ public class SpecialtyRoleSplitRespVO {
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "规划内容")
@Schema(description = "项目任务包")
private String planningContent;
@Schema(description = "专业编码")

View File

@@ -25,6 +25,8 @@ public class ProjectPlanningDO extends TenantBaseDO {
private Long projectId;
private Integer sortNo;
private String ownershipType;
private String calculationMethod;
@@ -33,10 +35,20 @@ public class ProjectPlanningDO extends TenantBaseDO {
private BigDecimal planningAmount;
private BigDecimal contractValueQuantity;
private BigDecimal contractValueUnitPrice;
private BigDecimal managementFeeRate;
private BigDecimal managementFee;
private BigDecimal vatRate;
private BigDecimal vatAmount;
private BigDecimal projectBudgetOutputValue;
private String implementationTeam;
private Integer planningStartYear;

View File

@@ -28,15 +28,19 @@ public class ProjectDO extends TenantBaseDO {
@TableId
private Long id;
/**
* 工程名称
* 项目名称
*/
private String projectName;
/**
* 排序
*/
private Integer sortNo;
/**
* 是否签订合同
*/
private Boolean contractSignedFlag;
/**
* 合同金额
* 合同产值
*/
private BigDecimal contractAmount;
/**
@@ -48,11 +52,11 @@ public class ProjectDO extends TenantBaseDO {
*/
private String constructionUnitName;
/**
* 联系人
* 建设单位联系人
*/
private String contactName;
/**
* 联系方式
* 建设单位联系电话
*/
private String contactPhone;
/**

View File

@@ -25,7 +25,8 @@ public interface ProjectPlanningMapper extends BaseMapperX<ProjectPlanningDO> {
.likeIfPresent(ProjectPlanningDO::getPlanningContent, reqVO.getPlanningContent())
.eqIfPresent(ProjectPlanningDO::getPlanningStartYear, reqVO.getPlanningStartYear())
.betweenIfPresent(ProjectPlanningDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ProjectPlanningDO::getId));
.orderByAsc(ProjectPlanningDO::getSortNo)
.orderByAsc(ProjectPlanningDO::getId));
}
default List<ProjectPlanningDO> selectListByProjectId(Long projectId) {
@@ -34,4 +35,11 @@ public interface ProjectPlanningMapper extends BaseMapperX<ProjectPlanningDO> {
.orderByDesc(ProjectPlanningDO::getId));
}
default List<ProjectPlanningDO> selectDisplayListByProjectId(Long projectId) {
return selectList(new LambdaQueryWrapperX<ProjectPlanningDO>()
.eq(ProjectPlanningDO::getProjectId, projectId)
.orderByAsc(ProjectPlanningDO::getSortNo)
.orderByAsc(ProjectPlanningDO::getId));
}
}

View File

@@ -22,7 +22,8 @@ public interface ProjectMapper extends BaseMapperX<ProjectDO> {
.eqIfPresent(ProjectDO::getProjectStartYear, reqVO.getProjectStartYear())
.eqIfPresent(ProjectDO::getProjectStatus, reqVO.getProjectStatus())
.betweenIfPresent(ProjectDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ProjectDO::getId));
.orderByAsc(ProjectDO::getSortNo)
.orderByAsc(ProjectDO::getId));
}
}

View File

@@ -33,7 +33,7 @@ public final class OutputSplitBizConstants {
public static final String ROLE_ENGINEERING_PRINCIPAL = "engineering_principal";
public static final List<SpecialtyItem> ASSIGNMENT_SPECIALTY_ITEMS = Arrays.asList(
new SpecialtyItem(SPECIALTY_PROJECT_LEAD, "项目经理/项目负责人", 0),
new SpecialtyItem(SPECIALTY_PROJECT_LEAD, "项目经理/工程负责人", 0),
new SpecialtyItem(SPECIALTY_ARCH, "建筑", 1),
new SpecialtyItem(SPECIALTY_DECOR, "装饰", 2),
new SpecialtyItem(SPECIALTY_STRUCT, "结构", 3),
@@ -63,7 +63,7 @@ public final class OutputSplitBizConstants {
public static final List<RoleItem> PROJECT_LEAD_ROLE_ITEMS = Arrays.asList(
new RoleItem(ROLE_PROJECT_MANAGER, "项目经理", 1),
new RoleItem(ROLE_ENGINEERING_PRINCIPAL, "项目负责人", 2)
new RoleItem(ROLE_ENGINEERING_PRINCIPAL, "工程负责人", 2)
);
private OutputSplitBizConstants() {

View File

@@ -133,11 +133,13 @@ public class EmployeeServiceImpl implements EmployeeService {
if (officeIds == null || officeIds.isEmpty()) {
return Collections.emptyMap();
}
officeIds.removeIf(Objects::isNull);
if (officeIds.isEmpty()) {
Set<Long> validOfficeIds = officeIds.stream()
.filter(Objects::nonNull)
.collect(java.util.stream.Collectors.toSet());
if (validOfficeIds.isEmpty()) {
return Collections.emptyMap();
}
return CollectionUtils.convertMap(officeMapper.selectBatchIds(officeIds), OfficeDO::getId);
return CollectionUtils.convertMap(officeMapper.selectBatchIds(validOfficeIds), OfficeDO::getId);
}
private EmployeeRespVO toRespVO(EmployeeDO employee, Map<Long, OfficeDO> officeMap) {

View File

@@ -51,6 +51,7 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
private static final int AMOUNT_SCALE = 2;
private static final int RATIO_SCALE = 4;
private static final int FACTOR_SCALE = 2;
private static final int QUANTITY_SCALE = 4;
private static final BigDecimal ZERO_AMOUNT = BigDecimal.ZERO.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
private static final BigDecimal ZERO_RATIO = BigDecimal.ZERO.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
@@ -142,7 +143,7 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
@Override
public List<ProjectPlanningDO> getProjectPlanningListByProjectId(Long projectId) {
validateProjectExists(projectId);
return projectPlanningMapper.selectListByProjectId(projectId);
return projectPlanningMapper.selectDisplayListByProjectId(projectId);
}
@Override
@@ -197,14 +198,22 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
}
private void prepareProjectPlanning(ProjectPlanningDO planning, ProjectDO project) {
if (planning.getSortNo() == null) {
planning.setSortNo(0);
}
if (planning.getPlanningStartYear() == null) {
planning.setPlanningStartYear(project.getProjectStartYear());
}
if (planning.getReviewOutsourceFlag() == null) {
planning.setReviewOutsourceFlag(Boolean.FALSE);
}
planning.setPlanningAmount(amount(planning.getPlanningAmount()));
planning.setContractValueQuantity(quantity(planning.getContractValueQuantity()));
planning.setContractValueUnitPrice(quantity(planning.getContractValueUnitPrice()));
planning.setPlanningAmount(multiplyAmount(
planning.getContractValueQuantity(),
planning.getContractValueUnitPrice()));
planning.setManagementFeeRate(ratio(planning.getManagementFeeRate()));
planning.setVatRate(ratio(planning.getVatRate()));
if (planning.getPlanningArea() == null) {
planning.setPlanningArea(project.getTotalConstructionArea());
}
@@ -240,6 +249,10 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
private void calculateProjectPlanning(ProjectPlanningDO planning) {
planning.setManagementFee(multiplyAmount(planning.getPlanningAmount(), planning.getManagementFeeRate()));
planning.setVatAmount(multiplyAmount(planning.getPlanningAmount(), planning.getVatRate()));
planning.setProjectBudgetOutputValue(amount(planning.getPlanningAmount()
.subtract(planning.getManagementFee())
.subtract(planning.getVatAmount())));
planning.setContractUnitPrice(divideAmount(planning.getPlanningAmount(), planning.getPlanningArea()));
planning.setTotalAdjustmentFactor(ZERO_RATIO);
planning.setAssessmentArea(ZERO_AMOUNT);
@@ -409,6 +422,11 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
return value == null ? null : factor(value);
}
private BigDecimal quantity(BigDecimal value) {
return value == null ? BigDecimal.ZERO.setScale(QUANTITY_SCALE, RoundingMode.HALF_UP)
: value.setScale(QUANTITY_SCALE, RoundingMode.HALF_UP);
}
private BigDecimal ratio(BigDecimal value) {
return value == null ? ZERO_RATIO : value.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
}

View File

@@ -64,7 +64,8 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
.eqIfPresent(ProjectDO::getContractSignedFlag, pageReqVO.getContractSignedFlag())
.eqIfPresent(ProjectDO::getProjectStartYear, pageReqVO.getProjectStartYear())
.betweenIfPresent(ProjectDO::getCreateTime, pageReqVO.getCreateTime())
.orderByDesc(ProjectDO::getId));
.orderByAsc(ProjectDO::getSortNo)
.orderByAsc(ProjectDO::getId));
if (pageResult.getList().isEmpty()) {
return new PageResult<>(Collections.emptyList(), pageResult.getTotal());
}
@@ -123,6 +124,7 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
ProjectProfitRespVO respVO = new ProjectProfitRespVO();
respVO.setProjectId(project.getId());
respVO.setProjectName(project.getProjectName());
respVO.setSortNo(project.getSortNo());
respVO.setContractSignedFlag(project.getContractSignedFlag());
respVO.setContractAmount(contractAmount);
respVO.setFinalSettlementAmount(finalSettlementAmount);

View File

@@ -50,7 +50,7 @@ public class ProjectServiceImpl implements ProjectService {
private static final String ROLE_CODE_PROJECT_MANAGER = "project_manager";
private static final String ROLE_CODE_ENGINEERING_PRINCIPAL = "engineering_principal";
private static final String ROLE_NAME_PROJECT_MANAGER = "项目经理";
private static final String ROLE_NAME_ENGINEERING_PRINCIPAL = "项目负责人";
private static final String ROLE_NAME_ENGINEERING_PRINCIPAL = "工程负责人";
private static final String STATUS_IN_PROGRESS = "进行中";
private static final String STATUS_COMPLETED = "完成";
private static final String STATUS_PAUSED = "暂停";
@@ -147,6 +147,9 @@ public class ProjectServiceImpl implements ProjectService {
if (project.getArchiveTime() == null && dbProject != null) {
project.setArchiveTime(dbProject.getArchiveTime());
}
if (project.getSortNo() == null) {
project.setSortNo(dbProject == null || dbProject.getSortNo() == null ? 0 : dbProject.getSortNo());
}
}
private void saveProjectRolePersons(Long projectId, List<ProjectRolePersonSaveReqVO> reqList) {