异常优化

This commit is contained in:
lzm
2026-06-03 18:10:03 +08:00
parent ac3b1050cb
commit 33c5fe89b6
5 changed files with 83 additions and 56 deletions

View File

@@ -0,0 +1,48 @@
package cn.iocoder.lyzsys.module.tjt.service.outputsplit;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.outputsplit.ProjectOutputSplitDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planning.ProjectPlanningDO;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 页面 4 拆分比例默认值构造器。
*
* <p>所有“没有拆分记录时的默认比例”都从这里生成,避免页面、专业内分配、报表之间规则漂移。</p>
*
* @author Codex
*/
public final class ProjectOutputSplitDefaults {
private static final int RATIO_SCALE = 4;
private static final BigDecimal ZERO_RATIO = BigDecimal.ZERO.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
private static final BigDecimal ONE_RATIO = BigDecimal.ONE.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
private ProjectOutputSplitDefaults() {
}
public static ProjectOutputSplitDO build(ProjectPlanningDO planning) {
return build(planning, 0);
}
public static ProjectOutputSplitDO build(ProjectPlanningDO planning, Integer fallbackYear) {
ProjectOutputSplitDO outputSplit = new ProjectOutputSplitDO();
if (planning != null) {
outputSplit.setProjectId(planning.getProjectId());
outputSplit.setPlanningId(planning.getId());
outputSplit.setYear(planning.getPlanningStartYear() == null ? fallbackYear : planning.getPlanningStartYear());
}
outputSplit.setProjectLeadRatio(ZERO_RATIO);
outputSplit.setOfficeRatio(ONE_RATIO);
outputSplit.setArchRatio(ONE_RATIO);
outputSplit.setDecorRatio(ZERO_RATIO);
outputSplit.setStructRatio(ZERO_RATIO);
outputSplit.setWaterRatio(ZERO_RATIO);
outputSplit.setElecRatio(ZERO_RATIO);
outputSplit.setHvacRatio(ZERO_RATIO);
outputSplit.setDigitalRatio(ZERO_RATIO);
return outputSplit;
}
}

View File

@@ -62,7 +62,7 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
ProjectDO project = validateProjectExists(planning.getProjectId()); ProjectDO project = validateProjectExists(planning.getProjectId());
ProjectOutputSplitDO outputSplit = projectOutputSplitMapper.selectByPlanningId(planningId); ProjectOutputSplitDO outputSplit = projectOutputSplitMapper.selectByPlanningId(planningId);
if (outputSplit == null) { if (outputSplit == null) {
outputSplit = buildDefaultOutputSplit(planning); outputSplit = ProjectOutputSplitDefaults.build(planning);
} }
return buildRespVO(outputSplit, planning, project); return buildRespVO(outputSplit, planning, project);
} }
@@ -112,7 +112,7 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
if (outputSplit != null) { if (outputSplit != null) {
return outputSplit; return outputSplit;
} }
ProjectOutputSplitDO createObj = buildDefaultOutputSplit(planning); ProjectOutputSplitDO createObj = ProjectOutputSplitDefaults.build(planning);
try { try {
projectOutputSplitMapper.insert(createObj); projectOutputSplitMapper.insert(createObj);
return createObj; return createObj;
@@ -205,23 +205,6 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
return project; return project;
} }
private ProjectOutputSplitDO buildDefaultOutputSplit(ProjectPlanningDO planning) {
ProjectOutputSplitDO outputSplit = new ProjectOutputSplitDO();
outputSplit.setProjectId(planning.getProjectId());
outputSplit.setPlanningId(planning.getId());
outputSplit.setYear(getPlanningYear(planning));
outputSplit.setProjectLeadRatio(ZERO_RATIO);
outputSplit.setOfficeRatio(ONE_RATIO);
outputSplit.setArchRatio(ONE_RATIO);
outputSplit.setDecorRatio(ZERO_RATIO);
outputSplit.setStructRatio(ZERO_RATIO);
outputSplit.setWaterRatio(ZERO_RATIO);
outputSplit.setElecRatio(ZERO_RATIO);
outputSplit.setHvacRatio(ZERO_RATIO);
outputSplit.setDigitalRatio(ZERO_RATIO);
return outputSplit;
}
private Integer getPlanningYear(ProjectPlanningDO planning) { private Integer getPlanningYear(ProjectPlanningDO planning) {
return planning.getPlanningStartYear() == null ? 0 : planning.getPlanningStartYear(); return planning.getPlanningStartYear() == null ? 0 : planning.getPlanningStartYear();
} }

View File

@@ -30,6 +30,7 @@ import cn.iocoder.lyzsys.module.tjt.dal.mysql.yearkvalue.YearKValueMapper;
import cn.iocoder.lyzsys.module.tjt.enums.OutputSplitBizConstants; import cn.iocoder.lyzsys.module.tjt.enums.OutputSplitBizConstants;
import cn.iocoder.lyzsys.module.tjt.enums.ProjectPlanningBizTypeConstants; import cn.iocoder.lyzsys.module.tjt.enums.ProjectPlanningBizTypeConstants;
import cn.iocoder.lyzsys.module.tjt.enums.ProjectStatusEnum; import cn.iocoder.lyzsys.module.tjt.enums.ProjectStatusEnum;
import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitDefaults;
import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService; import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService;
import cn.iocoder.lyzsys.module.tjt.service.planningguidedetail.ProjectPlanningGuideDetailService; import cn.iocoder.lyzsys.module.tjt.service.planningguidedetail.ProjectPlanningGuideDetailService;
import cn.iocoder.lyzsys.module.tjt.service.report.builder.*; import cn.iocoder.lyzsys.module.tjt.service.report.builder.*;
@@ -405,10 +406,10 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
List<ProjectPlanningDO> planningList = Collections.singletonList(anchorPlanning); List<ProjectPlanningDO> planningList = Collections.singletonList(anchorPlanning);
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList); Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList);
List<ProjectPlanningDO> relevantPlanningList = getSpecialtyPersonRelevantPlanningList(anchorPlanning); List<ProjectPlanningDO> relevantPlanningList = getSpecialtyPersonRelevantPlanningList(anchorPlanning);
Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(relevantPlanningList); Map<Long, ProjectOutputSplitDO> outputSplitMap = getDefaultedOutputSplitMap(relevantPlanningList);
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList); Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList);
List<SpecialtyRoleSplitRespVO> anchorRoleList = List<SpecialtyRoleSplitRespVO> anchorRoleList =
specialtyRoleSplitService.getSpecialtyRoleSplitListByPlanningId(anchorPlanning.getId()); roleSplitMap.getOrDefault(anchorPlanning.getId(), Collections.emptyList());
SpecialtyPersonOutputPreviewRespVO respVO = new SpecialtyPersonOutputPreviewRespVO(); SpecialtyPersonOutputPreviewRespVO respVO = new SpecialtyPersonOutputPreviewRespVO();
respVO.setPlanningId(anchorPlanning.getId()); respVO.setPlanningId(anchorPlanning.getId());
@@ -647,13 +648,11 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
List<ProjectPlanningDO> planningList = Collections.singletonList(anchorPlanning); List<ProjectPlanningDO> planningList = Collections.singletonList(anchorPlanning);
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList); Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList);
List<ProjectPlanningDO> relevantPlanningList = getSpecialtyPersonRelevantPlanningList(anchorPlanning); List<ProjectPlanningDO> relevantPlanningList = getSpecialtyPersonRelevantPlanningList(anchorPlanning);
Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(relevantPlanningList); Map<Long, ProjectOutputSplitDO> outputSplitMap = getDefaultedOutputSplitMap(relevantPlanningList);
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList); Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList);
List<ProjectRolePersonDO> projectRolePersons = projectRolePersonMapper.selectListByProjectId(project.getId()); List<ProjectRolePersonDO> projectRolePersons = projectRolePersonMapper.selectListByProjectId(project.getId());
List<SpecialtyRoleSplitRespVO> anchorRoleList = roleSplitMap.get(anchorPlanning.getId()); List<SpecialtyRoleSplitRespVO> anchorRoleList =
if (anchorRoleList == null) { roleSplitMap.getOrDefault(anchorPlanning.getId(), Collections.emptyList());
anchorRoleList = specialtyRoleSplitService.getSpecialtyRoleSplitListByPlanningId(anchorPlanning.getId());
}
SpecialtyRoleSplitRespVO projectManagerRow = findRoleRow(anchorRoleList, SpecialtyRoleSplitRespVO projectManagerRow = findRoleRow(anchorRoleList,
OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD, OutputSplitBizConstants.ROLE_PROJECT_MANAGER); OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD, OutputSplitBizConstants.ROLE_PROJECT_MANAGER);
SpecialtyRoleSplitRespVO engineeringPrincipalRow = findRoleRow(anchorRoleList, SpecialtyRoleSplitRespVO engineeringPrincipalRow = findRoleRow(anchorRoleList,
@@ -734,7 +733,7 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
Map<Long, ProjectDO> projectMap = getProjectMap(planningList); Map<Long, ProjectDO> projectMap = getProjectMap(planningList);
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList); Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList);
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(planningList); Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(planningList);
Map<Long, ProjectOutputSplitDO> outputSplitMap = getExistingOutputSplitMap(planningList); Map<Long, ProjectOutputSplitDO> outputSplitMap = getDefaultedOutputSplitMap(planningList);
Map<Long, ProjectOverviewAccumulator> accumulatorMap = new LinkedHashMap<>(); Map<Long, ProjectOverviewAccumulator> accumulatorMap = new LinkedHashMap<>();
for (ProjectPlanningDO planning : planningList) { for (ProjectPlanningDO planning : planningList) {
@@ -810,7 +809,7 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
List<ProjectPlanningDO> relevantPlanningList = getEmployeeOutputSummaryPlanningList(reqVO.getYear(), employeeIds); List<ProjectPlanningDO> relevantPlanningList = getEmployeeOutputSummaryPlanningList(reqVO.getYear(), employeeIds);
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(relevantPlanningList); Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(relevantPlanningList);
Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(relevantPlanningList); Map<Long, ProjectOutputSplitDO> outputSplitMap = getDefaultedOutputSplitMap(relevantPlanningList);
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList); Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList);
Map<Long, EmployeeAccumulator> accumulatorMap = new LinkedHashMap<>(); Map<Long, EmployeeAccumulator> accumulatorMap = new LinkedHashMap<>();
employeeIds.forEach(id -> accumulatorMap.put(id, new EmployeeAccumulator())); employeeIds.forEach(id -> accumulatorMap.put(id, new EmployeeAccumulator()));
@@ -1721,32 +1720,13 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
private ProjectOutputSplitDO resolveQuarterOutputSplit(ProjectPlanningDO planning, private ProjectOutputSplitDO resolveQuarterOutputSplit(ProjectPlanningDO planning,
Map<Long, ProjectOutputSplitDO> outputSplitMap) { Map<Long, ProjectOutputSplitDO> outputSplitMap) {
if (planning == null) { if (planning == null) {
return buildQuarterOutputDefaultSplit(null); return ProjectOutputSplitDefaults.build(null);
} }
ProjectOutputSplitDO outputSplit = outputSplitMap == null ? null : outputSplitMap.get(planning.getId()); ProjectOutputSplitDO outputSplit = outputSplitMap == null ? null : outputSplitMap.get(planning.getId());
if (outputSplit != null) { if (outputSplit != null) {
return outputSplit; return outputSplit;
} }
return buildQuarterOutputDefaultSplit(planning); return ProjectOutputSplitDefaults.build(planning, resolveReportYear(planning));
}
private ProjectOutputSplitDO buildQuarterOutputDefaultSplit(ProjectPlanningDO planning) {
ProjectOutputSplitDO outputSplit = new ProjectOutputSplitDO();
if (planning != null) {
outputSplit.setProjectId(planning.getProjectId());
outputSplit.setPlanningId(planning.getId());
outputSplit.setYear(resolveReportYear(planning));
}
outputSplit.setProjectLeadRatio(ZERO_RATIO);
outputSplit.setOfficeRatio(FULL_RATIO);
outputSplit.setArchRatio(FULL_RATIO);
outputSplit.setDecorRatio(ZERO_RATIO);
outputSplit.setStructRatio(ZERO_RATIO);
outputSplit.setWaterRatio(ZERO_RATIO);
outputSplit.setElecRatio(ZERO_RATIO);
outputSplit.setHvacRatio(ZERO_RATIO);
outputSplit.setDigitalRatio(ZERO_RATIO);
return outputSplit;
} }
private int designPartOrder(String designPart) { private int designPartOrder(String designPart) {
@@ -1797,13 +1777,15 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
.collect(Collectors.groupingBy(ProjectPlanningQuarterDO::getPlanningId, LinkedHashMap::new, Collectors.toList())); .collect(Collectors.groupingBy(ProjectPlanningQuarterDO::getPlanningId, LinkedHashMap::new, Collectors.toList()));
} }
private Map<Long, ProjectOutputSplitDO> getOutputSplitMap(Collection<ProjectPlanningDO> planningList) { private Map<Long, ProjectOutputSplitDO> getDefaultedOutputSplitMap(Collection<ProjectPlanningDO> planningList) {
if (planningList == null || planningList.isEmpty()) { if (planningList == null || planningList.isEmpty()) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
Map<Long, ProjectOutputSplitDO> map = new LinkedHashMap<>(); Map<Long, ProjectOutputSplitDO> map = new LinkedHashMap<>(getExistingOutputSplitMap(planningList));
for (ProjectPlanningDO planning : planningList) { for (ProjectPlanningDO planning : planningList) {
map.put(planning.getId(), projectOutputSplitService.getOrCreateProjectOutputSplit(planning.getId())); if (planning != null && planning.getId() != null && !map.containsKey(planning.getId())) {
map.put(planning.getId(), ProjectOutputSplitDefaults.build(planning, resolveReportYear(planning)));
}
} }
return map; return map;
} }
@@ -1824,7 +1806,7 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
.map(ProjectPlanningDO::getId) .map(ProjectPlanningDO::getId)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toList()); .collect(Collectors.toList());
return specialtyRoleSplitService.getExistingSpecialtyRoleSplitListMapByPlanningIds(planningIds); return specialtyRoleSplitService.getReadonlySpecialtyRoleSplitListMapByPlanningIds(planningIds);
} }
private Map<Long, ProjectDO> getProjectMap(Collection<ProjectPlanningDO> planningList) { private Map<Long, ProjectDO> getProjectMap(Collection<ProjectPlanningDO> planningList) {

View File

@@ -20,6 +20,8 @@ public interface SpecialtyRoleSplitService {
Map<Long, List<SpecialtyRoleSplitRespVO>> getExistingSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds); Map<Long, List<SpecialtyRoleSplitRespVO>> getExistingSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds);
Map<Long, List<SpecialtyRoleSplitRespVO>> getReadonlySpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds);
void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO); void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO);
void deleteByOutputSplitId(Long outputSplitId); void deleteByOutputSplitId(Long outputSplitId);

View File

@@ -16,6 +16,7 @@ import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplit.SpecialtyRoleSp
import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplitperson.SpecialtyRoleSplitPersonMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplitperson.SpecialtyRoleSplitPersonMapper;
import cn.iocoder.lyzsys.module.tjt.enums.OutputSplitBizConstants; import cn.iocoder.lyzsys.module.tjt.enums.OutputSplitBizConstants;
import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService; import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService;
import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitDefaults;
import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService; import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -66,16 +67,21 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
@Override @Override
public Map<Long, List<SpecialtyRoleSplitRespVO>> getSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds) { public Map<Long, List<SpecialtyRoleSplitRespVO>> getSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds) {
return getSpecialtyRoleSplitListMapByPlanningIds(planningIds, true); return getSpecialtyRoleSplitListMapByPlanningIds(planningIds, true, false);
} }
@Override @Override
public Map<Long, List<SpecialtyRoleSplitRespVO>> getExistingSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds) { public Map<Long, List<SpecialtyRoleSplitRespVO>> getExistingSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds) {
return getSpecialtyRoleSplitListMapByPlanningIds(planningIds, false); return getSpecialtyRoleSplitListMapByPlanningIds(planningIds, false, false);
}
@Override
public Map<Long, List<SpecialtyRoleSplitRespVO>> getReadonlySpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds) {
return getSpecialtyRoleSplitListMapByPlanningIds(planningIds, false, true);
} }
private Map<Long, List<SpecialtyRoleSplitRespVO>> getSpecialtyRoleSplitListMapByPlanningIds( private Map<Long, List<SpecialtyRoleSplitRespVO>> getSpecialtyRoleSplitListMapByPlanningIds(
Collection<Long> planningIds, boolean createMissingOutputSplit) { Collection<Long> planningIds, boolean createMissingOutputSplit, boolean defaultMissingOutputSplit) {
if (planningIds == null || planningIds.isEmpty()) { if (planningIds == null || planningIds.isEmpty()) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
@@ -112,6 +118,12 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
projectOutputSplitService.getOrCreateProjectOutputSplit(planning.getId())); projectOutputSplitService.getOrCreateProjectOutputSplit(planning.getId()));
} }
} }
} else if (defaultMissingOutputSplit) {
for (ProjectPlanningDO planning : planningMap.values()) {
if (!outputSplitMap.containsKey(planning.getId())) {
outputSplitMap.put(planning.getId(), ProjectOutputSplitDefaults.build(planning));
}
}
} }
List<Long> outputSplitIds = outputSplitMap.values().stream() List<Long> outputSplitIds = outputSplitMap.values().stream()