diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/EmployeeController.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/EmployeeController.java index 6634cd4..1d55bd3 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/EmployeeController.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/EmployeeController.java @@ -74,8 +74,9 @@ public class EmployeeController { @RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "officeId", required = false) Long officeId, @RequestParam(value = "status", required = false) String status, - @RequestParam(value = "enabledFlag", required = false) Boolean enabledFlag) { - return success(employeeService.getEmployeeSimpleList(keyword, officeId, status, enabledFlag)); + @RequestParam(value = "enabledFlag", required = false) Boolean enabledFlag, + @RequestParam(value = "officeLeaderFlag", required = false) Boolean officeLeaderFlag) { + return success(employeeService.getEmployeeSimpleList(keyword, officeId, status, enabledFlag, officeLeaderFlag)); } } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeePageReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeePageReqVO.java index 8f53e89..805f462 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeePageReqVO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeePageReqVO.java @@ -22,4 +22,7 @@ public class EmployeePageReqVO extends PageParam { @Schema(description = "是否启用", example = "true") private Boolean enabledFlag; + @Schema(description = "是否所长", example = "false") + private Boolean officeLeaderFlag; + } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeRespVO.java index 35a0d1c..2440478 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeRespVO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeRespVO.java @@ -46,6 +46,9 @@ public class EmployeeRespVO { @Schema(description = "备注") private String remark; + @Schema(description = "是否所长") + private Boolean officeLeaderFlag; + @Schema(description = "排序号") private Integer sortNo; diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSaveReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSaveReqVO.java index b73ea28..78ef5fd 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSaveReqVO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSaveReqVO.java @@ -64,6 +64,9 @@ public class EmployeeSaveReqVO { @Size(max = 255, message = "备注长度不能超过 255 个字符") private String remark; + @Schema(description = "是否所长", example = "false") + private Boolean officeLeaderFlag; + @Schema(description = "排序号", example = "1") private Integer sortNo; diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSimpleRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSimpleRespVO.java index 3438270..8904f76 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSimpleRespVO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employee/vo/EmployeeSimpleRespVO.java @@ -28,4 +28,7 @@ public class EmployeeSimpleRespVO { @Schema(description = "职称") private String jobTitle; + @Schema(description = "是否所长") + private Boolean officeLeaderFlag; + } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/EmployeeYearCostBudgetController.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/EmployeeYearCostBudgetController.java index 4a9a3a1..b484d09 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/EmployeeYearCostBudgetController.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/EmployeeYearCostBudgetController.java @@ -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.PageResult; -import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetPageReqVO; -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.controller.admin.employeeyearcostbudget.vo.*; import cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget.EmployeeYearCostBudgetService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -34,6 +32,14 @@ public class EmployeeYearCostBudgetController { return success(employeeYearCostBudgetService.createEmployeeYearCostBudget(createReqVO)); } + @PostMapping("/generate") + @Operation(summary = "按年度生成员工年度成本预算") + @PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:create')") + public CommonResult generateEmployeeYearCostBudget( + @Valid @RequestBody EmployeeYearCostBudgetGenerateReqVO generateReqVO) { + return success(employeeYearCostBudgetService.generateEmployeeYearCostBudget(generateReqVO)); + } + @PutMapping("/update") @Operation(summary = "修改员工年度成本预算") @PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:update')") diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/vo/EmployeeYearCostBudgetGenerateReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/vo/EmployeeYearCostBudgetGenerateReqVO.java new file mode 100644 index 0000000..da09733 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/vo/EmployeeYearCostBudgetGenerateReqVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/vo/EmployeeYearCostBudgetGenerateRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/vo/EmployeeYearCostBudgetGenerateRespVO.java new file mode 100644 index 0000000..ffafb7b --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearcostbudget/vo/EmployeeYearCostBudgetGenerateRespVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/EmployeeYearLeaderOutputController.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/EmployeeYearLeaderOutputController.java new file mode 100644 index 0000000..77093c4 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/EmployeeYearLeaderOutputController.java @@ -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 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 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 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 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 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> getEmployeeYearLeaderOutputPage( + @Valid EmployeeYearLeaderOutputPageReqVO pageReqVO) { + return success(employeeYearLeaderOutputService.getEmployeeYearLeaderOutputPage(pageReqVO)); + } + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputGenerateReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputGenerateReqVO.java new file mode 100644 index 0000000..64b1b32 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputGenerateReqVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputGenerateRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputGenerateRespVO.java new file mode 100644 index 0000000..be42208 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputGenerateRespVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputPageReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputPageReqVO.java new file mode 100644 index 0000000..820258e --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputPageReqVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputRespVO.java new file mode 100644 index 0000000..4238de5 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputRespVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputSaveReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputSaveReqVO.java new file mode 100644 index 0000000..246080b --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/employeeyearleaderoutput/vo/EmployeeYearLeaderOutputSaveReqVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/profit/vo/ProjectProfitRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/profit/vo/ProjectProfitRespVO.java index f216c31..94f110b 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/profit/vo/ProjectProfitRespVO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/profit/vo/ProjectProfitRespVO.java @@ -28,6 +28,9 @@ public class ProjectProfitRespVO { @Schema(description = "最终结算金额") private BigDecimal finalSettlementAmount; + @Schema(description = "有效结算金额,最终结算金额大于 0 时取最终结算金额,否则取合同产值") + private BigDecimal effectiveSettlementAmount; + @Schema(description = "综合所协作金额") private BigDecimal comprehensivePlanningAmount; diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/ProjectOutputReportController.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/ProjectOutputReportController.java index d048460..f669dc2 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/ProjectOutputReportController.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/ProjectOutputReportController.java @@ -1,12 +1,8 @@ package cn.iocoder.lyzsys.module.tjt.controller.admin.report; import cn.iocoder.lyzsys.framework.apilog.core.annotation.ApiAccessLog; -import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.EmployeeOutputSummaryExportReqVO; -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 cn.iocoder.lyzsys.framework.common.pojo.CommonResult; +import cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.*; import cn.iocoder.lyzsys.module.tjt.service.report.ProjectOutputReportService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,6 +18,7 @@ import javax.validation.Valid; import java.io.IOException; import static cn.iocoder.lyzsys.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.lyzsys.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 产值报表导出") @RestController @@ -69,6 +66,22 @@ public class ProjectOutputReportController { 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 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 getProjectOverviewPreview( + @Valid ProjectOverviewExportReqVO reqVO) { + return success(projectOutputReportService.getProjectOverviewPreview(reqVO)); + } + @GetMapping("/project-overview/export-excel") @Operation(summary = "导出项目总览表") @PreAuthorize("@ss.hasPermission('tjt:report-summary:export')") @@ -78,6 +91,14 @@ public class ProjectOutputReportController { projectOutputReportService.exportProjectOverviewExcel(response, reqVO); } + @GetMapping("/employee-output-summary/preview") + @Operation(summary = "预览员工个人考核产值汇总表") + @PreAuthorize("@ss.hasAnyPermissions('tjt:report-summary:query', 'tjt:report-summary:export')") + public CommonResult getEmployeeOutputSummaryPreview( + @Valid EmployeeOutputSummaryExportReqVO reqVO) { + return success(projectOutputReportService.getEmployeeOutputSummaryPreview(reqVO)); + } + @GetMapping("/employee-output-summary/export-excel") @Operation(summary = "导出员工个人考核产值汇总表") @PreAuthorize("@ss.hasPermission('tjt:report-summary:export')") diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/EmployeeOutputSummaryPreviewRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/EmployeeOutputSummaryPreviewRespVO.java new file mode 100644 index 0000000..f121bdc --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/EmployeeOutputSummaryPreviewRespVO.java @@ -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 rows = Collections.emptyList(); + + @Schema(description = "合计行,金额单位:万元") + private EmployeeOutputSummaryExcelRespVO totalRow; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/ProjectOverviewPreviewRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/ProjectOverviewPreviewRespVO.java new file mode 100644 index 0000000..feb2201 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/ProjectOverviewPreviewRespVO.java @@ -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 employeeColumns = Collections.emptyList(); + + @Schema(description = "项目行") + private List 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 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; + + } + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/SpecialtyPersonOutputPreviewReqVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/SpecialtyPersonOutputPreviewReqVO.java new file mode 100644 index 0000000..27b5d96 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/SpecialtyPersonOutputPreviewReqVO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/SpecialtyPersonOutputPreviewRespVO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/SpecialtyPersonOutputPreviewRespVO.java new file mode 100644 index 0000000..e0a04b3 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/controller/admin/report/vo/SpecialtyPersonOutputPreviewRespVO.java @@ -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 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 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 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; + + } + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employee/EmployeeDO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employee/EmployeeDO.java index 6528e3e..e5967f2 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employee/EmployeeDO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employee/EmployeeDO.java @@ -38,6 +38,8 @@ public class EmployeeDO extends TenantBaseDO { private String remark; + private Boolean officeLeaderFlag; + private Integer sortNo; private Boolean enabledFlag; diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employeeyearleaderoutput/EmployeeYearLeaderOutputDO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employeeyearleaderoutput/EmployeeYearLeaderOutputDO.java new file mode 100644 index 0000000..c16ee9d --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/employeeyearleaderoutput/EmployeeYearLeaderOutputDO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplit/SpecialtyRoleSplitDO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplit/SpecialtyRoleSplitDO.java index cc15458..fd0ea89 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplit/SpecialtyRoleSplitDO.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplit/SpecialtyRoleSplitDO.java @@ -35,8 +35,6 @@ public class SpecialtyRoleSplitDO extends TenantBaseDO { private BigDecimal roleRatio; - private String personsJson; - private Integer sortNo; } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplitperson/SpecialtyRoleSplitPersonDO.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplitperson/SpecialtyRoleSplitPersonDO.java new file mode 100644 index 0000000..f5bdbec --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/dataobject/specialtyrolesplitperson/SpecialtyRoleSplitPersonDO.java @@ -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; + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employee/EmployeeMapper.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employee/EmployeeMapper.java index ecf9e51..1e42a02 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employee/EmployeeMapper.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employee/EmployeeMapper.java @@ -18,16 +18,34 @@ public interface EmployeeMapper extends BaseMapperX { .eqIfPresent(EmployeeDO::getOfficeId, reqVO.getOfficeId()) .eqIfPresent(EmployeeDO::getEmployeeStatus, reqVO.getEmployeeStatus()) .eqIfPresent(EmployeeDO::getEnabledFlag, reqVO.getEnabledFlag()) + .eqIfPresent(EmployeeDO::getOfficeLeaderFlag, reqVO.getOfficeLeaderFlag()) .orderByAsc(EmployeeDO::getSortNo) .orderByAsc(EmployeeDO::getId)); } - default List selectSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag) { + default List selectSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag, + Boolean officeLeaderFlag) { return selectList(new LambdaQueryWrapperX() .likeIfPresent(EmployeeDO::getEmployeeName, keyword) .eqIfPresent(EmployeeDO::getOfficeId, officeId) .eqIfPresent(EmployeeDO::getEmployeeStatus, status) .eqIfPresent(EmployeeDO::getEnabledFlag, enabledFlag) + .eqIfPresent(EmployeeDO::getOfficeLeaderFlag, officeLeaderFlag) + .orderByAsc(EmployeeDO::getSortNo) + .orderByAsc(EmployeeDO::getId)); + } + + default List selectEnabledList() { + return selectList(new LambdaQueryWrapperX() + .eq(EmployeeDO::getEnabledFlag, Boolean.TRUE) + .orderByAsc(EmployeeDO::getSortNo) + .orderByAsc(EmployeeDO::getId)); + } + + default List selectEnabledLeaderList() { + return selectList(new LambdaQueryWrapperX() + .eq(EmployeeDO::getEnabledFlag, Boolean.TRUE) + .eq(EmployeeDO::getOfficeLeaderFlag, Boolean.TRUE) .orderByAsc(EmployeeDO::getSortNo) .orderByAsc(EmployeeDO::getId)); } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearcostbudget/EmployeeYearCostBudgetMapper.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearcostbudget/EmployeeYearCostBudgetMapper.java index f7b1972..8531a7a 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearcostbudget/EmployeeYearCostBudgetMapper.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearcostbudget/EmployeeYearCostBudgetMapper.java @@ -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 org.apache.ibatis.annotations.Mapper; +import java.util.List; + @Mapper public interface EmployeeYearCostBudgetMapper extends BaseMapperX { @@ -27,6 +29,11 @@ public interface EmployeeYearCostBudgetMapper extends BaseMapperX selectListByBudgetYear(Integer budgetYear) { + return selectList(new LambdaQueryWrapperX() + .eq(EmployeeYearCostBudgetDO::getBudgetYear, budgetYear)); + } + default Long selectCountByEmployeeId(Long employeeId) { return selectCount(new LambdaQueryWrapperX() .eq(EmployeeYearCostBudgetDO::getEmployeeId, employeeId)); diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearleaderoutput/EmployeeYearLeaderOutputMapper.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearleaderoutput/EmployeeYearLeaderOutputMapper.java new file mode 100644 index 0000000..a3ef9c6 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/employeeyearleaderoutput/EmployeeYearLeaderOutputMapper.java @@ -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 { + + default PageResult selectPage(EmployeeYearLeaderOutputPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .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() + .eq(EmployeeYearLeaderOutputDO::getEmployeeId, employeeId) + .eq(EmployeeYearLeaderOutputDO::getOutputYear, outputYear)); + } + + default List selectListByOutputYear(Integer outputYear) { + return selectList(new LambdaQueryWrapperX() + .eq(EmployeeYearLeaderOutputDO::getOutputYear, outputYear)); + } + + default List selectEnabledListByOutputYear(Integer outputYear, + Collection employeeIds) { + return selectList(new LambdaQueryWrapperX() + .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() + .eq(EmployeeYearLeaderOutputDO::getEmployeeId, employeeId)); + } + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/projectroleperson/ProjectRolePersonMapper.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/projectroleperson/ProjectRolePersonMapper.java index e9ffac5..90caa97 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/projectroleperson/ProjectRolePersonMapper.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/projectroleperson/ProjectRolePersonMapper.java @@ -34,6 +34,19 @@ public interface ProjectRolePersonMapper extends BaseMapperX selectListByEmployeeIds(Collection employeeIds) { + if (employeeIds == null || employeeIds.isEmpty()) { + return Collections.emptyList(); + } + return selectList(new LambdaQueryWrapperX() + .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) { return selectCount(new LambdaQueryWrapperX() .eq(ProjectRolePersonDO::getEmployeeId, employeeId)); diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplit/SpecialtyRoleSplitMapper.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplit/SpecialtyRoleSplitMapper.java index aca69ac..1382311 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplit/SpecialtyRoleSplitMapper.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplit/SpecialtyRoleSplitMapper.java @@ -5,6 +5,8 @@ import cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.lyzsys.module.tjt.dal.dataobject.specialtyrolesplit.SpecialtyRoleSplitDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -22,9 +24,15 @@ public interface SpecialtyRoleSplitMapper extends BaseMapperX selectListByPersonsJsonKeyword(String keyword) { + default List selectListByOutputSplitIds(Collection outputSplitIds) { + if (outputSplitIds == null || outputSplitIds.isEmpty()) { + return Collections.emptyList(); + } return selectList(new LambdaQueryWrapperX() - .like(SpecialtyRoleSplitDO::getPersonsJson, keyword)); + .in(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitIds) + .orderByAsc(SpecialtyRoleSplitDO::getOutputSplitId) + .orderByAsc(SpecialtyRoleSplitDO::getSortNo) + .orderByAsc(SpecialtyRoleSplitDO::getId)); } } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplitperson/SpecialtyRoleSplitPersonMapper.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplitperson/SpecialtyRoleSplitPersonMapper.java new file mode 100644 index 0000000..1eeb1da --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/dal/mysql/specialtyrolesplitperson/SpecialtyRoleSplitPersonMapper.java @@ -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 { + + default List selectListByRoleSplitId(Long roleSplitId) { + return selectList(new LambdaQueryWrapperX() + .eq(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitId) + .orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo) + .orderByAsc(SpecialtyRoleSplitPersonDO::getId)); + } + + default List selectListByRoleSplitIds(Collection roleSplitIds) { + if (roleSplitIds == null || roleSplitIds.isEmpty()) { + return Collections.emptyList(); + } + return selectList(new LambdaQueryWrapperX() + .in(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitIds) + .orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId) + .orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo) + .orderByAsc(SpecialtyRoleSplitPersonDO::getId)); + } + + default List selectListByOutputSplitIds(Collection outputSplitIds) { + if (outputSplitIds == null || outputSplitIds.isEmpty()) { + return Collections.emptyList(); + } + return selectList(new LambdaQueryWrapperX() + .in(SpecialtyRoleSplitPersonDO::getOutputSplitId, outputSplitIds) + .orderByAsc(SpecialtyRoleSplitPersonDO::getOutputSplitId) + .orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId) + .orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo) + .orderByAsc(SpecialtyRoleSplitPersonDO::getId)); + } + + default List selectListByEmployeeIds(Collection employeeIds) { + if (employeeIds == null || employeeIds.isEmpty()) { + return Collections.emptyList(); + } + return selectList(new LambdaQueryWrapperX() + .in(SpecialtyRoleSplitPersonDO::getEmployeeId, employeeIds) + .orderByAsc(SpecialtyRoleSplitPersonDO::getPlanningId) + .orderByAsc(SpecialtyRoleSplitPersonDO::getRoleSplitId) + .orderByAsc(SpecialtyRoleSplitPersonDO::getSortNo) + .orderByAsc(SpecialtyRoleSplitPersonDO::getId)); + } + + default List selectListByPlanningIdsAndEmployeeIds(Collection planningIds, + Collection employeeIds) { + if (planningIds == null || planningIds.isEmpty() || employeeIds == null || employeeIds.isEmpty()) { + return Collections.emptyList(); + } + return selectList(new LambdaQueryWrapperX() + .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 roleSplitIds) { + if (roleSplitIds == null || roleSplitIds.isEmpty()) { + return; + } + delete(new LambdaQueryWrapperX() + .in(SpecialtyRoleSplitPersonDO::getRoleSplitId, roleSplitIds)); + } + + default void deleteByOutputSplitId(Long outputSplitId) { + delete(SpecialtyRoleSplitPersonDO::getOutputSplitId, outputSplitId); + } + + default void deleteByOutputSplitIds(Collection outputSplitIds) { + if (outputSplitIds == null || outputSplitIds.isEmpty()) { + return; + } + delete(new LambdaQueryWrapperX() + .in(SpecialtyRoleSplitPersonDO::getOutputSplitId, outputSplitIds)); + } + + default Long selectCountByEmployeeId(Long employeeId) { + return selectCount(new LambdaQueryWrapperX() + .eq(SpecialtyRoleSplitPersonDO::getEmployeeId, employeeId)); + } + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/enums/ErrorCodeConstants.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/enums/ErrorCodeConstants.java index 463ee7a..1e736d6 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/enums/ErrorCodeConstants.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/enums/ErrorCodeConstants.java @@ -55,9 +55,14 @@ public interface ErrorCodeConstants { // ========== 员工管理 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_NOT_OFFICE_LEADER = new ErrorCode(1_020_008_002, "当前员工未启用或未标记为所长,不能维护年度所长考核产值"); // ========== 员工年度成本预算 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, "当前员工该年度预计发生成本已存在"); + // ========== 年度所长考核产值 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, "当前所长该年度考核产值已存在"); + } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeService.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeService.java index 1ecf6bf..245348c 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeService.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeService.java @@ -24,6 +24,7 @@ public interface EmployeeService { PageResult getEmployeePage(EmployeePageReqVO pageReqVO); - List getEmployeeSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag); + List getEmployeeSimpleList(String keyword, Long officeId, String status, + Boolean enabledFlag, Boolean officeLeaderFlag); } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeServiceImpl.java index f643d57..ed985c8 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employee/EmployeeServiceImpl.java @@ -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.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.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.EmployeeSaveReqVO; 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.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.employeeyearleaderoutput.EmployeeYearLeaderOutputMapper; 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.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 org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -43,9 +41,11 @@ public class EmployeeServiceImpl implements EmployeeService { @Resource private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper; @Resource + private EmployeeYearLeaderOutputMapper employeeYearLeaderOutputMapper; + @Resource private ProjectRolePersonMapper projectRolePersonMapper; @Resource - private SpecialtyRoleSplitMapper specialtyRoleSplitMapper; + private SpecialtyRoleSplitPersonMapper specialtyRoleSplitPersonMapper; @Resource private OfficeService officeService; @@ -56,6 +56,9 @@ public class EmployeeServiceImpl implements EmployeeService { if (employee.getEnabledFlag() == null) { employee.setEnabledFlag(Boolean.TRUE); } + if (employee.getOfficeLeaderFlag() == null) { + employee.setOfficeLeaderFlag(Boolean.FALSE); + } employeeMapper.insert(employee); return employee.getId(); } @@ -64,13 +67,18 @@ public class EmployeeServiceImpl implements EmployeeService { public void updateEmployee(EmployeeSaveReqVO updateReqVO) { validateEmployeeExists(updateReqVO.getId()); 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 public void deleteEmployee(Long id) { validateEmployeeExists(id); if (employeeYearCostBudgetMapper.selectCountByEmployeeId(id) > 0 + || employeeYearLeaderOutputMapper.selectCountByEmployeeId(id) > 0 || projectRolePersonMapper.selectCountByEmployeeId(id) > 0 || existsInSpecialtyRoleSplit(id)) { throw exception(EMPLOYEE_IN_USE); @@ -104,8 +112,10 @@ public class EmployeeServiceImpl implements EmployeeService { } @Override - public List getEmployeeSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag) { - List list = employeeMapper.selectSimpleList(keyword, officeId, status, enabledFlag == null ? Boolean.TRUE : enabledFlag); + public List getEmployeeSimpleList(String keyword, Long officeId, String status, + Boolean enabledFlag, Boolean officeLeaderFlag) { + List list = employeeMapper.selectSimpleList(keyword, officeId, status, + enabledFlag == null ? Boolean.TRUE : enabledFlag, officeLeaderFlag); Map officeMap = getOfficeMap(CollectionUtils.convertSet(list, EmployeeDO::getOfficeId)); return BeanUtils.toBean(list, EmployeeSimpleRespVO.class, respVO -> respVO.setOfficeName(officeMap.containsKey(respVO.getOfficeId()) @@ -113,20 +123,7 @@ public class EmployeeServiceImpl implements EmployeeService { } private boolean existsInSpecialtyRoleSplit(Long employeeId) { - List candidateList = specialtyRoleSplitMapper.selectListByPersonsJsonKeyword("\"employeeId\":" + employeeId); - for (SpecialtyRoleSplitDO item : candidateList) { - List 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; + return specialtyRoleSplitPersonMapper.selectCountByEmployeeId(employeeId) > 0; } private Map getOfficeMap(Set officeIds) { diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetService.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetService.java index b401483..c4beaea 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetService.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetService.java @@ -1,9 +1,7 @@ package cn.iocoder.lyzsys.module.tjt.service.employeeyearcostbudget; 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.EmployeeYearCostBudgetRespVO; -import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetSaveReqVO; +import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.*; import javax.validation.Valid; @@ -11,6 +9,8 @@ public interface EmployeeYearCostBudgetService { Long createEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO createReqVO); + EmployeeYearCostBudgetGenerateRespVO generateEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetGenerateReqVO reqVO); + void updateEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO updateReqVO); void deleteEmployeeYearCostBudget(Long id); diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetServiceImpl.java index 7cf5572..d3c8bba 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearcostbudget/EmployeeYearCostBudgetServiceImpl.java @@ -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.util.object.BeanUtils; -import cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.vo.EmployeeYearCostBudgetPageReqVO; -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.controller.admin.employeeyearcostbudget.vo.*; 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.mysql.employee.EmployeeMapper; import cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget.EmployeeYearCostBudgetMapper; 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.EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE; @@ -26,6 +30,8 @@ public class EmployeeYearCostBudgetServiceImpl implements EmployeeYearCostBudget @Resource private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper; @Resource + private EmployeeMapper employeeMapper; + @Resource private EmployeeService employeeService; @Override @@ -41,6 +47,32 @@ public class EmployeeYearCostBudgetServiceImpl implements EmployeeYearCostBudget return budget.getId(); } + @Override + public EmployeeYearCostBudgetGenerateRespVO generateEmployeeYearCostBudget(EmployeeYearCostBudgetGenerateReqVO reqVO) { + BigDecimal expectedCostAmount = amount(reqVO.getExpectedCostAmount()); + List enabledEmployees = employeeMapper.selectEnabledList(); + Set existingEmployeeIds = employeeYearCostBudgetMapper.selectListByBudgetYear(reqVO.getBudgetYear()) + .stream() + .map(EmployeeYearCostBudgetDO::getEmployeeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + List 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 public void updateEmployeeYearCostBudget(EmployeeYearCostBudgetSaveReqVO updateReqVO) { 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); + } + } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearleaderoutput/EmployeeYearLeaderOutputService.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearleaderoutput/EmployeeYearLeaderOutputService.java new file mode 100644 index 0000000..17f64c4 --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearleaderoutput/EmployeeYearLeaderOutputService.java @@ -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 getEmployeeYearLeaderOutputPage( + EmployeeYearLeaderOutputPageReqVO pageReqVO); + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearleaderoutput/EmployeeYearLeaderOutputServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearleaderoutput/EmployeeYearLeaderOutputServiceImpl.java new file mode 100644 index 0000000..37d457a --- /dev/null +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/employeeyearleaderoutput/EmployeeYearLeaderOutputServiceImpl.java @@ -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 enabledLeaders = employeeMapper.selectEnabledLeaderList(); + Set existingEmployeeIds = employeeYearLeaderOutputMapper.selectListByOutputYear(reqVO.getOutputYear()) + .stream() + .map(EmployeeYearLeaderOutputDO::getEmployeeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + List 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 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); + } + +} diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/profit/ProjectProfitServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/profit/ProjectProfitServiceImpl.java index a1de15d..c4fd553 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/profit/ProjectProfitServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/profit/ProjectProfitServiceImpl.java @@ -104,22 +104,24 @@ public class ProjectProfitServiceImpl implements ProjectProfitService { BigDecimal majorExpectedPerformance = calculateMajorExpectedPerformance(majorPlanningList); BigDecimal contractAmount = amount(project.getContractAmount()); BigDecimal finalSettlementAmount = amount(project.getFinalSettlementAmount()); + BigDecimal effectiveSettlementAmount = finalSettlementAmount.compareTo(BigDecimal.ZERO) > 0 + ? finalSettlementAmount : contractAmount; BigDecimal innovationOutputRate = project.getInnovationOutputRate() == null ? DEFAULT_INNOVATION_OUTPUT_RATE : ratio(project.getInnovationOutputRate()); BigDecimal innovationOutputValue = contractAmount.compareTo(BigDecimal.ZERO) <= 0 ? ZERO_AMOUNT : contractAmount.multiply(innovationOutputRate).setScale(2, RoundingMode.HALF_UP); BigDecimal otherCost = amount(project.getOtherCost()); - BigDecimal profitLossValue = finalSettlementAmount + BigDecimal profitLossValue = effectiveSettlementAmount .subtract(comprehensivePlanningAmount) .subtract(subcontractPlanningAmount) .subtract(majorExpectedPerformance) .subtract(innovationOutputValue) .subtract(otherCost) .setScale(2, RoundingMode.HALF_UP); - BigDecimal profitLossRate = finalSettlementAmount.compareTo(BigDecimal.ZERO) == 0 + BigDecimal profitLossRate = effectiveSettlementAmount.compareTo(BigDecimal.ZERO) == 0 ? ZERO_RATIO - : profitLossValue.divide(finalSettlementAmount, 4, RoundingMode.HALF_UP); + : profitLossValue.divide(effectiveSettlementAmount, 4, RoundingMode.HALF_UP); ProjectProfitRespVO respVO = new ProjectProfitRespVO(); respVO.setProjectId(project.getId()); @@ -128,6 +130,7 @@ public class ProjectProfitServiceImpl implements ProjectProfitService { respVO.setContractSignedFlag(project.getContractSignedFlag()); respVO.setContractAmount(contractAmount); respVO.setFinalSettlementAmount(finalSettlementAmount); + respVO.setEffectiveSettlementAmount(effectiveSettlementAmount); respVO.setComprehensivePlanningAmount(comprehensivePlanningAmount.setScale(2, RoundingMode.HALF_UP)); respVO.setSubcontractPlanningAmount(subcontractPlanningAmount.setScale(2, RoundingMode.HALF_UP)); respVO.setMajorOutputValue(majorOutputValue.setScale(2, RoundingMode.HALF_UP)); diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportService.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportService.java index be9decb..ad99fa8 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportService.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportService.java @@ -1,11 +1,6 @@ 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.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 cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -25,9 +20,15 @@ public interface ProjectOutputReportService { void exportSpecialtyPersonOutputExcel(HttpServletResponse response, SpecialtyPersonOutputExportReqVO reqVO) throws IOException; + SpecialtyPersonOutputPreviewRespVO getSpecialtyPersonOutputPreview(SpecialtyPersonOutputPreviewReqVO reqVO); + + ProjectOverviewPreviewRespVO getProjectOverviewPreview(ProjectOverviewExportReqVO reqVO); + void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO) throws IOException; + EmployeeOutputSummaryPreviewRespVO getEmployeeOutputSummaryPreview(EmployeeOutputSummaryExportReqVO reqVO); + void exportEmployeeOutputSummaryExcel(HttpServletResponse response, EmployeeOutputSummaryExportReqVO reqVO) throws IOException; diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java index 8e3b2ef..bbcc0c4 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/ProjectOutputReportServiceImpl.java @@ -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.dal.dataobject.employee.EmployeeDO; 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.outputsplit.ProjectOutputSplitDO; 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.project.ProjectDO; 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.mysql.employee.EmployeeMapper; 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.planning.ProjectPlanningMapper; 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.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.enums.OutputSplitBizConstants; import cn.iocoder.lyzsys.module.tjt.enums.ProjectPlanningBizTypeConstants; @@ -69,12 +73,16 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic @Resource private ProjectRolePersonMapper projectRolePersonMapper; @Resource + private SpecialtyRoleSplitPersonMapper specialtyRoleSplitPersonMapper; + @Resource private EmployeeMapper employeeMapper; @Resource private OfficeMapper officeMapper; @Resource private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper; @Resource + private EmployeeYearLeaderOutputMapper employeeYearLeaderOutputMapper; + @Resource private YearKValueMapper yearKValueMapper; @Resource private ProjectOutputSplitService projectOutputSplitService; @@ -247,6 +255,260 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic @Override public void exportSpecialtyPersonOutputExcel(HttpServletResponse response, 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 planningList = sortPlanningList(projectPlanningMapper.selectListByProjectId(project.getId())); + Map> quarterMap = getQuarterMap(planningList); + List relevantPlanningList = planningList.stream() + .filter(item -> hasYearAmount(quarterMap.get(item.getId()), reportYear)) + .collect(Collectors.toList()); + Map outputSplitMap = getOutputSplitMap(relevantPlanningList); + Map> roleSplitMap = getRoleSplitMap(relevantPlanningList); + List 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 buildSpecialtyPersonPreviewGroups( + List anchorRoleList, + List relevantPlanningList, + Map> quarterMap, + Map outputSplitMap, + Map> roleSplitMap, + Integer reportYear) { + if (anchorRoleList == null || anchorRoleList.isEmpty()) { + return Collections.emptyList(); + } + Map> groupMap = anchorRoleList.stream() + .filter(Objects::nonNull) + .collect(Collectors.groupingBy(SpecialtyRoleSplitRespVO::getSpecialtyCode, + LinkedHashMap::new, Collectors.toList())); + List groups = new ArrayList<>(); + for (Map.Entry> entry : groupMap.entrySet()) { + String specialtyCode = entry.getKey(); + if (!isSpecialtyPersonExportable(specialtyCode)) { + continue; + } + List 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 relevantPlanningList, + Map> quarterMap, + Map outputSplitMap, + Map> 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 specialtyRoleRows = (roleSplitMap == null ? Collections.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 buildSpecialtyPreviewRoleRows( + List roleRows, + SpecialtyQuarterPreviewAggregate aggregate) { + List 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 buildSpecialtyPreviewPersons( + SpecialtyRoleSplitRespVO roleRow, + SpecialtyQuarterPreviewAggregate aggregate) { + if (roleRow.getPersons() == null || roleRow.getPersons().isEmpty()) { + return Collections.emptyList(); + } + List 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 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 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 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 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()); ProjectPlanningDO anchorPlanning = validatePlanningExists(reqVO.getPlanningId()); ProjectDO project = validateProjectExists(anchorPlanning.getProjectId()); @@ -288,7 +550,6 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic data.setEngineeringPrincipalRatio(engineeringPrincipalRow == null ? ZERO_RATIO : ratio(engineeringPrincipalRow.getRoleRatio())); data.setYear(reportYear); - data.setCenterSignerLabel("设计中心相关负责人(签名):"); data.setProjectSignerLabel("项目经理 / 工程负责人(签名):"); data.setRolePersonModules(buildSpecialtyRolePersonModules(relevantPlanningList, roleSplitMap, reqVO.getSpecialtyCode())); @@ -296,14 +557,29 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic data.setRows(buildSpecialtyPlanningRows(relevantPlanningList, quarterMap, outputSplitMap, roleSplitMap, project.getProjectName(), reqVO.getSpecialtyCode(), reportYear)); - specialtyPersonOutputExcelBuilder.writeWorkbook(response, - buildFileName(project.getProjectName(), reportYear, data.getSpecialtyName() + "专业内人员年度季度计取表"), - specialtyPersonOutputExcelBuilder.build(data)); + SpecialtyPersonOutputBuildResult result = new SpecialtyPersonOutputBuildResult(); + result.setAnchorPlanning(anchorPlanning); + result.setProject(project); + result.setReportYear(reportYear); + result.setData(data); + return result; + } + + @Override + public ProjectOverviewPreviewRespVO getProjectOverviewPreview(ProjectOverviewExportReqVO reqVO) { + return buildProjectOverviewPreviewResp(buildProjectOverviewExportData(reqVO)); } @Override public void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO) 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()); OfficeDO office = validateOfficeExists(reqVO.getOfficeId()); List employeeList = employeeMapper.selectList(new LambdaQueryWrapperX() @@ -318,16 +594,14 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic Set employeeIds = employeeList.stream() .map(EmployeeDO::getId) .collect(Collectors.toCollection(LinkedHashSet::new)); - List majorPlanningList = projectPlanningMapper.selectList( - new LambdaQueryWrapperX() - .eq(ProjectPlanningDO::getOwnershipType, ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR)); - Map projectMap = getProjectMap(majorPlanningList); - Map> quarterMap = getQuarterMap(majorPlanningList); - Map outputSplitMap = getOutputSplitMap(majorPlanningList); - Map> roleSplitMap = getRoleSplitMap(majorPlanningList); + List planningList = getProjectOverviewPlanningList(reportYear, employeeIds); + Map projectMap = getProjectMap(planningList); + Map> quarterMap = getQuarterMap(planningList); + Map outputSplitMap = getOutputSplitMap(planningList); + Map> roleSplitMap = getRoleSplitMap(planningList); Map accumulatorMap = new LinkedHashMap<>(); - for (ProjectPlanningDO planning : majorPlanningList) { + for (ProjectPlanningDO planning : planningList) { QuarterSummary quarterSummary = buildQuarterSummary(planning, quarterMap.get(planning.getId()), reportYear); if (quarterSummary.getYearTotalAmount().compareTo(ZERO_AMOUNT) <= 0) { continue; @@ -360,14 +634,25 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic data.setRows(rows); data.setTotalRow(buildProjectOverviewTotalRow(new ArrayList<>(accumulatorMap.values()), employeeList)); - projectOverviewOutputExcelBuilder.writeWorkbook(response, - buildFileName(office.getOfficeName(), reportYear, "项目总览表"), - projectOverviewOutputExcelBuilder.build(data)); + return data; + } + + @Override + public EmployeeOutputSummaryPreviewRespVO getEmployeeOutputSummaryPreview(EmployeeOutputSummaryExportReqVO reqVO) { + return buildEmployeeOutputSummaryPreviewResp(buildEmployeeOutputSummaryExportData(reqVO)); } @Override public void exportEmployeeOutputSummaryExcel(HttpServletResponse response, 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()); BigDecimal kValue = yearKValue == null ? DEFAULT_K_VALUE : ratio(yearKValue.getKValue()); List employeeList = employeeMapper.selectList(new LambdaQueryWrapperX() @@ -382,23 +667,13 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic data.setYear(reqVO.getYear()); data.setKValue(kValue); data.setRows(Collections.emptyList()); - employeeOutputSummaryExcelBuilder.writeWorkbook(response, - buildFileName("员工个人考核产值", reqVO.getYear(), "汇总表"), - employeeOutputSummaryExcelBuilder.build(data)); - return; + return data; } Set employeeIds = employeeList.stream().map(EmployeeDO::getId).collect(Collectors.toCollection(LinkedHashSet::new)); - List majorPlanningList = projectPlanningMapper.selectList( - new LambdaQueryWrapperX() - .eq(ProjectPlanningDO::getOwnershipType, ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR)); - Map> quarterMap = getQuarterMap(majorPlanningList); - - List relevantPlanningList = majorPlanningList.stream() - .filter(item -> hasYearAmount(quarterMap.get(item.getId()), reqVO.getYear())) - .collect(Collectors.toList()); - + List relevantPlanningList = getEmployeeOutputSummaryPlanningList(reqVO.getYear(), employeeIds); + Map> quarterMap = getQuarterMap(relevantPlanningList); Map outputSplitMap = getOutputSplitMap(relevantPlanningList); Map> roleSplitMap = getRoleSplitMap(relevantPlanningList); Map accumulatorMap = new LinkedHashMap<>(); @@ -437,6 +712,10 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic .inIfPresent(EmployeeYearCostBudgetDO::getEmployeeId, employeeIds)) .stream() .collect(Collectors.toMap(EmployeeYearCostBudgetDO::getEmployeeId, item -> item, (a, b) -> a)); + Map leaderOutputMap = employeeYearLeaderOutputMapper + .selectEnabledListByOutputYear(reqVO.getYear(), employeeIds) + .stream() + .collect(Collectors.toMap(EmployeeYearLeaderOutputDO::getEmployeeId, item -> item, (a, b) -> a)); List rows = new ArrayList<>(); for (EmployeeDO employee : employeeList) { @@ -445,8 +724,9 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic accumulator = new EmployeeAccumulator(); } EmployeeYearCostBudgetDO costBudget = costBudgetMap.get(employee.getId()); + EmployeeYearLeaderOutputDO leaderOutput = leaderOutputMap.get(employee.getId()); 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 totalAssessmentOutputAmount = annualTotalAmount.add(officeLeaderOrBimAmount) .setScale(2, RoundingMode.HALF_UP); @@ -483,9 +763,129 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic data.setYear(reqVO.getYear()); data.setKValue(kValue); data.setRows(rows); - employeeOutputSummaryExcelBuilder.writeWorkbook(response, - buildFileName("员工个人考核产值", reqVO.getYear(), "汇总表"), - employeeOutputSummaryExcelBuilder.build(data)); + return 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 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 rows = data.getRows() == null + ? Collections.emptyList() : data.getRows(); + respVO.setRows(rows); + respVO.setTotalRow(buildEmployeeOutputSummaryTotalRow(rows)); + return respVO; + } + + private EmployeeOutputSummaryExcelRespVO buildEmployeeOutputSummaryTotalRow( + List 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) { @@ -528,6 +928,96 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic .collect(Collectors.toList()); } + private List getAssignablePlanningList() { + return projectPlanningMapper.selectList(new LambdaQueryWrapperX() + .in(ProjectPlanningDO::getOwnershipType, Arrays.asList( + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_MAJOR, + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_COMPREHENSIVE, + ProjectPlanningBizTypeConstants.OWNERSHIP_TYPE_SUBCONTRACT + ))); + } + + private List getProjectOverviewPlanningList(Integer reportYear, Set employeeIds) { + if (reportYear == null || employeeIds == null || employeeIds.isEmpty()) { + return Collections.emptyList(); + } + Set yearPlanningIds = getYearAmountPlanningIds(reportYear); + if (yearPlanningIds.isEmpty()) { + return Collections.emptyList(); + } + List personList = specialtyRoleSplitPersonMapper + .selectListByPlanningIdsAndEmployeeIds(yearPlanningIds, employeeIds); + if (personList.isEmpty()) { + return Collections.emptyList(); + } + Set matchedPlanningIds = personList.stream() + .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 getEmployeeOutputSummaryPlanningList(Integer reportYear, Set employeeIds) { + if (reportYear == null || employeeIds == null || employeeIds.isEmpty()) { + return Collections.emptyList(); + } + Set yearPlanningIds = getYearAmountPlanningIds(reportYear); + if (yearPlanningIds.isEmpty()) { + return Collections.emptyList(); + } + + Set matchedPlanningIds = specialtyRoleSplitPersonMapper + .selectListByPlanningIdsAndEmployeeIds(yearPlanningIds, employeeIds) + .stream() + .map(SpecialtyRoleSplitPersonDO::getPlanningId) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + Set projectIds = projectRolePersonMapper.selectListByEmployeeIds(employeeIds) + .stream() + .map(ProjectRolePersonDO::getProjectId) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + if (!projectIds.isEmpty()) { + projectPlanningMapper.selectList(new LambdaQueryWrapperX() + .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 getYearAmountPlanningIds(Integer reportYear) { + if (reportYear == null) { + return Collections.emptySet(); + } + return projectPlanningQuarterMapper.selectList(new LambdaQueryWrapperX() + .eq(ProjectPlanningQuarterDO::getDistributionYear, reportYear) + .gt(ProjectPlanningQuarterDO::getDistributionAmount, BigDecimal.ZERO)) + .stream() + .map(ProjectPlanningQuarterDO::getPlanningId) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + private List buildProjectQuarterOutputRows( List planningList, Map> quarterMap, Map outputSplitMap, Integer reportYear) { @@ -1021,9 +1511,8 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic outputSplit.setYear(resolveReportYear(planning)); } outputSplit.setProjectLeadRatio(ZERO_RATIO); - boolean majorPlanning = planning != null && ProjectPlanningBizTypeConstants.isMajor(planning.getOwnershipType()); - outputSplit.setOfficeRatio(majorPlanning ? FULL_RATIO : ZERO_RATIO); - outputSplit.setArchRatio(majorPlanning ? FULL_RATIO : ZERO_RATIO); + outputSplit.setOfficeRatio(FULL_RATIO); + outputSplit.setArchRatio(FULL_RATIO); outputSplit.setDecorRatio(ZERO_RATIO); outputSplit.setStructRatio(ZERO_RATIO); outputSplit.setWaterRatio(ZERO_RATIO); @@ -1101,11 +1590,11 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic if (planningList == null || planningList.isEmpty()) { return Collections.emptyMap(); } - Map> map = new LinkedHashMap<>(); - for (ProjectPlanningDO planning : planningList) { - map.put(planning.getId(), specialtyRoleSplitService.getSpecialtyRoleSplitListByPlanningId(planning.getId())); - } - return map; + List planningIds = planningList.stream() + .map(ProjectPlanningDO::getId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + return specialtyRoleSplitService.getSpecialtyRoleSplitListMapByPlanningIds(planningIds); } private Map getProjectMap(Collection planningList) { @@ -1492,14 +1981,24 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic private void accumulateSpecialtyPersonAmount(SpecialtyPersonOutputExcelBuilder.PersonAmountValue value, QuarterSummary quarterSummary, BigDecimal amountRatio) { + value.setQuarterOneRatio(addRatio(value.getQuarterOneRatio(), + multiplyRatio(quarterSummary.getQuarterOneRatio(), amountRatio))); value.setQuarterOneAmountWan(addAmountValue(value.getQuarterOneAmountWan(), amountToWan(multiplyAmount(quarterSummary.getQuarterOneAmount(), amountRatio)))); + value.setQuarterTwoRatio(addRatio(value.getQuarterTwoRatio(), + multiplyRatio(quarterSummary.getQuarterTwoRatio(), amountRatio))); value.setQuarterTwoAmountWan(addAmountValue(value.getQuarterTwoAmountWan(), amountToWan(multiplyAmount(quarterSummary.getQuarterTwoAmount(), amountRatio)))); + value.setQuarterThreeRatio(addRatio(value.getQuarterThreeRatio(), + multiplyRatio(quarterSummary.getQuarterThreeRatio(), amountRatio))); value.setQuarterThreeAmountWan(addAmountValue(value.getQuarterThreeAmountWan(), amountToWan(multiplyAmount(quarterSummary.getQuarterThreeAmount(), amountRatio)))); + value.setQuarterFourRatio(addRatio(value.getQuarterFourRatio(), + multiplyRatio(quarterSummary.getQuarterFourRatio(), amountRatio))); value.setQuarterFourAmountWan(addAmountValue(value.getQuarterFourAmountWan(), amountToWan(multiplyAmount(quarterSummary.getQuarterFourAmount(), amountRatio)))); + value.setYearTotalRatio(addRatio(value.getYearTotalRatio(), + multiplyRatio(quarterSummary.getCurrentYearRatio(), amountRatio))); value.setYearTotalAmountWan(addAmountValue(value.getYearTotalAmountWan(), amountToWan(multiplyAmount(quarterSummary.getYearTotalAmount(), amountRatio)))); } @@ -1886,6 +2385,24 @@ public class ProjectOutputReportServiceImpl implements ProjectOutputReportServic 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 rolePersonAmountMap = new LinkedHashMap<>(); + } + @Data private static class PlanningOfficeContribution { private BigDecimal totalOutputAmount = ZERO_AMOUNT; diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/builder/SpecialtyPersonOutputExcelBuilder.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/builder/SpecialtyPersonOutputExcelBuilder.java index 8537e9a..09284d5 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/builder/SpecialtyPersonOutputExcelBuilder.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/report/builder/SpecialtyPersonOutputExcelBuilder.java @@ -637,10 +637,15 @@ public class SpecialtyPersonOutputExcelBuilder extends AbstractProjectOutputExce @Data public static class PersonAmountValue { + private BigDecimal quarterOneRatio; private BigDecimal quarterOneAmountWan; + private BigDecimal quarterTwoRatio; private BigDecimal quarterTwoAmountWan; + private BigDecimal quarterThreeRatio; private BigDecimal quarterThreeAmountWan; + private BigDecimal quarterFourRatio; private BigDecimal quarterFourAmountWan; + private BigDecimal yearTotalRatio; private BigDecimal yearTotalAmountWan; } diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitService.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitService.java index 8db4a8d..3912bd5 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitService.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitService.java @@ -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.SpecialtyRoleSplitRespVO; +import java.util.Collection; import java.util.List; +import java.util.Map; /** * 页面5角色比例 Service 接口 @@ -14,6 +16,8 @@ public interface SpecialtyRoleSplitService { List getSpecialtyRoleSplitListByPlanningId(Long planningId); + Map> getSpecialtyRoleSplitListMapByPlanningIds(Collection planningIds); + void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO); void deleteByOutputSplitId(Long outputSplitId); diff --git a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java index d58ad4d..6a3e588 100644 --- a/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java +++ b/lyzsys-module-tjt/src/main/java/cn/iocoder/lyzsys/module/tjt/service/specialtyrolesplit/SpecialtyRoleSplitServiceImpl.java @@ -1,48 +1,34 @@ 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.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRolePersonRespVO; -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.controller.admin.specialtyrolesplit.vo.*; 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.planning.ProjectPlanningDO; 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.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.project.ProjectMapper; 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.enums.OutputSplitBizConstants; import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService; import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; 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.PROJECT_NOT_EXISTS; -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; +import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.*; @Service @Validated @@ -58,6 +44,8 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService @Resource private SpecialtyRoleSplitMapper specialtyRoleSplitMapper; @Resource + private SpecialtyRoleSplitPersonMapper specialtyRoleSplitPersonMapper; + @Resource private ProjectOutputSplitService projectOutputSplitService; @Resource private ProjectPlanningMapper projectPlanningMapper; @@ -71,15 +59,102 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService @Override public List getSpecialtyRoleSplitListByPlanningId(Long planningId) { ProjectPlanningDO planning = validatePlanningExists(planningId); - ProjectDO project = validateProjectExists(planning.getProjectId()); - ProjectOutputSplitDO outputSplit = projectOutputSplitService.getOrCreateProjectOutputSplit(planningId); - List dbList = specialtyRoleSplitMapper.selectListByOutputSplitId(outputSplit.getId()); - Map dbMap = dbList.stream().collect(Collectors.toMap( - item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b)); - Map> projectRolePersonMap = projectRolePersonMapper - .selectListByProjectId(project.getId()).stream() - .collect(Collectors.groupingBy(ProjectRolePersonDO::getRoleCode, LinkedHashMap::new, Collectors.toList())); + validateProjectExists(planning.getProjectId()); + return getSpecialtyRoleSplitListMapByPlanningIds(Collections.singletonList(planningId)) + .getOrDefault(planningId, Collections.emptyList()); + } + @Override + public Map> getSpecialtyRoleSplitListMapByPlanningIds(Collection planningIds) { + if (planningIds == null || planningIds.isEmpty()) { + return Collections.emptyMap(); + } + List normalizedPlanningIds = planningIds.stream() + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + if (normalizedPlanningIds.isEmpty()) { + return Collections.emptyMap(); + } + + Map 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 projectIds = planningMap.values().stream() + .map(ProjectPlanningDO::getProjectId) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + Map 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 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 outputSplitIds = outputSplitMap.values().stream() + .filter(Objects::nonNull) + .map(ProjectOutputSplitDO::getId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + Map> roleSplitMap = specialtyRoleSplitMapper + .selectListByOutputSplitIds(outputSplitIds).stream() + .collect(Collectors.groupingBy(SpecialtyRoleSplitDO::getOutputSplitId, + LinkedHashMap::new, Collectors.toList())); + List roleSplitIds = roleSplitMap.values().stream() + .flatMap(Collection::stream) + .map(SpecialtyRoleSplitDO::getId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + Map> personMap = specialtyRoleSplitPersonMapper + .selectListByRoleSplitIds(roleSplitIds) + .stream() + .collect(Collectors.groupingBy(SpecialtyRoleSplitPersonDO::getRoleSplitId, + LinkedHashMap::new, Collectors.toList())); + + Map>> projectRolePersonMap = projectRolePersonMapper + .selectListByProjectIds(projectIds).stream() + .collect(Collectors.groupingBy(ProjectRolePersonDO::getProjectId, LinkedHashMap::new, + Collectors.groupingBy(ProjectRolePersonDO::getRoleCode, LinkedHashMap::new, Collectors.toList()))); + + Map> 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 roleList = roleSplitMap.getOrDefault(outputSplit.getId(), Collections.emptyList()); + Map> projectPersons = projectRolePersonMap + .getOrDefault(planning.getProjectId(), Collections.emptyMap()); + result.put(planningId, buildRoleSplitRespList(planning, project, outputSplit, roleList, projectPersons, personMap)); + } + return result; + } + + private List buildRoleSplitRespList(ProjectPlanningDO planning, + ProjectDO project, + ProjectOutputSplitDO outputSplit, + List dbList, + Map> projectRolePersonMap, + Map> personMap) { + List safeDbList = dbList == null ? Collections.emptyList() : dbList; + Map dbMap = safeDbList.stream().collect(Collectors.toMap( + item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b)); List result = new ArrayList<>(); BigDecimal assessmentOutputValue = planning.getAssessmentOutputValue(); for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) { @@ -92,7 +167,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService dbItem, specialtyItem.getCode(), roleItem.getCode(), defaultRoleRatioMap); BigDecimal roleAmount = multiplyAmount(specialtyAmount, roleRatio); List persons = buildRespPersons( - dbItem, specialtyItem.getCode(), roleItem.getCode(), roleAmount, roleRatio, projectRolePersonMap); + dbItem, specialtyItem.getCode(), roleItem.getCode(), roleAmount, projectRolePersonMap, personMap); SpecialtyRoleSplitRespVO respVO = dbItem == null ? new SpecialtyRoleSplitRespVO() : BeanUtils.toBean(dbItem, SpecialtyRoleSplitRespVO.class); @@ -102,7 +177,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService + OutputSplitBizConstants.getRoleSortNo(roleItem.getCode())); } respVO.setPlanningId(planning.getId()); - respVO.setProjectName(project.getProjectName()); + respVO.setProjectName(project == null ? "" : project.getProjectName()); respVO.setPlanningContent(planning.getPlanningContent()); respVO.setSpecialtyCode(specialtyItem.getCode()); respVO.setSpecialtyName(specialtyItem.getName()); @@ -119,6 +194,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService } @Override + @Transactional(rollbackFor = Exception.class) public void saveSpecialtyRoleSplitBatch(SpecialtyRoleSplitBatchSaveReqVO reqVO) { ProjectPlanningDO planning = validatePlanningExists(reqVO.getPlanningId()); ProjectOutputSplitDO outputSplit = projectOutputSplitService.getOrCreateProjectOutputSplit(reqVO.getPlanningId()); @@ -140,25 +216,28 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService getSavePersons(roleMap, roleItem.getCode())); validateRolePersons(roleItem.getCode(), roleAmount, persons); roleTotal = roleTotal.add(roleRatio).setScale(RATIO_SCALE, RoundingMode.HALF_UP); - upsertRole(dbMap, outputSplit.getId(), specialtyItem.getCode(), specialtyItem.getName(), - roleItem.getCode(), roleRatio, - OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyItem.getCode()) - ? null : toPersonJson(persons)); + SpecialtyRoleSplitDO role = upsertRole(dbMap, outputSplit.getId(), specialtyItem.getCode(), + specialtyItem.getName(), roleItem.getCode(), roleRatio); + refreshRolePersons(role, outputSplit, persons); } validateRoleTotal(roleTotal); } } @Override + @Transactional(rollbackFor = Exception.class) public void deleteByOutputSplitId(Long outputSplitId) { + specialtyRoleSplitPersonMapper.deleteByOutputSplitId(outputSplitId); specialtyRoleSplitMapper.delete(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitId); } @Override + @Transactional(rollbackFor = Exception.class) public void deleteByOutputSplitIds(List outputSplitIds) { if (outputSplitIds == null || outputSplitIds.isEmpty()) { return; } + specialtyRoleSplitPersonMapper.deleteByOutputSplitIds(outputSplitIds); specialtyRoleSplitMapper.delete(new cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX() .in(SpecialtyRoleSplitDO::getOutputSplitId, outputSplitIds)); } @@ -181,8 +260,9 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService return result; } - private void upsertRole(Map dbMap, Long outputSplitId, String specialtyCode, - String specialtyName, String roleCode, BigDecimal roleRatio, String personsJson) { + private SpecialtyRoleSplitDO upsertRole(Map dbMap, Long outputSplitId, + String specialtyCode, String specialtyName, String roleCode, + BigDecimal roleRatio) { String key = specialtyCode + ":" + roleCode; SpecialtyRoleSplitDO dbItem = dbMap.get(key); Integer sortNo = dbItem != null && dbItem.getSortNo() != null @@ -197,10 +277,10 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService createObj.setRoleCode(roleCode); createObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode)); createObj.setRoleRatio(ratio(roleRatio)); - createObj.setPersonsJson(personsJson); createObj.setSortNo(sortNo); specialtyRoleSplitMapper.insert(createObj); - return; + dbMap.put(key, createObj); + return createObj; } SpecialtyRoleSplitDO updateObj = new SpecialtyRoleSplitDO(); updateObj.setId(dbItem.getId()); @@ -210,9 +290,46 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService updateObj.setRoleCode(roleCode); updateObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode)); updateObj.setRoleRatio(ratio(roleRatio)); - updateObj.setPersonsJson(personsJson); updateObj.setSortNo(sortNo); specialtyRoleSplitMapper.updateById(updateObj); + dbMap.put(key, updateObj); + return updateObj; + } + + private void refreshRolePersons(SpecialtyRoleSplitDO role, ProjectOutputSplitDO outputSplit, + List 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 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 getSavePersons(Map roleMap, @@ -298,13 +415,13 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService private List buildRespPersons(SpecialtyRoleSplitDO dbItem, String specialtyCode, String roleCode, BigDecimal roleAmount, - BigDecimal roleRatio, - Map> projectRolePersonMap) { + Map> projectRolePersonMap, + Map> personMap) { List sourcePersons; if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) { sourcePersons = buildDefaultProjectLeadPersons(projectRolePersonMap.get(roleCode)); } else { - sourcePersons = parseStoredPersons(dbItem); + sourcePersons = buildStoredPersons(dbItem, personMap); } List result = new ArrayList<>(); for (SpecialtyRolePersonSaveReqVO person : sourcePersons) { @@ -318,12 +435,13 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService return result; } - private List parseStoredPersons(SpecialtyRoleSplitDO dbItem) { - if (dbItem == null || dbItem.getPersonsJson() == null || dbItem.getPersonsJson().trim().isEmpty()) { + private List buildStoredPersons(SpecialtyRoleSplitDO dbItem, + Map> personMap) { + if (dbItem == null || dbItem.getId() == null || personMap == null || personMap.isEmpty()) { return new ArrayList<>(); } - List persons = JsonUtils.parseArray(dbItem.getPersonsJson(), SpecialtyRolePersonSaveReqVO.class); - if (persons == null) { + List persons = personMap.get(dbItem.getId()); + if (persons == null || persons.isEmpty()) { return new ArrayList<>(); } return persons.stream() @@ -401,10 +519,6 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService return projectOutputSplitService.getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyCode); } - private String toPersonJson(List persons) { - return persons == null || persons.isEmpty() ? null : JsonUtils.toJsonString(persons); - } - private BigDecimal sumPersonRatios(List persons) { BigDecimal sum = ZERO_RATIO; if (persons == null || persons.isEmpty()) { diff --git a/lyzsys-server/src/main/resources/application-local.yaml b/lyzsys-server/src/main/resources/application-local.yaml index 03f35d1..6e8cff2 100644 --- a/lyzsys-server/src/main/resources/application-local.yaml +++ b/lyzsys-server/src/main/resources/application-local.yaml @@ -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 # username: sa # 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 连接的示例 password: tjt@Admin2026 # SQL Server 连接的示例 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: - host: 127.0.0.1 # 地址 -# host: 8.163.1.126 +# host: 127.0.0.1 # 地址 + host: 8.163.1.126 port: 6379 # 端口 database: 8 # 数据库索引 - password: lyzsys@2026 -# password: lyzbim2016 +# password: lyzsys@2026 + password: lyzbim2016 --- #################### 定时任务相关配置 #################### diff --git a/lyzsys-server/src/main/resources/application-prod.yaml b/lyzsys-server/src/main/resources/application-prod.yaml new file mode 100644 index 0000000..570ae5b --- /dev/null +++ b/lyzsys-server/src/main/resources/application-prod.yaml @@ -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 分钟