0512新功能优化

This commit is contained in:
lzm
2026-05-12 10:31:20 +08:00
parent 1d26048bc1
commit c496f00fd2
45 changed files with 2179 additions and 149 deletions

View File

@@ -74,8 +74,9 @@ public class EmployeeController {
@RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "officeId", required = false) Long officeId, @RequestParam(value = "officeId", required = false) Long officeId,
@RequestParam(value = "status", required = false) String status, @RequestParam(value = "status", required = false) String status,
@RequestParam(value = "enabledFlag", required = false) Boolean enabledFlag) { @RequestParam(value = "enabledFlag", required = false) Boolean enabledFlag,
return success(employeeService.getEmployeeSimpleList(keyword, officeId, status, enabledFlag)); @RequestParam(value = "officeLeaderFlag", required = false) Boolean officeLeaderFlag) {
return success(employeeService.getEmployeeSimpleList(keyword, officeId, status, enabledFlag, officeLeaderFlag));
} }
} }

View File

@@ -22,4 +22,7 @@ public class EmployeePageReqVO extends PageParam {
@Schema(description = "是否启用", example = "true") @Schema(description = "是否启用", example = "true")
private Boolean enabledFlag; private Boolean enabledFlag;
@Schema(description = "是否所长", example = "false")
private Boolean officeLeaderFlag;
} }

View File

@@ -46,6 +46,9 @@ public class EmployeeRespVO {
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;
@Schema(description = "是否所长")
private Boolean officeLeaderFlag;
@Schema(description = "排序号") @Schema(description = "排序号")
private Integer sortNo; private Integer sortNo;

View File

@@ -64,6 +64,9 @@ public class EmployeeSaveReqVO {
@Size(max = 255, message = "备注长度不能超过 255 个字符") @Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark; private String remark;
@Schema(description = "是否所长", example = "false")
private Boolean officeLeaderFlag;
@Schema(description = "排序号", example = "1") @Schema(description = "排序号", example = "1")
private Integer sortNo; private Integer sortNo;

View File

@@ -28,4 +28,7 @@ public class EmployeeSimpleRespVO {
@Schema(description = "职称") @Schema(description = "职称")
private String jobTitle; private String jobTitle;
@Schema(description = "是否所长")
private Boolean officeLeaderFlag;
} }

View File

@@ -2,9 +2,7 @@ package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget;
import cn.iocoder.lyzsys.framework.common.pojo.CommonResult; import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult; import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetPageReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.*;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetRespVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget.EmployeeYearCostBudgetService; import cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget.EmployeeYearCostBudgetService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@@ -34,6 +32,14 @@ public class EmployeeYearCostBudgetController {
return success(employeeYearCostBudgetService.createEmployeeYearCostBudget(createReqVO)); return success(employeeYearCostBudgetService.createEmployeeYearCostBudget(createReqVO));
} }
@PostMapping("/generate")
@Operation(summary = "按年度生成员工年度成本预算")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:create')")
public CommonResult<EmployeeYearCostBudgetGenerateRespVO> generateEmployeeYearCostBudget(
@Valid @RequestBody EmployeeYearCostBudgetGenerateReqVO generateReqVO) {
return success(employeeYearCostBudgetService.generateEmployeeYearCostBudget(generateReqVO));
}
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "修改员工年度成本预算") @Operation(summary = "修改员工年度成本预算")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:update')") @PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:update')")

View File

@@ -0,0 +1,22 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 员工年度成本预算按年度生成 Request VO")
@Data
public class EmployeeYearCostBudgetGenerateReqVO {
@Schema(description = "预算年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
@NotNull(message = "预算年度不能为空")
private Integer budgetYear;
@Schema(description = "默认预计发生成本", example = "0")
@DecimalMin(value = "0", message = "默认预计发生成本不能小于 0")
private BigDecimal expectedCostAmount;
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 员工年度成本预算按年度生成 Response VO")
@Data
public class EmployeeYearCostBudgetGenerateRespVO {
@Schema(description = "预算年度")
private Integer budgetYear;
@Schema(description = "已启用员工数量")
private Integer totalEnabledEmployeeCount;
@Schema(description = "本次新增预算记录数量")
private Integer createdCount;
@Schema(description = "已存在并跳过的预算记录数量")
private Integer skippedCount;
}

View File

@@ -0,0 +1,78 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput;
import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo.*;
import cn.iocoder.lyzsys.module.tjt.service.employeeyearleaderoutput.EmployeeYearLeaderOutputService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.lyzsys.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 年度所长考核产值")
@RestController
@RequestMapping("/tjt/employee-year-leader-output")
@Validated
public class EmployeeYearLeaderOutputController {
@Resource
private EmployeeYearLeaderOutputService employeeYearLeaderOutputService;
@PostMapping("/create")
@Operation(summary = "创建年度所长考核产值")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-leader-output:create')")
public CommonResult<Long> createEmployeeYearLeaderOutput(
@Valid @RequestBody EmployeeYearLeaderOutputSaveReqVO createReqVO) {
return success(employeeYearLeaderOutputService.createEmployeeYearLeaderOutput(createReqVO));
}
@PostMapping("/generate")
@Operation(summary = "按年度生成年度所长考核产值")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-leader-output:create')")
public CommonResult<EmployeeYearLeaderOutputGenerateRespVO> generateEmployeeYearLeaderOutput(
@Valid @RequestBody EmployeeYearLeaderOutputGenerateReqVO generateReqVO) {
return success(employeeYearLeaderOutputService.generateEmployeeYearLeaderOutput(generateReqVO));
}
@PutMapping("/update")
@Operation(summary = "修改年度所长考核产值")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-leader-output:update')")
public CommonResult<Boolean> updateEmployeeYearLeaderOutput(
@Valid @RequestBody EmployeeYearLeaderOutputSaveReqVO updateReqVO) {
employeeYearLeaderOutputService.updateEmployeeYearLeaderOutput(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除年度所长考核产值")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-leader-output:delete')")
public CommonResult<Boolean> deleteEmployeeYearLeaderOutput(@RequestParam("id") Long id) {
employeeYearLeaderOutputService.deleteEmployeeYearLeaderOutput(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得年度所长考核产值详情")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-leader-output:query')")
public CommonResult<EmployeeYearLeaderOutputRespVO> getEmployeeYearLeaderOutput(@RequestParam("id") Long id) {
return success(employeeYearLeaderOutputService.getEmployeeYearLeaderOutput(id));
}
@GetMapping("/page")
@Operation(summary = "获得年度所长考核产值分页")
@PreAuthorize("@ss.hasPermission('tjt:employee-year-leader-output:query')")
public CommonResult<PageResult<EmployeeYearLeaderOutputRespVO>> getEmployeeYearLeaderOutputPage(
@Valid EmployeeYearLeaderOutputPageReqVO pageReqVO) {
return success(employeeYearLeaderOutputService.getEmployeeYearLeaderOutputPage(pageReqVO));
}
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 年度所长考核产值按年度生成 Request VO")
@Data
public class EmployeeYearLeaderOutputGenerateReqVO {
@Schema(description = "产值年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
@NotNull(message = "产值年度不能为空")
private Integer outputYear;
@Schema(description = "默认所长考核产值", example = "0")
@DecimalMin(value = "0", message = "默认所长考核产值不能小于 0")
private BigDecimal leaderOutputAmount;
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 年度所长考核产值按年度生成 Response VO")
@Data
public class EmployeeYearLeaderOutputGenerateRespVO {
@Schema(description = "产值年度")
private Integer outputYear;
@Schema(description = "已启用所长数量")
private Integer totalEnabledLeaderCount;
@Schema(description = "本次新增记录数量")
private Integer createdCount;
@Schema(description = "已存在并跳过的记录数量")
private Integer skippedCount;
}

View File

@@ -0,0 +1,25 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo;
import cn.iocoder.lyzsys.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 年度所长考核产值分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class EmployeeYearLeaderOutputPageReqVO extends PageParam {
@Schema(description = "员工 ID", example = "1")
private Long employeeId;
@Schema(description = "员工姓名", example = "")
private String employeeName;
@Schema(description = "产值年度", example = "2026")
private Integer outputYear;
@Schema(description = "是否启用", example = "true")
private Boolean enabledFlag;
}

View File

@@ -0,0 +1,40 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 年度所长考核产值 Response VO")
@Data
public class EmployeeYearLeaderOutputRespVO {
@Schema(description = "记录 ID", example = "1")
private Long id;
@Schema(description = "员工 ID")
private Long employeeId;
@Schema(description = "员工姓名")
private String employeeName;
@Schema(description = "产值年度")
private Integer outputYear;
@Schema(description = "所长考核产值")
private BigDecimal leaderOutputAmount;
@Schema(description = "备注")
private String remark;
@Schema(description = "排序号")
private Integer sortNo;
@Schema(description = "是否启用")
private Boolean enabledFlag;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,43 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 年度所长考核产值新增/修改 Request VO")
@Data
public class EmployeeYearLeaderOutputSaveReqVO {
@Schema(description = "记录 ID", example = "1")
private Long id;
@Schema(description = "员工 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "员工 ID 不能为空")
private Long employeeId;
@Schema(description = "员工姓名,后端根据 employeeId 回填", example = "张三")
@Size(max = 64, message = "员工姓名长度不能超过 64 个字符")
private String employeeName;
@Schema(description = "产值年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
@NotNull(message = "产值年度不能为空")
private Integer outputYear;
@Schema(description = "所长考核产值", requiredMode = Schema.RequiredMode.REQUIRED, example = "100000")
@NotNull(message = "所长考核产值不能为空")
private BigDecimal leaderOutputAmount;
@Schema(description = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
@Schema(description = "排序号", example = "1")
private Integer sortNo;
@Schema(description = "是否启用", example = "true")
private Boolean enabledFlag;
}

View File

@@ -28,6 +28,9 @@ public class ProjectProfitRespVO {
@Schema(description = "最终结算金额") @Schema(description = "最终结算金额")
private BigDecimal finalSettlementAmount; private BigDecimal finalSettlementAmount;
@Schema(description = "有效结算金额,最终结算金额大于 0 时取最终结算金额,否则取合同产值")
private BigDecimal effectiveSettlementAmount;
@Schema(description = "综合所协作金额") @Schema(description = "综合所协作金额")
private BigDecimal comprehensivePlanningAmount; private BigDecimal comprehensivePlanningAmount;

View File

@@ -1,12 +1,8 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.report; package cn.iocoder.lyzsys.module.tjt.controller.admin.report;
import cn.iocoder.lyzsys.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.lyzsys.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.EmployeeOutputSummaryExportReqVO; import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectBudgetExportReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.*;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectLeadQuarterOutputExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectOverviewExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectQuarterOutputExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.SpecialtyPersonOutputExportReqVO;
import cn.iocoder.lyzsys.module.tjt.service.report.ProjectOutputReportService; import cn.iocoder.lyzsys.module.tjt.service.report.ProjectOutputReportService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,6 +18,7 @@ import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
import static cn.iocoder.lyzsys.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.lyzsys.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.lyzsys.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 产值报表导出") @Tag(name = "管理后台 - 产值报表导出")
@RestController @RestController
@@ -69,6 +66,22 @@ public class ProjectOutputReportController {
projectOutputReportService.exportSpecialtyPersonOutputExcel(response, reqVO); projectOutputReportService.exportSpecialtyPersonOutputExcel(response, reqVO);
} }
@GetMapping("/specialty-person-output/preview")
@Operation(summary = "预览专业内人员年度季度计取表")
@PreAuthorize("@ss.hasAnyPermissions('tjt:report-specialty-person:query', 'tjt:report-specialty-person:export')")
public CommonResult<SpecialtyPersonOutputPreviewRespVO> getSpecialtyPersonOutputPreview(
@Valid SpecialtyPersonOutputPreviewReqVO reqVO) {
return success(projectOutputReportService.getSpecialtyPersonOutputPreview(reqVO));
}
@GetMapping("/project-overview/preview")
@Operation(summary = "预览项目总览表")
@PreAuthorize("@ss.hasAnyPermissions('tjt:report-summary:query', 'tjt:report-summary:export')")
public CommonResult<ProjectOverviewPreviewRespVO> getProjectOverviewPreview(
@Valid ProjectOverviewExportReqVO reqVO) {
return success(projectOutputReportService.getProjectOverviewPreview(reqVO));
}
@GetMapping("/project-overview/export-excel") @GetMapping("/project-overview/export-excel")
@Operation(summary = "导出项目总览表") @Operation(summary = "导出项目总览表")
@PreAuthorize("@ss.hasPermission('tjt:report-summary:export')") @PreAuthorize("@ss.hasPermission('tjt:report-summary:export')")
@@ -78,6 +91,14 @@ public class ProjectOutputReportController {
projectOutputReportService.exportProjectOverviewExcel(response, reqVO); projectOutputReportService.exportProjectOverviewExcel(response, reqVO);
} }
@GetMapping("/employee-output-summary/preview")
@Operation(summary = "预览员工个人考核产值汇总表")
@PreAuthorize("@ss.hasAnyPermissions('tjt:report-summary:query', 'tjt:report-summary:export')")
public CommonResult<EmployeeOutputSummaryPreviewRespVO> getEmployeeOutputSummaryPreview(
@Valid EmployeeOutputSummaryExportReqVO reqVO) {
return success(projectOutputReportService.getEmployeeOutputSummaryPreview(reqVO));
}
@GetMapping("/employee-output-summary/export-excel") @GetMapping("/employee-output-summary/export-excel")
@Operation(summary = "导出员工个人考核产值汇总表") @Operation(summary = "导出员工个人考核产值汇总表")
@PreAuthorize("@ss.hasPermission('tjt:report-summary:export')") @PreAuthorize("@ss.hasPermission('tjt:report-summary:export')")

View File

@@ -0,0 +1,26 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
@Schema(description = "管理后台 - 员工个人考核产值汇总表预览 Response VO")
@Data
public class EmployeeOutputSummaryPreviewRespVO {
@Schema(description = "年度", example = "2026")
private Integer year;
@Schema(description = "预计 K 值,小数值,例如 0.4 表示 40%")
private BigDecimal kValue;
@Schema(description = "员工明细行,金额单位:万元")
private List<EmployeeOutputSummaryExcelRespVO> rows = Collections.emptyList();
@Schema(description = "合计行,金额单位:万元")
private EmployeeOutputSummaryExcelRespVO totalRow;
}

View File

@@ -0,0 +1,103 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Schema(description = "管理后台 - 项目总览表预览 Response VO")
@Data
public class ProjectOverviewPreviewRespVO {
@Schema(description = "年度", example = "2026")
private Integer year;
@Schema(description = "专业所名称", example = "给排水所")
private String officeName;
@Schema(description = "员工动态列")
private List<EmployeeColumn> employeeColumns = Collections.emptyList();
@Schema(description = "项目行")
private List<ProjectRow> rows = Collections.emptyList();
@Schema(description = "合计行")
private ProjectRow totalRow;
@Schema(description = "员工动态列")
@Data
public static class EmployeeColumn {
@Schema(description = "员工 ID", example = "1")
private Long employeeId;
@Schema(description = "员工姓名", example = "张三")
private String employeeName;
}
@Schema(description = "项目总览行")
@Data
public static class ProjectRow {
@Schema(description = "序号", example = "1")
private Integer serialNo;
@Schema(description = "是否合计行", example = "false")
private Boolean totalRow = false;
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "工程进度情况及其它说明")
private String progressText;
@Schema(description = "工作阶段")
private String workStage;
@Schema(description = "本专业 + 项目总核算总产值,单位:万元")
private BigDecimal totalOutputAmountWan;
@Schema(description = "往期已发放比例,小数值,例如 0.2 表示 20%")
private BigDecimal historicalIssuedRatio;
@Schema(description = "本期结算占比,小数值,例如 0.2 表示 20%")
private BigDecimal currentSettlementRatio;
@Schema(description = "本期结算考核产值,单位:万元")
private BigDecimal currentSettlementAmountWan;
@Schema(description = "未结算比例,小数值,例如 0.2 表示 20%")
private BigDecimal pendingRatio;
@Schema(description = "员工季度金额key 为员工 ID金额单位万元")
private Map<Long, EmployeeAmountValue> employeeAmountMap = new LinkedHashMap<>();
}
@Schema(description = "员工季度金额")
@Data
public static class EmployeeAmountValue {
@Schema(description = "一季度,单位:万元")
private BigDecimal quarterOneAmountWan;
@Schema(description = "二季度,单位:万元")
private BigDecimal quarterTwoAmountWan;
@Schema(description = "三季度,单位:万元")
private BigDecimal quarterThreeAmountWan;
@Schema(description = "四季度,单位:万元")
private BigDecimal quarterFourAmountWan;
@Schema(description = "本年度小计,单位:万元")
private BigDecimal annualTotalAmountWan;
}
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 专业内人员年度季度计取预览 Request VO")
@Data
public class SpecialtyPersonOutputPreviewReqVO {
@Schema(description = "合约规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "合约规划 ID 不能为空")
private Long planningId;
@Schema(description = "预览年度", example = "2026")
private Integer year;
}

View File

@@ -0,0 +1,157 @@
package cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - 专业内人员年度季度计取预览 Response VO")
@Data
public class SpecialtyPersonOutputPreviewRespVO {
@Schema(description = "锚点合约规划 ID")
private Long planningId;
@Schema(description = "预览年度")
private Integer year;
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "专业分组")
private List<GroupRow> groups;
@Schema(description = "专业分组")
@Data
public static class GroupRow {
@Schema(description = "专业编码")
private String specialtyCode;
@Schema(description = "专业名称")
private String specialtyName;
@Schema(description = "是否允许导出专业内人员计取表")
private Boolean exportable;
@Schema(description = "专业金额(元)")
private BigDecimal specialtyAmount;
@Schema(description = "角色比例合计")
private BigDecimal roleTotal;
@Schema(description = "已配置人数")
private Integer personCount;
@Schema(description = "是否超额")
private Boolean overRatio;
@Schema(description = "专业一季度金额(万元)")
private BigDecimal specialtyQuarterOneAmountWan;
@Schema(description = "专业二季度金额(万元)")
private BigDecimal specialtyQuarterTwoAmountWan;
@Schema(description = "专业三季度金额(万元)")
private BigDecimal specialtyQuarterThreeAmountWan;
@Schema(description = "专业四季度金额(万元)")
private BigDecimal specialtyQuarterFourAmountWan;
@Schema(description = "专业本年度小计金额(万元)")
private BigDecimal specialtyYearTotalAmountWan;
@Schema(description = "角色人员年度季度计取明细")
private List<RoleRow> rows;
}
@Schema(description = "角色人员年度季度计取明细")
@Data
public static class RoleRow {
@Schema(description = "专业编码")
private String specialtyCode;
@Schema(description = "专业名称")
private String specialtyName;
@Schema(description = "角色编码")
private String roleCode;
@Schema(description = "角色名称")
private String roleName;
@Schema(description = "角色比例")
private BigDecimal roleRatio;
@Schema(description = "角色金额(元)")
private BigDecimal roleAmount;
@Schema(description = "人员比例合计")
private BigDecimal personTotalRatio;
@Schema(description = "人员明细")
private List<PersonRow> persons;
}
@Schema(description = "人员年度季度计取明细")
@Data
public static class PersonRow {
@Schema(description = "人员唯一键")
private String personKey;
@Schema(description = "员工 ID")
private Long employeeId;
@Schema(description = "员工姓名")
private String employeeName;
@Schema(description = "人员工作量比例")
private BigDecimal personRatio;
@Schema(description = "人员金额(元)")
private BigDecimal personAmount;
@Schema(description = "参与角色")
private String roleNames;
@Schema(description = "占专业比例合计")
private BigDecimal adjustedPersonRatio;
@Schema(description = "一季度比例")
private BigDecimal quarterOneRatio;
@Schema(description = "一季度金额(万元)")
private BigDecimal quarterOneAmountWan;
@Schema(description = "二季度比例")
private BigDecimal quarterTwoRatio;
@Schema(description = "二季度金额(万元)")
private BigDecimal quarterTwoAmountWan;
@Schema(description = "三季度比例")
private BigDecimal quarterThreeRatio;
@Schema(description = "三季度金额(万元)")
private BigDecimal quarterThreeAmountWan;
@Schema(description = "四季度比例")
private BigDecimal quarterFourRatio;
@Schema(description = "四季度金额(万元)")
private BigDecimal quarterFourAmountWan;
@Schema(description = "本年度小计比例")
private BigDecimal yearTotalRatio;
@Schema(description = "本年度小计金额(万元)")
private BigDecimal yearTotalAmountWan;
}
}

View File

@@ -38,6 +38,8 @@ public class EmployeeDO extends TenantBaseDO {
private String remark; private String remark;
private Boolean officeLeaderFlag;
private Integer sortNo; private Integer sortNo;
private Boolean enabledFlag; private Boolean enabledFlag;

View File

@@ -0,0 +1,35 @@
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearleaderoutput;
import cn.iocoder.lyzsys.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@TableName("tjt_employee_year_leader_output")
@KeySequence("tjt_employee_year_leader_output_seq")
@Data
@EqualsAndHashCode(callSuper = true)
public class EmployeeYearLeaderOutputDO extends TenantBaseDO {
@TableId
private Long id;
private Long employeeId;
private String employeeName;
private Integer outputYear;
private BigDecimal leaderOutputAmount;
private String remark;
private Integer sortNo;
private Boolean enabledFlag;
}

View File

@@ -35,8 +35,6 @@ public class SpecialtyRoleSplitDO extends TenantBaseDO {
private BigDecimal roleRatio; private BigDecimal roleRatio;
private String personsJson;
private Integer sortNo; private Integer sortNo;
} }

View File

@@ -0,0 +1,50 @@
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplitperson;
import cn.iocoder.lyzsys.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 页面 5 角色人员分配明细 DO
*
* @author Codex
*/
@TableName("tjt_specialty_role_split_person")
@KeySequence("tjt_specialty_role_split_person_seq")
@Data
@EqualsAndHashCode(callSuper = true)
public class SpecialtyRoleSplitPersonDO extends TenantBaseDO {
@TableId
private Long id;
private Long roleSplitId;
private Long outputSplitId;
private Long projectId;
private Long planningId;
private String specialtyCode;
private String specialtyName;
private String roleCode;
private String roleName;
private Long employeeId;
private String employeeName;
private BigDecimal personRatio;
private Integer sortNo;
}

View File

@@ -18,16 +18,34 @@ public interface EmployeeMapper extends BaseMapperX<EmployeeDO> {
.eqIfPresent(EmployeeDO::getOfficeId, reqVO.getOfficeId()) .eqIfPresent(EmployeeDO::getOfficeId, reqVO.getOfficeId())
.eqIfPresent(EmployeeDO::getEmployeeStatus, reqVO.getEmployeeStatus()) .eqIfPresent(EmployeeDO::getEmployeeStatus, reqVO.getEmployeeStatus())
.eqIfPresent(EmployeeDO::getEnabledFlag, reqVO.getEnabledFlag()) .eqIfPresent(EmployeeDO::getEnabledFlag, reqVO.getEnabledFlag())
.eqIfPresent(EmployeeDO::getOfficeLeaderFlag, reqVO.getOfficeLeaderFlag())
.orderByAsc(EmployeeDO::getSortNo) .orderByAsc(EmployeeDO::getSortNo)
.orderByAsc(EmployeeDO::getId)); .orderByAsc(EmployeeDO::getId));
} }
default List<EmployeeDO> selectSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag) { default List<EmployeeDO> selectSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag,
Boolean officeLeaderFlag) {
return selectList(new LambdaQueryWrapperX<EmployeeDO>() return selectList(new LambdaQueryWrapperX<EmployeeDO>()
.likeIfPresent(EmployeeDO::getEmployeeName, keyword) .likeIfPresent(EmployeeDO::getEmployeeName, keyword)
.eqIfPresent(EmployeeDO::getOfficeId, officeId) .eqIfPresent(EmployeeDO::getOfficeId, officeId)
.eqIfPresent(EmployeeDO::getEmployeeStatus, status) .eqIfPresent(EmployeeDO::getEmployeeStatus, status)
.eqIfPresent(EmployeeDO::getEnabledFlag, enabledFlag) .eqIfPresent(EmployeeDO::getEnabledFlag, enabledFlag)
.eqIfPresent(EmployeeDO::getOfficeLeaderFlag, officeLeaderFlag)
.orderByAsc(EmployeeDO::getSortNo)
.orderByAsc(EmployeeDO::getId));
}
default List<EmployeeDO> selectEnabledList() {
return selectList(new LambdaQueryWrapperX<EmployeeDO>()
.eq(EmployeeDO::getEnabledFlag, Boolean.TRUE)
.orderByAsc(EmployeeDO::getSortNo)
.orderByAsc(EmployeeDO::getId));
}
default List<EmployeeDO> selectEnabledLeaderList() {
return selectList(new LambdaQueryWrapperX<EmployeeDO>()
.eq(EmployeeDO::getEnabledFlag, Boolean.TRUE)
.eq(EmployeeDO::getOfficeLeaderFlag, Boolean.TRUE)
.orderByAsc(EmployeeDO::getSortNo) .orderByAsc(EmployeeDO::getSortNo)
.orderByAsc(EmployeeDO::getId)); .orderByAsc(EmployeeDO::getId));
} }

View File

@@ -7,6 +7,8 @@ import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.E
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper @Mapper
public interface EmployeeYearCostBudgetMapper extends BaseMapperX<EmployeeYearCostBudgetDO> { public interface EmployeeYearCostBudgetMapper extends BaseMapperX<EmployeeYearCostBudgetDO> {
@@ -27,6 +29,11 @@ public interface EmployeeYearCostBudgetMapper extends BaseMapperX<EmployeeYearCo
.eq(EmployeeYearCostBudgetDO::getBudgetYear, budgetYear)); .eq(EmployeeYearCostBudgetDO::getBudgetYear, budgetYear));
} }
default List<EmployeeYearCostBudgetDO> selectListByBudgetYear(Integer budgetYear) {
return selectList(new LambdaQueryWrapperX<EmployeeYearCostBudgetDO>()
.eq(EmployeeYearCostBudgetDO::getBudgetYear, budgetYear));
}
default Long selectCountByEmployeeId(Long employeeId) { default Long selectCountByEmployeeId(Long employeeId) {
return selectCount(new LambdaQueryWrapperX<EmployeeYearCostBudgetDO>() return selectCount(new LambdaQueryWrapperX<EmployeeYearCostBudgetDO>()
.eq(EmployeeYearCostBudgetDO::getEmployeeId, employeeId)); .eq(EmployeeYearCostBudgetDO::getEmployeeId, employeeId));

View File

@@ -0,0 +1,53 @@
package cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearleaderoutput;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo.EmployeeYearLeaderOutputPageReqVO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearleaderoutput.EmployeeYearLeaderOutputDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
public interface EmployeeYearLeaderOutputMapper extends BaseMapperX<EmployeeYearLeaderOutputDO> {
default PageResult<EmployeeYearLeaderOutputDO> selectPage(EmployeeYearLeaderOutputPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<EmployeeYearLeaderOutputDO>()
.eqIfPresent(EmployeeYearLeaderOutputDO::getEmployeeId, reqVO.getEmployeeId())
.likeIfPresent(EmployeeYearLeaderOutputDO::getEmployeeName, reqVO.getEmployeeName())
.eqIfPresent(EmployeeYearLeaderOutputDO::getOutputYear, reqVO.getOutputYear())
.eqIfPresent(EmployeeYearLeaderOutputDO::getEnabledFlag, reqVO.getEnabledFlag())
.orderByDesc(EmployeeYearLeaderOutputDO::getOutputYear)
.orderByAsc(EmployeeYearLeaderOutputDO::getSortNo)
.orderByAsc(EmployeeYearLeaderOutputDO::getId));
}
default EmployeeYearLeaderOutputDO selectByEmployeeIdAndOutputYear(Long employeeId, Integer outputYear) {
return selectOne(new LambdaQueryWrapperX<EmployeeYearLeaderOutputDO>()
.eq(EmployeeYearLeaderOutputDO::getEmployeeId, employeeId)
.eq(EmployeeYearLeaderOutputDO::getOutputYear, outputYear));
}
default List<EmployeeYearLeaderOutputDO> selectListByOutputYear(Integer outputYear) {
return selectList(new LambdaQueryWrapperX<EmployeeYearLeaderOutputDO>()
.eq(EmployeeYearLeaderOutputDO::getOutputYear, outputYear));
}
default List<EmployeeYearLeaderOutputDO> selectEnabledListByOutputYear(Integer outputYear,
Collection<Long> employeeIds) {
return selectList(new LambdaQueryWrapperX<EmployeeYearLeaderOutputDO>()
.eq(EmployeeYearLeaderOutputDO::getOutputYear, outputYear)
.eq(EmployeeYearLeaderOutputDO::getEnabledFlag, Boolean.TRUE)
.inIfPresent(EmployeeYearLeaderOutputDO::getEmployeeId, employeeIds)
.orderByAsc(EmployeeYearLeaderOutputDO::getSortNo)
.orderByAsc(EmployeeYearLeaderOutputDO::getId));
}
default Long selectCountByEmployeeId(Long employeeId) {
return selectCount(new LambdaQueryWrapperX<EmployeeYearLeaderOutputDO>()
.eq(EmployeeYearLeaderOutputDO::getEmployeeId, employeeId));
}
}

View File

@@ -34,6 +34,19 @@ public interface ProjectRolePersonMapper extends BaseMapperX<ProjectRolePersonDO
.orderByAsc(ProjectRolePersonDO::getId)); .orderByAsc(ProjectRolePersonDO::getId));
} }
default List<ProjectRolePersonDO> selectListByEmployeeIds(Collection<Long> employeeIds) {
if (employeeIds == null || employeeIds.isEmpty()) {
return Collections.emptyList();
}
return selectList(new LambdaQueryWrapperX<ProjectRolePersonDO>()
.in(ProjectRolePersonDO::getEmployeeId, employeeIds)
.eq(ProjectRolePersonDO::getEnabledFlag, Boolean.TRUE)
.orderByAsc(ProjectRolePersonDO::getProjectId)
.orderByAsc(ProjectRolePersonDO::getRoleCode)
.orderByAsc(ProjectRolePersonDO::getSortNo)
.orderByAsc(ProjectRolePersonDO::getId));
}
default Long selectCountByEmployeeId(Long employeeId) { default Long selectCountByEmployeeId(Long employeeId) {
return selectCount(new LambdaQueryWrapperX<ProjectRolePersonDO>() return selectCount(new LambdaQueryWrapperX<ProjectRolePersonDO>()
.eq(ProjectRolePersonDO::getEmployeeId, employeeId)); .eq(ProjectRolePersonDO::getEmployeeId, employeeId));

View File

@@ -5,6 +5,8 @@ import cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplit.SpecialtyRoleSplitDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplit.SpecialtyRoleSplitDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -22,9 +24,15 @@ public interface SpecialtyRoleSplitMapper extends BaseMapperX<SpecialtyRoleSplit
.orderByAsc(SpecialtyRoleSplitDO::getId)); .orderByAsc(SpecialtyRoleSplitDO::getId));
} }
default List<SpecialtyRoleSplitDO> selectListByPersonsJsonKeyword(String keyword) { default List<SpecialtyRoleSplitDO> selectListByOutputSplitIds(Collection<Long> outputSplitIds) {
if (outputSplitIds == null || outputSplitIds.isEmpty()) {
return Collections.emptyList();
}
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitDO>() return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitDO>()
.like(SpecialtyRoleSplitDO::getPersonsJson, keyword)); .in(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitIds)
.orderByAsc(SpecialtyRoleSplitDO::getOutputSplitId)
.orderByAsc(SpecialtyRoleSplitDO::getSortNo)
.orderByAsc(SpecialtyRoleSplitDO::getId));
} }
} }

View File

@@ -0,0 +1,105 @@
package cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplitperson;
import cn.iocoder.lyzsys.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplitperson.SpecialtyRoleSplitPersonDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* 页面 5 角色人员分配明细 Mapper
*
* @author Codex
*/
@Mapper
public interface SpecialtyRoleSplitPersonMapper extends BaseMapperX<SpecialtyRoleSplitPersonDO> {
default List<SpecialtyRoleSplitPersonDO> selectListByRoleSplitId(Long roleSplitId) {
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.eq(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo)
.orderByAsc(SpecialtyRoleSplitPersonDO::getId));
}
default List<SpecialtyRoleSplitPersonDO> selectListByRoleSplitIds(Collection<Long> roleSplitIds) {
if (roleSplitIds == null || roleSplitIds.isEmpty()) {
return Collections.emptyList();
}
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.in(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitIds)
.orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo)
.orderByAsc(SpecialtyRoleSplitPersonDO::getId));
}
default List<SpecialtyRoleSplitPersonDO> selectListByOutputSplitIds(Collection<Long> outputSplitIds) {
if (outputSplitIds == null || outputSplitIds.isEmpty()) {
return Collections.emptyList();
}
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.in(SpecialtyRoleSplitPersonDO::getOutputSplitId, outputSplitIds)
.orderByAsc(SpecialtyRoleSplitPersonDO::getOutputSplitId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo)
.orderByAsc(SpecialtyRoleSplitPersonDO::getId));
}
default List<SpecialtyRoleSplitPersonDO> selectListByEmployeeIds(Collection<Long> employeeIds) {
if (employeeIds == null || employeeIds.isEmpty()) {
return Collections.emptyList();
}
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.in(SpecialtyRoleSplitPersonDO::getEmployeeId, employeeIds)
.orderByAsc(SpecialtyRoleSplitPersonDO::getPlanningId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo)
.orderByAsc(SpecialtyRoleSplitPersonDO::getId));
}
default List<SpecialtyRoleSplitPersonDO> selectListByPlanningIdsAndEmployeeIds(Collection<Long> planningIds,
Collection<Long> employeeIds) {
if (planningIds == null || planningIds.isEmpty() || employeeIds == null || employeeIds.isEmpty()) {
return Collections.emptyList();
}
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.in(SpecialtyRoleSplitPersonDO::getPlanningId, planningIds)
.in(SpecialtyRoleSplitPersonDO::getEmployeeId, employeeIds)
.orderByAsc(SpecialtyRoleSplitPersonDO::getPlanningId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId)
.orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo)
.orderByAsc(SpecialtyRoleSplitPersonDO::getId));
}
default void deleteByRoleSplitId(Long roleSplitId) {
delete(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitId);
}
default void deleteByRoleSplitIds(Collection<Long> roleSplitIds) {
if (roleSplitIds == null || roleSplitIds.isEmpty()) {
return;
}
delete(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.in(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitIds));
}
default void deleteByOutputSplitId(Long outputSplitId) {
delete(SpecialtyRoleSplitPersonDO::getOutputSplitId, outputSplitId);
}
default void deleteByOutputSplitIds(Collection<Long> outputSplitIds) {
if (outputSplitIds == null || outputSplitIds.isEmpty()) {
return;
}
delete(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.in(SpecialtyRoleSplitPersonDO::getOutputSplitId, outputSplitIds));
}
default Long selectCountByEmployeeId(Long employeeId) {
return selectCount(new LambdaQueryWrapperX<SpecialtyRoleSplitPersonDO>()
.eq(SpecialtyRoleSplitPersonDO::getEmployeeId, employeeId));
}
}

View File

@@ -55,9 +55,14 @@ public interface ErrorCodeConstants {
// ========== 员工管理 1-020-008-000 ========== // ========== 员工管理 1-020-008-000 ==========
ErrorCode EMPLOYEE_NOT_EXISTS = new ErrorCode(1_020_008_000, "员工记录不存在"); ErrorCode EMPLOYEE_NOT_EXISTS = new ErrorCode(1_020_008_000, "员工记录不存在");
ErrorCode EMPLOYEE_IN_USE = new ErrorCode(1_020_008_001, "当前员工已被业务数据引用,不能删除"); ErrorCode EMPLOYEE_IN_USE = new ErrorCode(1_020_008_001, "当前员工已被业务数据引用,不能删除");
ErrorCode EMPLOYEE_NOT_OFFICE_LEADER = new ErrorCode(1_020_008_002, "当前员工未启用或未标记为所长,不能维护年度所长考核产值");
// ========== 员工年度成本预算 1-020-009-000 ========== // ========== 员工年度成本预算 1-020-009-000 ==========
ErrorCode EMPLOYEE_YEAR_COST_BUDGET_NOT_EXISTS = new ErrorCode(1_020_009_000, "员工年度成本预算记录不存在"); ErrorCode EMPLOYEE_YEAR_COST_BUDGET_NOT_EXISTS = new ErrorCode(1_020_009_000, "员工年度成本预算记录不存在");
ErrorCode EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE = new ErrorCode(1_020_009_001, "当前员工该年度预计发生成本已存在"); ErrorCode EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE = new ErrorCode(1_020_009_001, "当前员工该年度预计发生成本已存在");
// ========== 年度所长考核产值 1-020-010-000 ==========
ErrorCode EMPLOYEE_YEAR_LEADER_OUTPUT_NOT_EXISTS = new ErrorCode(1_020_010_000, "年度所长考核产值记录不存在");
ErrorCode EMPLOYEE_YEAR_LEADER_OUTPUT_DUPLICATE = new ErrorCode(1_020_010_001, "当前所长该年度考核产值已存在");
} }

View File

@@ -24,6 +24,7 @@ public interface EmployeeService {
PageResult<EmployeeRespVO> getEmployeePage(EmployeePageReqVO pageReqVO); PageResult<EmployeeRespVO> getEmployeePage(EmployeePageReqVO pageReqVO);
List<EmployeeSimpleRespVO> getEmployeeSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag); List<EmployeeSimpleRespVO> getEmployeeSimpleList(String keyword, Long officeId, String status,
Boolean enabledFlag, Boolean officeLeaderFlag);
} }

View File

@@ -2,21 +2,19 @@ package cn.iocoder.lyzsys.module.tjt.service.employee;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult; import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.framework.common.util.collection.CollectionUtils; import cn.iocoder.lyzsys.framework.common.util.collection.CollectionUtils;
import cn.iocoder.lyzsys.framework.common.util.json.JsonUtils;
import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils; import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeePageReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeePageReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeeRespVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeeRespVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeeSaveReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeeSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeeSimpleRespVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo.EmployeeSimpleRespVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRolePersonSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplit.SpecialtyRoleSplitDO;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearleaderoutput.EmployeeYearLeaderOutputMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.office.OfficeMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.office.OfficeMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson.ProjectRolePersonMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson.ProjectRolePersonMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplit.SpecialtyRoleSplitMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplitperson.SpecialtyRoleSplitPersonMapper;
import cn.iocoder.lyzsys.module.tjt.service.office.OfficeService; import cn.iocoder.lyzsys.module.tjt.service.office.OfficeService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -43,9 +41,11 @@ public class EmployeeServiceImpl implements EmployeeService {
@Resource @Resource
private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper; private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper;
@Resource @Resource
private EmployeeYearLeaderOutputMapper employeeYearLeaderOutputMapper;
@Resource
private ProjectRolePersonMapper projectRolePersonMapper; private ProjectRolePersonMapper projectRolePersonMapper;
@Resource @Resource
private SpecialtyRoleSplitMapper specialtyRoleSplitMapper; private SpecialtyRoleSplitPersonMapper specialtyRoleSplitPersonMapper;
@Resource @Resource
private OfficeService officeService; private OfficeService officeService;
@@ -56,6 +56,9 @@ public class EmployeeServiceImpl implements EmployeeService {
if (employee.getEnabledFlag() == null) { if (employee.getEnabledFlag() == null) {
employee.setEnabledFlag(Boolean.TRUE); employee.setEnabledFlag(Boolean.TRUE);
} }
if (employee.getOfficeLeaderFlag() == null) {
employee.setOfficeLeaderFlag(Boolean.FALSE);
}
employeeMapper.insert(employee); employeeMapper.insert(employee);
return employee.getId(); return employee.getId();
} }
@@ -64,13 +67,18 @@ public class EmployeeServiceImpl implements EmployeeService {
public void updateEmployee(EmployeeSaveReqVO updateReqVO) { public void updateEmployee(EmployeeSaveReqVO updateReqVO) {
validateEmployeeExists(updateReqVO.getId()); validateEmployeeExists(updateReqVO.getId());
officeService.validateOfficeExists(updateReqVO.getOfficeId()); officeService.validateOfficeExists(updateReqVO.getOfficeId());
employeeMapper.updateById(BeanUtils.toBean(updateReqVO, EmployeeDO.class)); EmployeeDO employee = BeanUtils.toBean(updateReqVO, EmployeeDO.class);
if (employee.getOfficeLeaderFlag() == null) {
employee.setOfficeLeaderFlag(Boolean.FALSE);
}
employeeMapper.updateById(employee);
} }
@Override @Override
public void deleteEmployee(Long id) { public void deleteEmployee(Long id) {
validateEmployeeExists(id); validateEmployeeExists(id);
if (employeeYearCostBudgetMapper.selectCountByEmployeeId(id) > 0 if (employeeYearCostBudgetMapper.selectCountByEmployeeId(id) > 0
|| employeeYearLeaderOutputMapper.selectCountByEmployeeId(id) > 0
|| projectRolePersonMapper.selectCountByEmployeeId(id) > 0 || projectRolePersonMapper.selectCountByEmployeeId(id) > 0
|| existsInSpecialtyRoleSplit(id)) { || existsInSpecialtyRoleSplit(id)) {
throw exception(EMPLOYEE_IN_USE); throw exception(EMPLOYEE_IN_USE);
@@ -104,8 +112,10 @@ public class EmployeeServiceImpl implements EmployeeService {
} }
@Override @Override
public List<EmployeeSimpleRespVO> getEmployeeSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag) { public List<EmployeeSimpleRespVO> getEmployeeSimpleList(String keyword, Long officeId, String status,
List<EmployeeDO> list = employeeMapper.selectSimpleList(keyword, officeId, status, enabledFlag == null ? Boolean.TRUE : enabledFlag); Boolean enabledFlag, Boolean officeLeaderFlag) {
List<EmployeeDO> list = employeeMapper.selectSimpleList(keyword, officeId, status,
enabledFlag == null ? Boolean.TRUE : enabledFlag, officeLeaderFlag);
Map<Long, OfficeDO> officeMap = getOfficeMap(CollectionUtils.convertSet(list, EmployeeDO::getOfficeId)); Map<Long, OfficeDO> officeMap = getOfficeMap(CollectionUtils.convertSet(list, EmployeeDO::getOfficeId));
return BeanUtils.toBean(list, EmployeeSimpleRespVO.class, respVO -> return BeanUtils.toBean(list, EmployeeSimpleRespVO.class, respVO ->
respVO.setOfficeName(officeMap.containsKey(respVO.getOfficeId()) respVO.setOfficeName(officeMap.containsKey(respVO.getOfficeId())
@@ -113,20 +123,7 @@ public class EmployeeServiceImpl implements EmployeeService {
} }
private boolean existsInSpecialtyRoleSplit(Long employeeId) { private boolean existsInSpecialtyRoleSplit(Long employeeId) {
List<SpecialtyRoleSplitDO> candidateList = specialtyRoleSplitMapper.selectListByPersonsJsonKeyword("\"employeeId\":" + employeeId); return specialtyRoleSplitPersonMapper.selectCountByEmployeeId(employeeId) > 0;
for (SpecialtyRoleSplitDO item : candidateList) {
List<SpecialtyRolePersonSaveReqVO> persons = JsonUtils.parseArray(item.getPersonsJson(), SpecialtyRolePersonSaveReqVO.class);
if (persons == null) {
continue;
}
boolean matched = persons.stream()
.filter(Objects::nonNull)
.anyMatch(person -> Objects.equals(person.getEmployeeId(), employeeId));
if (matched) {
return true;
}
}
return false;
} }
private Map<Long, OfficeDO> getOfficeMap(Set<Long> officeIds) { private Map<Long, OfficeDO> getOfficeMap(Set<Long> officeIds) {

View File

@@ -1,9 +1,7 @@
package cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget; package cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult; import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetPageReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.*;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetRespVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetSaveReqVO;
import javax.validation.Valid; import javax.validation.Valid;
@@ -11,6 +9,8 @@ public interface EmployeeYearCostBudgetService {
Long createEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO createReqVO); Long createEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO createReqVO);
EmployeeYearCostBudgetGenerateRespVO generateEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetGenerateReqVO reqVO);
void updateEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO updateReqVO); void updateEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO updateReqVO);
void deleteEmployeeYearCostBudget(Long id); void deleteEmployeeYearCostBudget(Long id);

View File

@@ -2,18 +2,22 @@ package cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult; import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils; import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetPageReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.*;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetRespVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper;
import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService; import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE; import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE;
@@ -26,6 +30,8 @@ public class EmployeeYearCostBudgetServiceImpl implements EmployeeYearCostBudget
@Resource @Resource
private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper; private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper;
@Resource @Resource
private EmployeeMapper employeeMapper;
@Resource
private EmployeeService employeeService; private EmployeeService employeeService;
@Override @Override
@@ -41,6 +47,32 @@ public class EmployeeYearCostBudgetServiceImpl implements EmployeeYearCostBudget
return budget.getId(); return budget.getId();
} }
@Override
public EmployeeYearCostBudgetGenerateRespVO generateEmployeeYearCostBudget(EmployeeYearCostBudgetGenerateReqVO reqVO) {
BigDecimal expectedCostAmount = amount(reqVO.getExpectedCostAmount());
List<EmployeeDO> enabledEmployees = employeeMapper.selectEnabledList();
Set<Long> existingEmployeeIds = employeeYearCostBudgetMapper.selectListByBudgetYear(reqVO.getBudgetYear())
.stream()
.map(EmployeeYearCostBudgetDO::getEmployeeId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
List<EmployeeYearCostBudgetDO> createList = enabledEmployees.stream()
.filter(employee -> !existingEmployeeIds.contains(employee.getId()))
.map(employee -> buildInitialBudget(employee, reqVO.getBudgetYear(), expectedCostAmount))
.collect(Collectors.toList());
if (!createList.isEmpty()) {
employeeYearCostBudgetMapper.insertBatch(createList);
}
EmployeeYearCostBudgetGenerateRespVO respVO = new EmployeeYearCostBudgetGenerateRespVO();
respVO.setBudgetYear(reqVO.getBudgetYear());
respVO.setTotalEnabledEmployeeCount(enabledEmployees.size());
respVO.setCreatedCount(createList.size());
respVO.setSkippedCount(enabledEmployees.size() - createList.size());
return respVO;
}
@Override @Override
public void updateEmployeeYearCostBudget(EmployeeYearCostBudgetSaveReqVO updateReqVO) { public void updateEmployeeYearCostBudget(EmployeeYearCostBudgetSaveReqVO updateReqVO) {
validateExists(updateReqVO.getId()); validateExists(updateReqVO.getId());
@@ -82,4 +114,21 @@ public class EmployeeYearCostBudgetServiceImpl implements EmployeeYearCostBudget
} }
} }
private EmployeeYearCostBudgetDO buildInitialBudget(EmployeeDO employee, Integer budgetYear, BigDecimal expectedCostAmount) {
EmployeeYearCostBudgetDO budget = new EmployeeYearCostBudgetDO();
budget.setEmployeeId(employee.getId());
budget.setEmployeeName(employee.getEmployeeName());
budget.setBudgetYear(budgetYear);
budget.setExpectedCostAmount(expectedCostAmount);
budget.setSortNo(employee.getSortNo() == null ? 0 : employee.getSortNo());
budget.setEnabledFlag(Boolean.TRUE);
budget.setRemark("");
return budget;
}
private BigDecimal amount(BigDecimal value) {
return value == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
: value.setScale(2, RoundingMode.HALF_UP);
}
} }

View File

@@ -0,0 +1,24 @@
package cn.iocoder.lyzsys.module.tjt.service.employeeyearleaderoutput;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo.*;
import javax.validation.Valid;
public interface EmployeeYearLeaderOutputService {
Long createEmployeeYearLeaderOutput(@Valid EmployeeYearLeaderOutputSaveReqVO createReqVO);
EmployeeYearLeaderOutputGenerateRespVO generateEmployeeYearLeaderOutput(
@Valid EmployeeYearLeaderOutputGenerateReqVO reqVO);
void updateEmployeeYearLeaderOutput(@Valid EmployeeYearLeaderOutputSaveReqVO updateReqVO);
void deleteEmployeeYearLeaderOutput(Long id);
EmployeeYearLeaderOutputRespVO getEmployeeYearLeaderOutput(Long id);
PageResult<EmployeeYearLeaderOutputRespVO> getEmployeeYearLeaderOutputPage(
EmployeeYearLeaderOutputPageReqVO pageReqVO);
}

View File

@@ -0,0 +1,148 @@
package cn.iocoder.lyzsys.module.tjt.service.employeeyearleaderoutput;
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils;
import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearleaderoutput.vo.*;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearleaderoutput.EmployeeYearLeaderOutputDO;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearleaderoutput.EmployeeYearLeaderOutputMapper;
import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.*;
@Service
@Validated
public class EmployeeYearLeaderOutputServiceImpl implements EmployeeYearLeaderOutputService {
@Resource
private EmployeeYearLeaderOutputMapper employeeYearLeaderOutputMapper;
@Resource
private EmployeeMapper employeeMapper;
@Resource
private EmployeeService employeeService;
@Override
public Long createEmployeeYearLeaderOutput(EmployeeYearLeaderOutputSaveReqVO createReqVO) {
EmployeeDO employee = validateEmployeeIsOfficeLeader(createReqVO.getEmployeeId());
validateDuplicate(null, createReqVO.getEmployeeId(), createReqVO.getOutputYear());
EmployeeYearLeaderOutputDO output = BeanUtils.toBean(createReqVO, EmployeeYearLeaderOutputDO.class);
output.setEmployeeName(employee.getEmployeeName());
output.setLeaderOutputAmount(amount(output.getLeaderOutputAmount()));
if (output.getEnabledFlag() == null) {
output.setEnabledFlag(Boolean.TRUE);
}
employeeYearLeaderOutputMapper.insert(output);
return output.getId();
}
@Override
public EmployeeYearLeaderOutputGenerateRespVO generateEmployeeYearLeaderOutput(
EmployeeYearLeaderOutputGenerateReqVO reqVO) {
BigDecimal leaderOutputAmount = amount(reqVO.getLeaderOutputAmount());
List<EmployeeDO> enabledLeaders = employeeMapper.selectEnabledLeaderList();
Set<Long> existingEmployeeIds = employeeYearLeaderOutputMapper.selectListByOutputYear(reqVO.getOutputYear())
.stream()
.map(EmployeeYearLeaderOutputDO::getEmployeeId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
List<EmployeeYearLeaderOutputDO> createList = enabledLeaders.stream()
.filter(employee -> !existingEmployeeIds.contains(employee.getId()))
.map(employee -> buildInitialOutput(employee, reqVO.getOutputYear(), leaderOutputAmount))
.collect(Collectors.toList());
if (!createList.isEmpty()) {
employeeYearLeaderOutputMapper.insertBatch(createList);
}
EmployeeYearLeaderOutputGenerateRespVO respVO = new EmployeeYearLeaderOutputGenerateRespVO();
respVO.setOutputYear(reqVO.getOutputYear());
respVO.setTotalEnabledLeaderCount(enabledLeaders.size());
respVO.setCreatedCount(createList.size());
respVO.setSkippedCount(enabledLeaders.size() - createList.size());
return respVO;
}
@Override
public void updateEmployeeYearLeaderOutput(EmployeeYearLeaderOutputSaveReqVO updateReqVO) {
validateExists(updateReqVO.getId());
EmployeeDO employee = validateEmployeeIsOfficeLeader(updateReqVO.getEmployeeId());
validateDuplicate(updateReqVO.getId(), updateReqVO.getEmployeeId(), updateReqVO.getOutputYear());
EmployeeYearLeaderOutputDO updateObj = BeanUtils.toBean(updateReqVO, EmployeeYearLeaderOutputDO.class);
updateObj.setEmployeeName(employee.getEmployeeName());
updateObj.setLeaderOutputAmount(amount(updateObj.getLeaderOutputAmount()));
employeeYearLeaderOutputMapper.updateById(updateObj);
}
@Override
public void deleteEmployeeYearLeaderOutput(Long id) {
validateExists(id);
employeeYearLeaderOutputMapper.deleteById(id);
}
@Override
public EmployeeYearLeaderOutputRespVO getEmployeeYearLeaderOutput(Long id) {
return BeanUtils.toBean(validateExists(id), EmployeeYearLeaderOutputRespVO.class);
}
@Override
public PageResult<EmployeeYearLeaderOutputRespVO> getEmployeeYearLeaderOutputPage(
EmployeeYearLeaderOutputPageReqVO pageReqVO) {
return BeanUtils.toBean(employeeYearLeaderOutputMapper.selectPage(pageReqVO),
EmployeeYearLeaderOutputRespVO.class);
}
private EmployeeYearLeaderOutputDO validateExists(Long id) {
EmployeeYearLeaderOutputDO output = employeeYearLeaderOutputMapper.selectById(id);
if (output == null) {
throw exception(EMPLOYEE_YEAR_LEADER_OUTPUT_NOT_EXISTS);
}
return output;
}
private EmployeeDO validateEmployeeIsOfficeLeader(Long employeeId) {
EmployeeDO employee = employeeService.validateEmployeeExists(employeeId);
if (!Boolean.TRUE.equals(employee.getEnabledFlag()) || !Boolean.TRUE.equals(employee.getOfficeLeaderFlag())) {
throw exception(EMPLOYEE_NOT_OFFICE_LEADER);
}
return employee;
}
private void validateDuplicate(Long id, Long employeeId, Integer outputYear) {
EmployeeYearLeaderOutputDO duplicate =
employeeYearLeaderOutputMapper.selectByEmployeeIdAndOutputYear(employeeId, outputYear);
if (duplicate != null && !Objects.equals(duplicate.getId(), id)) {
throw exception(EMPLOYEE_YEAR_LEADER_OUTPUT_DUPLICATE);
}
}
private EmployeeYearLeaderOutputDO buildInitialOutput(EmployeeDO employee, Integer outputYear,
BigDecimal leaderOutputAmount) {
EmployeeYearLeaderOutputDO output = new EmployeeYearLeaderOutputDO();
output.setEmployeeId(employee.getId());
output.setEmployeeName(employee.getEmployeeName());
output.setOutputYear(outputYear);
output.setLeaderOutputAmount(leaderOutputAmount);
output.setSortNo(employee.getSortNo() == null ? 0 : employee.getSortNo());
output.setEnabledFlag(Boolean.TRUE);
output.setRemark("");
return output;
}
private BigDecimal amount(BigDecimal value) {
return value == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
: value.setScale(2, RoundingMode.HALF_UP);
}
}

View File

@@ -104,22 +104,24 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
BigDecimal majorExpectedPerformance = calculateMajorExpectedPerformance(majorPlanningList); BigDecimal majorExpectedPerformance = calculateMajorExpectedPerformance(majorPlanningList);
BigDecimal contractAmount = amount(project.getContractAmount()); BigDecimal contractAmount = amount(project.getContractAmount());
BigDecimal finalSettlementAmount = amount(project.getFinalSettlementAmount()); BigDecimal finalSettlementAmount = amount(project.getFinalSettlementAmount());
BigDecimal effectiveSettlementAmount = finalSettlementAmount.compareTo(BigDecimal.ZERO) > 0
? finalSettlementAmount : contractAmount;
BigDecimal innovationOutputRate = project.getInnovationOutputRate() == null BigDecimal innovationOutputRate = project.getInnovationOutputRate() == null
? DEFAULT_INNOVATION_OUTPUT_RATE : ratio(project.getInnovationOutputRate()); ? DEFAULT_INNOVATION_OUTPUT_RATE : ratio(project.getInnovationOutputRate());
BigDecimal innovationOutputValue = contractAmount.compareTo(BigDecimal.ZERO) <= 0 BigDecimal innovationOutputValue = contractAmount.compareTo(BigDecimal.ZERO) <= 0
? ZERO_AMOUNT ? ZERO_AMOUNT
: contractAmount.multiply(innovationOutputRate).setScale(2, RoundingMode.HALF_UP); : contractAmount.multiply(innovationOutputRate).setScale(2, RoundingMode.HALF_UP);
BigDecimal otherCost = amount(project.getOtherCost()); BigDecimal otherCost = amount(project.getOtherCost());
BigDecimal profitLossValue = finalSettlementAmount BigDecimal profitLossValue = effectiveSettlementAmount
.subtract(comprehensivePlanningAmount) .subtract(comprehensivePlanningAmount)
.subtract(subcontractPlanningAmount) .subtract(subcontractPlanningAmount)
.subtract(majorExpectedPerformance) .subtract(majorExpectedPerformance)
.subtract(innovationOutputValue) .subtract(innovationOutputValue)
.subtract(otherCost) .subtract(otherCost)
.setScale(2, RoundingMode.HALF_UP); .setScale(2, RoundingMode.HALF_UP);
BigDecimal profitLossRate = finalSettlementAmount.compareTo(BigDecimal.ZERO) == 0 BigDecimal profitLossRate = effectiveSettlementAmount.compareTo(BigDecimal.ZERO) == 0
? ZERO_RATIO ? ZERO_RATIO
: profitLossValue.divide(finalSettlementAmount, 4, RoundingMode.HALF_UP); : profitLossValue.divide(effectiveSettlementAmount, 4, RoundingMode.HALF_UP);
ProjectProfitRespVO respVO = new ProjectProfitRespVO(); ProjectProfitRespVO respVO = new ProjectProfitRespVO();
respVO.setProjectId(project.getId()); respVO.setProjectId(project.getId());
@@ -128,6 +130,7 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
respVO.setContractSignedFlag(project.getContractSignedFlag()); respVO.setContractSignedFlag(project.getContractSignedFlag());
respVO.setContractAmount(contractAmount); respVO.setContractAmount(contractAmount);
respVO.setFinalSettlementAmount(finalSettlementAmount); respVO.setFinalSettlementAmount(finalSettlementAmount);
respVO.setEffectiveSettlementAmount(effectiveSettlementAmount);
respVO.setComprehensivePlanningAmount(comprehensivePlanningAmount.setScale(2, RoundingMode.HALF_UP)); respVO.setComprehensivePlanningAmount(comprehensivePlanningAmount.setScale(2, RoundingMode.HALF_UP));
respVO.setSubcontractPlanningAmount(subcontractPlanningAmount.setScale(2, RoundingMode.HALF_UP)); respVO.setSubcontractPlanningAmount(subcontractPlanningAmount.setScale(2, RoundingMode.HALF_UP));
respVO.setMajorOutputValue(majorOutputValue.setScale(2, RoundingMode.HALF_UP)); respVO.setMajorOutputValue(majorOutputValue.setScale(2, RoundingMode.HALF_UP));

View File

@@ -1,11 +1,6 @@
package cn.iocoder.lyzsys.module.tjt.service.report; package cn.iocoder.lyzsys.module.tjt.service.report;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.EmployeeOutputSummaryExportReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.*;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectBudgetExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectLeadQuarterOutputExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectOverviewExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.ProjectQuarterOutputExportReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.SpecialtyPersonOutputExportReqVO;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
@@ -25,9 +20,15 @@ public interface ProjectOutputReportService {
void exportSpecialtyPersonOutputExcel(HttpServletResponse response, SpecialtyPersonOutputExportReqVO reqVO) void exportSpecialtyPersonOutputExcel(HttpServletResponse response, SpecialtyPersonOutputExportReqVO reqVO)
throws IOException; throws IOException;
SpecialtyPersonOutputPreviewRespVO getSpecialtyPersonOutputPreview(SpecialtyPersonOutputPreviewReqVO reqVO);
ProjectOverviewPreviewRespVO getProjectOverviewPreview(ProjectOverviewExportReqVO reqVO);
void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO) void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO)
throws IOException; throws IOException;
EmployeeOutputSummaryPreviewRespVO getEmployeeOutputSummaryPreview(EmployeeOutputSummaryExportReqVO reqVO);
void exportEmployeeOutputSummaryExcel(HttpServletResponse response, EmployeeOutputSummaryExportReqVO reqVO) void exportEmployeeOutputSummaryExcel(HttpServletResponse response, EmployeeOutputSummaryExportReqVO reqVO)
throws IOException; throws IOException;

View File

@@ -6,6 +6,7 @@ import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.Speci
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitRespVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitRespVO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearleaderoutput.EmployeeYearLeaderOutputDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.outputsplit.ProjectOutputSplitDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.outputsplit.ProjectOutputSplitDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planning.ProjectPlanningDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planning.ProjectPlanningDO;
@@ -13,14 +14,17 @@ import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planningguidedetail.ProjectPl
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planningquarter.ProjectPlanningQuarterDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planningquarter.ProjectPlanningQuarterDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.project.ProjectDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.project.ProjectDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.projectroleperson.ProjectRolePersonDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.projectroleperson.ProjectRolePersonDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplitperson.SpecialtyRoleSplitPersonDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.yearkvalue.YearKValueDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.yearkvalue.YearKValueDO;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearleaderoutput.EmployeeYearLeaderOutputMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.office.OfficeMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.office.OfficeMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.planning.ProjectPlanningMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.planning.ProjectPlanningMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.planningquarter.ProjectPlanningQuarterMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.planningquarter.ProjectPlanningQuarterMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.project.ProjectMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.project.ProjectMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson.ProjectRolePersonMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson.ProjectRolePersonMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplitperson.SpecialtyRoleSplitPersonMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.yearkvalue.YearKValueMapper; 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;
@@ -69,12 +73,16 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
@Resource @Resource
private ProjectRolePersonMapper projectRolePersonMapper; private ProjectRolePersonMapper projectRolePersonMapper;
@Resource @Resource
private SpecialtyRoleSplitPersonMapper specialtyRoleSplitPersonMapper;
@Resource
private EmployeeMapper employeeMapper; private EmployeeMapper employeeMapper;
@Resource @Resource
private OfficeMapper officeMapper; private OfficeMapper officeMapper;
@Resource @Resource
private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper; private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper;
@Resource @Resource
private EmployeeYearLeaderOutputMapper employeeYearLeaderOutputMapper;
@Resource
private YearKValueMapper yearKValueMapper; private YearKValueMapper yearKValueMapper;
@Resource @Resource
private ProjectOutputSplitService projectOutputSplitService; private ProjectOutputSplitService projectOutputSplitService;
@@ -247,6 +255,260 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
@Override @Override
public void exportSpecialtyPersonOutputExcel(HttpServletResponse response, public void exportSpecialtyPersonOutputExcel(HttpServletResponse response,
SpecialtyPersonOutputExportReqVO reqVO) throws IOException { SpecialtyPersonOutputExportReqVO reqVO) throws IOException {
SpecialtyPersonOutputBuildResult result = buildSpecialtyPersonOutputData(reqVO);
SpecialtyPersonOutputExcelBuilder.ExportData data = result.getData();
specialtyPersonOutputExcelBuilder.writeWorkbook(response,
buildFileName(result.getProject().getProjectName(), result.getReportYear(),
data.getSpecialtyName() + "专业内人员年度季度计取表"),
specialtyPersonOutputExcelBuilder.build(data));
}
@Override
public SpecialtyPersonOutputPreviewRespVO getSpecialtyPersonOutputPreview(SpecialtyPersonOutputPreviewReqVO reqVO) {
ProjectPlanningDO anchorPlanning = validatePlanningExists(reqVO.getPlanningId());
ProjectDO project = validateProjectExists(anchorPlanning.getProjectId());
Integer reportYear = resolveExportYear(reqVO.getYear());
List<ProjectPlanningDO> planningList = sortPlanningList(projectPlanningMapper.selectListByProjectId(project.getId()));
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList);
List<ProjectPlanningDO> relevantPlanningList = planningList.stream()
.filter(item -> hasYearAmount(quarterMap.get(item.getId()), reportYear))
.collect(Collectors.toList());
Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(relevantPlanningList);
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(relevantPlanningList);
List<SpecialtyRoleSplitRespVO> anchorRoleList =
specialtyRoleSplitService.getSpecialtyRoleSplitListByPlanningId(anchorPlanning.getId());
SpecialtyPersonOutputPreviewRespVO respVO = new SpecialtyPersonOutputPreviewRespVO();
respVO.setPlanningId(anchorPlanning.getId());
respVO.setYear(reportYear);
respVO.setProjectName(project.getProjectName());
respVO.setGroups(buildSpecialtyPersonPreviewGroups(anchorRoleList, relevantPlanningList, quarterMap,
outputSplitMap, roleSplitMap, reportYear));
return respVO;
}
private List<SpecialtyPersonOutputPreviewRespVO.GroupRow> buildSpecialtyPersonPreviewGroups(
List<SpecialtyRoleSplitRespVO> anchorRoleList,
List<ProjectPlanningDO> relevantPlanningList,
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap,
Map<Long, ProjectOutputSplitDO> outputSplitMap,
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap,
Integer reportYear) {
if (anchorRoleList == null || anchorRoleList.isEmpty()) {
return Collections.emptyList();
}
Map<String, List<SpecialtyRoleSplitRespVO>> groupMap = anchorRoleList.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(SpecialtyRoleSplitRespVO::getSpecialtyCode,
LinkedHashMap::new, Collectors.toList()));
List<SpecialtyPersonOutputPreviewRespVO.GroupRow> groups = new ArrayList<>();
for (Map.Entry<String, List<SpecialtyRoleSplitRespVO>> entry : groupMap.entrySet()) {
String specialtyCode = entry.getKey();
if (!isSpecialtyPersonExportable(specialtyCode)) {
continue;
}
List<SpecialtyRoleSplitRespVO> roleRows = entry.getValue().stream()
.sorted(Comparator.comparing(SpecialtyRoleSplitRespVO::getSortNo,
Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
SpecialtyQuarterPreviewAggregate aggregate = buildSpecialtyQuarterPreviewAggregate(relevantPlanningList,
quarterMap, outputSplitMap, roleSplitMap, specialtyCode, reportYear);
SpecialtyPersonOutputPreviewRespVO.GroupRow group = new SpecialtyPersonOutputPreviewRespVO.GroupRow();
group.setSpecialtyCode(specialtyCode);
group.setSpecialtyName(resolveSpecialtyName(roleRows, specialtyCode));
group.setExportable(Boolean.TRUE);
group.setSpecialtyAmount(amount(roleRows.isEmpty() ? null : roleRows.get(0).getSpecialtyAmount()));
group.setRoleTotal(sumRoleRatio(roleRows));
group.setPersonCount(countPreviewPersons(roleRows));
group.setOverRatio(group.getRoleTotal().compareTo(FULL_RATIO) > 0);
group.setSpecialtyQuarterOneAmountWan(aggregate.getSpecialtyQuarterOneAmountWan());
group.setSpecialtyQuarterTwoAmountWan(aggregate.getSpecialtyQuarterTwoAmountWan());
group.setSpecialtyQuarterThreeAmountWan(aggregate.getSpecialtyQuarterThreeAmountWan());
group.setSpecialtyQuarterFourAmountWan(aggregate.getSpecialtyQuarterFourAmountWan());
group.setSpecialtyYearTotalAmountWan(aggregate.getSpecialtyYearTotalAmountWan());
group.setRows(buildSpecialtyPreviewRoleRows(roleRows, aggregate));
groups.add(group);
}
return groups;
}
private SpecialtyQuarterPreviewAggregate buildSpecialtyQuarterPreviewAggregate(
List<ProjectPlanningDO> relevantPlanningList,
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap,
Map<Long, ProjectOutputSplitDO> outputSplitMap,
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap,
String specialtyCode,
Integer reportYear) {
SpecialtyQuarterPreviewAggregate aggregate = new SpecialtyQuarterPreviewAggregate();
if (relevantPlanningList == null || relevantPlanningList.isEmpty()) {
return aggregate;
}
for (ProjectPlanningDO planning : relevantPlanningList) {
QuarterSummary quarterSummary = buildQuarterSummary(planning, quarterMap.get(planning.getId()), reportYear);
ProjectOutputSplitDO outputSplit = outputSplitMap.get(planning.getId());
BigDecimal specialtyRatio = getSpecialtyRatio(outputSplit, specialtyCode);
BigDecimal officeRatio = outputSplit == null ? ZERO_RATIO : ratio(outputSplit.getOfficeRatio());
BigDecimal specialtyBaseRatio = multiplyRatio(officeRatio, specialtyRatio);
aggregate.setSpecialtyQuarterOneAmountWan(addAmountValue(aggregate.getSpecialtyQuarterOneAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterOneAmount(), specialtyBaseRatio))));
aggregate.setSpecialtyQuarterTwoAmountWan(addAmountValue(aggregate.getSpecialtyQuarterTwoAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterTwoAmount(), specialtyBaseRatio))));
aggregate.setSpecialtyQuarterThreeAmountWan(addAmountValue(aggregate.getSpecialtyQuarterThreeAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterThreeAmount(), specialtyBaseRatio))));
aggregate.setSpecialtyQuarterFourAmountWan(addAmountValue(aggregate.getSpecialtyQuarterFourAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterFourAmount(), specialtyBaseRatio))));
aggregate.setSpecialtyYearTotalAmountWan(addAmountValue(aggregate.getSpecialtyYearTotalAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getYearTotalAmount(), specialtyBaseRatio))));
List<SpecialtyRoleSplitRespVO> specialtyRoleRows = (roleSplitMap == null ? Collections.<SpecialtyRoleSplitRespVO>emptyList()
: roleSplitMap.getOrDefault(planning.getId(), Collections.emptyList()))
.stream()
.filter(item -> Objects.equals(item.getSpecialtyCode(), specialtyCode))
.collect(Collectors.toList());
for (SpecialtyRoleSplitRespVO roleRow : specialtyRoleRows) {
if (roleRow.getPersons() == null || roleRow.getPersons().isEmpty()) {
continue;
}
BigDecimal roleRatio = ratio(roleRow.getRoleRatio());
for (SpecialtyRolePersonRespVO person : roleRow.getPersons()) {
if (!isValidSpecialtyRolePerson(person)) {
continue;
}
BigDecimal personRatio = ratio(person.getPersonRatio());
BigDecimal amountRatio = multiplyRatio(specialtyBaseRatio, roleRatio, personRatio);
String rolePersonKey = buildSpecialtyRolePersonModuleKey(roleRow.getRoleCode(),
person.getEmployeeId(), person.getEmployeeName());
SpecialtyPersonOutputExcelBuilder.PersonAmountValue value = aggregate.getRolePersonAmountMap()
.computeIfAbsent(rolePersonKey, key -> new SpecialtyPersonOutputExcelBuilder.PersonAmountValue());
accumulateSpecialtyPersonAmount(value, quarterSummary, amountRatio);
}
}
}
return aggregate;
}
private List<SpecialtyPersonOutputPreviewRespVO.RoleRow> buildSpecialtyPreviewRoleRows(
List<SpecialtyRoleSplitRespVO> roleRows,
SpecialtyQuarterPreviewAggregate aggregate) {
List<SpecialtyPersonOutputPreviewRespVO.RoleRow> result = new ArrayList<>();
for (SpecialtyRoleSplitRespVO roleRow : roleRows) {
SpecialtyPersonOutputPreviewRespVO.RoleRow row = new SpecialtyPersonOutputPreviewRespVO.RoleRow();
row.setSpecialtyCode(roleRow.getSpecialtyCode());
row.setSpecialtyName(roleRow.getSpecialtyName());
row.setRoleCode(roleRow.getRoleCode());
row.setRoleName(roleRow.getRoleName());
row.setRoleRatio(ratio(roleRow.getRoleRatio()));
row.setRoleAmount(amount(roleRow.getRoleAmount()));
row.setPersonTotalRatio(sumPersonRatio(roleRow.getPersons()));
row.setPersons(buildSpecialtyPreviewPersons(roleRow, aggregate));
result.add(row);
}
return result;
}
private List<SpecialtyPersonOutputPreviewRespVO.PersonRow> buildSpecialtyPreviewPersons(
SpecialtyRoleSplitRespVO roleRow,
SpecialtyQuarterPreviewAggregate aggregate) {
if (roleRow.getPersons() == null || roleRow.getPersons().isEmpty()) {
return Collections.emptyList();
}
List<SpecialtyPersonOutputPreviewRespVO.PersonRow> result = new ArrayList<>();
BigDecimal roleRatio = ratio(roleRow.getRoleRatio());
for (SpecialtyRolePersonRespVO person : roleRow.getPersons()) {
if (!isValidSpecialtyRolePerson(person)) {
continue;
}
BigDecimal personRatio = ratio(person.getPersonRatio());
String personKey = buildSpecialtyPersonModuleKey(person.getEmployeeId(), person.getEmployeeName());
String rolePersonKey = buildSpecialtyRolePersonModuleKey(roleRow.getRoleCode(),
person.getEmployeeId(), person.getEmployeeName());
SpecialtyPersonOutputExcelBuilder.PersonAmountValue value =
aggregate.getRolePersonAmountMap().get(rolePersonKey);
SpecialtyPersonOutputPreviewRespVO.PersonRow row = new SpecialtyPersonOutputPreviewRespVO.PersonRow();
row.setPersonKey(personKey);
row.setEmployeeId(person.getEmployeeId());
row.setEmployeeName(defaultString(person.getEmployeeName()));
row.setPersonRatio(personRatio);
row.setPersonAmount(amount(person.getPersonAmount()));
row.setRoleNames(defaultString(roleRow.getRoleName()));
row.setAdjustedPersonRatio(multiplyRatio(roleRatio, personRatio));
row.setQuarterOneRatio(value == null ? ZERO_RATIO : ratio(value.getQuarterOneRatio()));
row.setQuarterOneAmountWan(value == null ? ZERO_AMOUNT : amount(value.getQuarterOneAmountWan()));
row.setQuarterTwoRatio(value == null ? ZERO_RATIO : ratio(value.getQuarterTwoRatio()));
row.setQuarterTwoAmountWan(value == null ? ZERO_AMOUNT : amount(value.getQuarterTwoAmountWan()));
row.setQuarterThreeRatio(value == null ? ZERO_RATIO : ratio(value.getQuarterThreeRatio()));
row.setQuarterThreeAmountWan(value == null ? ZERO_AMOUNT : amount(value.getQuarterThreeAmountWan()));
row.setQuarterFourRatio(value == null ? ZERO_RATIO : ratio(value.getQuarterFourRatio()));
row.setQuarterFourAmountWan(value == null ? ZERO_AMOUNT : amount(value.getQuarterFourAmountWan()));
row.setYearTotalRatio(value == null ? ZERO_RATIO : ratio(value.getYearTotalRatio()));
row.setYearTotalAmountWan(value == null ? ZERO_AMOUNT : amount(value.getYearTotalAmountWan()));
result.add(row);
}
return result;
}
private boolean isSpecialtyPersonExportable(String specialtyCode) {
return OutputSplitBizConstants.isValidSpecialtyCode(specialtyCode)
&& !OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode);
}
private String resolveSpecialtyName(List<SpecialtyRoleSplitRespVO> rows, String specialtyCode) {
if (rows != null) {
for (SpecialtyRoleSplitRespVO row : rows) {
if (row != null && !defaultString(row.getSpecialtyName()).isEmpty()) {
return defaultString(row.getSpecialtyName());
}
}
}
return OutputSplitBizConstants.getSpecialtyName(specialtyCode);
}
private BigDecimal sumRoleRatio(List<SpecialtyRoleSplitRespVO> roleRows) {
BigDecimal total = ZERO_RATIO;
if (roleRows == null) {
return total;
}
for (SpecialtyRoleSplitRespVO row : roleRows) {
total = addRatio(total, row.getRoleRatio());
}
return total;
}
private BigDecimal sumPersonRatio(List<SpecialtyRolePersonRespVO> persons) {
BigDecimal total = ZERO_RATIO;
if (persons == null) {
return total;
}
for (SpecialtyRolePersonRespVO person : persons) {
if (isValidSpecialtyRolePerson(person)) {
total = addRatio(total, person.getPersonRatio());
}
}
return total;
}
private int countPreviewPersons(List<SpecialtyRoleSplitRespVO> roleRows) {
if (roleRows == null) {
return 0;
}
int total = 0;
for (SpecialtyRoleSplitRespVO row : roleRows) {
if (row.getPersons() == null) {
continue;
}
for (SpecialtyRolePersonRespVO person : row.getPersons()) {
if (isValidSpecialtyRolePerson(person)) {
total++;
}
}
}
return total;
}
private SpecialtyPersonOutputBuildResult buildSpecialtyPersonOutputData(SpecialtyPersonOutputExportReqVO reqVO) {
validateSpecialtyCode(reqVO.getSpecialtyCode()); validateSpecialtyCode(reqVO.getSpecialtyCode());
ProjectPlanningDO anchorPlanning = validatePlanningExists(reqVO.getPlanningId()); ProjectPlanningDO anchorPlanning = validatePlanningExists(reqVO.getPlanningId());
ProjectDO project = validateProjectExists(anchorPlanning.getProjectId()); ProjectDO project = validateProjectExists(anchorPlanning.getProjectId());
@@ -288,7 +550,6 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
data.setEngineeringPrincipalRatio(engineeringPrincipalRow == null data.setEngineeringPrincipalRatio(engineeringPrincipalRow == null
? ZERO_RATIO : ratio(engineeringPrincipalRow.getRoleRatio())); ? ZERO_RATIO : ratio(engineeringPrincipalRow.getRoleRatio()));
data.setYear(reportYear); data.setYear(reportYear);
data.setCenterSignerLabel("设计中心相关负责人(签名):"); data.setCenterSignerLabel("设计中心相关负责人(签名):");
data.setProjectSignerLabel("项目经理 / 工程负责人(签名):"); data.setProjectSignerLabel("项目经理 / 工程负责人(签名):");
data.setRolePersonModules(buildSpecialtyRolePersonModules(relevantPlanningList, roleSplitMap, reqVO.getSpecialtyCode())); data.setRolePersonModules(buildSpecialtyRolePersonModules(relevantPlanningList, roleSplitMap, reqVO.getSpecialtyCode()));
@@ -296,14 +557,29 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
data.setRows(buildSpecialtyPlanningRows(relevantPlanningList, quarterMap, outputSplitMap, data.setRows(buildSpecialtyPlanningRows(relevantPlanningList, quarterMap, outputSplitMap,
roleSplitMap, project.getProjectName(), reqVO.getSpecialtyCode(), reportYear)); roleSplitMap, project.getProjectName(), reqVO.getSpecialtyCode(), reportYear));
specialtyPersonOutputExcelBuilder.writeWorkbook(response, SpecialtyPersonOutputBuildResult result = new SpecialtyPersonOutputBuildResult();
buildFileName(project.getProjectName(), reportYear, data.getSpecialtyName() + "专业内人员年度季度计取表"), result.setAnchorPlanning(anchorPlanning);
specialtyPersonOutputExcelBuilder.build(data)); result.setProject(project);
result.setReportYear(reportYear);
result.setData(data);
return result;
}
@Override
public ProjectOverviewPreviewRespVO getProjectOverviewPreview(ProjectOverviewExportReqVO reqVO) {
return buildProjectOverviewPreviewResp(buildProjectOverviewExportData(reqVO));
} }
@Override @Override
public void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO) public void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO)
throws IOException { throws IOException {
ProjectOverviewOutputExcelBuilder.ExportData data = buildProjectOverviewExportData(reqVO);
projectOverviewOutputExcelBuilder.writeWorkbook(response,
buildFileName(data.getOfficeName(), data.getYear(), "项目总览表"),
projectOverviewOutputExcelBuilder.build(data));
}
private ProjectOverviewOutputExcelBuilder.ExportData buildProjectOverviewExportData(ProjectOverviewExportReqVO reqVO) {
Integer reportYear = resolveExportYear(reqVO.getYear()); Integer reportYear = resolveExportYear(reqVO.getYear());
OfficeDO office = validateOfficeExists(reqVO.getOfficeId()); OfficeDO office = validateOfficeExists(reqVO.getOfficeId());
List<EmployeeDO> employeeList = employeeMapper.selectList(new LambdaQueryWrapperX<EmployeeDO>() List<EmployeeDO> employeeList = employeeMapper.selectList(new LambdaQueryWrapperX<EmployeeDO>()
@@ -318,16 +594,14 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
Set<Long> employeeIds = employeeList.stream() Set<Long> employeeIds = employeeList.stream()
.map(EmployeeDO::getId) .map(EmployeeDO::getId)
.collect(Collectors.toCollection(LinkedHashSet::new)); .collect(Collectors.toCollection(LinkedHashSet::new));
List<ProjectPlanningDO> majorPlanningList = projectPlanningMapper.selectList( List<ProjectPlanningDO> planningList = getProjectOverviewPlanningList(reportYear, employeeIds);
new LambdaQueryWrapperX<ProjectPlanningDO>() Map<Long, ProjectDO> projectMap = getProjectMap(planningList);
.eq(ProjectPlanningDO::getOwnershipType, ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR)); Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(planningList);
Map<Long, ProjectDO> projectMap = getProjectMap(majorPlanningList); Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(planningList);
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(majorPlanningList); Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(planningList);
Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(majorPlanningList);
Map<Long, List<SpecialtyRoleSplitRespVO>> roleSplitMap = getRoleSplitMap(majorPlanningList);
Map<Long, ProjectOverviewAccumulator> accumulatorMap = new LinkedHashMap<>(); Map<Long, ProjectOverviewAccumulator> accumulatorMap = new LinkedHashMap<>();
for (ProjectPlanningDO planning : majorPlanningList) { for (ProjectPlanningDO planning : planningList) {
QuarterSummary quarterSummary = buildQuarterSummary(planning, quarterMap.get(planning.getId()), reportYear); QuarterSummary quarterSummary = buildQuarterSummary(planning, quarterMap.get(planning.getId()), reportYear);
if (quarterSummary.getYearTotalAmount().compareTo(ZERO_AMOUNT) <= 0) { if (quarterSummary.getYearTotalAmount().compareTo(ZERO_AMOUNT) <= 0) {
continue; continue;
@@ -360,14 +634,25 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
data.setRows(rows); data.setRows(rows);
data.setTotalRow(buildProjectOverviewTotalRow(new ArrayList<>(accumulatorMap.values()), employeeList)); data.setTotalRow(buildProjectOverviewTotalRow(new ArrayList<>(accumulatorMap.values()), employeeList));
projectOverviewOutputExcelBuilder.writeWorkbook(response, return data;
buildFileName(office.getOfficeName(), reportYear, "项目总览表"), }
projectOverviewOutputExcelBuilder.build(data));
@Override
public EmployeeOutputSummaryPreviewRespVO getEmployeeOutputSummaryPreview(EmployeeOutputSummaryExportReqVO reqVO) {
return buildEmployeeOutputSummaryPreviewResp(buildEmployeeOutputSummaryExportData(reqVO));
} }
@Override @Override
public void exportEmployeeOutputSummaryExcel(HttpServletResponse response, public void exportEmployeeOutputSummaryExcel(HttpServletResponse response,
EmployeeOutputSummaryExportReqVO reqVO) throws IOException { EmployeeOutputSummaryExportReqVO reqVO) throws IOException {
EmployeeOutputSummaryExcelBuilder.ExportData data = buildEmployeeOutputSummaryExportData(reqVO);
employeeOutputSummaryExcelBuilder.writeWorkbook(response,
buildFileName("员工个人考核产值", reqVO.getYear(), "汇总表"),
employeeOutputSummaryExcelBuilder.build(data));
}
private EmployeeOutputSummaryExcelBuilder.ExportData buildEmployeeOutputSummaryExportData(
EmployeeOutputSummaryExportReqVO reqVO) {
YearKValueDO yearKValue = yearKValueMapper.selectEnabledByKYear(reqVO.getYear()); YearKValueDO yearKValue = yearKValueMapper.selectEnabledByKYear(reqVO.getYear());
BigDecimal kValue = yearKValue == null ? DEFAULT_K_VALUE : ratio(yearKValue.getKValue()); BigDecimal kValue = yearKValue == null ? DEFAULT_K_VALUE : ratio(yearKValue.getKValue());
List<EmployeeDO> employeeList = employeeMapper.selectList(new LambdaQueryWrapperX<EmployeeDO>() List<EmployeeDO> employeeList = employeeMapper.selectList(new LambdaQueryWrapperX<EmployeeDO>()
@@ -382,23 +667,13 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
data.setYear(reqVO.getYear()); data.setYear(reqVO.getYear());
data.setKValue(kValue); data.setKValue(kValue);
data.setRows(Collections.emptyList()); data.setRows(Collections.emptyList());
employeeOutputSummaryExcelBuilder.writeWorkbook(response, return data;
buildFileName("员工个人考核产值", reqVO.getYear(), "汇总表"),
employeeOutputSummaryExcelBuilder.build(data));
return;
} }
Set<Long> employeeIds = employeeList.stream().map(EmployeeDO::getId).collect(Collectors.toCollection(LinkedHashSet::new)); Set<Long> employeeIds = employeeList.stream().map(EmployeeDO::getId).collect(Collectors.toCollection(LinkedHashSet::new));
List<ProjectPlanningDO> majorPlanningList = projectPlanningMapper.selectList( List<ProjectPlanningDO> relevantPlanningList = getEmployeeOutputSummaryPlanningList(reqVO.getYear(), employeeIds);
new LambdaQueryWrapperX<ProjectPlanningDO>() Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(relevantPlanningList);
.eq(ProjectPlanningDO::getOwnershipType, ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR));
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = getQuarterMap(majorPlanningList);
List<ProjectPlanningDO> relevantPlanningList = majorPlanningList.stream()
.filter(item -> hasYearAmount(quarterMap.get(item.getId()), reqVO.getYear()))
.collect(Collectors.toList());
Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(relevantPlanningList); Map<Long, ProjectOutputSplitDO> outputSplitMap = getOutputSplitMap(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<>();
@@ -437,6 +712,10 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
.inIfPresent(EmployeeYearCostBudgetDO::getEmployeeId, employeeIds)) .inIfPresent(EmployeeYearCostBudgetDO::getEmployeeId, employeeIds))
.stream() .stream()
.collect(Collectors.toMap(EmployeeYearCostBudgetDO::getEmployeeId, item -> item, (a, b) -> a)); .collect(Collectors.toMap(EmployeeYearCostBudgetDO::getEmployeeId, item -> item, (a, b) -> a));
Map<Long, EmployeeYearLeaderOutputDO> leaderOutputMap = employeeYearLeaderOutputMapper
.selectEnabledListByOutputYear(reqVO.getYear(), employeeIds)
.stream()
.collect(Collectors.toMap(EmployeeYearLeaderOutputDO::getEmployeeId, item -> item, (a, b) -> a));
List<EmployeeOutputSummaryExcelRespVO> rows = new ArrayList<>(); List<EmployeeOutputSummaryExcelRespVO> rows = new ArrayList<>();
for (EmployeeDO employee : employeeList) { for (EmployeeDO employee : employeeList) {
@@ -445,8 +724,9 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
accumulator = new EmployeeAccumulator(); accumulator = new EmployeeAccumulator();
} }
EmployeeYearCostBudgetDO costBudget = costBudgetMap.get(employee.getId()); EmployeeYearCostBudgetDO costBudget = costBudgetMap.get(employee.getId());
EmployeeYearLeaderOutputDO leaderOutput = leaderOutputMap.get(employee.getId());
BigDecimal expectedCostAmount = costBudget == null ? ZERO_AMOUNT : amount(costBudget.getExpectedCostAmount()); BigDecimal expectedCostAmount = costBudget == null ? ZERO_AMOUNT : amount(costBudget.getExpectedCostAmount());
BigDecimal officeLeaderOrBimAmount = ZERO_AMOUNT; BigDecimal officeLeaderOrBimAmount = leaderOutput == null ? ZERO_AMOUNT : amount(leaderOutput.getLeaderOutputAmount());
BigDecimal annualTotalAmount = accumulator.getAnnualTotalAmount(); BigDecimal annualTotalAmount = accumulator.getAnnualTotalAmount();
BigDecimal totalAssessmentOutputAmount = annualTotalAmount.add(officeLeaderOrBimAmount) BigDecimal totalAssessmentOutputAmount = annualTotalAmount.add(officeLeaderOrBimAmount)
.setScale(2, RoundingMode.HALF_UP); .setScale(2, RoundingMode.HALF_UP);
@@ -483,9 +763,129 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
data.setYear(reqVO.getYear()); data.setYear(reqVO.getYear());
data.setKValue(kValue); data.setKValue(kValue);
data.setRows(rows); data.setRows(rows);
employeeOutputSummaryExcelBuilder.writeWorkbook(response, return data;
buildFileName("员工个人考核产值", reqVO.getYear(), "汇总表"), }
employeeOutputSummaryExcelBuilder.build(data));
private ProjectOverviewPreviewRespVO buildProjectOverviewPreviewResp(
ProjectOverviewOutputExcelBuilder.ExportData data) {
ProjectOverviewPreviewRespVO respVO = new ProjectOverviewPreviewRespVO();
respVO.setYear(data.getYear());
respVO.setOfficeName(data.getOfficeName());
respVO.setEmployeeColumns(data.getEmployeeColumns() == null
? Collections.emptyList()
: data.getEmployeeColumns().stream()
.map(this::toProjectOverviewPreviewEmployeeColumn)
.collect(Collectors.toList()));
respVO.setRows(data.getRows() == null
? Collections.emptyList()
: data.getRows().stream()
.map(row -> toProjectOverviewPreviewRow(row, false))
.collect(Collectors.toList()));
respVO.setTotalRow(toProjectOverviewPreviewRow(data.getTotalRow(), true));
return respVO;
}
private ProjectOverviewPreviewRespVO.EmployeeColumn toProjectOverviewPreviewEmployeeColumn(
ProjectOverviewOutputExcelBuilder.EmployeeColumn column) {
ProjectOverviewPreviewRespVO.EmployeeColumn previewColumn =
new ProjectOverviewPreviewRespVO.EmployeeColumn();
if (column == null) {
return previewColumn;
}
previewColumn.setEmployeeId(column.getEmployeeId());
previewColumn.setEmployeeName(column.getEmployeeName());
return previewColumn;
}
private ProjectOverviewPreviewRespVO.ProjectRow toProjectOverviewPreviewRow(
ProjectOverviewOutputExcelBuilder.ProjectRow row, boolean totalRow) {
ProjectOverviewPreviewRespVO.ProjectRow previewRow = new ProjectOverviewPreviewRespVO.ProjectRow();
previewRow.setTotalRow(totalRow);
if (row == null) {
return previewRow;
}
previewRow.setSerialNo(row.getSerialNo());
previewRow.setProjectName(totalRow ? "合计" : row.getProjectName());
previewRow.setProgressText(row.getProgressText());
previewRow.setWorkStage(row.getWorkStage());
previewRow.setTotalOutputAmountWan(amountToWan(row.getTotalOutputAmount()));
previewRow.setHistoricalIssuedRatio(row.getHistoricalIssuedRatio());
previewRow.setCurrentSettlementRatio(row.getCurrentSettlementRatio());
previewRow.setCurrentSettlementAmountWan(amountToWan(row.getCurrentSettlementAmount()));
previewRow.setPendingRatio(row.getPendingRatio());
Map<Long, ProjectOverviewPreviewRespVO.EmployeeAmountValue> employeeAmountMap = new LinkedHashMap<>();
if (row.getEmployeeAmountMap() != null) {
row.getEmployeeAmountMap().forEach((employeeId, value) ->
employeeAmountMap.put(employeeId, toProjectOverviewPreviewEmployeeAmount(value)));
}
previewRow.setEmployeeAmountMap(employeeAmountMap);
return previewRow;
}
private ProjectOverviewPreviewRespVO.EmployeeAmountValue toProjectOverviewPreviewEmployeeAmount(
ProjectOverviewOutputExcelBuilder.EmployeeAmountValue value) {
ProjectOverviewPreviewRespVO.EmployeeAmountValue previewValue =
new ProjectOverviewPreviewRespVO.EmployeeAmountValue();
if (value == null) {
return previewValue;
}
previewValue.setQuarterOneAmountWan(amountToWan(value.getQuarterOneAmount()));
previewValue.setQuarterTwoAmountWan(amountToWan(value.getQuarterTwoAmount()));
previewValue.setQuarterThreeAmountWan(amountToWan(value.getQuarterThreeAmount()));
previewValue.setQuarterFourAmountWan(amountToWan(value.getQuarterFourAmount()));
previewValue.setAnnualTotalAmountWan(amountToWan(value.getAnnualTotalAmount()));
return previewValue;
}
private EmployeeOutputSummaryPreviewRespVO buildEmployeeOutputSummaryPreviewResp(
EmployeeOutputSummaryExcelBuilder.ExportData data) {
EmployeeOutputSummaryPreviewRespVO respVO = new EmployeeOutputSummaryPreviewRespVO();
respVO.setYear(data.getYear());
respVO.setKValue(data.getKValue());
List<EmployeeOutputSummaryExcelRespVO> rows = data.getRows() == null
? Collections.emptyList() : data.getRows();
respVO.setRows(rows);
respVO.setTotalRow(buildEmployeeOutputSummaryTotalRow(rows));
return respVO;
}
private EmployeeOutputSummaryExcelRespVO buildEmployeeOutputSummaryTotalRow(
List<EmployeeOutputSummaryExcelRespVO> rows) {
EmployeeOutputSummaryExcelRespVO totalRow = new EmployeeOutputSummaryExcelRespVO();
totalRow.setEmployeeName("合计");
totalRow.setQuarterOneAmount(ZERO_AMOUNT);
totalRow.setQuarterTwoAmount(ZERO_AMOUNT);
totalRow.setQuarterThreeAmount(ZERO_AMOUNT);
totalRow.setQuarterFourAmount(ZERO_AMOUNT);
totalRow.setAnnualTotalAmount(ZERO_AMOUNT);
totalRow.setOfficeLeaderOrBimAmount(ZERO_AMOUNT);
totalRow.setTotalAssessmentOutputAmount(ZERO_AMOUNT);
totalRow.setExpectedCostAmount(ZERO_AMOUNT);
totalRow.setBasicAssessmentOutputAmount(ZERO_AMOUNT);
totalRow.setRemainingOutputAmount(ZERO_AMOUNT);
totalRow.setEstimatedYearEndPerformanceAmount(ZERO_AMOUNT);
if (rows == null) {
return totalRow;
}
for (EmployeeOutputSummaryExcelRespVO row : rows) {
totalRow.setQuarterOneAmount(addAmountValue(totalRow.getQuarterOneAmount(), row.getQuarterOneAmount()));
totalRow.setQuarterTwoAmount(addAmountValue(totalRow.getQuarterTwoAmount(), row.getQuarterTwoAmount()));
totalRow.setQuarterThreeAmount(addAmountValue(totalRow.getQuarterThreeAmount(), row.getQuarterThreeAmount()));
totalRow.setQuarterFourAmount(addAmountValue(totalRow.getQuarterFourAmount(), row.getQuarterFourAmount()));
totalRow.setAnnualTotalAmount(addAmountValue(totalRow.getAnnualTotalAmount(), row.getAnnualTotalAmount()));
totalRow.setOfficeLeaderOrBimAmount(addAmountValue(
totalRow.getOfficeLeaderOrBimAmount(), row.getOfficeLeaderOrBimAmount()));
totalRow.setTotalAssessmentOutputAmount(addAmountValue(
totalRow.getTotalAssessmentOutputAmount(), row.getTotalAssessmentOutputAmount()));
totalRow.setExpectedCostAmount(addAmountValue(totalRow.getExpectedCostAmount(), row.getExpectedCostAmount()));
totalRow.setBasicAssessmentOutputAmount(addAmountValue(
totalRow.getBasicAssessmentOutputAmount(), row.getBasicAssessmentOutputAmount()));
totalRow.setRemainingOutputAmount(addAmountValue(
totalRow.getRemainingOutputAmount(), row.getRemainingOutputAmount()));
totalRow.setEstimatedYearEndPerformanceAmount(addAmountValue(
totalRow.getEstimatedYearEndPerformanceAmount(), row.getEstimatedYearEndPerformanceAmount()));
}
return totalRow;
} }
private ProjectPlanningDO validatePlanningExists(Long planningId) { private ProjectPlanningDO validatePlanningExists(Long planningId) {
@@ -528,6 +928,96 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private List<ProjectPlanningDO> getAssignablePlanningList() {
return projectPlanningMapper.selectList(new LambdaQueryWrapperX<ProjectPlanningDO>()
.in(ProjectPlanningDO::getOwnershipType, Arrays.asList(
ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR,
ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_COMPREHENSIVE,
ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_SUBCONTRACT
)));
}
private List<ProjectPlanningDO> getProjectOverviewPlanningList(Integer reportYear, Set<Long> employeeIds) {
if (reportYear == null || employeeIds == null || employeeIds.isEmpty()) {
return Collections.emptyList();
}
Set<Long> yearPlanningIds = getYearAmountPlanningIds(reportYear);
if (yearPlanningIds.isEmpty()) {
return Collections.emptyList();
}
List<SpecialtyRoleSplitPersonDO> personList = specialtyRoleSplitPersonMapper
.selectListByPlanningIdsAndEmployeeIds(yearPlanningIds, employeeIds);
if (personList.isEmpty()) {
return Collections.emptyList();
}
Set<Long> matchedPlanningIds = personList.stream()
.map(SpecialtyRoleSplitPersonDO::getPlanningId)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (matchedPlanningIds.isEmpty()) {
return Collections.emptyList();
}
return sortPlanningList(projectPlanningMapper.selectBatchIds(matchedPlanningIds).stream()
.filter(item -> item != null && ProjectPlanningBizTypeConstants.isValidOwnershipType(item.getOwnershipType()))
.collect(Collectors.toList()));
}
private List<ProjectPlanningDO> getEmployeeOutputSummaryPlanningList(Integer reportYear, Set<Long> employeeIds) {
if (reportYear == null || employeeIds == null || employeeIds.isEmpty()) {
return Collections.emptyList();
}
Set<Long> yearPlanningIds = getYearAmountPlanningIds(reportYear);
if (yearPlanningIds.isEmpty()) {
return Collections.emptyList();
}
Set<Long> matchedPlanningIds = specialtyRoleSplitPersonMapper
.selectListByPlanningIdsAndEmployeeIds(yearPlanningIds, employeeIds)
.stream()
.map(SpecialtyRoleSplitPersonDO::getPlanningId)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
Set<Long> projectIds = projectRolePersonMapper.selectListByEmployeeIds(employeeIds)
.stream()
.map(ProjectRolePersonDO::getProjectId)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (!projectIds.isEmpty()) {
projectPlanningMapper.selectList(new LambdaQueryWrapperX<ProjectPlanningDO>()
.in(ProjectPlanningDO::getId, yearPlanningIds)
.in(ProjectPlanningDO::getProjectId, projectIds)
.in(ProjectPlanningDO::getOwnershipType, Arrays.asList(
ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR,
ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_COMPREHENSIVE,
ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_SUBCONTRACT
)))
.stream()
.map(ProjectPlanningDO::getId)
.filter(Objects::nonNull)
.forEach(matchedPlanningIds::add);
}
if (matchedPlanningIds.isEmpty()) {
return Collections.emptyList();
}
return sortPlanningList(projectPlanningMapper.selectBatchIds(matchedPlanningIds).stream()
.filter(item -> item != null && ProjectPlanningBizTypeConstants.isValidOwnershipType(item.getOwnershipType()))
.collect(Collectors.toList()));
}
private Set<Long> getYearAmountPlanningIds(Integer reportYear) {
if (reportYear == null) {
return Collections.emptySet();
}
return projectPlanningQuarterMapper.selectList(new LambdaQueryWrapperX<ProjectPlanningQuarterDO>()
.eq(ProjectPlanningQuarterDO::getDistributionYear, reportYear)
.gt(ProjectPlanningQuarterDO::getDistributionAmount, BigDecimal.ZERO))
.stream()
.map(ProjectPlanningQuarterDO::getPlanningId)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
}
private List<ProjectQuarterOutputExcelBuilder.QuarterRow> buildProjectQuarterOutputRows( private List<ProjectQuarterOutputExcelBuilder.QuarterRow> buildProjectQuarterOutputRows(
List<ProjectPlanningDO> planningList, Map<Long, List<ProjectPlanningQuarterDO>> quarterMap, List<ProjectPlanningDO> planningList, Map<Long, List<ProjectPlanningQuarterDO>> quarterMap,
Map<Long, ProjectOutputSplitDO> outputSplitMap, Integer reportYear) { Map<Long, ProjectOutputSplitDO> outputSplitMap, Integer reportYear) {
@@ -1021,9 +1511,8 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
outputSplit.setYear(resolveReportYear(planning)); outputSplit.setYear(resolveReportYear(planning));
} }
outputSplit.setProjectLeadRatio(ZERO_RATIO); outputSplit.setProjectLeadRatio(ZERO_RATIO);
boolean majorPlanning = planning != null && ProjectPlanningBizTypeConstants.isMajor(planning.getOwnershipType()); outputSplit.setOfficeRatio(FULL_RATIO);
outputSplit.setOfficeRatio(majorPlanning ? FULL_RATIO : ZERO_RATIO); outputSplit.setArchRatio(FULL_RATIO);
outputSplit.setArchRatio(majorPlanning ? FULL_RATIO : ZERO_RATIO);
outputSplit.setDecorRatio(ZERO_RATIO); outputSplit.setDecorRatio(ZERO_RATIO);
outputSplit.setStructRatio(ZERO_RATIO); outputSplit.setStructRatio(ZERO_RATIO);
outputSplit.setWaterRatio(ZERO_RATIO); outputSplit.setWaterRatio(ZERO_RATIO);
@@ -1101,11 +1590,11 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
if (planningList == null || planningList.isEmpty()) { if (planningList == null || planningList.isEmpty()) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
Map<Long, List<SpecialtyRoleSplitRespVO>> map = new LinkedHashMap<>(); List<Long> planningIds = planningList.stream()
for (ProjectPlanningDO planning : planningList) { .map(ProjectPlanningDO::getId)
map.put(planning.getId(), specialtyRoleSplitService.getSpecialtyRoleSplitListByPlanningId(planning.getId())); .filter(Objects::nonNull)
} .collect(Collectors.toList());
return map; return specialtyRoleSplitService.getSpecialtyRoleSplitListMapByPlanningIds(planningIds);
} }
private Map<Long, ProjectDO> getProjectMap(Collection<ProjectPlanningDO> planningList) { private Map<Long, ProjectDO> getProjectMap(Collection<ProjectPlanningDO> planningList) {
@@ -1492,14 +1981,24 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
private void accumulateSpecialtyPersonAmount(SpecialtyPersonOutputExcelBuilder.PersonAmountValue value, private void accumulateSpecialtyPersonAmount(SpecialtyPersonOutputExcelBuilder.PersonAmountValue value,
QuarterSummary quarterSummary, QuarterSummary quarterSummary,
BigDecimal amountRatio) { BigDecimal amountRatio) {
value.setQuarterOneRatio(addRatio(value.getQuarterOneRatio(),
multiplyRatio(quarterSummary.getQuarterOneRatio(), amountRatio)));
value.setQuarterOneAmountWan(addAmountValue(value.getQuarterOneAmountWan(), value.setQuarterOneAmountWan(addAmountValue(value.getQuarterOneAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterOneAmount(), amountRatio)))); amountToWan(multiplyAmount(quarterSummary.getQuarterOneAmount(), amountRatio))));
value.setQuarterTwoRatio(addRatio(value.getQuarterTwoRatio(),
multiplyRatio(quarterSummary.getQuarterTwoRatio(), amountRatio)));
value.setQuarterTwoAmountWan(addAmountValue(value.getQuarterTwoAmountWan(), value.setQuarterTwoAmountWan(addAmountValue(value.getQuarterTwoAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterTwoAmount(), amountRatio)))); amountToWan(multiplyAmount(quarterSummary.getQuarterTwoAmount(), amountRatio))));
value.setQuarterThreeRatio(addRatio(value.getQuarterThreeRatio(),
multiplyRatio(quarterSummary.getQuarterThreeRatio(), amountRatio)));
value.setQuarterThreeAmountWan(addAmountValue(value.getQuarterThreeAmountWan(), value.setQuarterThreeAmountWan(addAmountValue(value.getQuarterThreeAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterThreeAmount(), amountRatio)))); amountToWan(multiplyAmount(quarterSummary.getQuarterThreeAmount(), amountRatio))));
value.setQuarterFourRatio(addRatio(value.getQuarterFourRatio(),
multiplyRatio(quarterSummary.getQuarterFourRatio(), amountRatio)));
value.setQuarterFourAmountWan(addAmountValue(value.getQuarterFourAmountWan(), value.setQuarterFourAmountWan(addAmountValue(value.getQuarterFourAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getQuarterFourAmount(), amountRatio)))); amountToWan(multiplyAmount(quarterSummary.getQuarterFourAmount(), amountRatio))));
value.setYearTotalRatio(addRatio(value.getYearTotalRatio(),
multiplyRatio(quarterSummary.getCurrentYearRatio(), amountRatio)));
value.setYearTotalAmountWan(addAmountValue(value.getYearTotalAmountWan(), value.setYearTotalAmountWan(addAmountValue(value.getYearTotalAmountWan(),
amountToWan(multiplyAmount(quarterSummary.getYearTotalAmount(), amountRatio)))); amountToWan(multiplyAmount(quarterSummary.getYearTotalAmount(), amountRatio))));
} }
@@ -1886,6 +2385,24 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic
return value == null ? "" : value.trim(); return value == null ? "" : value.trim();
} }
@Data
private static class SpecialtyPersonOutputBuildResult {
private ProjectPlanningDO anchorPlanning;
private ProjectDO project;
private Integer reportYear;
private SpecialtyPersonOutputExcelBuilder.ExportData data;
}
@Data
private static class SpecialtyQuarterPreviewAggregate {
private BigDecimal specialtyQuarterOneAmountWan = ZERO_AMOUNT;
private BigDecimal specialtyQuarterTwoAmountWan = ZERO_AMOUNT;
private BigDecimal specialtyQuarterThreeAmountWan = ZERO_AMOUNT;
private BigDecimal specialtyQuarterFourAmountWan = ZERO_AMOUNT;
private BigDecimal specialtyYearTotalAmountWan = ZERO_AMOUNT;
private Map<String, SpecialtyPersonOutputExcelBuilder.PersonAmountValue> rolePersonAmountMap = new LinkedHashMap<>();
}
@Data @Data
private static class PlanningOfficeContribution { private static class PlanningOfficeContribution {
private BigDecimal totalOutputAmount = ZERO_AMOUNT; private BigDecimal totalOutputAmount = ZERO_AMOUNT;

View File

@@ -637,10 +637,15 @@ public class SpecialtyPersonOutputExcelBuilder extends AbstractProjectOutputExce
@Data @Data
public static class PersonAmountValue { public static class PersonAmountValue {
private BigDecimal quarterOneRatio;
private BigDecimal quarterOneAmountWan; private BigDecimal quarterOneAmountWan;
private BigDecimal quarterTwoRatio;
private BigDecimal quarterTwoAmountWan; private BigDecimal quarterTwoAmountWan;
private BigDecimal quarterThreeRatio;
private BigDecimal quarterThreeAmountWan; private BigDecimal quarterThreeAmountWan;
private BigDecimal quarterFourRatio;
private BigDecimal quarterFourAmountWan; private BigDecimal quarterFourAmountWan;
private BigDecimal yearTotalRatio;
private BigDecimal yearTotalAmountWan; private BigDecimal yearTotalAmountWan;
} }

View File

@@ -3,7 +3,9 @@ package cn.iocoder.lyzsys.module.tjt.service.specialtyrolesplit;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitBatchSaveReqVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitBatchSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitRespVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitRespVO;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 页面5角色比例 Service 接口 * 页面5角色比例 Service 接口
@@ -14,6 +16,8 @@ public interface SpecialtyRoleSplitService {
List<SpecialtyRoleSplitRespVO> getSpecialtyRoleSplitListByPlanningId(Long planningId); List<SpecialtyRoleSplitRespVO> getSpecialtyRoleSplitListByPlanningId(Long planningId);
Map<Long, List<SpecialtyRoleSplitRespVO>> getSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds);
void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO); void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO);
void deleteByOutputSplitId(Long outputSplitId); void deleteByOutputSplitId(Long outputSplitId);

View File

@@ -1,48 +1,34 @@
package cn.iocoder.lyzsys.module.tjt.service.specialtyrolesplit; package cn.iocoder.lyzsys.module.tjt.service.specialtyrolesplit;
import cn.iocoder.lyzsys.framework.common.util.json.JsonUtils;
import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils; import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRolePersonRespVO; import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.*;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRolePersonSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitBatchSaveReqVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitRespVO;
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitSaveItemReqVO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.outputsplit.ProjectOutputSplitDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.outputsplit.ProjectOutputSplitDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planning.ProjectPlanningDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planning.ProjectPlanningDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.project.ProjectDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.project.ProjectDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.projectroleperson.ProjectRolePersonDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.projectroleperson.ProjectRolePersonDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplit.SpecialtyRoleSplitDO; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplit.SpecialtyRoleSplitDO;
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplitperson.SpecialtyRoleSplitPersonDO;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.planning.ProjectPlanningMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.planning.ProjectPlanningMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.project.ProjectMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.project.ProjectMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson.ProjectRolePersonMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson.ProjectRolePersonMapper;
import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplit.SpecialtyRoleSplitMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.specialtyrolesplit.SpecialtyRoleSplitMapper;
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.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.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_NOT_EXISTS; import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.*;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_OUTPUT_SPLIT_PLANNING_NOT_EXISTS;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_ROLE_SPLIT_DESIGN_PERSON_REQUIRED;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_ROLE_SPLIT_PERSON_INVALID;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_ROLE_SPLIT_PERSON_RATIO_INVALID;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_ROLE_SPLIT_ROLE_INVALID;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_ROLE_SPLIT_ROLE_RATIO_INVALID;
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_ROLE_SPLIT_SPECIALTY_INVALID;
@Service @Service
@Validated @Validated
@@ -58,6 +44,8 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
@Resource @Resource
private SpecialtyRoleSplitMapper specialtyRoleSplitMapper; private SpecialtyRoleSplitMapper specialtyRoleSplitMapper;
@Resource @Resource
private SpecialtyRoleSplitPersonMapper specialtyRoleSplitPersonMapper;
@Resource
private ProjectOutputSplitService projectOutputSplitService; private ProjectOutputSplitService projectOutputSplitService;
@Resource @Resource
private ProjectPlanningMapper projectPlanningMapper; private ProjectPlanningMapper projectPlanningMapper;
@@ -71,15 +59,102 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
@Override @Override
public List<SpecialtyRoleSplitRespVO> getSpecialtyRoleSplitListByPlanningId(Long planningId) { public List<SpecialtyRoleSplitRespVO> getSpecialtyRoleSplitListByPlanningId(Long planningId) {
ProjectPlanningDO planning = validatePlanningExists(planningId); ProjectPlanningDO planning = validatePlanningExists(planningId);
ProjectDO project = validateProjectExists(planning.getProjectId()); validateProjectExists(planning.getProjectId());
ProjectOutputSplitDO outputSplit = projectOutputSplitService.getOrCreateProjectOutputSplit(planningId); return getSpecialtyRoleSplitListMapByPlanningIds(Collections.singletonList(planningId))
List<SpecialtyRoleSplitDO> dbList = specialtyRoleSplitMapper.selectListByOutputSplitId(outputSplit.getId()); .getOrDefault(planningId, Collections.emptyList());
Map<String, SpecialtyRoleSplitDO> dbMap = dbList.stream().collect(Collectors.toMap( }
item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b));
Map<String, List<ProjectRolePersonDO>> projectRolePersonMap = projectRolePersonMapper
.selectListByProjectId(project.getId()).stream()
.collect(Collectors.groupingBy(ProjectRolePersonDO::getRoleCode, LinkedHashMap::new, Collectors.toList()));
@Override
public Map<Long, List<SpecialtyRoleSplitRespVO>> getSpecialtyRoleSplitListMapByPlanningIds(Collection<Long> planningIds) {
if (planningIds == null || planningIds.isEmpty()) {
return Collections.emptyMap();
}
List<Long> normalizedPlanningIds = planningIds.stream()
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (normalizedPlanningIds.isEmpty()) {
return Collections.emptyMap();
}
Map<Long, ProjectPlanningDO> planningMap = projectPlanningMapper.selectBatchIds(normalizedPlanningIds).stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(ProjectPlanningDO::getId, item -> item, (a, b) -> a, LinkedHashMap::new));
if (planningMap.isEmpty()) {
return Collections.emptyMap();
}
Set<Long> projectIds = planningMap.values().stream()
.map(ProjectPlanningDO::getProjectId)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
Map<Long, ProjectDO> projectMap = projectIds.isEmpty()
? Collections.emptyMap()
: projectMapper.selectBatchIds(projectIds).stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(ProjectDO::getId, item -> item, (a, b) -> a, LinkedHashMap::new));
Map<Long, ProjectOutputSplitDO> outputSplitMap = new LinkedHashMap<>(
projectOutputSplitService.getProjectOutputSplitMap(planningMap.keySet()));
for (ProjectPlanningDO planning : planningMap.values()) {
if (!outputSplitMap.containsKey(planning.getId())) {
outputSplitMap.put(planning.getId(),
projectOutputSplitService.getOrCreateProjectOutputSplit(planning.getId()));
}
}
List<Long> outputSplitIds = outputSplitMap.values().stream()
.filter(Objects::nonNull)
.map(ProjectOutputSplitDO::getId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
Map<Long, List<SpecialtyRoleSplitDO>> roleSplitMap = specialtyRoleSplitMapper
.selectListByOutputSplitIds(outputSplitIds).stream()
.collect(Collectors.groupingBy(SpecialtyRoleSplitDO::getOutputSplitId,
LinkedHashMap::new, Collectors.toList()));
List<Long> roleSplitIds = roleSplitMap.values().stream()
.flatMap(Collection::stream)
.map(SpecialtyRoleSplitDO::getId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
Map<Long, List<SpecialtyRoleSplitPersonDO>> personMap = specialtyRoleSplitPersonMapper
.selectListByRoleSplitIds(roleSplitIds)
.stream()
.collect(Collectors.groupingBy(SpecialtyRoleSplitPersonDO::getRoleSplitId,
LinkedHashMap::new, Collectors.toList()));
Map<Long, Map<String, List<ProjectRolePersonDO>>> projectRolePersonMap = projectRolePersonMapper
.selectListByProjectIds(projectIds).stream()
.collect(Collectors.groupingBy(ProjectRolePersonDO::getProjectId, LinkedHashMap::new,
Collectors.groupingBy(ProjectRolePersonDO::getRoleCode, LinkedHashMap::new, Collectors.toList())));
Map<Long, List<SpecialtyRoleSplitRespVO>> result = new LinkedHashMap<>();
for (Long planningId : normalizedPlanningIds) {
ProjectPlanningDO planning = planningMap.get(planningId);
if (planning == null) {
continue;
}
ProjectOutputSplitDO outputSplit = outputSplitMap.get(planningId);
if (outputSplit == null) {
continue;
}
ProjectDO project = projectMap.get(planning.getProjectId());
List<SpecialtyRoleSplitDO> roleList = roleSplitMap.getOrDefault(outputSplit.getId(), Collections.emptyList());
Map<String, List<ProjectRolePersonDO>> projectPersons = projectRolePersonMap
.getOrDefault(planning.getProjectId(), Collections.emptyMap());
result.put(planningId, buildRoleSplitRespList(planning, project, outputSplit, roleList, projectPersons, personMap));
}
return result;
}
private List<SpecialtyRoleSplitRespVO> buildRoleSplitRespList(ProjectPlanningDO planning,
ProjectDO project,
ProjectOutputSplitDO outputSplit,
List<SpecialtyRoleSplitDO> dbList,
Map<String, List<ProjectRolePersonDO>> projectRolePersonMap,
Map<Long, List<SpecialtyRoleSplitPersonDO>> personMap) {
List<SpecialtyRoleSplitDO> safeDbList = dbList == null ? Collections.emptyList() : dbList;
Map<String, SpecialtyRoleSplitDO> dbMap = safeDbList.stream().collect(Collectors.toMap(
item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b));
List<SpecialtyRoleSplitRespVO> result = new ArrayList<>(); List<SpecialtyRoleSplitRespVO> result = new ArrayList<>();
BigDecimal assessmentOutputValue = planning.getAssessmentOutputValue(); BigDecimal assessmentOutputValue = planning.getAssessmentOutputValue();
for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) { for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) {
@@ -92,7 +167,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
dbItem, specialtyItem.getCode(), roleItem.getCode(), defaultRoleRatioMap); dbItem, specialtyItem.getCode(), roleItem.getCode(), defaultRoleRatioMap);
BigDecimal roleAmount = multiplyAmount(specialtyAmount, roleRatio); BigDecimal roleAmount = multiplyAmount(specialtyAmount, roleRatio);
List<SpecialtyRolePersonRespVO> persons = buildRespPersons( List<SpecialtyRolePersonRespVO> persons = buildRespPersons(
dbItem, specialtyItem.getCode(), roleItem.getCode(), roleAmount, roleRatio, projectRolePersonMap); dbItem, specialtyItem.getCode(), roleItem.getCode(), roleAmount, projectRolePersonMap, personMap);
SpecialtyRoleSplitRespVO respVO = dbItem == null SpecialtyRoleSplitRespVO respVO = dbItem == null
? new SpecialtyRoleSplitRespVO() ? new SpecialtyRoleSplitRespVO()
: BeanUtils.toBean(dbItem, SpecialtyRoleSplitRespVO.class); : BeanUtils.toBean(dbItem, SpecialtyRoleSplitRespVO.class);
@@ -102,7 +177,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
+ OutputSplitBizConstants.getRoleSortNo(roleItem.getCode())); + OutputSplitBizConstants.getRoleSortNo(roleItem.getCode()));
} }
respVO.setPlanningId(planning.getId()); respVO.setPlanningId(planning.getId());
respVO.setProjectName(project.getProjectName()); respVO.setProjectName(project == null ? "" : project.getProjectName());
respVO.setPlanningContent(planning.getPlanningContent()); respVO.setPlanningContent(planning.getPlanningContent());
respVO.setSpecialtyCode(specialtyItem.getCode()); respVO.setSpecialtyCode(specialtyItem.getCode());
respVO.setSpecialtyName(specialtyItem.getName()); respVO.setSpecialtyName(specialtyItem.getName());
@@ -119,6 +194,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO) { public void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO) {
ProjectPlanningDO planning = validatePlanningExists(reqVO.getPlanningId()); ProjectPlanningDO planning = validatePlanningExists(reqVO.getPlanningId());
ProjectOutputSplitDO outputSplit = projectOutputSplitService.getOrCreateProjectOutputSplit(reqVO.getPlanningId()); ProjectOutputSplitDO outputSplit = projectOutputSplitService.getOrCreateProjectOutputSplit(reqVO.getPlanningId());
@@ -140,25 +216,28 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
getSavePersons(roleMap, roleItem.getCode())); getSavePersons(roleMap, roleItem.getCode()));
validateRolePersons(roleItem.getCode(), roleAmount, persons); validateRolePersons(roleItem.getCode(), roleAmount, persons);
roleTotal = roleTotal.add(roleRatio).setScale(RATIO_SCALE, RoundingMode.HALF_UP); roleTotal = roleTotal.add(roleRatio).setScale(RATIO_SCALE, RoundingMode.HALF_UP);
upsertRole(dbMap, outputSplit.getId(), specialtyItem.getCode(), specialtyItem.getName(), SpecialtyRoleSplitDO role = upsertRole(dbMap, outputSplit.getId(), specialtyItem.getCode(),
roleItem.getCode(), roleRatio, specialtyItem.getName(), roleItem.getCode(), roleRatio);
OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyItem.getCode()) refreshRolePersons(role, outputSplit, persons);
? null : toPersonJson(persons));
} }
validateRoleTotal(roleTotal); validateRoleTotal(roleTotal);
} }
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void deleteByOutputSplitId(Long outputSplitId) { public void deleteByOutputSplitId(Long outputSplitId) {
specialtyRoleSplitPersonMapper.deleteByOutputSplitId(outputSplitId);
specialtyRoleSplitMapper.delete(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitId); specialtyRoleSplitMapper.delete(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitId);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void deleteByOutputSplitIds(List<Long> outputSplitIds) { public void deleteByOutputSplitIds(List<Long> outputSplitIds) {
if (outputSplitIds == null || outputSplitIds.isEmpty()) { if (outputSplitIds == null || outputSplitIds.isEmpty()) {
return; return;
} }
specialtyRoleSplitPersonMapper.deleteByOutputSplitIds(outputSplitIds);
specialtyRoleSplitMapper.delete(new cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX<SpecialtyRoleSplitDO>() specialtyRoleSplitMapper.delete(new cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX<SpecialtyRoleSplitDO>()
.in(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitIds)); .in(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitIds));
} }
@@ -181,8 +260,9 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
return result; return result;
} }
private void upsertRole(Map<String, SpecialtyRoleSplitDO> dbMap, Long outputSplitId, String specialtyCode, private SpecialtyRoleSplitDO upsertRole(Map<String, SpecialtyRoleSplitDO> dbMap, Long outputSplitId,
String specialtyName, String roleCode, BigDecimal roleRatio, String personsJson) { String specialtyCode, String specialtyName, String roleCode,
BigDecimal roleRatio) {
String key = specialtyCode + ":" + roleCode; String key = specialtyCode + ":" + roleCode;
SpecialtyRoleSplitDO dbItem = dbMap.get(key); SpecialtyRoleSplitDO dbItem = dbMap.get(key);
Integer sortNo = dbItem != null && dbItem.getSortNo() != null Integer sortNo = dbItem != null && dbItem.getSortNo() != null
@@ -197,10 +277,10 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
createObj.setRoleCode(roleCode); createObj.setRoleCode(roleCode);
createObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode)); createObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode));
createObj.setRoleRatio(ratio(roleRatio)); createObj.setRoleRatio(ratio(roleRatio));
createObj.setPersonsJson(personsJson);
createObj.setSortNo(sortNo); createObj.setSortNo(sortNo);
specialtyRoleSplitMapper.insert(createObj); specialtyRoleSplitMapper.insert(createObj);
return; dbMap.put(key, createObj);
return createObj;
} }
SpecialtyRoleSplitDO updateObj = new SpecialtyRoleSplitDO(); SpecialtyRoleSplitDO updateObj = new SpecialtyRoleSplitDO();
updateObj.setId(dbItem.getId()); updateObj.setId(dbItem.getId());
@@ -210,9 +290,46 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
updateObj.setRoleCode(roleCode); updateObj.setRoleCode(roleCode);
updateObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode)); updateObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode));
updateObj.setRoleRatio(ratio(roleRatio)); updateObj.setRoleRatio(ratio(roleRatio));
updateObj.setPersonsJson(personsJson);
updateObj.setSortNo(sortNo); updateObj.setSortNo(sortNo);
specialtyRoleSplitMapper.updateById(updateObj); specialtyRoleSplitMapper.updateById(updateObj);
dbMap.put(key, updateObj);
return updateObj;
}
private void refreshRolePersons(SpecialtyRoleSplitDO role, ProjectOutputSplitDO outputSplit,
List<SpecialtyRolePersonSaveReqVO> persons) {
if (role == null || role.getId() == null) {
return;
}
specialtyRoleSplitPersonMapper.deleteByRoleSplitId(role.getId());
if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(role.getSpecialtyCode())
|| persons == null || persons.isEmpty()) {
return;
}
List<SpecialtyRoleSplitPersonDO> createList = new ArrayList<>();
for (int i = 0; i < persons.size(); i++) {
SpecialtyRolePersonSaveReqVO person = persons.get(i);
if (person == null || person.getEmployeeId() == null) {
continue;
}
SpecialtyRoleSplitPersonDO createObj = new SpecialtyRoleSplitPersonDO();
createObj.setRoleSplitId(role.getId());
createObj.setOutputSplitId(outputSplit.getId());
createObj.setProjectId(outputSplit.getProjectId());
createObj.setPlanningId(outputSplit.getPlanningId());
createObj.setSpecialtyCode(role.getSpecialtyCode());
createObj.setSpecialtyName(role.getSpecialtyName());
createObj.setRoleCode(role.getRoleCode());
createObj.setRoleName(role.getRoleName());
createObj.setEmployeeId(person.getEmployeeId());
createObj.setEmployeeName(person.getEmployeeName());
createObj.setPersonRatio(ratio(person.getPersonRatio()));
createObj.setSortNo(i + 1);
createList.add(createObj);
}
if (!createList.isEmpty()) {
specialtyRoleSplitPersonMapper.insertBatch(createList);
}
} }
private List<SpecialtyRolePersonSaveReqVO> getSavePersons(Map<String, SpecialtyRoleSplitSaveItemReqVO> roleMap, private List<SpecialtyRolePersonSaveReqVO> getSavePersons(Map<String, SpecialtyRoleSplitSaveItemReqVO> roleMap,
@@ -298,13 +415,13 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
private List<SpecialtyRolePersonRespVO> buildRespPersons(SpecialtyRoleSplitDO dbItem, String specialtyCode, private List<SpecialtyRolePersonRespVO> buildRespPersons(SpecialtyRoleSplitDO dbItem, String specialtyCode,
String roleCode, BigDecimal roleAmount, String roleCode, BigDecimal roleAmount,
BigDecimal roleRatio, Map<String, List<ProjectRolePersonDO>> projectRolePersonMap,
Map<String, List<ProjectRolePersonDO>> projectRolePersonMap) { Map<Long, List<SpecialtyRoleSplitPersonDO>> personMap) {
List<SpecialtyRolePersonSaveReqVO> sourcePersons; List<SpecialtyRolePersonSaveReqVO> sourcePersons;
if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) { if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) {
sourcePersons = buildDefaultProjectLeadPersons(projectRolePersonMap.get(roleCode)); sourcePersons = buildDefaultProjectLeadPersons(projectRolePersonMap.get(roleCode));
} else { } else {
sourcePersons = parseStoredPersons(dbItem); sourcePersons = buildStoredPersons(dbItem, personMap);
} }
List<SpecialtyRolePersonRespVO> result = new ArrayList<>(); List<SpecialtyRolePersonRespVO> result = new ArrayList<>();
for (SpecialtyRolePersonSaveReqVO person : sourcePersons) { for (SpecialtyRolePersonSaveReqVO person : sourcePersons) {
@@ -318,12 +435,13 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
return result; return result;
} }
private List<SpecialtyRolePersonSaveReqVO> parseStoredPersons(SpecialtyRoleSplitDO dbItem) { private List<SpecialtyRolePersonSaveReqVO> buildStoredPersons(SpecialtyRoleSplitDO dbItem,
if (dbItem == null || dbItem.getPersonsJson() == null || dbItem.getPersonsJson().trim().isEmpty()) { Map<Long, List<SpecialtyRoleSplitPersonDO>> personMap) {
if (dbItem == null || dbItem.getId() == null || personMap == null || personMap.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
List<SpecialtyRolePersonSaveReqVO> persons = JsonUtils.parseArray(dbItem.getPersonsJson(), SpecialtyRolePersonSaveReqVO.class); List<SpecialtyRoleSplitPersonDO> persons = personMap.get(dbItem.getId());
if (persons == null) { if (persons == null || persons.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
return persons.stream() return persons.stream()
@@ -401,10 +519,6 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
return projectOutputSplitService.getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyCode); return projectOutputSplitService.getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyCode);
} }
private String toPersonJson(List<SpecialtyRolePersonSaveReqVO> persons) {
return persons == null || persons.isEmpty() ? null : JsonUtils.toJsonString(persons);
}
private BigDecimal sumPersonRatios(List<SpecialtyRolePersonSaveReqVO> persons) { private BigDecimal sumPersonRatios(List<SpecialtyRolePersonSaveReqVO> persons) {
BigDecimal sum = ZERO_RATIO; BigDecimal sum = ZERO_RATIO;
if (persons == null || persons.isEmpty()) { if (persons == null || persons.isEmpty()) {

View File

@@ -51,18 +51,18 @@ spring:
# url: jdbc:sqlserver://47.106.184.244:14333;DatabaseName=tjt_czjs;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # url: jdbc:sqlserver://47.106.184.244:14333;DatabaseName=tjt_czjs;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8
# username: sa # SQL Server 连接的示例 # username: sa # SQL Server 连接的示例
# password: sql123456 # SQL Server 连接的示例 # password: sql123456 # SQL Server 连接的示例
url: jdbc:sqlserver://localhost:1433;DatabaseName=tjt_czjs;SelectMethod=cursor;encrypt=false;trustServerCertificate=true;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 url: jdbc:sqlserver://47.106.184.244:14333;DatabaseName=tjt_czjs;SelectMethod=cursor;encrypt=false;trustServerCertificate=true;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8
username: tjt_user # SQL Server 连接的示例 username: tjt_user # SQL Server 连接的示例
password: tjt@Admin2026 # SQL Server 连接的示例 password: tjt@Admin2026 # SQL Server 连接的示例
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis: redis:
host: 127.0.0.1 # 地址 # host: 127.0.0.1 # 地址
# host: 8.163.1.126 host: 8.163.1.126
port: 6379 # 端口 port: 6379 # 端口
database: 8 # 数据库索引 database: 8 # 数据库索引
password: lyzsys@2026 # password: lyzsys@2026
# password: lyzbim2016 password: lyzbim2016
--- #################### 定时任务相关配置 #################### --- #################### 定时任务相关配置 ####################

View File

@@ -0,0 +1,251 @@
server:
port: 48080
--- #################### 数据库相关配置 ####################
spring:
autoconfigure:
# noinspection SpringBootApplicationYaml
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
- org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant手动创建
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus手动创建
# 数据源配置项
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: # 控制台管理用户名和密码
login-password:
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量
max-active: 5 # 最大连接池数量
max-wait: 60000 # 配置获取连接等待超时的时间单位毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测检测需要关闭的空闲连接单位毫秒1 分钟)
min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间单位毫秒10 分钟)
max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间单位毫秒30 分钟)
validation-query: SELECT 1 # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master
datasource:
master:
url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=tjt_czjs;SelectMethod=cursor;encrypt=false;trustServerCertificate=true;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8
username: tjt_user # SQL Server 连接的示例
password: tjt@Admin2026 # SQL Server 连接的示例
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 127.0.0.1 # 地址
port: 6379 # 端口
database: 8 # 数据库索引
password: lyzsys@2026
--- #################### 定时任务相关配置 ####################
# Quartz 配置项,对应 QuartzProperties 配置类
spring:
quartz:
auto-startup: true # 本地开发环境,尽量不要开启 Job
scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档
org:
quartz:
# Scheduler 相关配置
scheduler:
instanceName: schedulerName
instanceId: AUTO # 自动生成 instance ID
# JobStore 相关配置
jobStore:
# JobStore 实现类。可见博客https://blog.csdn.net/weixin_42458219/article/details/122247162
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
isClustered: true # 是集群模式
clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000即 15 秒
misfireThreshold: 60000 # misfire 阀值,单位:毫秒。
# 线程池相关配置
threadPool:
threadCount: 25 # 线程池大小。默认为 10 。
threadPriority: 5 # 线程优先级
class: org.quartz.simpl.SimpleThreadPool # 线程池类型
jdbc: # 使用 JDBC 的 JobStore 的时候JDBC 的配置
initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。
--- #################### 消息队列相关 ####################
# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
name-server: 127.0.0.1:9876 # RocketMQ Namesrv
spring:
# RabbitMQ 配置项,对应 RabbitProperties 配置类
rabbitmq:
host: 127.0.0.1 # RabbitMQ 服务的地址
port: 5672 # RabbitMQ 服务的端口
username: rabbit # RabbitMQ 服务的账号
password: rabbit # RabbitMQ 服务的密码
# Kafka 配置项,对应 KafkaProperties 配置类
kafka:
bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项
lock4j:
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
endpoints:
web:
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
exposure:
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
# Spring Boot Admin 配置项
spring:
boot:
admin:
# Spring Boot Admin Client 客户端的相关配置
client:
url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址
instance:
service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
username: admin
password: admin
# Spring Boot Admin Server 服务端的相关配置
context-path: /admin # 配置 Spring
# 日志文件配置
logging:
file:
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
level:
# 配置自己写的 MyBatis Mapper 打印日志
cn.iocoder.lyzsys.module.bpm.dal.mysql: debug
cn.iocoder.lyzsys.module.infra.dal.mysql: debug
cn.iocoder.lyzsys.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info避免和 GlobalExceptionHandler 重复打印
cn.iocoder.lyzsys.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info
cn.iocoder.lyzsys.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info
cn.iocoder.lyzsys.module.pay.dal.mysql: debug
cn.iocoder.lyzsys.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info
cn.iocoder.lyzsys.module.system.dal.mysql: debug
cn.iocoder.lyzsys.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
cn.iocoder.lyzsys.module.tool.dal.mysql: debug
cn.iocoder.lyzsys.module.member.dal.mysql: debug
cn.iocoder.lyzsys.module.trade.dal.mysql: debug
cn.iocoder.lyzsys.module.promotion.dal.mysql: debug
cn.iocoder.lyzsys.module.statistics.dal.mysql: debug
cn.iocoder.lyzsys.module.crm.dal.mysql: debug
cn.iocoder.lyzsys.module.erp.dal.mysql: debug
cn.iocoder.lyzsys.module.iot.dal.mysql: debug
cn.iocoder.lyzsys.module.iot.dal.tdengine: DEBUG
cn.iocoder.lyzsys.module.iot.service.rule: debug
cn.iocoder.lyzsys.module.ai.dal.mysql: debug
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示
debug: false
--- #################### 微信公众号、小程序相关配置 ####################
wx:
mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档
# app-id: wx041349c6f39b268b # 测试号(牛希尧提供的)
# secret: 5abee519483bc9f8cb37ce280e814bd0
# app-id: wx5b23ba7a5589ecbb # 测试号(自己的)
# secret: 2a7b3b20c537e52e74afd395eb85f61f
app-id: wxf56b1542b9e85f8a # 测试号Kongdy 提供的)
secret: 496379dcef1ba869e9234de8d598cfd3
# 存储配置,解决 AccessToken 的跨节点的共享
config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis会自动从 Spring 中获取
key-prefix: wx # Redis Key 的前缀
http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档
# appid: wx62056c0d5e8db250 # 测试号(牛希尧提供的)
# secret: 333ae72f41552af1e998fe1f54e1584a
# appid: wx63c280fe3248a3e7 # wenhualian的接口测试号
# secret: 6f270509224a7ae1296bbf1c8cb97aed
appid: wxc4598c446f8a9cb3 # 测试号Kongdy 提供的)
secret: 4a1a04e07f6a4a0751b39c3064a92c8b
# appid: wx66186af0759f47c9 # 测试号puhui 提供的)
# secret: 3218bcbd112cbc614c7264ceb20144ac
config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis会自动从 Spring 中获取
key-prefix: wa # Redis Key 的前缀
http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置
lyzsys:
captcha:
enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试;
security:
mock-enable: true
pay:
order-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
refund-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
transfer-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址
access-log: # 访问日志的配置项
enable: false
demo: false # 关闭演示模式
wxa-code:
env-version: develop # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop"
wxa-subscribe-message:
miniprogram-state: developer # 跳转小程序类型:开发版为 “developer”体验版为 “trial”为正式版为 “formal”
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
justauth:
enabled: true
type:
DINGTALK: # 钉钉
client-id: dingvrnreaje3yqvzhxg
client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI
ignore-check-redirect-uri: true
WECHAT_ENTERPRISE: # 企业微信
client-id: wwd411c69a39ad2e54
client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw
agent-id: 1000004
ignore-check-redirect-uri: true
# noinspection SpringBootApplicationYaml
WECHAT_MINI_PROGRAM: # 微信小程序
client-id: ${wx.miniapp.appid}
client-secret: ${wx.miniapp.secret}
ignore-check-redirect-uri: true
ignore-check-state: true # 微信小程序,不会使用到 state所以不进行校验
WECHAT_MP: # 微信公众号
client-id: ${wx.mp.app-id}
client-secret: ${wx.mp.secret}
ignore-check-redirect-uri: true
ALIPAY: # 支付宝小程序
client-id: xx
client-secret: xx
alipay-public-key: xx
ignore-check-redirect-uri: true
ignore-check-state: true
cache:
type: REDIS
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟