diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java index 469bb08..31ad597 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java @@ -600,8 +600,8 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic List planningList = getProjectOverviewPlanningList(reportYear, employeeIds); Map projectMap = getProjectMap(planningList); Map> quarterMap = getQuarterMap(planningList); - Map outputSplitMap = getOutputSplitMap(planningList); Map> roleSplitMap = getRoleSplitMap(planningList); + Map outputSplitMap = getExistingOutputSplitMap(planningList); Map accumulatorMap = new LinkedHashMap<>(); for (ProjectPlanningDO planning : planningList) { @@ -945,19 +945,33 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic if (reportYear == null || employeeIds == null || employeeIds.isEmpty()) { return Collections.emptyList(); } - Set yearPlanningIds = getYearAmountPlanningIds(reportYear); - if (yearPlanningIds.isEmpty()) { - return Collections.emptyList(); - } - List personList = specialtyRoleSplitPersonMapper - .selectListByPlanningIdsAndEmployeeIds(yearPlanningIds, employeeIds); - if (personList.isEmpty()) { - return Collections.emptyList(); - } - Set matchedPlanningIds = personList.stream() + Set candidatePlanningIds = specialtyRoleSplitPersonMapper.selectListByEmployeeIds(employeeIds).stream() .map(SpecialtyRoleSplitPersonDO::getPlanningId) .filter(Objects::nonNull) .collect(Collectors.toCollection(LinkedHashSet::new)); + + Set projectLeadProjectIds = projectRolePersonMapper.selectListByEmployeeIds(employeeIds).stream() + .filter(item -> Objects.equals(item.getRoleCode(), OutputSplitBizConstants.ROLE_PROJECT_MANAGER) + || Objects.equals(item.getRoleCode(), OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL)) + .map(ProjectRolePersonDO::getProjectId) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + if (!projectLeadProjectIds.isEmpty()) { + projectPlanningMapper.selectList(new LambdaQueryWrapperX() + .in(ProjectPlanningDO::getProjectId, projectLeadProjectIds) + .in(ProjectPlanningDO::getOwnershipType, Arrays.asList( + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR, + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_COMPREHENSIVE, + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_SPECIAL_SUBCONTRACT, + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_SOURCE_COOP_SUBCONTRACT + ))) + .stream() + .map(ProjectPlanningDO::getId) + .filter(Objects::nonNull) + .forEach(candidatePlanningIds::add); + } + + Set matchedPlanningIds = getYearAmountPlanningIds(reportYear, candidatePlanningIds); if (matchedPlanningIds.isEmpty()) { return Collections.emptyList(); } @@ -1023,6 +1037,42 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic .collect(Collectors.toCollection(LinkedHashSet::new)); } + private Set getYearAmountPlanningIds(Integer reportYear, Collection planningIds) { + if (reportYear == null || planningIds == null || planningIds.isEmpty()) { + return Collections.emptySet(); + } + Set result = new LinkedHashSet<>(); + for (List partition : partitionIds(planningIds, 1000)) { + projectPlanningQuarterMapper.selectList(new LambdaQueryWrapperX() + .in(ProjectPlanningQuarterDO::getPlanningId, partition) + .eq(ProjectPlanningQuarterDO::getDistributionYear, reportYear) + .gt(ProjectPlanningQuarterDO::getDistributionAmount, BigDecimal.ZERO)) + .stream() + .map(ProjectPlanningQuarterDO::getPlanningId) + .filter(Objects::nonNull) + .forEach(result::add); + } + return result; + } + + private List> partitionIds(Collection ids, int partitionSize) { + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + List normalizedIds = ids.stream() + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + if (normalizedIds.isEmpty()) { + return Collections.emptyList(); + } + List> result = new ArrayList<>(); + for (int start = 0; start < normalizedIds.size(); start += partitionSize) { + result.add(normalizedIds.subList(start, Math.min(start + partitionSize, normalizedIds.size()))); + } + return result; + } + private List buildProjectQuarterOutputRows( List planningList, Map> quarterMap, Map outputSplitMap, Integer reportYear) { diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java index 5d8203c..6528938 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java @@ -157,14 +157,17 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b)); List result = new ArrayList<>(); BigDecimal assessmentOutputValue = planning.getAssessmentOutputValue(); + boolean useDefaultProjectLeadRoleRatio = shouldUseDefaultProjectLeadRoleRatio(dbMap, projectRolePersonMap); for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) { BigDecimal specialtyAmount = getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyItem.getCode()); Map defaultRoleRatioMap = buildDefaultRoleRatioMap( specialtyItem.getCode(), projectRolePersonMap); for (OutputSplitBizConstants.RoleItem roleItem : OutputSplitBizConstants.getRoleItems(specialtyItem.getCode())) { SpecialtyRoleSplitDO dbItem = dbMap.get(specialtyItem.getCode() + ":" + roleItem.getCode()); - BigDecimal roleRatio = getStoredRoleRatio( - dbItem, specialtyItem.getCode(), roleItem.getCode(), defaultRoleRatioMap); + BigDecimal roleRatio = useDefaultProjectLeadRoleRatio + && OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyItem.getCode()) + ? ratio(defaultRoleRatioMap.get(roleItem.getCode())) + : getStoredRoleRatio(dbItem, specialtyItem.getCode(), roleItem.getCode(), defaultRoleRatioMap); BigDecimal roleAmount = multiplyAmount(specialtyAmount, roleRatio); List persons = buildRespPersons( dbItem, specialtyItem.getCode(), roleItem.getCode(), roleAmount, projectRolePersonMap, personMap); @@ -193,6 +196,33 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService return result; } + private boolean shouldUseDefaultProjectLeadRoleRatio(Map dbMap, + Map> projectRolePersonMap) { + if (projectRolePersonMap == null || projectRolePersonMap.isEmpty()) { + return false; + } + boolean hasProjectLeadPerson = (projectRolePersonMap.get(OutputSplitBizConstants.ROLE_PROJECT_MANAGER) != null + && !projectRolePersonMap.get(OutputSplitBizConstants.ROLE_PROJECT_MANAGER).isEmpty()) + || (projectRolePersonMap.get(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL) != null + && !projectRolePersonMap.get(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL).isEmpty()); + if (!hasProjectLeadPerson || dbMap == null || dbMap.isEmpty()) { + return false; + } + BigDecimal storedTotal = ZERO_RATIO; + boolean hasStoredProjectLead = false; + for (String roleCode : Arrays.asList( + OutputSplitBizConstants.ROLE_PROJECT_MANAGER, + OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL)) { + SpecialtyRoleSplitDO dbItem = dbMap.get(OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD + ":" + roleCode); + if (dbItem == null) { + continue; + } + hasStoredProjectLead = true; + storedTotal = storedTotal.add(ratio(dbItem.getRoleRatio())).setScale(RATIO_SCALE, RoundingMode.HALF_UP); + } + return hasStoredProjectLead && storedTotal.compareTo(ZERO_RATIO) == 0; + } + @Override @Transactional(rollbackFor = Exception.class) public void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO) { @@ -217,6 +247,9 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService BigDecimal assessmentOutputValue, boolean strictValidate) { for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) { + if (!groupedMap.containsKey(specialtyItem.getCode())) { + continue; + } Map roleMap = groupedMap.getOrDefault( specialtyItem.getCode(), new LinkedHashMap<>()); BigDecimal roleTotal = ZERO_RATIO;