添加基础表维护
This commit is contained in:
@@ -172,6 +172,6 @@ http://127.0.0.1:48080/swagger-ui
|
||||
|
||||
- `doc/后端开发文档.md`
|
||||
|
||||
特建投框架调研补充文档:
|
||||
特建投业务分析与计划文档:
|
||||
|
||||
- [`../doc/tejiantou_ai_requirements_20260410_v2_framework.md`](../doc/tejiantou_ai_requirements_20260410_v2_framework.md)
|
||||
- [`../doc/特建投业务分析与计划.md`](../doc/特建投业务分析与计划.md)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employee;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
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.service.employee.EmployeeService;
|
||||
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 java.util.List;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 员工")
|
||||
@RestController
|
||||
@RequestMapping("/tjt/employee")
|
||||
@Validated
|
||||
public class EmployeeController {
|
||||
|
||||
@Resource
|
||||
private EmployeeService employeeService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建员工")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee:create')")
|
||||
public CommonResult<Long> createEmployee(@Valid @RequestBody EmployeeSaveReqVO createReqVO) {
|
||||
return success(employeeService.createEmployee(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改员工")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee:update')")
|
||||
public CommonResult<Boolean> updateEmployee(@Valid @RequestBody EmployeeSaveReqVO updateReqVO) {
|
||||
employeeService.updateEmployee(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除员工")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee:delete')")
|
||||
public CommonResult<Boolean> deleteEmployee(@RequestParam("id") Long id) {
|
||||
employeeService.deleteEmployee(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得员工详情")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee:query')")
|
||||
public CommonResult<EmployeeRespVO> getEmployee(@RequestParam("id") Long id) {
|
||||
return success(employeeService.getEmployee(id));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得员工分页")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee:query')")
|
||||
public CommonResult<PageResult<EmployeeRespVO>> getEmployeePage(@Valid EmployeePageReqVO pageReqVO) {
|
||||
return success(employeeService.getEmployeePage(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获得员工精简列表")
|
||||
public CommonResult<List<EmployeeSimpleRespVO>> getEmployeeSimpleList(
|
||||
@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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employee.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 EmployeePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "员工姓名", example = "张")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "所属专业所 ID", example = "1")
|
||||
private Long officeId;
|
||||
|
||||
@Schema(description = "状态", example = "在职")
|
||||
private String employeeStatus;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 员工 Response VO")
|
||||
@Data
|
||||
public class EmployeeRespVO {
|
||||
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "员工姓名")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "性别")
|
||||
private String gender;
|
||||
|
||||
@Schema(description = "所属专业所 ID")
|
||||
private Long officeId;
|
||||
|
||||
@Schema(description = "所属专业所名称")
|
||||
private String officeName;
|
||||
|
||||
@Schema(description = "注册类型及等级")
|
||||
private String registrationType;
|
||||
|
||||
@Schema(description = "职称")
|
||||
private String jobTitle;
|
||||
|
||||
@Schema(description = "注册章号")
|
||||
private String registrationSealNo;
|
||||
|
||||
@Schema(description = "入职时间")
|
||||
private LocalDate entryDate;
|
||||
|
||||
@Schema(description = "离职时间")
|
||||
private LocalDate leaveDate;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String employeeStatus;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sortNo;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "管理后台 - 员工新增/修改 Request VO")
|
||||
@Data
|
||||
public class EmployeeSaveReqVO {
|
||||
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "员工姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@NotBlank(message = "员工姓名不能为空")
|
||||
@Size(max = 64, message = "员工姓名长度不能超过 64 个字符")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "男")
|
||||
@NotBlank(message = "性别不能为空")
|
||||
@Size(max = 2, message = "性别长度不能超过 2 个字符")
|
||||
private String gender;
|
||||
|
||||
@Schema(description = "所属专业所 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "所属专业所不能为空")
|
||||
private Long officeId;
|
||||
|
||||
@Schema(description = "注册类型及等级", example = "一级注册建筑师")
|
||||
@Size(max = 100, message = "注册类型及等级长度不能超过 100 个字符")
|
||||
private String registrationType;
|
||||
|
||||
@Schema(description = "职称", example = "正高级")
|
||||
@Size(max = 50, message = "职称长度不能超过 50 个字符")
|
||||
private String jobTitle;
|
||||
|
||||
@Schema(description = "注册章号", example = "A123456")
|
||||
@Size(max = 100, message = "注册章号长度不能超过 100 个字符")
|
||||
private String registrationSealNo;
|
||||
|
||||
@Schema(description = "入职时间", example = "2026-01-01")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate entryDate;
|
||||
|
||||
@Schema(description = "离职时间", example = "2026-12-31")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate leaveDate;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "在职")
|
||||
@NotBlank(message = "状态不能为空")
|
||||
@Size(max = 20, message = "状态长度不能超过 20 个字符")
|
||||
private String employeeStatus;
|
||||
|
||||
@Schema(description = "备注")
|
||||
@Size(max = 255, message = "备注长度不能超过 255 个字符")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序号", example = "1")
|
||||
private Integer sortNo;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employee.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 员工精简 Response VO")
|
||||
@Data
|
||||
public class EmployeeSimpleRespVO {
|
||||
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "员工姓名")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "所属专业所 ID")
|
||||
private Long officeId;
|
||||
|
||||
@Schema(description = "所属专业所名称")
|
||||
private String officeName;
|
||||
|
||||
@Schema(description = "员工状态")
|
||||
private String employeeStatus;
|
||||
|
||||
@Schema(description = "注册类型及等级")
|
||||
private String registrationType;
|
||||
|
||||
@Schema(description = "职称")
|
||||
private String jobTitle;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
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.service.employeeyearcostbudget.EmployeeYearCostBudgetService;
|
||||
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-cost-budget")
|
||||
@Validated
|
||||
public class EmployeeYearCostBudgetController {
|
||||
|
||||
@Resource
|
||||
private EmployeeYearCostBudgetService employeeYearCostBudgetService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建员工年度成本预算")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:create')")
|
||||
public CommonResult<Long> createEmployeeYearCostBudget(@Valid @RequestBody EmployeeYearCostBudgetSaveReqVO createReqVO) {
|
||||
return success(employeeYearCostBudgetService.createEmployeeYearCostBudget(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改员工年度成本预算")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:update')")
|
||||
public CommonResult<Boolean> updateEmployeeYearCostBudget(@Valid @RequestBody EmployeeYearCostBudgetSaveReqVO updateReqVO) {
|
||||
employeeYearCostBudgetService.updateEmployeeYearCostBudget(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除员工年度成本预算")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:delete')")
|
||||
public CommonResult<Boolean> deleteEmployeeYearCostBudget(@RequestParam("id") Long id) {
|
||||
employeeYearCostBudgetService.deleteEmployeeYearCostBudget(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得员工年度成本预算详情")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:query')")
|
||||
public CommonResult<EmployeeYearCostBudgetRespVO> getEmployeeYearCostBudget(@RequestParam("id") Long id) {
|
||||
return success(employeeYearCostBudgetService.getEmployeeYearCostBudget(id));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得员工年度成本预算分页")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:employee-year-cost-budget:query')")
|
||||
public CommonResult<PageResult<EmployeeYearCostBudgetRespVO>> getEmployeeYearCostBudgetPage(
|
||||
@Valid EmployeeYearCostBudgetPageReqVO pageReqVO) {
|
||||
return success(employeeYearCostBudgetService.getEmployeeYearCostBudgetPage(pageReqVO));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.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 EmployeeYearCostBudgetPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long employeeId;
|
||||
|
||||
@Schema(description = "员工姓名", example = "张")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "预算年度", example = "2026")
|
||||
private Integer budgetYear;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.employeeyearcostbudget.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 EmployeeYearCostBudgetRespVO {
|
||||
|
||||
@Schema(description = "记录 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "员工 ID")
|
||||
private Long employeeId;
|
||||
|
||||
@Schema(description = "员工姓名")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "预算年度")
|
||||
private Integer budgetYear;
|
||||
|
||||
@Schema(description = "预计发生成本")
|
||||
private BigDecimal expectedCostAmount;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sortNo;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
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.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 员工年度成本预算新增/修改 Request VO")
|
||||
@Data
|
||||
public class EmployeeYearCostBudgetSaveReqVO {
|
||||
|
||||
@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 budgetYear;
|
||||
|
||||
@Schema(description = "预计发生成本", requiredMode = Schema.RequiredMode.REQUIRED, example = "100000")
|
||||
@NotNull(message = "预计发生成本不能为空")
|
||||
private BigDecimal expectedCostAmount;
|
||||
|
||||
@Schema(description = "备注")
|
||||
@Size(max = 255, message = "备注长度不能超过 255 个字符")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序号", example = "1")
|
||||
private Integer sortNo;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.office;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeSimpleRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.office.OfficeService;
|
||||
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 java.util.List;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 专业所")
|
||||
@RestController
|
||||
@RequestMapping("/tjt/office")
|
||||
@Validated
|
||||
public class OfficeController {
|
||||
|
||||
@Resource
|
||||
private OfficeService officeService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建专业所")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:office:create')")
|
||||
public CommonResult<Long> createOffice(@Valid @RequestBody OfficeSaveReqVO createReqVO) {
|
||||
return success(officeService.createOffice(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改专业所")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:office:update')")
|
||||
public CommonResult<Boolean> updateOffice(@Valid @RequestBody OfficeSaveReqVO updateReqVO) {
|
||||
officeService.updateOffice(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除专业所")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:office:delete')")
|
||||
public CommonResult<Boolean> deleteOffice(@RequestParam("id") Long id) {
|
||||
officeService.deleteOffice(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得专业所详情")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:office:query')")
|
||||
public CommonResult<OfficeRespVO> getOffice(@RequestParam("id") Long id) {
|
||||
return success(officeService.getOffice(id));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得专业所分页")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:office:query')")
|
||||
public CommonResult<PageResult<OfficeRespVO>> getOfficePage(@Valid OfficePageReqVO pageReqVO) {
|
||||
return success(officeService.getOfficePage(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获得专业所精简列表")
|
||||
public CommonResult<List<OfficeSimpleRespVO>> getOfficeSimpleList() {
|
||||
return success(officeService.getOfficeSimpleList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.office.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 OfficePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "专业所名称", example = "建筑")
|
||||
private String officeName;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 专业所 Response VO")
|
||||
@Data
|
||||
public class OfficeRespVO {
|
||||
|
||||
@Schema(description = "专业所 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "专业所名称", example = "建筑一所")
|
||||
private String officeName;
|
||||
|
||||
@Schema(description = "专业所编码", example = "JZY")
|
||||
private String officeCode;
|
||||
|
||||
@Schema(description = "排序号", example = "1")
|
||||
private Integer sortNo;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Schema(description = "管理后台 - 专业所新增/修改 Request VO")
|
||||
@Data
|
||||
public class OfficeSaveReqVO {
|
||||
|
||||
@Schema(description = "专业所 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "专业所名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "建筑一所")
|
||||
@NotBlank(message = "专业所名称不能为空")
|
||||
@Size(max = 100, message = "专业所名称长度不能超过 100 个字符")
|
||||
private String officeName;
|
||||
|
||||
@Schema(description = "专业所编码", example = "JZY")
|
||||
@Size(max = 50, message = "专业所编码长度不能超过 50 个字符")
|
||||
private String officeCode;
|
||||
|
||||
@Schema(description = "排序号", example = "1")
|
||||
private Integer sortNo;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
@Schema(description = "备注", example = "默认专业所")
|
||||
@Size(max = 255, message = "备注长度不能超过 255 个字符")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 专业所精简 Response VO")
|
||||
@Data
|
||||
public class OfficeSimpleRespVO {
|
||||
|
||||
@Schema(description = "专业所 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "专业所名称", example = "建筑一所")
|
||||
private String officeName;
|
||||
|
||||
}
|
||||
@@ -36,17 +36,14 @@ public class ProjectOutputSplitRespVO {
|
||||
@Schema(description = "项目负责人")
|
||||
private String engineeringLeaderName;
|
||||
|
||||
@Schema(description = "项目经理比例")
|
||||
private BigDecimal projectManagerRatio;
|
||||
@Schema(description = "项目经理/项目负责人")
|
||||
private String projectLeadName;
|
||||
|
||||
@Schema(description = "项目经理金额")
|
||||
private BigDecimal projectManagerAmount;
|
||||
@Schema(description = "项目经理/项目负责人合并比例")
|
||||
private BigDecimal projectLeadRatio;
|
||||
|
||||
@Schema(description = "项目负责人比例")
|
||||
private BigDecimal engineeringLeaderRatio;
|
||||
|
||||
@Schema(description = "项目负责人金额")
|
||||
private BigDecimal engineeringLeaderAmount;
|
||||
@Schema(description = "项目经理/项目负责人合并金额")
|
||||
private BigDecimal projectLeadAmount;
|
||||
|
||||
@Schema(description = "专业所比例")
|
||||
private BigDecimal officeRatio;
|
||||
|
||||
@@ -3,6 +3,8 @@ package cn.iocoder.lyzsys.module.tjt.controller.admin.outputsplit.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.DecimalMax;
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -10,48 +12,62 @@ import java.math.BigDecimal;
|
||||
@Data
|
||||
public class ProjectOutputSplitSaveReqVO {
|
||||
|
||||
@Schema(description = "合同规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "合同规划 ID 不能为空")
|
||||
@Schema(description = "合约规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "合约规划 ID 不能为空")
|
||||
private Long planningId;
|
||||
|
||||
@Schema(description = "项目经理比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0200")
|
||||
@NotNull(message = "项目经理比例不能为空")
|
||||
private BigDecimal projectManagerRatio;
|
||||
|
||||
@Schema(description = "项目负责人比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0300")
|
||||
@NotNull(message = "项目负责人比例不能为空")
|
||||
private BigDecimal engineeringLeaderRatio;
|
||||
@Schema(description = "项目经理/项目负责人合并比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0550")
|
||||
@NotNull(message = "项目经理/项目负责人合并比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "projectLeadRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "projectLeadRatio must be <= 1")
|
||||
private BigDecimal projectLeadRatio;
|
||||
|
||||
@Schema(description = "专业所比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.9500")
|
||||
@NotNull(message = "专业所比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "officeRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "officeRatio must be <= 1")
|
||||
private BigDecimal officeRatio;
|
||||
|
||||
@Schema(description = "建筑专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.5000")
|
||||
@NotNull(message = "建筑专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "archRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "archRatio must be <= 1")
|
||||
private BigDecimal archRatio;
|
||||
|
||||
@Schema(description = "装修专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0000")
|
||||
@NotNull(message = "装修专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "decorRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "decorRatio must be <= 1")
|
||||
private BigDecimal decorRatio;
|
||||
|
||||
@Schema(description = "结构专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.2000")
|
||||
@NotNull(message = "结构专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "structRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "structRatio must be <= 1")
|
||||
private BigDecimal structRatio;
|
||||
|
||||
@Schema(description = "水专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.1000")
|
||||
@NotNull(message = "水专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "waterRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "waterRatio must be <= 1")
|
||||
private BigDecimal waterRatio;
|
||||
|
||||
@Schema(description = "电气专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.1000")
|
||||
@NotNull(message = "电气专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "elecRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "elecRatio must be <= 1")
|
||||
private BigDecimal elecRatio;
|
||||
|
||||
@Schema(description = "暖通专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0500")
|
||||
@NotNull(message = "暖通专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "hvacRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "hvacRatio must be <= 1")
|
||||
private BigDecimal hvacRatio;
|
||||
|
||||
@Schema(description = "数字化设计专业比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0500")
|
||||
@NotNull(message = "数字化设计专业比例不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "digitalRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "digitalRatio must be <= 1")
|
||||
private BigDecimal digitalRatio;
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ public class ProjectPlanningRespVO {
|
||||
@Schema(description = "归属类型")
|
||||
private String ownershipType;
|
||||
|
||||
@Schema(description = "设计部位")
|
||||
private String designPart;
|
||||
|
||||
@Schema(description = "建筑类型")
|
||||
private String buildingType;
|
||||
|
||||
@Schema(description = "产值计算方式")
|
||||
private String calculationMethod;
|
||||
|
||||
@@ -64,7 +70,7 @@ public class ProjectPlanningRespVO {
|
||||
@Schema(description = "待分配比例")
|
||||
private BigDecimal pendingAmount;
|
||||
|
||||
@Schema(description = "Planning progress remark")
|
||||
@Schema(description = "提取进度备注")
|
||||
private String progressRemark;
|
||||
|
||||
@Schema(description = "楼栋数或户型数")
|
||||
@@ -100,9 +106,6 @@ public class ProjectPlanningRespVO {
|
||||
@Schema(description = "指导总价")
|
||||
private BigDecimal guidanceTotalPrice;
|
||||
|
||||
@Schema(description = "虚拟总价")
|
||||
private BigDecimal virtualTotalPrice;
|
||||
|
||||
@Schema(description = "产值计算比例")
|
||||
private BigDecimal calculationRatio;
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package cn.iocoder.lyzsys.module.tjt.controller.admin.planning.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.DecimalMax;
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
@@ -24,8 +26,15 @@ public class ProjectPlanningSaveReqVO {
|
||||
@Size(max = 20, message = "归属类型长度不能超过 20 个字符")
|
||||
private String ownershipType;
|
||||
|
||||
@Schema(description = "产值计算方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "指导价法")
|
||||
@NotBlank(message = "产值计算方式不能为空")
|
||||
@Schema(description = "设计部位", example = "地上部分")
|
||||
@Size(max = 20, message = "设计部位长度不能超过 20 个字符")
|
||||
private String designPart;
|
||||
|
||||
@Schema(description = "建筑类型", example = "住宅")
|
||||
@Size(max = 100, message = "建筑类型长度不能超过 100 个字符")
|
||||
private String buildingType;
|
||||
|
||||
@Schema(description = "产值计算方式,页面 2 维护", example = "指导价法")
|
||||
@Size(max = 30, message = "产值计算方式长度不能超过 30 个字符")
|
||||
private String calculationMethod;
|
||||
|
||||
@@ -40,6 +49,8 @@ public class ProjectPlanningSaveReqVO {
|
||||
|
||||
@Schema(description = "管理费费率", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.0500")
|
||||
@NotNull(message = "管理费费率不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "managementFeeRate must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "managementFeeRate must be <= 1")
|
||||
private BigDecimal managementFeeRate;
|
||||
|
||||
@Schema(description = "实施团队", example = "建筑一所")
|
||||
@@ -57,19 +68,25 @@ public class ProjectPlanningSaveReqVO {
|
||||
private String designStage;
|
||||
|
||||
@Schema(description = "本次设计阶段比例", example = "0.3000")
|
||||
@DecimalMin(value = "0.0000", message = "currentDesignStageRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "currentDesignStageRatio must be <= 1")
|
||||
private BigDecimal currentDesignStageRatio;
|
||||
|
||||
@Schema(description = "审核审定是否外包", example = "false")
|
||||
private Boolean reviewOutsourceFlag;
|
||||
|
||||
@Schema(description = "审核审定占比", example = "0.0600")
|
||||
@DecimalMin(value = "0.0000", message = "reviewOutsourceRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "reviewOutsourceRatio must be <= 1")
|
||||
private BigDecimal reviewOutsourceRatio;
|
||||
|
||||
@Schema(description = "总分配比例", example = "1.0000")
|
||||
@DecimalMin(value = "0.0000", message = "totalDistributionAmount must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "totalDistributionAmount must be <= 1")
|
||||
private BigDecimal totalDistributionAmount;
|
||||
|
||||
@Schema(description = "Planning progress remark", example = "Q1 extraction arrangement")
|
||||
@Size(max = 500, message = "Progress remark length must be within 500 characters")
|
||||
@Schema(description = "提取进度备注", example = "Q1 提取安排")
|
||||
@Size(max = 500, message = "提取进度备注长度不能超过 500 个字符")
|
||||
private String progressRemark;
|
||||
|
||||
@Schema(description = "楼栋数或户型数", example = "10")
|
||||
@@ -85,12 +102,14 @@ public class ProjectPlanningSaveReqVO {
|
||||
private BigDecimal modificationFactor;
|
||||
|
||||
@Schema(description = "复杂系数/复杂等级,按比例值存储(100%=1.0000)", example = "1.0000")
|
||||
@DecimalMin(value = "0.0000", message = "complexityFactor must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "complexityFactor must be <= 1")
|
||||
private BigDecimal complexityFactor;
|
||||
|
||||
@Schema(description = "内部指导单价(元/㎡)", example = "80.00")
|
||||
private BigDecimal internalGuidanceUnitPrice;
|
||||
|
||||
@Schema(description = "虚拟产值计算方式", example = "工日法")
|
||||
@Schema(description = "虚拟产值计算方式:指导单价法 / 指导总价法 / 工日法", example = "工日法")
|
||||
@Size(max = 30, message = "虚拟产值计算方式长度不能超过 30 个字符")
|
||||
private String virtualCalculationMethod;
|
||||
|
||||
@@ -106,10 +125,9 @@ public class ProjectPlanningSaveReqVO {
|
||||
@Schema(description = "指导总价", example = "880000.00")
|
||||
private BigDecimal guidanceTotalPrice;
|
||||
|
||||
@Schema(description = "虚拟总价", example = "600000.00")
|
||||
private BigDecimal virtualTotalPrice;
|
||||
|
||||
@Schema(description = "产值计算比例", example = "0.0800")
|
||||
@DecimalMin(value = "0.0000", message = "calculationRatio must be >= 0")
|
||||
@DecimalMax(value = "1.0000", message = "calculationRatio must be <= 1")
|
||||
private BigDecimal calculationRatio;
|
||||
|
||||
}
|
||||
|
||||
@@ -6,32 +6,29 @@ import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 季度分配 Response VO")
|
||||
@Schema(description = "Admin - project planning quarter Response VO")
|
||||
@Data
|
||||
public class ProjectPlanningQuarterRespVO {
|
||||
|
||||
@Schema(description = "季度分配 ID", example = "1")
|
||||
@Schema(description = "Quarter distribution ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "合约规划 ID", example = "1")
|
||||
@Schema(description = "Planning ID", example = "1")
|
||||
private Long planningId;
|
||||
|
||||
@Schema(description = "分配年度")
|
||||
@Schema(description = "Distribution year")
|
||||
private Integer distributionYear;
|
||||
|
||||
@Schema(description = "季度")
|
||||
@Schema(description = "Quarter number")
|
||||
private Integer quarterNo;
|
||||
|
||||
@Schema(description = "分配比例")
|
||||
@Schema(description = "Distribution ratio")
|
||||
private BigDecimal distributionRatio;
|
||||
|
||||
@Schema(description = "分配金额")
|
||||
@Schema(description = "Distribution amount")
|
||||
private BigDecimal distributionAmount;
|
||||
|
||||
@Schema(description = "提取进度备注")
|
||||
private String progressRemark;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@Schema(description = "Create time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -6,35 +6,30 @@ import lombok.Data;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 季度分配新增/修改 Request VO")
|
||||
@Schema(description = "Admin - project planning quarter save Request VO")
|
||||
@Data
|
||||
public class ProjectPlanningQuarterSaveReqVO {
|
||||
|
||||
@Schema(description = "季度分配 ID", example = "1")
|
||||
@Schema(description = "Quarter distribution ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "合约规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "合约规划 ID 不能为空")
|
||||
@Schema(description = "Planning ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "planningId cannot be null")
|
||||
private Long planningId;
|
||||
|
||||
@Schema(description = "分配年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
|
||||
@NotNull(message = "分配年度不能为空")
|
||||
@Schema(description = "Distribution year", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
|
||||
@NotNull(message = "distributionYear cannot be null")
|
||||
private Integer distributionYear;
|
||||
|
||||
@Schema(description = "季度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "季度不能为空")
|
||||
@Min(value = 1, message = "季度必须在 1 到 4 之间")
|
||||
@Max(value = 4, message = "季度必须在 1 到 4 之间")
|
||||
@Schema(description = "Quarter number", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "quarterNo cannot be null")
|
||||
@Min(value = 1, message = "quarterNo must be between 1 and 4")
|
||||
@Max(value = 4, message = "quarterNo must be between 1 and 4")
|
||||
private Integer quarterNo;
|
||||
|
||||
@Schema(description = "分配比例", example = "0.2500")
|
||||
@Schema(description = "Distribution ratio", example = "0.2500")
|
||||
private BigDecimal distributionRatio;
|
||||
|
||||
@Schema(description = "提取进度备注", example = "Q1 提取")
|
||||
@Size(max = 500, message = "提取进度备注长度不能超过 500 个字符")
|
||||
private String progressRemark;
|
||||
|
||||
}
|
||||
|
||||
@@ -34,12 +34,18 @@ public class ProjectProfitRespVO {
|
||||
@Schema(description = "专业所产值")
|
||||
private BigDecimal majorOutputValue;
|
||||
|
||||
@Schema(description = "预计 K 值")
|
||||
private BigDecimal expectedKValue;
|
||||
|
||||
@Schema(description = "专业所预计绩效")
|
||||
private BigDecimal majorExpectedPerformance;
|
||||
|
||||
@Schema(description = "科创产值比例")
|
||||
private BigDecimal innovationOutputRate;
|
||||
|
||||
@Schema(description = "科创产值")
|
||||
private BigDecimal innovationOutputValue;
|
||||
|
||||
@Schema(description = "其他成本")
|
||||
private BigDecimal otherCost;
|
||||
|
||||
@Schema(description = "盈亏值")
|
||||
private BigDecimal profitLossValue;
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@ package cn.iocoder.lyzsys.module.tjt.controller.admin.project;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
|
||||
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.project.vo.ProjectPageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.project.ProjectDO;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.project.ProjectService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -67,8 +65,7 @@ public class ProjectController {
|
||||
@Operation(summary = "获得项目分页")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:project:query')")
|
||||
public CommonResult<PageResult<ProjectRespVO>> getProjectPage(@Valid ProjectPageReqVO pageReqVO) {
|
||||
PageResult<ProjectDO> pageResult = projectService.getProjectPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, ProjectRespVO.class));
|
||||
return success(projectService.getProjectPage(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@@ -76,7 +73,7 @@ public class ProjectController {
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:project:query')")
|
||||
public CommonResult<ProjectRespVO> getProject(@RequestParam("id") Long id) {
|
||||
return success(BeanUtils.toBean(projectService.getProject(id), ProjectRespVO.class));
|
||||
return success(projectService.getProject(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ public class ProjectPageReqVO extends PageParam {
|
||||
@Schema(description = "项目开始年度", example = "2026")
|
||||
private Integer projectStartYear;
|
||||
|
||||
@Schema(description = "项目状态", example = "进行中")
|
||||
private String projectStatus;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@@ -9,6 +9,7 @@ import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 项目 Response VO")
|
||||
@Data
|
||||
@@ -66,20 +67,47 @@ public class ProjectRespVO {
|
||||
@ExcelProperty("工程类型")
|
||||
private String projectType;
|
||||
|
||||
@Schema(description = "工程类别")
|
||||
@ExcelProperty("工程类别")
|
||||
private String projectCategory;
|
||||
|
||||
@Schema(description = "项目开始年度")
|
||||
@ExcelProperty("项目开始年度")
|
||||
private Integer projectStartYear;
|
||||
|
||||
@Schema(description = "项目状态")
|
||||
@ExcelProperty("项目状态")
|
||||
private String projectStatus;
|
||||
|
||||
@Schema(description = "是否封档")
|
||||
private Boolean archiveFlag;
|
||||
|
||||
@Schema(description = "封档时间")
|
||||
private LocalDateTime archiveTime;
|
||||
|
||||
@Schema(description = "暂停原因")
|
||||
private String pauseReason;
|
||||
|
||||
@Schema(description = "中止原因")
|
||||
private String terminateReason;
|
||||
|
||||
@Schema(description = "最终结算金额")
|
||||
@ExcelProperty("最终结算金额")
|
||||
private BigDecimal finalSettlementAmount;
|
||||
|
||||
@Schema(description = "预计 K 值")
|
||||
@ExcelProperty("预计 K 值")
|
||||
private BigDecimal expectedKValue;
|
||||
@Schema(description = "科创产值比例")
|
||||
@ExcelProperty("科创产值比例")
|
||||
private BigDecimal innovationOutputRate;
|
||||
|
||||
@Schema(description = "其他成本")
|
||||
@ExcelProperty("其他成本")
|
||||
private BigDecimal otherCost;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "项目角色人员列表")
|
||||
private List<ProjectRolePersonRespVO> rolePersons;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 项目角色人员 Response VO")
|
||||
@Data
|
||||
public class ProjectRolePersonRespVO {
|
||||
|
||||
@Schema(description = "主键 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "项目 ID", example = "1")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "角色编码", example = "project_manager")
|
||||
private String roleCode;
|
||||
|
||||
@Schema(description = "角色名称", example = "项目经理")
|
||||
private String roleName;
|
||||
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long employeeId;
|
||||
|
||||
@Schema(description = "员工姓名", example = "张三")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "排序号", example = "1")
|
||||
private Integer sortNo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Schema(description = "管理后台 - 项目角色人员新增/修改 Request VO")
|
||||
@Data
|
||||
public class ProjectRolePersonSaveReqVO {
|
||||
|
||||
@Schema(description = "角色编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "project_manager")
|
||||
@NotBlank(message = "角色编码不能为空")
|
||||
private String roleCode;
|
||||
|
||||
@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 = "排序号", example = "1")
|
||||
private Integer sortNo;
|
||||
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.DecimalMax;
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
@@ -54,26 +57,43 @@ public class ProjectSaveReqVO {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate contractSigningDate;
|
||||
|
||||
@Schema(description = "项目经理", example = "李四")
|
||||
@Size(max = 64, message = "项目经理长度不能超过 64 个字符")
|
||||
private String projectManagerName;
|
||||
|
||||
@Schema(description = "工程负责人", example = "王五")
|
||||
@Size(max = 64, message = "工程负责人长度不能超过 64 个字符")
|
||||
private String engineeringPrincipalName;
|
||||
|
||||
@Schema(description = "工程类型", example = "住宅")
|
||||
@Schema(description = "工程类型", example = "建筑工程")
|
||||
@Size(max = 50, message = "工程类型长度不能超过 50 个字符")
|
||||
private String projectType;
|
||||
|
||||
@Schema(description = "工程类别", example = "住宅")
|
||||
@Size(max = 50, message = "工程类别长度不能超过 50 个字符")
|
||||
private String projectCategory;
|
||||
|
||||
@Schema(description = "项目开始年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
|
||||
@NotNull(message = "项目开始年度不能为空")
|
||||
private Integer projectStartYear;
|
||||
|
||||
@Schema(description = "项目状态", example = "进行中")
|
||||
@Size(max = 20, message = "项目状态长度不能超过 20 个字符")
|
||||
private String projectStatus;
|
||||
|
||||
@Schema(description = "暂停原因")
|
||||
@Size(max = 255, message = "暂停原因长度不能超过 255 个字符")
|
||||
private String pauseReason;
|
||||
|
||||
@Schema(description = "中止原因")
|
||||
@Size(max = 255, message = "中止原因长度不能超过 255 个字符")
|
||||
private String terminateReason;
|
||||
|
||||
@Schema(description = "最终结算金额", example = "1200000")
|
||||
private BigDecimal finalSettlementAmount;
|
||||
|
||||
@Schema(description = "预计 K 值", example = "0.8500")
|
||||
private BigDecimal expectedKValue;
|
||||
@Schema(description = "科创产值比例", example = "0.0100")
|
||||
@DecimalMin(value = "0.0000", message = "科创产值比例不能小于 0%")
|
||||
@DecimalMax(value = "1.0000", message = "科创产值比例不能大于 100%")
|
||||
private BigDecimal innovationOutputRate;
|
||||
|
||||
@Schema(description = "其他成本", example = "20000.00")
|
||||
private BigDecimal otherCost;
|
||||
|
||||
@Schema(description = "项目角色人员列表")
|
||||
@Valid
|
||||
private java.util.List<ProjectRolePersonSaveReqVO> rolePersons;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
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.module.tjt.service.report.ProjectOutputReportService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 产值报表导出")
|
||||
@RestController
|
||||
@RequestMapping("/tjt/report")
|
||||
@Validated
|
||||
public class ProjectOutputReportController {
|
||||
|
||||
@Resource
|
||||
private ProjectOutputReportService projectOutputReportService;
|
||||
|
||||
@GetMapping("/project-budget/export-excel")
|
||||
@Operation(summary = "导出项目考核产值预算表")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:report-budget:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportProjectBudgetExcel(HttpServletResponse response,
|
||||
@Valid ProjectBudgetExportReqVO reqVO) throws IOException {
|
||||
projectOutputReportService.exportProjectBudgetExcel(response, reqVO);
|
||||
}
|
||||
|
||||
@GetMapping("/project-quarter-output/export-excel")
|
||||
@Operation(summary = "导出项目级年度季度计取表")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:report-project-quarter:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportProjectQuarterOutputExcel(HttpServletResponse response,
|
||||
@Valid ProjectQuarterOutputExportReqVO reqVO) throws IOException {
|
||||
projectOutputReportService.exportProjectQuarterOutputExcel(response, reqVO);
|
||||
}
|
||||
|
||||
@GetMapping("/project-lead-quarter-output/export-excel")
|
||||
@Operation(summary = "导出项目负责人年度季度计取表")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:report-project-quarter:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportProjectLeadQuarterOutputExcel(HttpServletResponse response,
|
||||
@Valid ProjectLeadQuarterOutputExportReqVO reqVO)
|
||||
throws IOException {
|
||||
projectOutputReportService.exportProjectLeadQuarterOutputExcel(response, reqVO);
|
||||
}
|
||||
|
||||
@GetMapping("/specialty-person-output/export-excel")
|
||||
@Operation(summary = "导出专业内人员年度季度计取表")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:report-specialty-person:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportSpecialtyPersonOutputExcel(HttpServletResponse response,
|
||||
@Valid SpecialtyPersonOutputExportReqVO reqVO) throws IOException {
|
||||
projectOutputReportService.exportSpecialtyPersonOutputExcel(response, reqVO);
|
||||
}
|
||||
|
||||
@GetMapping("/project-overview/export-excel")
|
||||
@Operation(summary = "导出项目总览表")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:report-summary:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportProjectOverviewExcel(HttpServletResponse response,
|
||||
@Valid ProjectOverviewExportReqVO reqVO) throws IOException {
|
||||
projectOutputReportService.exportProjectOverviewExcel(response, reqVO);
|
||||
}
|
||||
|
||||
@GetMapping("/employee-output-summary/export-excel")
|
||||
@Operation(summary = "导出员工个人考核产值汇总表")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:report-summary:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportEmployeeOutputSummaryExcel(HttpServletResponse response,
|
||||
@Valid EmployeeOutputSummaryExportReqVO reqVO)
|
||||
throws IOException {
|
||||
projectOutputReportService.exportEmployeeOutputSummaryExcel(response, reqVO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 员工个人考核产值汇总 Excel 导出 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class EmployeeOutputSummaryExcelRespVO {
|
||||
|
||||
@ExcelProperty("序号")
|
||||
private Integer serialNo;
|
||||
|
||||
@ExcelProperty("姓名")
|
||||
private String employeeName;
|
||||
|
||||
@ExcelProperty("所属专业所")
|
||||
private String officeName;
|
||||
|
||||
@ExcelProperty("第一季度")
|
||||
private BigDecimal quarterOneAmount;
|
||||
|
||||
@ExcelProperty("第二季度")
|
||||
private BigDecimal quarterTwoAmount;
|
||||
|
||||
@ExcelProperty("第三季度")
|
||||
private BigDecimal quarterThreeAmount;
|
||||
|
||||
@ExcelProperty("第四季度")
|
||||
private BigDecimal quarterFourAmount;
|
||||
|
||||
@ExcelProperty("年度合计")
|
||||
private BigDecimal annualTotalAmount;
|
||||
|
||||
@ExcelProperty("所长/BIM考核产值")
|
||||
private BigDecimal officeLeaderOrBimAmount;
|
||||
|
||||
@ExcelProperty("年度考核产值合计")
|
||||
private BigDecimal totalAssessmentOutputAmount;
|
||||
|
||||
@ExcelProperty("1~12月份预计发生成本")
|
||||
private BigDecimal expectedCostAmount;
|
||||
|
||||
@ExcelProperty("基本考核产值")
|
||||
private BigDecimal basicAssessmentOutputAmount;
|
||||
|
||||
@ExcelProperty("剩余产值")
|
||||
private BigDecimal remainingOutputAmount;
|
||||
|
||||
@ExcelProperty("预估年底绩效")
|
||||
private BigDecimal estimatedYearEndPerformanceAmount;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
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 EmployeeOutputSummaryExportReqVO {
|
||||
|
||||
@Schema(description = "年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
|
||||
@NotNull(message = "年度不能为空")
|
||||
private Integer year;
|
||||
|
||||
@Schema(description = "专业所 ID", example = "1")
|
||||
private Long officeId;
|
||||
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long employeeId;
|
||||
|
||||
@Schema(description = "员工状态", example = "在职")
|
||||
private String employeeStatus;
|
||||
|
||||
@Schema(description = "排序方式", example = "annual_total_desc")
|
||||
private String sortType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
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 ProjectBudgetExportReqVO {
|
||||
|
||||
@Schema(description = "项目 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "项目 ID 不能为空")
|
||||
private Long projectId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
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 ProjectLeadQuarterOutputExportReqVO {
|
||||
|
||||
@Schema(description = "合约规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "合约规划 ID 不能为空")
|
||||
private Long planningId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.report.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 项目总览表 Excel 导出 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ProjectOverviewExcelRespVO {
|
||||
|
||||
@ExcelProperty("序号")
|
||||
private Integer serialNo;
|
||||
|
||||
@ExcelProperty("项目名称")
|
||||
private String projectName;
|
||||
|
||||
@ExcelProperty("规划内容")
|
||||
private String planningContent;
|
||||
|
||||
@ExcelProperty("工程进度情况及其它说明")
|
||||
private String progressText;
|
||||
|
||||
@ExcelProperty("工作阶段")
|
||||
private String designStage;
|
||||
|
||||
@ExcelProperty("本专业+项总核算总产值")
|
||||
private BigDecimal totalOutputAmount;
|
||||
|
||||
@ExcelProperty("往年已发放比例")
|
||||
private String historicalIssuedRatioText;
|
||||
|
||||
@ExcelProperty("本期结算")
|
||||
private BigDecimal currentSettlementAmount;
|
||||
|
||||
@ExcelProperty("未结算比例")
|
||||
private String pendingRatioText;
|
||||
|
||||
@ExcelProperty("一季度")
|
||||
private BigDecimal quarterOneAmount;
|
||||
|
||||
@ExcelProperty("二季度")
|
||||
private BigDecimal quarterTwoAmount;
|
||||
|
||||
@ExcelProperty("三季度")
|
||||
private BigDecimal quarterThreeAmount;
|
||||
|
||||
@ExcelProperty("四季度")
|
||||
private BigDecimal quarterFourAmount;
|
||||
|
||||
@ExcelProperty("本年度小计")
|
||||
private BigDecimal yearTotalAmount;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
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.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 项目总览表导出 Request VO")
|
||||
@Data
|
||||
public class ProjectOverviewExportReqVO {
|
||||
|
||||
@Schema(description = "年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
|
||||
@NotNull(message = "年度不能为空")
|
||||
private Integer year;
|
||||
|
||||
@Schema(description = "专业编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "water")
|
||||
@NotBlank(message = "专业编码不能为空")
|
||||
private String specialtyCode;
|
||||
|
||||
@Schema(description = "排序方式", example = "output_desc")
|
||||
private String sortType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
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 ProjectQuarterOutputExportReqVO {
|
||||
|
||||
@Schema(description = "合约规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "合约规划 ID 不能为空")
|
||||
private Long planningId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
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.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 专业内人员年度季度计取表导出 Request VO")
|
||||
@Data
|
||||
public class SpecialtyPersonOutputExportReqVO {
|
||||
|
||||
@Schema(description = "合约规划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "合约规划 ID 不能为空")
|
||||
private Long planningId;
|
||||
|
||||
@Schema(description = "专业编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "water")
|
||||
@NotBlank(message = "专业编码不能为空")
|
||||
private String specialtyCode;
|
||||
|
||||
}
|
||||
@@ -9,8 +9,11 @@ import java.math.BigDecimal;
|
||||
@Data
|
||||
public class SpecialtyRolePersonRespVO {
|
||||
|
||||
@Schema(description = "人员名称")
|
||||
private String personName;
|
||||
@Schema(description = "员工 ID")
|
||||
private Long employeeId;
|
||||
|
||||
@Schema(description = "员工姓名")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "人员比例")
|
||||
private BigDecimal personRatio;
|
||||
|
||||
@@ -9,8 +9,11 @@ import java.math.BigDecimal;
|
||||
@Data
|
||||
public class SpecialtyRolePersonSaveReqVO {
|
||||
|
||||
@Schema(description = "人员名称", example = "张三")
|
||||
private String personName;
|
||||
@Schema(description = "员工 ID", example = "1")
|
||||
private Long employeeId;
|
||||
|
||||
@Schema(description = "员工姓名", example = "张三")
|
||||
private String employeeName;
|
||||
|
||||
@Schema(description = "人员比例", example = "0.1000")
|
||||
private BigDecimal personRatio;
|
||||
|
||||
@@ -16,7 +16,7 @@ public class SpecialtyRoleSplitRespVO {
|
||||
@Schema(description = "页面4拆分 ID", example = "1")
|
||||
private Long outputSplitId;
|
||||
|
||||
@Schema(description = "合同规划 ID", example = "1")
|
||||
@Schema(description = "合约规划 ID", example = "1")
|
||||
private Long planningId;
|
||||
|
||||
@Schema(description = "项目名称")
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.CommonResult;
|
||||
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.yearkvalue.vo.YearKValuePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValueRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValueSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.yearkvalue.YearKValueService;
|
||||
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.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||
import static cn.iocoder.lyzsys.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 年度 K 值")
|
||||
@RestController
|
||||
@RequestMapping("/tjt/year-k-value")
|
||||
@Validated
|
||||
public class YearKValueController {
|
||||
|
||||
@Resource
|
||||
private YearKValueService yearKValueService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建年度 K 值")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:year-k-value:create')")
|
||||
public CommonResult<Long> createYearKValue(@RequestBody Map<String, Object> requestBody) {
|
||||
YearKValueSaveReqVO createReqVO = buildSaveReqVO(requestBody, false);
|
||||
return success(yearKValueService.createYearKValue(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改年度 K 值")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:year-k-value:update')")
|
||||
public CommonResult<Boolean> updateYearKValue(@RequestBody Map<String, Object> requestBody) {
|
||||
YearKValueSaveReqVO updateReqVO = buildSaveReqVO(requestBody, true);
|
||||
yearKValueService.updateYearKValue(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除年度 K 值")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:year-k-value:delete')")
|
||||
public CommonResult<Boolean> deleteYearKValue(@RequestParam("id") Long id) {
|
||||
yearKValueService.deleteYearKValue(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得年度 K 值详情")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:year-k-value:query')")
|
||||
public CommonResult<YearKValueRespVO> getYearKValue(@RequestParam("id") Long id) {
|
||||
return success(yearKValueService.getYearKValue(id));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得年度 K 值分页")
|
||||
@PreAuthorize("@ss.hasPermission('tjt:year-k-value:query')")
|
||||
public CommonResult<PageResult<YearKValueRespVO>> getYearKValuePage(@Valid YearKValuePageReqVO pageReqVO) {
|
||||
return success(yearKValueService.getYearKValuePage(pageReqVO));
|
||||
}
|
||||
|
||||
private YearKValueSaveReqVO buildSaveReqVO(Map<String, Object> requestBody, boolean requireId) {
|
||||
YearKValueSaveReqVO reqVO = BeanUtils.toBean(requestBody, YearKValueSaveReqVO.class);
|
||||
if (requireId && reqVO.getId() == null) {
|
||||
throw invalidParamException("编号不能为空");
|
||||
}
|
||||
if (reqVO.getKYear() == null) {
|
||||
throw invalidParamException("年度不能为空");
|
||||
}
|
||||
if (reqVO.getKValue() == null) {
|
||||
throw invalidParamException("K值不能为空");
|
||||
}
|
||||
if (reqVO.getKValue().compareTo(BigDecimal.ZERO) < 0
|
||||
|| reqVO.getKValue().compareTo(BigDecimal.ONE) > 0) {
|
||||
throw invalidParamException("K值必须在 0% 到 100% 之间");
|
||||
}
|
||||
if (reqVO.getRemark() != null && reqVO.getRemark().length() > 255) {
|
||||
throw invalidParamException("备注长度不能超过 255 个字符");
|
||||
}
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.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 = "管理后台 - 年度 K 值分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class YearKValuePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "年度", example = "2026")
|
||||
private Integer kYear;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 年度 K 值 Response VO")
|
||||
@Data
|
||||
public class YearKValueRespVO {
|
||||
|
||||
@Schema(description = "主键 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "年度", example = "2026")
|
||||
private Integer kYear;
|
||||
|
||||
@Schema(description = "K 值", example = "0.4000")
|
||||
private BigDecimal kValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.DecimalMax;
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 年度 K 值新增/修改 Request VO")
|
||||
@Data
|
||||
public class YearKValueSaveReqVO {
|
||||
|
||||
@Schema(description = "主键 ID", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "年度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026")
|
||||
@NotNull(message = "年度不能为空")
|
||||
private Integer kYear;
|
||||
|
||||
@Schema(description = "K 值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.4000")
|
||||
@NotNull(message = "K 值不能为空")
|
||||
@DecimalMin(value = "0.0000", message = "K 值不能小于 0%")
|
||||
@DecimalMax(value = "1.0000", message = "K 值不能大于 100%")
|
||||
private BigDecimal kValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
@Size(max = 255, message = "备注长度不能超过 255 个字符")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee;
|
||||
|
||||
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.time.LocalDate;
|
||||
|
||||
@TableName("tjt_employee")
|
||||
@KeySequence("tjt_employee_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EmployeeDO extends TenantBaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private String employeeName;
|
||||
|
||||
private String gender;
|
||||
|
||||
private Long officeId;
|
||||
|
||||
private String registrationType;
|
||||
|
||||
private String jobTitle;
|
||||
|
||||
private String registrationSealNo;
|
||||
|
||||
private LocalDate entryDate;
|
||||
|
||||
private LocalDate leaveDate;
|
||||
|
||||
private String employeeStatus;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Integer sortNo;
|
||||
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget;
|
||||
|
||||
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_cost_budget")
|
||||
@KeySequence("tjt_employee_year_cost_budget_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EmployeeYearCostBudgetDO extends TenantBaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private Long employeeId;
|
||||
|
||||
private String employeeName;
|
||||
|
||||
private Integer budgetYear;
|
||||
|
||||
private BigDecimal expectedCostAmount;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Integer sortNo;
|
||||
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.office;
|
||||
|
||||
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;
|
||||
|
||||
@TableName("tjt_office")
|
||||
@KeySequence("tjt_office_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OfficeDO extends TenantBaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private String officeName;
|
||||
|
||||
private String officeCode;
|
||||
|
||||
private Integer sortNo;
|
||||
|
||||
private Boolean enabledFlag;
|
||||
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -29,9 +29,7 @@ public class ProjectOutputSplitDO extends TenantBaseDO {
|
||||
|
||||
private Integer year;
|
||||
|
||||
private BigDecimal projectManagerRatio;
|
||||
|
||||
private BigDecimal engineeringLeaderRatio;
|
||||
private BigDecimal projectLeadRatio;
|
||||
|
||||
private BigDecimal officeRatio;
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ public class ProjectPlanningDO extends TenantBaseDO {
|
||||
|
||||
private String ownershipType;
|
||||
|
||||
private String designPart;
|
||||
|
||||
private String buildingType;
|
||||
|
||||
private String calculationMethod;
|
||||
|
||||
private String planningContent;
|
||||
@@ -77,8 +81,6 @@ public class ProjectPlanningDO extends TenantBaseDO {
|
||||
|
||||
private BigDecimal guidanceTotalPrice;
|
||||
|
||||
private BigDecimal virtualTotalPrice;
|
||||
|
||||
private BigDecimal calculationRatio;
|
||||
|
||||
private BigDecimal contractUnitPrice;
|
||||
|
||||
@@ -9,6 +9,7 @@ import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 项目 DO
|
||||
@@ -58,29 +59,49 @@ public class ProjectDO extends TenantBaseDO {
|
||||
* 合同签订日期
|
||||
*/
|
||||
private LocalDate contractSigningDate;
|
||||
/**
|
||||
* 项目经理
|
||||
*/
|
||||
private String projectManagerName;
|
||||
/**
|
||||
* 工程负责人
|
||||
*/
|
||||
private String engineeringPrincipalName;
|
||||
/**
|
||||
* 工程类型
|
||||
*/
|
||||
private String projectType;
|
||||
/**
|
||||
* 工程类别
|
||||
*/
|
||||
private String projectCategory;
|
||||
/**
|
||||
* 项目开始年度
|
||||
*/
|
||||
private Integer projectStartYear;
|
||||
/**
|
||||
* 项目状态
|
||||
*/
|
||||
private String projectStatus;
|
||||
/**
|
||||
* 是否封档
|
||||
*/
|
||||
private Boolean archiveFlag;
|
||||
/**
|
||||
* 封档时间
|
||||
*/
|
||||
private LocalDateTime archiveTime;
|
||||
/**
|
||||
* 暂停原因
|
||||
*/
|
||||
private String pauseReason;
|
||||
/**
|
||||
* 中止原因
|
||||
*/
|
||||
private String terminateReason;
|
||||
/**
|
||||
* 最终结算金额
|
||||
*/
|
||||
private BigDecimal finalSettlementAmount;
|
||||
/**
|
||||
* 预计 K 值
|
||||
* 科创产值比例
|
||||
*/
|
||||
private BigDecimal expectedKValue;
|
||||
private BigDecimal innovationOutputRate;
|
||||
/**
|
||||
* 其他成本
|
||||
*/
|
||||
private BigDecimal otherCost;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.projectroleperson;
|
||||
|
||||
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;
|
||||
|
||||
@TableName("tjt_project_role_person")
|
||||
@KeySequence("tjt_project_role_person_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ProjectRolePersonDO extends TenantBaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private Long projectId;
|
||||
|
||||
private String roleCode;
|
||||
|
||||
private String roleName;
|
||||
|
||||
private Long employeeId;
|
||||
|
||||
private String employeeName;
|
||||
|
||||
private Integer sortNo;
|
||||
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class SpecialtyRoleSplitDO extends TenantBaseDO {
|
||||
|
||||
private BigDecimal roleRatio;
|
||||
|
||||
private String personNames;
|
||||
private String personsJson;
|
||||
|
||||
private Integer sortNo;
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.dataobject.yearkvalue;
|
||||
|
||||
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_year_k_value")
|
||||
@KeySequence("tjt_year_k_value_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class YearKValueDO extends TenantBaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private Integer kYear;
|
||||
|
||||
private BigDecimal kValue;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Boolean enabledFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.mysql.employee;
|
||||
|
||||
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.employee.vo.EmployeePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface EmployeeMapper extends BaseMapperX<EmployeeDO> {
|
||||
|
||||
default PageResult<EmployeeDO> selectPage(EmployeePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<EmployeeDO>()
|
||||
.likeIfPresent(EmployeeDO::getEmployeeName, reqVO.getEmployeeName())
|
||||
.eqIfPresent(EmployeeDO::getOfficeId, reqVO.getOfficeId())
|
||||
.eqIfPresent(EmployeeDO::getEmployeeStatus, reqVO.getEmployeeStatus())
|
||||
.eqIfPresent(EmployeeDO::getEnabledFlag, reqVO.getEnabledFlag())
|
||||
.orderByAsc(EmployeeDO::getSortNo)
|
||||
.orderByAsc(EmployeeDO::getId));
|
||||
}
|
||||
|
||||
default List<EmployeeDO> selectSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag) {
|
||||
return selectList(new LambdaQueryWrapperX<EmployeeDO>()
|
||||
.likeIfPresent(EmployeeDO::getEmployeeName, keyword)
|
||||
.eqIfPresent(EmployeeDO::getOfficeId, officeId)
|
||||
.eqIfPresent(EmployeeDO::getEmployeeStatus, status)
|
||||
.eqIfPresent(EmployeeDO::getEnabledFlag, enabledFlag)
|
||||
.orderByAsc(EmployeeDO::getSortNo)
|
||||
.orderByAsc(EmployeeDO::getId));
|
||||
}
|
||||
|
||||
default Long selectCountByOfficeId(Long officeId) {
|
||||
return selectCount(new LambdaQueryWrapperX<EmployeeDO>()
|
||||
.eq(EmployeeDO::getOfficeId, officeId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.mysql.employeeyearcostbudget;
|
||||
|
||||
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.employeeyearcostbudget.vo.EmployeeYearCostBudgetPageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EmployeeYearCostBudgetMapper extends BaseMapperX<EmployeeYearCostBudgetDO> {
|
||||
|
||||
default PageResult<EmployeeYearCostBudgetDO> selectPage(EmployeeYearCostBudgetPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<EmployeeYearCostBudgetDO>()
|
||||
.eqIfPresent(EmployeeYearCostBudgetDO::getEmployeeId, reqVO.getEmployeeId())
|
||||
.likeIfPresent(EmployeeYearCostBudgetDO::getEmployeeName, reqVO.getEmployeeName())
|
||||
.eqIfPresent(EmployeeYearCostBudgetDO::getBudgetYear, reqVO.getBudgetYear())
|
||||
.eqIfPresent(EmployeeYearCostBudgetDO::getEnabledFlag, reqVO.getEnabledFlag())
|
||||
.orderByDesc(EmployeeYearCostBudgetDO::getBudgetYear)
|
||||
.orderByAsc(EmployeeYearCostBudgetDO::getSortNo)
|
||||
.orderByAsc(EmployeeYearCostBudgetDO::getId));
|
||||
}
|
||||
|
||||
default EmployeeYearCostBudgetDO selectByEmployeeIdAndBudgetYear(Long employeeId, Integer budgetYear) {
|
||||
return selectOne(new LambdaQueryWrapperX<EmployeeYearCostBudgetDO>()
|
||||
.eq(EmployeeYearCostBudgetDO::getEmployeeId, employeeId)
|
||||
.eq(EmployeeYearCostBudgetDO::getBudgetYear, budgetYear));
|
||||
}
|
||||
|
||||
default Long selectCountByEmployeeId(Long employeeId) {
|
||||
return selectCount(new LambdaQueryWrapperX<EmployeeYearCostBudgetDO>()
|
||||
.eq(EmployeeYearCostBudgetDO::getEmployeeId, employeeId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.mysql.office;
|
||||
|
||||
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.office.vo.OfficePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface OfficeMapper extends BaseMapperX<OfficeDO> {
|
||||
|
||||
default PageResult<OfficeDO> selectPage(OfficePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<OfficeDO>()
|
||||
.likeIfPresent(OfficeDO::getOfficeName, reqVO.getOfficeName())
|
||||
.eqIfPresent(OfficeDO::getEnabledFlag, reqVO.getEnabledFlag())
|
||||
.orderByAsc(OfficeDO::getSortNo)
|
||||
.orderByAsc(OfficeDO::getId));
|
||||
}
|
||||
|
||||
default List<OfficeDO> selectSimpleList() {
|
||||
return selectList(new LambdaQueryWrapperX<OfficeDO>()
|
||||
.eq(OfficeDO::getEnabledFlag, Boolean.TRUE)
|
||||
.orderByAsc(OfficeDO::getSortNo)
|
||||
.orderByAsc(OfficeDO::getId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public interface ProjectMapper extends BaseMapperX<ProjectDO> {
|
||||
.likeIfPresent(ProjectDO::getProjectName, reqVO.getProjectName())
|
||||
.eqIfPresent(ProjectDO::getContractSignedFlag, reqVO.getContractSignedFlag())
|
||||
.eqIfPresent(ProjectDO::getProjectStartYear, reqVO.getProjectStartYear())
|
||||
.eqIfPresent(ProjectDO::getProjectStatus, reqVO.getProjectStatus())
|
||||
.betweenIfPresent(ProjectDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(ProjectDO::getId));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.mysql.projectroleperson;
|
||||
|
||||
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.projectroleperson.ProjectRolePersonDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ProjectRolePersonMapper extends BaseMapperX<ProjectRolePersonDO> {
|
||||
|
||||
default List<ProjectRolePersonDO> selectListByProjectId(Long projectId) {
|
||||
return selectList(new LambdaQueryWrapperX<ProjectRolePersonDO>()
|
||||
.eq(ProjectRolePersonDO::getProjectId, projectId)
|
||||
.eq(ProjectRolePersonDO::getEnabledFlag, Boolean.TRUE)
|
||||
.orderByAsc(ProjectRolePersonDO::getRoleCode)
|
||||
.orderByAsc(ProjectRolePersonDO::getSortNo)
|
||||
.orderByAsc(ProjectRolePersonDO::getId));
|
||||
}
|
||||
|
||||
default List<ProjectRolePersonDO> selectListByProjectIds(Collection<Long> projectIds) {
|
||||
if (projectIds == null || projectIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return selectList(new LambdaQueryWrapperX<ProjectRolePersonDO>()
|
||||
.in(ProjectRolePersonDO::getProjectId, projectIds)
|
||||
.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<ProjectRolePersonDO>()
|
||||
.eq(ProjectRolePersonDO::getEmployeeId, employeeId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,4 +22,9 @@ public interface SpecialtyRoleSplitMapper extends BaseMapperX<SpecialtyRoleSplit
|
||||
.orderByAsc(SpecialtyRoleSplitDO::getId));
|
||||
}
|
||||
|
||||
default List<SpecialtyRoleSplitDO> selectListByPersonsJsonKeyword(String keyword) {
|
||||
return selectList(new LambdaQueryWrapperX<SpecialtyRoleSplitDO>()
|
||||
.like(SpecialtyRoleSplitDO::getPersonsJson, keyword));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.dal.mysql.yearkvalue;
|
||||
|
||||
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.yearkvalue.vo.YearKValuePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.yearkvalue.YearKValueDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface YearKValueMapper extends BaseMapperX<YearKValueDO> {
|
||||
|
||||
default PageResult<YearKValueDO> selectPage(YearKValuePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<YearKValueDO>()
|
||||
.eqIfPresent(YearKValueDO::getKYear, reqVO.getKYear())
|
||||
.eqIfPresent(YearKValueDO::getEnabledFlag, reqVO.getEnabledFlag())
|
||||
.orderByAsc(YearKValueDO::getKYear));
|
||||
}
|
||||
|
||||
default YearKValueDO selectByKYear(Integer kYear) {
|
||||
return selectOne(new LambdaQueryWrapperX<YearKValueDO>()
|
||||
.eq(YearKValueDO::getKYear, kYear));
|
||||
}
|
||||
|
||||
default YearKValueDO selectEnabledByKYear(Integer kYear) {
|
||||
return selectOne(new LambdaQueryWrapperX<YearKValueDO>()
|
||||
.eq(YearKValueDO::getKYear, kYear)
|
||||
.eq(YearKValueDO::getEnabledFlag, Boolean.TRUE));
|
||||
}
|
||||
|
||||
default List<YearKValueDO> selectEnabledListByYears(Collection<Integer> years) {
|
||||
if (years == null || years.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return selectList(new LambdaQueryWrapperX<YearKValueDO>()
|
||||
.in(YearKValueDO::getKYear, years)
|
||||
.eq(YearKValueDO::getEnabledFlag, Boolean.TRUE));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,9 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode PROJECT_PLANNING_OWNERSHIP_TYPE_IMMUTABLE = new ErrorCode(1_020_002_004, "归属类型保存后不允许修改");
|
||||
ErrorCode PROJECT_PLANNING_CALCULATION_METHOD_IMMUTABLE = new ErrorCode(1_020_002_005, "产值计算方式保存后不允许修改");
|
||||
ErrorCode PROJECT_PLANNING_VIRTUAL_CALCULATION_METHOD_INVALID = new ErrorCode(1_020_002_006, "虚拟产值计算方式不正确");
|
||||
ErrorCode PROJECT_PLANNING_WORKING_DAY_COUNT_REQUIRED = new ErrorCode(1_020_002_007, "工日法下工日不能为空");
|
||||
ErrorCode PROJECT_PLANNING_WORKING_DAY_UNIT_PRICE_REQUIRED = new ErrorCode(1_020_002_008, "工日法下工日单价不能为空");
|
||||
ErrorCode PROJECT_PLANNING_DESIGN_PART_INVALID = new ErrorCode(1_020_002_009, "设计部位不正确");
|
||||
|
||||
// ========== 季度分配管理 1-020-003-000 ==========
|
||||
ErrorCode PROJECT_PLANNING_QUARTER_NOT_EXISTS = new ErrorCode(1_020_003_000, "季度分配明细不存在");
|
||||
@@ -36,8 +39,24 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_ROLE_RATIO_INVALID = new ErrorCode(1_020_005_001, "页面5五类角色比例合计必须等于 100%");
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_SPECIALTY_INVALID = new ErrorCode(1_020_005_002, "专业编码不正确");
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_ROLE_INVALID = new ErrorCode(1_020_005_003, "角色编码不正确");
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_PERSON_INVALID = new ErrorCode(1_020_005_004, "页面5人员名称和比例必须同时填写");
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_PERSON_INVALID = new ErrorCode(1_020_005_004, "页面5人员和比例必须同时填写");
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_DESIGN_PERSON_REQUIRED = new ErrorCode(1_020_005_005, "页面5设计角色金额大于 0 时必须配置人员");
|
||||
ErrorCode SPECIALTY_ROLE_SPLIT_PERSON_RATIO_INVALID = new ErrorCode(1_020_005_007, "页面5同一角色下人员比例之和不能大于 100%");
|
||||
|
||||
// ========== 年度 K 值管理 1-020-006-000 ==========
|
||||
ErrorCode YEAR_K_VALUE_NOT_EXISTS = new ErrorCode(1_020_006_000, "年度 K 值记录不存在");
|
||||
ErrorCode YEAR_K_VALUE_DUPLICATE = new ErrorCode(1_020_006_001, "同一年度的 K 值记录已存在");
|
||||
|
||||
// ========== 专业所管理 1-020-007-000 ==========
|
||||
ErrorCode OFFICE_NOT_EXISTS = new ErrorCode(1_020_007_000, "专业所记录不存在");
|
||||
ErrorCode OFFICE_IN_USE = new ErrorCode(1_020_007_001, "当前专业所已被员工引用,不能删除");
|
||||
|
||||
// ========== 员工管理 1-020-008-000 ==========
|
||||
ErrorCode EMPLOYEE_NOT_EXISTS = new ErrorCode(1_020_008_000, "员工记录不存在");
|
||||
ErrorCode EMPLOYEE_IN_USE = new ErrorCode(1_020_008_001, "当前员工已被业务数据引用,不能删除");
|
||||
|
||||
// ========== 员工年度成本预算 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, "当前员工该年度预计发生成本已存在");
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ import java.util.Map;
|
||||
*/
|
||||
public final class OutputSplitBizConstants {
|
||||
|
||||
public static final String OWNERSHIP_TYPE_MAJOR = "专业所";
|
||||
|
||||
public static final String SPECIALTY_PROJECT_LEAD = "project_lead";
|
||||
public static final String SPECIALTY_ARCH = "arch";
|
||||
public static final String SPECIALTY_DECOR = "decor";
|
||||
public static final String SPECIALTY_STRUCT = "struct";
|
||||
@@ -30,18 +29,31 @@ public final class OutputSplitBizConstants {
|
||||
public static final String ROLE_REVIEW = "review";
|
||||
public static final String ROLE_APPROVE = "approve";
|
||||
public static final String ROLE_DESIGN = "design";
|
||||
public static final String ROLE_PROJECT_MANAGER = "project_manager";
|
||||
public static final String ROLE_ENGINEERING_PRINCIPAL = "engineering_principal";
|
||||
|
||||
public static final List<SpecialtyItem> SPECIALTY_ITEMS = Arrays.asList(
|
||||
public static final List<SpecialtyItem> ASSIGNMENT_SPECIALTY_ITEMS = Arrays.asList(
|
||||
new SpecialtyItem(SPECIALTY_PROJECT_LEAD, "项目经理/项目负责人", 0),
|
||||
new SpecialtyItem(SPECIALTY_ARCH, "建筑", 1),
|
||||
new SpecialtyItem(SPECIALTY_DECOR, "装修", 2),
|
||||
new SpecialtyItem(SPECIALTY_DECOR, "装饰", 2),
|
||||
new SpecialtyItem(SPECIALTY_STRUCT, "结构", 3),
|
||||
new SpecialtyItem(SPECIALTY_WATER, "水", 4),
|
||||
new SpecialtyItem(SPECIALTY_WATER, "给排水", 4),
|
||||
new SpecialtyItem(SPECIALTY_ELEC, "电气", 5),
|
||||
new SpecialtyItem(SPECIALTY_HVAC, "暖通", 6),
|
||||
new SpecialtyItem(SPECIALTY_DIGITAL, "数字化设计", 7)
|
||||
);
|
||||
|
||||
public static final List<RoleItem> ROLE_ITEMS = Arrays.asList(
|
||||
public static final List<SpecialtyItem> SPECIALTY_ITEMS = Arrays.asList(
|
||||
new SpecialtyItem(SPECIALTY_ARCH, "建筑", 1),
|
||||
new SpecialtyItem(SPECIALTY_DECOR, "装饰", 2),
|
||||
new SpecialtyItem(SPECIALTY_STRUCT, "结构", 3),
|
||||
new SpecialtyItem(SPECIALTY_WATER, "给排水", 4),
|
||||
new SpecialtyItem(SPECIALTY_ELEC, "电气", 5),
|
||||
new SpecialtyItem(SPECIALTY_HVAC, "暖通", 6),
|
||||
new SpecialtyItem(SPECIALTY_DIGITAL, "数字化设计", 7)
|
||||
);
|
||||
|
||||
public static final List<RoleItem> SPECIALTY_ROLE_ITEMS = Arrays.asList(
|
||||
new RoleItem(ROLE_DIRECTOR, "专业负责人", 1),
|
||||
new RoleItem(ROLE_CHECK, "校对", 2),
|
||||
new RoleItem(ROLE_REVIEW, "审核", 3),
|
||||
@@ -49,23 +61,33 @@ public final class OutputSplitBizConstants {
|
||||
new RoleItem(ROLE_DESIGN, "设计", 5)
|
||||
);
|
||||
|
||||
public static final List<RoleItem> PROJECT_LEAD_ROLE_ITEMS = Arrays.asList(
|
||||
new RoleItem(ROLE_PROJECT_MANAGER, "项目经理", 1),
|
||||
new RoleItem(ROLE_ENGINEERING_PRINCIPAL, "项目负责人", 2)
|
||||
);
|
||||
|
||||
private OutputSplitBizConstants() {
|
||||
}
|
||||
|
||||
public static boolean isMajorOwnershipType(String value) {
|
||||
return OWNERSHIP_TYPE_MAJOR.equals(value);
|
||||
return ProjectPlanningBizTypeConstants.isMajor(value);
|
||||
}
|
||||
|
||||
public static boolean isValidSpecialtyCode(String code) {
|
||||
return SPECIALTY_ITEMS.stream().anyMatch(item -> item.getCode().equals(code));
|
||||
return ASSIGNMENT_SPECIALTY_ITEMS.stream().anyMatch(item -> item.getCode().equals(code));
|
||||
}
|
||||
|
||||
public static boolean isValidRoleCode(String code) {
|
||||
return ROLE_ITEMS.stream().anyMatch(item -> item.getCode().equals(code));
|
||||
return SPECIALTY_ROLE_ITEMS.stream().anyMatch(item -> item.getCode().equals(code))
|
||||
|| PROJECT_LEAD_ROLE_ITEMS.stream().anyMatch(item -> item.getCode().equals(code));
|
||||
}
|
||||
|
||||
public static boolean isValidRoleCode(String specialtyCode, String roleCode) {
|
||||
return getRoleItems(specialtyCode).stream().anyMatch(item -> item.getCode().equals(roleCode));
|
||||
}
|
||||
|
||||
public static String getSpecialtyName(String code) {
|
||||
return SPECIALTY_ITEMS.stream()
|
||||
return ASSIGNMENT_SPECIALTY_ITEMS.stream()
|
||||
.filter(item -> item.getCode().equals(code))
|
||||
.findFirst()
|
||||
.map(SpecialtyItem::getName)
|
||||
@@ -73,7 +95,7 @@ public final class OutputSplitBizConstants {
|
||||
}
|
||||
|
||||
public static String getRoleName(String code) {
|
||||
return ROLE_ITEMS.stream()
|
||||
return getAllRoleItems().stream()
|
||||
.filter(item -> item.getCode().equals(code))
|
||||
.findFirst()
|
||||
.map(RoleItem::getName)
|
||||
@@ -81,7 +103,7 @@ public final class OutputSplitBizConstants {
|
||||
}
|
||||
|
||||
public static int getRoleSortNo(String code) {
|
||||
return ROLE_ITEMS.stream()
|
||||
return getAllRoleItems().stream()
|
||||
.filter(item -> item.getCode().equals(code))
|
||||
.findFirst()
|
||||
.map(RoleItem::getSortNo)
|
||||
@@ -89,7 +111,7 @@ public final class OutputSplitBizConstants {
|
||||
}
|
||||
|
||||
public static int getSpecialtySortNo(String code) {
|
||||
return SPECIALTY_ITEMS.stream()
|
||||
return ASSIGNMENT_SPECIALTY_ITEMS.stream()
|
||||
.filter(item -> item.getCode().equals(code))
|
||||
.findFirst()
|
||||
.map(SpecialtyItem::getSortNo)
|
||||
@@ -104,6 +126,25 @@ public final class OutputSplitBizConstants {
|
||||
return map;
|
||||
}
|
||||
|
||||
public static List<RoleItem> getRoleItems(String specialtyCode) {
|
||||
if (SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) {
|
||||
return PROJECT_LEAD_ROLE_ITEMS;
|
||||
}
|
||||
return SPECIALTY_ROLE_ITEMS;
|
||||
}
|
||||
|
||||
private static List<RoleItem> getAllRoleItems() {
|
||||
return Arrays.asList(
|
||||
PROJECT_LEAD_ROLE_ITEMS.get(0),
|
||||
PROJECT_LEAD_ROLE_ITEMS.get(1),
|
||||
SPECIALTY_ROLE_ITEMS.get(0),
|
||||
SPECIALTY_ROLE_ITEMS.get(1),
|
||||
SPECIALTY_ROLE_ITEMS.get(2),
|
||||
SPECIALTY_ROLE_ITEMS.get(3),
|
||||
SPECIALTY_ROLE_ITEMS.get(4)
|
||||
);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class SpecialtyItem {
|
||||
|
||||
@@ -14,13 +14,15 @@ public final class ProjectPlanningBizTypeConstants {
|
||||
public static final String OWNERSHIP_TYPE_MAJOR = "专业所";
|
||||
public static final String OWNERSHIP_TYPE_COMPREHENSIVE = "综合所";
|
||||
public static final String OWNERSHIP_TYPE_SUBCONTRACT = "专业分包";
|
||||
public static final String DESIGN_PART_REAL_ESTATE = "地上部分";
|
||||
public static final String DESIGN_PART_UNDERGROUND = "地下部分";
|
||||
|
||||
public static final String CALCULATION_METHOD_GUIDANCE_PRICE = "指导价法";
|
||||
public static final String CALCULATION_METHOD_CONTRACT_PRICE = "合同价法";
|
||||
public static final String CALCULATION_METHOD_VIRTUAL_OUTPUT = "虚拟产值法";
|
||||
|
||||
public static final String VIRTUAL_CALCULATION_METHOD_GUIDANCE_PRICE = "指导单价法";
|
||||
public static final String VIRTUAL_CALCULATION_METHOD_VIRTUAL_TOTAL_PRICE = "虚拟总价法";
|
||||
public static final String VIRTUAL_CALCULATION_METHOD_GUIDANCE_TOTAL_PRICE = "指导总价法";
|
||||
public static final String VIRTUAL_CALCULATION_METHOD_WORKING_DAY = "工日法";
|
||||
|
||||
private static final Set<String> OWNERSHIP_TYPES = new HashSet<>(Arrays.asList(
|
||||
@@ -35,9 +37,14 @@ public final class ProjectPlanningBizTypeConstants {
|
||||
CALCULATION_METHOD_VIRTUAL_OUTPUT
|
||||
));
|
||||
|
||||
private static final Set<String> DESIGN_PARTS = new HashSet<>(Arrays.asList(
|
||||
DESIGN_PART_REAL_ESTATE,
|
||||
DESIGN_PART_UNDERGROUND
|
||||
));
|
||||
|
||||
private static final Set<String> VIRTUAL_CALCULATION_METHODS = new HashSet<>(Arrays.asList(
|
||||
VIRTUAL_CALCULATION_METHOD_GUIDANCE_PRICE,
|
||||
VIRTUAL_CALCULATION_METHOD_VIRTUAL_TOTAL_PRICE,
|
||||
VIRTUAL_CALCULATION_METHOD_GUIDANCE_TOTAL_PRICE,
|
||||
VIRTUAL_CALCULATION_METHOD_WORKING_DAY
|
||||
));
|
||||
|
||||
@@ -52,6 +59,10 @@ public final class ProjectPlanningBizTypeConstants {
|
||||
return CALCULATION_METHODS.contains(value);
|
||||
}
|
||||
|
||||
public static boolean isValidDesignPart(String value) {
|
||||
return DESIGN_PARTS.contains(value);
|
||||
}
|
||||
|
||||
public static boolean isValidVirtualCalculationMethod(String value) {
|
||||
return VIRTUAL_CALCULATION_METHODS.contains(value);
|
||||
}
|
||||
@@ -80,4 +91,16 @@ public final class ProjectPlanningBizTypeConstants {
|
||||
return CALCULATION_METHOD_VIRTUAL_OUTPUT.equals(value);
|
||||
}
|
||||
|
||||
public static boolean isWorkingDay(String value) {
|
||||
return VIRTUAL_CALCULATION_METHOD_WORKING_DAY.equals(value);
|
||||
}
|
||||
|
||||
public static boolean isVirtualGuidancePrice(String value) {
|
||||
return VIRTUAL_CALCULATION_METHOD_GUIDANCE_PRICE.equals(value);
|
||||
}
|
||||
|
||||
public static boolean isVirtualGuidanceTotalPrice(String value) {
|
||||
return VIRTUAL_CALCULATION_METHOD_GUIDANCE_TOTAL_PRICE.equals(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.employee;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
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.dal.dataobject.employee.EmployeeDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
public interface EmployeeService {
|
||||
|
||||
Long createEmployee(@Valid EmployeeSaveReqVO createReqVO);
|
||||
|
||||
void updateEmployee(@Valid EmployeeSaveReqVO updateReqVO);
|
||||
|
||||
void deleteEmployee(Long id);
|
||||
|
||||
EmployeeRespVO getEmployee(Long id);
|
||||
|
||||
EmployeeDO validateEmployeeExists(Long id);
|
||||
|
||||
PageResult<EmployeeRespVO> getEmployeePage(EmployeePageReqVO pageReqVO);
|
||||
|
||||
List<EmployeeSimpleRespVO> getEmployeeSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
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.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.service.office.OfficeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.EMPLOYEE_IN_USE;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.EMPLOYEE_NOT_EXISTS;
|
||||
|
||||
@Service
|
||||
@Validated
|
||||
public class EmployeeServiceImpl implements EmployeeService {
|
||||
|
||||
@Resource
|
||||
private EmployeeMapper employeeMapper;
|
||||
@Resource
|
||||
private OfficeMapper officeMapper;
|
||||
@Resource
|
||||
private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper;
|
||||
@Resource
|
||||
private ProjectRolePersonMapper projectRolePersonMapper;
|
||||
@Resource
|
||||
private SpecialtyRoleSplitMapper specialtyRoleSplitMapper;
|
||||
@Resource
|
||||
private OfficeService officeService;
|
||||
|
||||
@Override
|
||||
public Long createEmployee(EmployeeSaveReqVO createReqVO) {
|
||||
officeService.validateOfficeExists(createReqVO.getOfficeId());
|
||||
EmployeeDO employee = BeanUtils.toBean(createReqVO, EmployeeDO.class);
|
||||
if (employee.getEnabledFlag() == null) {
|
||||
employee.setEnabledFlag(Boolean.TRUE);
|
||||
}
|
||||
employeeMapper.insert(employee);
|
||||
return employee.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEmployee(EmployeeSaveReqVO updateReqVO) {
|
||||
validateEmployeeExists(updateReqVO.getId());
|
||||
officeService.validateOfficeExists(updateReqVO.getOfficeId());
|
||||
employeeMapper.updateById(BeanUtils.toBean(updateReqVO, EmployeeDO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEmployee(Long id) {
|
||||
validateEmployeeExists(id);
|
||||
if (employeeYearCostBudgetMapper.selectCountByEmployeeId(id) > 0
|
||||
|| projectRolePersonMapper.selectCountByEmployeeId(id) > 0
|
||||
|| existsInSpecialtyRoleSplit(id)) {
|
||||
throw exception(EMPLOYEE_IN_USE);
|
||||
}
|
||||
employeeMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmployeeRespVO getEmployee(Long id) {
|
||||
EmployeeDO employee = validateEmployeeExists(id);
|
||||
Map<Long, OfficeDO> officeMap = getOfficeMap(Collections.singleton(employee.getOfficeId()));
|
||||
return toRespVO(employee, officeMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmployeeDO validateEmployeeExists(Long id) {
|
||||
EmployeeDO employee = employeeMapper.selectById(id);
|
||||
if (employee == null) {
|
||||
throw exception(EMPLOYEE_NOT_EXISTS);
|
||||
}
|
||||
return employee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<EmployeeRespVO> getEmployeePage(EmployeePageReqVO pageReqVO) {
|
||||
PageResult<EmployeeDO> pageResult = employeeMapper.selectPage(pageReqVO);
|
||||
Map<Long, OfficeDO> officeMap = getOfficeMap(CollectionUtils.convertSet(pageResult.getList(), EmployeeDO::getOfficeId));
|
||||
return BeanUtils.toBean(pageResult, EmployeeRespVO.class, respVO ->
|
||||
respVO.setOfficeName(officeMap.containsKey(respVO.getOfficeId())
|
||||
? officeMap.get(respVO.getOfficeId()).getOfficeName() : null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmployeeSimpleRespVO> getEmployeeSimpleList(String keyword, Long officeId, String status, Boolean enabledFlag) {
|
||||
List<EmployeeDO> list = employeeMapper.selectSimpleList(keyword, officeId, status, enabledFlag == null ? Boolean.TRUE : enabledFlag);
|
||||
Map<Long, OfficeDO> officeMap = getOfficeMap(CollectionUtils.convertSet(list, EmployeeDO::getOfficeId));
|
||||
return BeanUtils.toBean(list, EmployeeSimpleRespVO.class, respVO ->
|
||||
respVO.setOfficeName(officeMap.containsKey(respVO.getOfficeId())
|
||||
? officeMap.get(respVO.getOfficeId()).getOfficeName() : null));
|
||||
}
|
||||
|
||||
private boolean existsInSpecialtyRoleSplit(Long employeeId) {
|
||||
List<SpecialtyRoleSplitDO> candidateList = specialtyRoleSplitMapper.selectListByPersonsJsonKeyword("\"employeeId\":" + employeeId);
|
||||
for (SpecialtyRoleSplitDO item : candidateList) {
|
||||
List<SpecialtyRolePersonSaveReqVO> persons = JsonUtils.parseArray(item.getPersonsJson(), SpecialtyRolePersonSaveReqVO.class);
|
||||
if (persons == null) {
|
||||
continue;
|
||||
}
|
||||
boolean matched = persons.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.anyMatch(person -> Objects.equals(person.getEmployeeId(), employeeId));
|
||||
if (matched) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Map<Long, OfficeDO> getOfficeMap(Set<Long> officeIds) {
|
||||
if (officeIds == null || officeIds.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
officeIds.removeIf(Objects::isNull);
|
||||
if (officeIds.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return CollectionUtils.convertMap(officeMapper.selectBatchIds(officeIds), OfficeDO::getId);
|
||||
}
|
||||
|
||||
private EmployeeRespVO toRespVO(EmployeeDO employee, Map<Long, OfficeDO> officeMap) {
|
||||
return BeanUtils.toBean(employee, EmployeeRespVO.class, respVO ->
|
||||
respVO.setOfficeName(officeMap.containsKey(respVO.getOfficeId())
|
||||
? officeMap.get(respVO.getOfficeId()).getOfficeName() : null));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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 javax.validation.Valid;
|
||||
|
||||
public interface EmployeeYearCostBudgetService {
|
||||
|
||||
Long createEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO createReqVO);
|
||||
|
||||
void updateEmployeeYearCostBudget(@Valid EmployeeYearCostBudgetSaveReqVO updateReqVO);
|
||||
|
||||
void deleteEmployeeYearCostBudget(Long id);
|
||||
|
||||
EmployeeYearCostBudgetRespVO getEmployeeYearCostBudget(Long id);
|
||||
|
||||
PageResult<EmployeeYearCostBudgetRespVO> getEmployeeYearCostBudgetPage(EmployeeYearCostBudgetPageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
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.dal.dataobject.employee.EmployeeDO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employeeyearcostbudget.EmployeeYearCostBudgetDO;
|
||||
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.util.Objects;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.EMPLOYEE_YEAR_COST_BUDGET_NOT_EXISTS;
|
||||
|
||||
@Service
|
||||
@Validated
|
||||
public class EmployeeYearCostBudgetServiceImpl implements EmployeeYearCostBudgetService {
|
||||
|
||||
@Resource
|
||||
private EmployeeYearCostBudgetMapper employeeYearCostBudgetMapper;
|
||||
@Resource
|
||||
private EmployeeService employeeService;
|
||||
|
||||
@Override
|
||||
public Long createEmployeeYearCostBudget(EmployeeYearCostBudgetSaveReqVO createReqVO) {
|
||||
EmployeeDO employee = employeeService.validateEmployeeExists(createReqVO.getEmployeeId());
|
||||
validateDuplicate(null, createReqVO.getEmployeeId(), createReqVO.getBudgetYear());
|
||||
EmployeeYearCostBudgetDO budget = BeanUtils.toBean(createReqVO, EmployeeYearCostBudgetDO.class);
|
||||
budget.setEmployeeName(employee.getEmployeeName());
|
||||
if (budget.getEnabledFlag() == null) {
|
||||
budget.setEnabledFlag(Boolean.TRUE);
|
||||
}
|
||||
employeeYearCostBudgetMapper.insert(budget);
|
||||
return budget.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEmployeeYearCostBudget(EmployeeYearCostBudgetSaveReqVO updateReqVO) {
|
||||
validateExists(updateReqVO.getId());
|
||||
EmployeeDO employee = employeeService.validateEmployeeExists(updateReqVO.getEmployeeId());
|
||||
validateDuplicate(updateReqVO.getId(), updateReqVO.getEmployeeId(), updateReqVO.getBudgetYear());
|
||||
EmployeeYearCostBudgetDO updateObj = BeanUtils.toBean(updateReqVO, EmployeeYearCostBudgetDO.class);
|
||||
updateObj.setEmployeeName(employee.getEmployeeName());
|
||||
employeeYearCostBudgetMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEmployeeYearCostBudget(Long id) {
|
||||
validateExists(id);
|
||||
employeeYearCostBudgetMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmployeeYearCostBudgetRespVO getEmployeeYearCostBudget(Long id) {
|
||||
return BeanUtils.toBean(validateExists(id), EmployeeYearCostBudgetRespVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<EmployeeYearCostBudgetRespVO> getEmployeeYearCostBudgetPage(EmployeeYearCostBudgetPageReqVO pageReqVO) {
|
||||
return BeanUtils.toBean(employeeYearCostBudgetMapper.selectPage(pageReqVO), EmployeeYearCostBudgetRespVO.class);
|
||||
}
|
||||
|
||||
private EmployeeYearCostBudgetDO validateExists(Long id) {
|
||||
EmployeeYearCostBudgetDO budget = employeeYearCostBudgetMapper.selectById(id);
|
||||
if (budget == null) {
|
||||
throw exception(EMPLOYEE_YEAR_COST_BUDGET_NOT_EXISTS);
|
||||
}
|
||||
return budget;
|
||||
}
|
||||
|
||||
private void validateDuplicate(Long id, Long employeeId, Integer budgetYear) {
|
||||
EmployeeYearCostBudgetDO duplicate = employeeYearCostBudgetMapper.selectByEmployeeIdAndBudgetYear(employeeId, budgetYear);
|
||||
if (duplicate != null && !Objects.equals(duplicate.getId(), id)) {
|
||||
throw exception(EMPLOYEE_YEAR_COST_BUDGET_DUPLICATE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.office;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeSimpleRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
public interface OfficeService {
|
||||
|
||||
Long createOffice(@Valid OfficeSaveReqVO createReqVO);
|
||||
|
||||
void updateOffice(@Valid OfficeSaveReqVO updateReqVO);
|
||||
|
||||
void deleteOffice(Long id);
|
||||
|
||||
OfficeRespVO getOffice(Long id);
|
||||
|
||||
OfficeDO validateOfficeExists(Long id);
|
||||
|
||||
PageResult<OfficeRespVO> getOfficePage(OfficePageReqVO pageReqVO);
|
||||
|
||||
List<OfficeSimpleRespVO> getOfficeSimpleList();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.office;
|
||||
|
||||
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.office.vo.OfficePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.office.vo.OfficeSimpleRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.office.OfficeDO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.mysql.employee.EmployeeMapper;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.mysql.office.OfficeMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.OFFICE_IN_USE;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.OFFICE_NOT_EXISTS;
|
||||
|
||||
@Service
|
||||
@Validated
|
||||
public class OfficeServiceImpl implements OfficeService {
|
||||
|
||||
@Resource
|
||||
private OfficeMapper officeMapper;
|
||||
@Resource
|
||||
private EmployeeMapper employeeMapper;
|
||||
|
||||
@Override
|
||||
public Long createOffice(OfficeSaveReqVO createReqVO) {
|
||||
OfficeDO office = BeanUtils.toBean(createReqVO, OfficeDO.class);
|
||||
if (office.getEnabledFlag() == null) {
|
||||
office.setEnabledFlag(Boolean.TRUE);
|
||||
}
|
||||
officeMapper.insert(office);
|
||||
return office.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOffice(OfficeSaveReqVO updateReqVO) {
|
||||
validateOfficeExists(updateReqVO.getId());
|
||||
officeMapper.updateById(BeanUtils.toBean(updateReqVO, OfficeDO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteOffice(Long id) {
|
||||
validateOfficeExists(id);
|
||||
if (employeeMapper.selectCountByOfficeId(id) > 0) {
|
||||
throw exception(OFFICE_IN_USE);
|
||||
}
|
||||
officeMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfficeRespVO getOffice(Long id) {
|
||||
return BeanUtils.toBean(validateOfficeExists(id), OfficeRespVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfficeDO validateOfficeExists(Long id) {
|
||||
OfficeDO office = officeMapper.selectById(id);
|
||||
if (office == null) {
|
||||
throw exception(OFFICE_NOT_EXISTS);
|
||||
}
|
||||
return office;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<OfficeRespVO> getOfficePage(OfficePageReqVO pageReqVO) {
|
||||
return BeanUtils.toBean(officeMapper.selectPage(pageReqVO), OfficeRespVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OfficeSimpleRespVO> getOfficeSimpleList() {
|
||||
return BeanUtils.toBean(officeMapper.selectSimpleList(), OfficeSimpleRespVO.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,9 +6,11 @@ import cn.iocoder.lyzsys.module.tjt.controller.admin.outputsplit.vo.ProjectOutpu
|
||||
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.mysql.outputsplit.ProjectOutputSplitMapper;
|
||||
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.enums.OutputSplitBizConstants;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -18,7 +20,9 @@ import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -49,6 +53,8 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
|
||||
private ProjectPlanningMapper projectPlanningMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ProjectRolePersonMapper projectRolePersonMapper;
|
||||
|
||||
@Override
|
||||
public ProjectOutputSplitRespVO getProjectOutputSplit(Long planningId) {
|
||||
@@ -134,18 +140,20 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
|
||||
private ProjectOutputSplitRespVO buildRespVO(ProjectOutputSplitDO outputSplit, ProjectPlanningDO planning, ProjectDO project) {
|
||||
ProjectOutputSplitRespVO respVO = BeanUtils.toBean(outputSplit, ProjectOutputSplitRespVO.class);
|
||||
BigDecimal assessmentOutputValue = amount(planning.getAssessmentOutputValue());
|
||||
BigDecimal projectManagerAmount = multiplyAmount(assessmentOutputValue, outputSplit.getProjectManagerRatio());
|
||||
BigDecimal engineeringLeaderAmount = multiplyAmount(assessmentOutputValue, outputSplit.getEngineeringLeaderRatio());
|
||||
BigDecimal projectLeadAmount = multiplyAmount(assessmentOutputValue, outputSplit.getProjectLeadRatio());
|
||||
BigDecimal officeAmount = multiplyAmount(assessmentOutputValue, outputSplit.getOfficeRatio());
|
||||
List<ProjectRolePersonDO> rolePersons = projectRolePersonMapper.selectListByProjectId(project.getId());
|
||||
String projectManagerName = joinRoleNames(rolePersons, OutputSplitBizConstants.ROLE_PROJECT_MANAGER);
|
||||
String engineeringPrincipalName = joinRoleNames(rolePersons, OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL);
|
||||
|
||||
respVO.setProjectName(project.getProjectName());
|
||||
respVO.setPlanningContent(planning.getPlanningContent());
|
||||
respVO.setYear(getPlanningYear(planning));
|
||||
respVO.setAssessmentOutputValue(assessmentOutputValue);
|
||||
respVO.setProjectManagerName(project.getProjectManagerName());
|
||||
respVO.setEngineeringLeaderName(project.getEngineeringPrincipalName());
|
||||
respVO.setProjectManagerAmount(projectManagerAmount);
|
||||
respVO.setEngineeringLeaderAmount(engineeringLeaderAmount);
|
||||
respVO.setProjectManagerName(projectManagerName);
|
||||
respVO.setEngineeringLeaderName(engineeringPrincipalName);
|
||||
respVO.setProjectLeadName(joinProjectLeadName(projectManagerName, engineeringPrincipalName));
|
||||
respVO.setProjectLeadAmount(projectLeadAmount);
|
||||
respVO.setOfficeAmount(officeAmount);
|
||||
respVO.setArchAmount(multiplyAmount(officeAmount, outputSplit.getArchRatio()));
|
||||
respVO.setDecorAmount(multiplyAmount(officeAmount, outputSplit.getDecorRatio()));
|
||||
@@ -181,8 +189,7 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
|
||||
outputSplit.setProjectId(planning.getProjectId());
|
||||
outputSplit.setPlanningId(planning.getId());
|
||||
outputSplit.setYear(getPlanningYear(planning));
|
||||
outputSplit.setProjectManagerRatio(ZERO_RATIO);
|
||||
outputSplit.setEngineeringLeaderRatio(ZERO_RATIO);
|
||||
outputSplit.setProjectLeadRatio(ZERO_RATIO);
|
||||
outputSplit.setOfficeRatio(ONE_RATIO);
|
||||
outputSplit.setArchRatio(ONE_RATIO);
|
||||
outputSplit.setDecorRatio(ZERO_RATIO);
|
||||
@@ -199,8 +206,16 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
|
||||
}
|
||||
|
||||
private void validateOutputSplitRatios(ProjectOutputSplitSaveReqVO reqVO) {
|
||||
BigDecimal projectTotal = ratio(reqVO.getProjectManagerRatio())
|
||||
.add(ratio(reqVO.getEngineeringLeaderRatio()))
|
||||
validateRatioRange(reqVO.getProjectLeadRatio());
|
||||
validateRatioRange(reqVO.getOfficeRatio());
|
||||
validateRatioRange(reqVO.getArchRatio());
|
||||
validateRatioRange(reqVO.getDecorRatio());
|
||||
validateRatioRange(reqVO.getStructRatio());
|
||||
validateRatioRange(reqVO.getWaterRatio());
|
||||
validateRatioRange(reqVO.getElecRatio());
|
||||
validateRatioRange(reqVO.getHvacRatio());
|
||||
validateRatioRange(reqVO.getDigitalRatio());
|
||||
BigDecimal projectTotal = ratio(reqVO.getProjectLeadRatio())
|
||||
.add(ratio(reqVO.getOfficeRatio()))
|
||||
.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
BigDecimal specialtyTotal = ratio(reqVO.getArchRatio())
|
||||
@@ -211,14 +226,20 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
|
||||
.add(ratio(reqVO.getHvacRatio()))
|
||||
.add(ratio(reqVO.getDigitalRatio()))
|
||||
.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
if (projectTotal.compareTo(ONE_RATIO) > 0 || specialtyTotal.compareTo(ONE_RATIO) != 0) {
|
||||
if (projectTotal.compareTo(ONE_RATIO) != 0 || specialtyTotal.compareTo(ONE_RATIO) != 0) {
|
||||
throw exception(PROJECT_OUTPUT_SPLIT_RATIO_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateRatioRange(BigDecimal value) {
|
||||
BigDecimal normalized = ratio(value);
|
||||
if (normalized.compareTo(ZERO_RATIO) < 0 || normalized.compareTo(ONE_RATIO) > 0) {
|
||||
throw exception(PROJECT_OUTPUT_SPLIT_RATIO_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizeRatios(ProjectOutputSplitDO outputSplit) {
|
||||
normalize(outputSplit::setProjectManagerRatio, outputSplit.getProjectManagerRatio());
|
||||
normalize(outputSplit::setEngineeringLeaderRatio, outputSplit.getEngineeringLeaderRatio());
|
||||
normalize(outputSplit::setProjectLeadRatio, outputSplit.getProjectLeadRatio());
|
||||
normalize(outputSplit::setOfficeRatio, outputSplit.getOfficeRatio());
|
||||
normalize(outputSplit::setArchRatio, outputSplit.getArchRatio());
|
||||
normalize(outputSplit::setDecorRatio, outputSplit.getDecorRatio());
|
||||
@@ -266,4 +287,26 @@ public class ProjectOutputSplitServiceImpl implements ProjectOutputSplitService
|
||||
return value == null ? ZERO_RATIO : value.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private String joinRoleNames(List<ProjectRolePersonDO> rolePersons, String roleCode) {
|
||||
return rolePersons.stream()
|
||||
.filter(item -> Objects.equals(item.getRoleCode(), roleCode))
|
||||
.map(ProjectRolePersonDO::getEmployeeName)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.joining("、"));
|
||||
}
|
||||
|
||||
private String joinProjectLeadName(String projectManagerName, String engineeringPrincipalName) {
|
||||
if ((projectManagerName == null || projectManagerName.isEmpty())
|
||||
&& (engineeringPrincipalName == null || engineeringPrincipalName.isEmpty())) {
|
||||
return "";
|
||||
}
|
||||
if (projectManagerName == null || projectManagerName.isEmpty()) {
|
||||
return engineeringPrincipalName;
|
||||
}
|
||||
if (engineeringPrincipalName == null || engineeringPrincipalName.isEmpty()) {
|
||||
return projectManagerName;
|
||||
}
|
||||
return projectManagerName + " / " + engineeringPrincipalName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,13 +29,15 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_CALCULATION_METHOD_IMMUTABLE;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_CALCULATION_METHOD_INVALID;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_DESIGN_PART_INVALID;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_NOT_EXISTS;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_OWNERSHIP_TYPE_IMMUTABLE;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_OWNERSHIP_TYPE_INVALID;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_PROJECT_NOT_EXISTS;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_VIRTUAL_CALCULATION_METHOD_INVALID;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_WORKING_DAY_COUNT_REQUIRED;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_PLANNING_WORKING_DAY_UNIT_PRICE_REQUIRED;
|
||||
|
||||
/**
|
||||
* 合约规划 Service 实现类
|
||||
@@ -57,7 +59,6 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
|
||||
private static final BigDecimal DEFAULT_SUBCONTRACT_RATIO = new BigDecimal("0.0400");
|
||||
private static final BigDecimal DEFAULT_MAJOR_OUTSOURCE_RATIO = new BigDecimal("0.0600");
|
||||
private static final BigDecimal DEFAULT_COMMON_OUTSOURCE_RATIO = new BigDecimal("0.2500");
|
||||
private static final BigDecimal DEFAULT_WORKING_DAY_UNIT_PRICE = new BigDecimal("1000.00");
|
||||
private static final BigDecimal MIN_GUIDANCE_PRICE_RATIO = new BigDecimal("0.6000");
|
||||
|
||||
@Resource
|
||||
@@ -160,7 +161,12 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
|
||||
if (!ProjectPlanningBizTypeConstants.isValidOwnershipType(reqVO.getOwnershipType())) {
|
||||
throw exception(PROJECT_PLANNING_OWNERSHIP_TYPE_INVALID);
|
||||
}
|
||||
if (!ProjectPlanningBizTypeConstants.isValidCalculationMethod(reqVO.getCalculationMethod())) {
|
||||
if (StrUtil.isNotBlank(reqVO.getDesignPart())
|
||||
&& !ProjectPlanningBizTypeConstants.isValidDesignPart(reqVO.getDesignPart())) {
|
||||
throw exception(PROJECT_PLANNING_DESIGN_PART_INVALID);
|
||||
}
|
||||
if (StrUtil.isNotBlank(reqVO.getCalculationMethod())
|
||||
&& !ProjectPlanningBizTypeConstants.isValidCalculationMethod(reqVO.getCalculationMethod())) {
|
||||
throw exception(PROJECT_PLANNING_CALCULATION_METHOD_INVALID);
|
||||
}
|
||||
if (ProjectPlanningBizTypeConstants.isVirtualOutput(reqVO.getCalculationMethod())
|
||||
@@ -168,15 +174,20 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
|
||||
&& !ProjectPlanningBizTypeConstants.isValidVirtualCalculationMethod(reqVO.getVirtualCalculationMethod())) {
|
||||
throw exception(PROJECT_PLANNING_VIRTUAL_CALCULATION_METHOD_INVALID);
|
||||
}
|
||||
if (ProjectPlanningBizTypeConstants.isWorkingDay(reqVO.getVirtualCalculationMethod())) {
|
||||
if (reqVO.getWorkingDayCount() == null) {
|
||||
throw exception(PROJECT_PLANNING_WORKING_DAY_COUNT_REQUIRED);
|
||||
}
|
||||
if (reqVO.getWorkingDayUnitPrice() == null) {
|
||||
throw exception(PROJECT_PLANNING_WORKING_DAY_UNIT_PRICE_REQUIRED);
|
||||
}
|
||||
}
|
||||
if (dbPlanning == null) {
|
||||
return;
|
||||
}
|
||||
if (!Objects.equals(dbPlanning.getOwnershipType(), reqVO.getOwnershipType())) {
|
||||
throw exception(PROJECT_PLANNING_OWNERSHIP_TYPE_IMMUTABLE);
|
||||
}
|
||||
if (!Objects.equals(dbPlanning.getCalculationMethod(), reqVO.getCalculationMethod())) {
|
||||
throw exception(PROJECT_PLANNING_CALCULATION_METHOD_IMMUTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareProjectPlanning(ProjectPlanningDO planning, ProjectDO project) {
|
||||
@@ -219,12 +230,6 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
|
||||
planning.setWorkingDayUnitPrice(amountNullable(planning.getWorkingDayUnitPrice()));
|
||||
planning.setGuidanceUnitPrice(amountNullable(planning.getGuidanceUnitPrice()));
|
||||
planning.setGuidanceTotalPrice(amountNullable(planning.getGuidanceTotalPrice()));
|
||||
planning.setVirtualTotalPrice(amountNullable(planning.getVirtualTotalPrice()));
|
||||
|
||||
if (ProjectPlanningBizTypeConstants.VIRTUAL_CALCULATION_METHOD_WORKING_DAY.equals(planning.getVirtualCalculationMethod())
|
||||
&& planning.getWorkingDayUnitPrice() == null) {
|
||||
planning.setWorkingDayUnitPrice(DEFAULT_WORKING_DAY_UNIT_PRICE);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateProjectPlanning(ProjectPlanningDO planning) {
|
||||
@@ -309,17 +314,14 @@ public class ProjectPlanningServiceImpl implements ProjectPlanningService {
|
||||
}
|
||||
|
||||
private BigDecimal calculateVirtualOutputValue(ProjectPlanningDO planning) {
|
||||
if (ProjectPlanningBizTypeConstants.VIRTUAL_CALCULATION_METHOD_WORKING_DAY.equals(planning.getVirtualCalculationMethod())) {
|
||||
if (ProjectPlanningBizTypeConstants.isWorkingDay(planning.getVirtualCalculationMethod())) {
|
||||
return multiplyAmount(planning.getWorkingDayCount(), planning.getWorkingDayUnitPrice());
|
||||
}
|
||||
if (ProjectPlanningBizTypeConstants.VIRTUAL_CALCULATION_METHOD_GUIDANCE_PRICE.equals(planning.getVirtualCalculationMethod())) {
|
||||
if (isPositive(planning.getGuidanceTotalPrice())) {
|
||||
return amount(planning.getGuidanceTotalPrice());
|
||||
}
|
||||
if (ProjectPlanningBizTypeConstants.isVirtualGuidancePrice(planning.getVirtualCalculationMethod())) {
|
||||
return multiplyAmount(planning.getGuidanceUnitPrice(), planning.getPlanningArea());
|
||||
}
|
||||
if (ProjectPlanningBizTypeConstants.VIRTUAL_CALCULATION_METHOD_VIRTUAL_TOTAL_PRICE.equals(planning.getVirtualCalculationMethod())) {
|
||||
return amount(planning.getVirtualTotalPrice());
|
||||
if (ProjectPlanningBizTypeConstants.isVirtualGuidanceTotalPrice(planning.getVirtualCalculationMethod())) {
|
||||
return amount(planning.getGuidanceTotalPrice());
|
||||
}
|
||||
return ZERO_AMOUNT;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,13 @@ import cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.profit.vo.ProjectProfitPageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.profit.vo.ProjectProfitRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.planning.ProjectPlanningDO;
|
||||
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.yearkvalue.YearKValueDO;
|
||||
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.yearkvalue.YearKValueMapper;
|
||||
import cn.iocoder.lyzsys.module.tjt.enums.ProjectPlanningBizTypeConstants;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -16,29 +20,34 @@ import org.springframework.validation.annotation.Validated;
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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.PROJECT_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 项目盈亏 Service 实现类
|
||||
*
|
||||
* @author Codex
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
|
||||
private static final BigDecimal ZERO_AMOUNT = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
||||
private static final BigDecimal ZERO_RATIO = BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP);
|
||||
private static final BigDecimal ONE_RATIO = BigDecimal.ONE.setScale(4, RoundingMode.HALF_UP);
|
||||
private static final BigDecimal DEFAULT_INNOVATION_OUTPUT_RATE = new BigDecimal("0.0100");
|
||||
private static final BigDecimal DEFAULT_YEAR_K_VALUE = new BigDecimal("0.4000");
|
||||
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ProjectPlanningMapper projectPlanningMapper;
|
||||
@Resource
|
||||
private ProjectPlanningQuarterMapper projectPlanningQuarterMapper;
|
||||
@Resource
|
||||
private YearKValueMapper yearKValueMapper;
|
||||
|
||||
@Override
|
||||
public ProjectProfitRespVO getProjectProfit(Long projectId) {
|
||||
@@ -59,9 +68,9 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
if (pageResult.getList().isEmpty()) {
|
||||
return new PageResult<>(Collections.emptyList(), pageResult.getTotal());
|
||||
}
|
||||
Set<Long> projectIds = CollectionUtils.convertSet(pageResult.getList(), ProjectDO::getId);
|
||||
Map<Long, List<ProjectPlanningDO>> planningMap = CollectionUtils.convertMultiMap(
|
||||
projectPlanningMapper.selectList(ProjectPlanningDO::getProjectId,
|
||||
CollectionUtils.convertSet(pageResult.getList(), ProjectDO::getId)),
|
||||
projectPlanningMapper.selectList(ProjectPlanningDO::getProjectId, projectIds),
|
||||
ProjectPlanningDO::getProjectId);
|
||||
List<ProjectProfitRespVO> list = CollectionUtils.convertList(pageResult.getList(),
|
||||
project -> buildProjectProfit(project, planningMap.get(project.getId())));
|
||||
@@ -73,6 +82,10 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
BigDecimal comprehensivePlanningAmount = ZERO_AMOUNT;
|
||||
BigDecimal subcontractPlanningAmount = ZERO_AMOUNT;
|
||||
BigDecimal majorOutputValue = ZERO_AMOUNT;
|
||||
List<ProjectPlanningDO> majorPlanningList = safePlanningList.stream()
|
||||
.filter(planning -> ProjectPlanningBizTypeConstants.isMajor(planning.getOwnershipType()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (ProjectPlanningDO planning : safePlanningList) {
|
||||
if (ProjectPlanningBizTypeConstants.isComprehensive(planning.getOwnershipType())) {
|
||||
comprehensivePlanningAmount = comprehensivePlanningAmount.add(amount(planning.getPlanningAmount()));
|
||||
@@ -86,13 +99,22 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
majorOutputValue = majorOutputValue.add(amount(planning.getAssessmentOutputValue()));
|
||||
}
|
||||
}
|
||||
BigDecimal expectedKValue = ratio(project.getExpectedKValue());
|
||||
BigDecimal majorExpectedPerformance = majorOutputValue.multiply(expectedKValue).setScale(2, RoundingMode.HALF_UP);
|
||||
|
||||
BigDecimal majorExpectedPerformance = calculateMajorExpectedPerformance(majorPlanningList);
|
||||
BigDecimal contractAmount = amount(project.getContractAmount());
|
||||
BigDecimal finalSettlementAmount = amount(project.getFinalSettlementAmount());
|
||||
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
|
||||
.subtract(comprehensivePlanningAmount)
|
||||
.subtract(subcontractPlanningAmount)
|
||||
.subtract(majorExpectedPerformance)
|
||||
.subtract(innovationOutputValue)
|
||||
.subtract(otherCost)
|
||||
.setScale(2, RoundingMode.HALF_UP);
|
||||
BigDecimal profitLossRate = finalSettlementAmount.compareTo(BigDecimal.ZERO) == 0
|
||||
? ZERO_RATIO
|
||||
@@ -102,13 +124,15 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
respVO.setProjectId(project.getId());
|
||||
respVO.setProjectName(project.getProjectName());
|
||||
respVO.setContractSignedFlag(project.getContractSignedFlag());
|
||||
respVO.setContractAmount(amount(project.getContractAmount()));
|
||||
respVO.setContractAmount(contractAmount);
|
||||
respVO.setFinalSettlementAmount(finalSettlementAmount);
|
||||
respVO.setComprehensivePlanningAmount(comprehensivePlanningAmount.setScale(2, RoundingMode.HALF_UP));
|
||||
respVO.setSubcontractPlanningAmount(subcontractPlanningAmount.setScale(2, RoundingMode.HALF_UP));
|
||||
respVO.setMajorOutputValue(majorOutputValue.setScale(2, RoundingMode.HALF_UP));
|
||||
respVO.setExpectedKValue(expectedKValue);
|
||||
respVO.setMajorExpectedPerformance(majorExpectedPerformance);
|
||||
respVO.setInnovationOutputRate(innovationOutputRate);
|
||||
respVO.setInnovationOutputValue(innovationOutputValue);
|
||||
respVO.setOtherCost(otherCost);
|
||||
respVO.setProfitLossValue(profitLossValue);
|
||||
respVO.setProfitLossRate(profitLossRate);
|
||||
respVO.setProjectStartYear(project.getProjectStartYear());
|
||||
@@ -116,6 +140,43 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
return respVO;
|
||||
}
|
||||
|
||||
private BigDecimal calculateMajorExpectedPerformance(List<ProjectPlanningDO> majorPlanningList) {
|
||||
if (majorPlanningList == null || majorPlanningList.isEmpty()) {
|
||||
return ZERO_AMOUNT;
|
||||
}
|
||||
List<Long> planningIds = majorPlanningList.stream().map(ProjectPlanningDO::getId).collect(Collectors.toList());
|
||||
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = CollectionUtils.convertMultiMap(
|
||||
projectPlanningQuarterMapper.selectListByPlanningIds(planningIds), ProjectPlanningQuarterDO::getPlanningId);
|
||||
Set<Integer> years = quarterMap.values().stream()
|
||||
.flatMap(Collection::stream)
|
||||
.map(ProjectPlanningQuarterDO::getDistributionYear)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Integer, BigDecimal> yearKValueMap = yearKValueMapper.selectEnabledListByYears(years).stream()
|
||||
.collect(Collectors.toMap(YearKValueDO::getKYear, item -> ratio(item.getKValue()), (a, b) -> b));
|
||||
|
||||
BigDecimal total = ZERO_AMOUNT;
|
||||
for (ProjectPlanningDO planning : majorPlanningList) {
|
||||
BigDecimal assessmentOutputValue = amount(planning.getAssessmentOutputValue());
|
||||
Map<Integer, BigDecimal> yearRatioMap = quarterMap.getOrDefault(planning.getId(), Collections.emptyList()).stream()
|
||||
.collect(Collectors.groupingBy(ProjectPlanningQuarterDO::getDistributionYear,
|
||||
Collectors.reducing(ZERO_RATIO,
|
||||
item -> ratio(item.getDistributionRatio()),
|
||||
BigDecimal::add)));
|
||||
BigDecimal allocatedRatio = ZERO_RATIO;
|
||||
for (Map.Entry<Integer, BigDecimal> entry : yearRatioMap.entrySet()) {
|
||||
BigDecimal yearRatio = ratio(entry.getValue());
|
||||
allocatedRatio = allocatedRatio.add(yearRatio).setScale(4, RoundingMode.HALF_UP);
|
||||
BigDecimal kValue = yearKValueMap.getOrDefault(entry.getKey(), DEFAULT_YEAR_K_VALUE);
|
||||
total = total.add(multiplyAmount(assessmentOutputValue, yearRatio, kValue));
|
||||
}
|
||||
BigDecimal unallocatedRatio = ONE_RATIO.subtract(allocatedRatio).setScale(4, RoundingMode.HALF_UP);
|
||||
if (unallocatedRatio.compareTo(ZERO_RATIO) > 0) {
|
||||
total = total.add(multiplyAmount(assessmentOutputValue, unallocatedRatio, DEFAULT_YEAR_K_VALUE));
|
||||
}
|
||||
}
|
||||
return total.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private ProjectDO validateProjectExists(Long projectId) {
|
||||
ProjectDO project = projectMapper.selectById(projectId);
|
||||
if (project == null) {
|
||||
@@ -132,4 +193,12 @@ public class ProjectProfitServiceImpl implements ProjectProfitService {
|
||||
return value == null ? ZERO_RATIO : value.setScale(4, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private BigDecimal multiplyAmount(BigDecimal... values) {
|
||||
BigDecimal result = BigDecimal.ONE;
|
||||
for (BigDecimal value : values) {
|
||||
result = result.multiply(value == null ? BigDecimal.ZERO : value);
|
||||
}
|
||||
return result.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package cn.iocoder.lyzsys.module.tjt.service.project;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectPageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.project.ProjectDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -22,8 +22,8 @@ public interface ProjectService {
|
||||
|
||||
void deleteProjectList(List<Long> ids);
|
||||
|
||||
PageResult<ProjectDO> getProjectPage(ProjectPageReqVO pageReqVO);
|
||||
PageResult<ProjectRespVO> getProjectPage(ProjectPageReqVO pageReqVO);
|
||||
|
||||
ProjectDO getProject(Long id);
|
||||
ProjectRespVO getProject(Long id);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,38 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.project;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.lyzsys.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.lyzsys.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectPageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectRolePersonRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectRolePersonSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.project.vo.ProjectSaveReqVO;
|
||||
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.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.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.service.employee.EmployeeService;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.specialtyrolesplit.SpecialtyRoleSplitService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
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;
|
||||
@@ -24,49 +46,261 @@ import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.PROJECT_NOT_
|
||||
@Validated
|
||||
public class ProjectServiceImpl implements ProjectService {
|
||||
|
||||
private static final String ROLE_CODE_PROJECT_MANAGER = "project_manager";
|
||||
private static final String ROLE_CODE_ENGINEERING_PRINCIPAL = "engineering_principal";
|
||||
private static final String ROLE_NAME_PROJECT_MANAGER = "项目经理";
|
||||
private static final String ROLE_NAME_ENGINEERING_PRINCIPAL = "项目负责人";
|
||||
private static final String STATUS_IN_PROGRESS = "进行中";
|
||||
private static final String STATUS_COMPLETED = "完成";
|
||||
private static final String STATUS_PAUSED = "暂停";
|
||||
private static final String STATUS_TERMINATED = "中止";
|
||||
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ProjectRolePersonMapper projectRolePersonMapper;
|
||||
@Resource
|
||||
private ProjectPlanningMapper projectPlanningMapper;
|
||||
@Resource
|
||||
private ProjectPlanningQuarterMapper projectPlanningQuarterMapper;
|
||||
@Resource
|
||||
private EmployeeService employeeService;
|
||||
@Resource
|
||||
private ProjectOutputSplitService projectOutputSplitService;
|
||||
@Resource
|
||||
private SpecialtyRoleSplitService specialtyRoleSplitService;
|
||||
|
||||
@Override
|
||||
public Long createProject(ProjectSaveReqVO createReqVO) {
|
||||
ProjectDO project = BeanUtils.toBean(createReqVO, ProjectDO.class);
|
||||
applyProjectDefaults(project, null);
|
||||
projectMapper.insert(project);
|
||||
saveProjectRolePersons(project.getId(), createReqVO.getRolePersons());
|
||||
return project.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProject(ProjectSaveReqVO updateReqVO) {
|
||||
validateProjectExists(updateReqVO.getId());
|
||||
ProjectDO dbProject = validateProjectExists(updateReqVO.getId());
|
||||
ProjectDO updateObj = BeanUtils.toBean(updateReqVO, ProjectDO.class);
|
||||
applyProjectDefaults(updateObj, dbProject);
|
||||
projectMapper.updateById(updateObj);
|
||||
saveProjectRolePersons(updateReqVO.getId(), updateReqVO.getRolePersons());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProject(Long id) {
|
||||
validateProjectExists(id);
|
||||
deleteProjectDependencies(Collections.singletonList(id));
|
||||
projectRolePersonMapper.delete(ProjectRolePersonDO::getProjectId, id);
|
||||
projectMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProjectList(List<Long> ids) {
|
||||
ids.forEach(this::validateProjectExists);
|
||||
deleteProjectDependencies(ids);
|
||||
projectRolePersonMapper.deleteBatch(ProjectRolePersonDO::getProjectId, ids);
|
||||
projectMapper.deleteBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ProjectDO> getProjectPage(ProjectPageReqVO pageReqVO) {
|
||||
return projectMapper.selectPage(pageReqVO);
|
||||
public PageResult<ProjectRespVO> getProjectPage(ProjectPageReqVO pageReqVO) {
|
||||
PageResult<ProjectDO> pageResult = projectMapper.selectPage(pageReqVO);
|
||||
if (pageResult.getList().isEmpty()) {
|
||||
return new PageResult<>(Collections.emptyList(), pageResult.getTotal());
|
||||
}
|
||||
List<ProjectDO> projects = pageResult.getList();
|
||||
List<Long> projectIds = projects.stream().map(ProjectDO::getId).collect(Collectors.toList());
|
||||
Map<Long, List<ProjectRolePersonDO>> rolePersonMap = CollectionUtils.convertMultiMap(
|
||||
projectRolePersonMapper.selectListByProjectIds(projectIds), ProjectRolePersonDO::getProjectId);
|
||||
List<ProjectRespVO> list = projects.stream()
|
||||
.map(project -> buildProjectRespVO(syncProjectStatus(project), rolePersonMap.get(project.getId())))
|
||||
.collect(Collectors.toList());
|
||||
return new PageResult<>(list, pageResult.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectDO getProject(Long id) {
|
||||
return projectMapper.selectById(id);
|
||||
public ProjectRespVO getProject(Long id) {
|
||||
ProjectDO project = syncProjectStatus(validateProjectExists(id));
|
||||
return buildProjectRespVO(project, projectRolePersonMapper.selectListByProjectId(id));
|
||||
}
|
||||
|
||||
private void validateProjectExists(Long id) {
|
||||
if (projectMapper.selectById(id) == null) {
|
||||
private ProjectDO validateProjectExists(Long id) {
|
||||
ProjectDO project = projectMapper.selectById(id);
|
||||
if (project == null) {
|
||||
throw exception(PROJECT_NOT_EXISTS);
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
private void applyProjectDefaults(ProjectDO project, ProjectDO dbProject) {
|
||||
if (project.getProjectStatus() == null || project.getProjectStatus().trim().isEmpty()) {
|
||||
project.setProjectStatus(dbProject == null ? STATUS_IN_PROGRESS : dbProject.getProjectStatus());
|
||||
}
|
||||
if (project.getArchiveFlag() == null) {
|
||||
project.setArchiveFlag(dbProject != null && Boolean.TRUE.equals(dbProject.getArchiveFlag()));
|
||||
}
|
||||
if (project.getArchiveTime() == null && dbProject != null) {
|
||||
project.setArchiveTime(dbProject.getArchiveTime());
|
||||
}
|
||||
}
|
||||
|
||||
private void saveProjectRolePersons(Long projectId, List<ProjectRolePersonSaveReqVO> reqList) {
|
||||
projectRolePersonMapper.delete(ProjectRolePersonDO::getProjectId, projectId);
|
||||
if (reqList == null || reqList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<ProjectRolePersonDO> createList = new ArrayList<>();
|
||||
int autoSortNo = 1;
|
||||
for (ProjectRolePersonSaveReqVO item : reqList) {
|
||||
if (item == null || item.getEmployeeId() == null) {
|
||||
continue;
|
||||
}
|
||||
String roleCode = item.getRoleCode() == null ? "" : item.getRoleCode().trim();
|
||||
if (!Objects.equals(roleCode, ROLE_CODE_PROJECT_MANAGER)
|
||||
&& !Objects.equals(roleCode, ROLE_CODE_ENGINEERING_PRINCIPAL)) {
|
||||
continue;
|
||||
}
|
||||
EmployeeDO employee = employeeService.validateEmployeeExists(item.getEmployeeId());
|
||||
ProjectRolePersonDO createObj = new ProjectRolePersonDO();
|
||||
createObj.setProjectId(projectId);
|
||||
createObj.setRoleCode(roleCode);
|
||||
createObj.setRoleName(getRoleName(roleCode));
|
||||
createObj.setEmployeeId(item.getEmployeeId());
|
||||
createObj.setEmployeeName(employee.getEmployeeName());
|
||||
createObj.setSortNo(item.getSortNo() == null ? autoSortNo++ : item.getSortNo());
|
||||
createObj.setEnabledFlag(Boolean.TRUE);
|
||||
createList.add(createObj);
|
||||
}
|
||||
for (ProjectRolePersonDO createObj : createList) {
|
||||
projectRolePersonMapper.insert(createObj);
|
||||
}
|
||||
}
|
||||
|
||||
private ProjectRespVO buildProjectRespVO(ProjectDO project, List<ProjectRolePersonDO> rolePersons) {
|
||||
List<ProjectRolePersonDO> safeRolePersons = rolePersons == null ? Collections.emptyList() : rolePersons;
|
||||
ProjectRespVO respVO = BeanUtils.toBean(project, ProjectRespVO.class);
|
||||
respVO.setProjectManagerName(joinPersonNamesByRoleCode(safeRolePersons, ROLE_CODE_PROJECT_MANAGER));
|
||||
respVO.setEngineeringPrincipalName(joinPersonNamesByRoleCode(safeRolePersons, ROLE_CODE_ENGINEERING_PRINCIPAL));
|
||||
respVO.setRolePersons(BeanUtils.toBean(safeRolePersons, ProjectRolePersonRespVO.class));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
private String joinPersonNamesByRoleCode(List<ProjectRolePersonDO> rolePersons, String roleCode) {
|
||||
return rolePersons.stream()
|
||||
.filter(item -> Objects.equals(item.getRoleCode(), roleCode))
|
||||
.map(ProjectRolePersonDO::getEmployeeName)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.joining("、"));
|
||||
}
|
||||
|
||||
private String getRoleName(String roleCode) {
|
||||
if (Objects.equals(roleCode, ROLE_CODE_PROJECT_MANAGER)) {
|
||||
return ROLE_NAME_PROJECT_MANAGER;
|
||||
}
|
||||
if (Objects.equals(roleCode, ROLE_CODE_ENGINEERING_PRINCIPAL)) {
|
||||
return ROLE_NAME_ENGINEERING_PRINCIPAL;
|
||||
}
|
||||
return roleCode;
|
||||
}
|
||||
|
||||
private ProjectDO syncProjectStatus(ProjectDO project) {
|
||||
String nextStatus = calculateProjectStatus(project);
|
||||
Boolean nextArchiveFlag = STATUS_COMPLETED.equals(nextStatus);
|
||||
LocalDateTime nextArchiveTime = nextArchiveFlag
|
||||
? (project.getArchiveTime() == null ? LocalDateTime.now() : project.getArchiveTime())
|
||||
: null;
|
||||
boolean needUpdate = !Objects.equals(project.getProjectStatus(), nextStatus)
|
||||
|| !Objects.equals(project.getArchiveFlag(), nextArchiveFlag)
|
||||
|| !Objects.equals(project.getArchiveTime(), nextArchiveTime);
|
||||
if (needUpdate) {
|
||||
ProjectDO updateObj = new ProjectDO();
|
||||
updateObj.setId(project.getId());
|
||||
updateObj.setProjectStatus(nextStatus);
|
||||
updateObj.setArchiveFlag(nextArchiveFlag);
|
||||
updateObj.setArchiveTime(nextArchiveTime);
|
||||
if (!nextArchiveFlag) {
|
||||
updateObj.setArchiveTime(null);
|
||||
}
|
||||
projectMapper.updateById(updateObj);
|
||||
project.setProjectStatus(nextStatus);
|
||||
project.setArchiveFlag(nextArchiveFlag);
|
||||
project.setArchiveTime(nextArchiveTime);
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
private String calculateProjectStatus(ProjectDO project) {
|
||||
if (STATUS_TERMINATED.equals(project.getProjectStatus())) {
|
||||
return STATUS_TERMINATED;
|
||||
}
|
||||
if (isProjectCompleted(project.getId())) {
|
||||
return STATUS_COMPLETED;
|
||||
}
|
||||
if (STATUS_PAUSED.equals(project.getProjectStatus())
|
||||
&& project.getPauseReason() != null
|
||||
&& !project.getPauseReason().trim().isEmpty()) {
|
||||
return STATUS_PAUSED;
|
||||
}
|
||||
int currentYear = LocalDateTime.now().getYear();
|
||||
if (project.getProjectStartYear() != null && currentYear - project.getProjectStartYear() >= 5) {
|
||||
return STATUS_PAUSED;
|
||||
}
|
||||
return STATUS_IN_PROGRESS;
|
||||
}
|
||||
|
||||
private boolean isProjectCompleted(Long projectId) {
|
||||
List<ProjectPlanningDO> planningList = projectPlanningMapper.selectListByProjectId(projectId);
|
||||
if (planningList == null || planningList.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
List<Long> planningIds = planningList.stream().map(ProjectPlanningDO::getId).collect(Collectors.toList());
|
||||
Map<Long, List<ProjectPlanningQuarterDO>> quarterMap = CollectionUtils.convertMultiMap(
|
||||
projectPlanningQuarterMapper.selectListByPlanningIds(planningIds), ProjectPlanningQuarterDO::getPlanningId);
|
||||
for (ProjectPlanningDO planning : planningList) {
|
||||
java.math.BigDecimal allocatedRatio = quarterMap.getOrDefault(planning.getId(), Collections.emptyList()).stream()
|
||||
.map(ProjectPlanningQuarterDO::getDistributionRatio)
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add)
|
||||
.setScale(4, java.math.RoundingMode.HALF_UP);
|
||||
java.math.BigDecimal totalDistributionAmount = planning.getTotalDistributionAmount() == null
|
||||
? java.math.BigDecimal.ONE.setScale(4, java.math.RoundingMode.HALF_UP)
|
||||
: planning.getTotalDistributionAmount().setScale(4, java.math.RoundingMode.HALF_UP);
|
||||
if (allocatedRatio.compareTo(totalDistributionAmount) < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void deleteProjectDependencies(Collection<Long> projectIds) {
|
||||
if (projectIds == null || projectIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<ProjectPlanningDO> planningList = projectPlanningMapper.selectList(
|
||||
new cn.iocoder.lyzsys.framework.mybatis.core.query.LambdaQueryWrapperX<ProjectPlanningDO>()
|
||||
.inIfPresent(ProjectPlanningDO::getProjectId, projectIds));
|
||||
if (planningList == null || planningList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<Long> planningIds = planningList.stream()
|
||||
.map(ProjectPlanningDO::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (planningIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<Long, ProjectOutputSplitDO> outputSplitMap = projectOutputSplitService.getProjectOutputSplitMap(planningIds);
|
||||
if (!outputSplitMap.isEmpty()) {
|
||||
specialtyRoleSplitService.deleteByOutputSplitIds(outputSplitMap.values().stream()
|
||||
.map(ProjectOutputSplitDO::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList()));
|
||||
projectOutputSplitService.deleteByPlanningIds(planningIds);
|
||||
}
|
||||
projectPlanningQuarterMapper.deleteBatch(ProjectPlanningQuarterDO::getPlanningId, planningIds);
|
||||
projectPlanningMapper.deleteBatchIds(planningIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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 javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ProjectOutputReportService {
|
||||
|
||||
void exportProjectBudgetExcel(HttpServletResponse response, ProjectBudgetExportReqVO reqVO)
|
||||
throws IOException;
|
||||
|
||||
void exportProjectQuarterOutputExcel(HttpServletResponse response, ProjectQuarterOutputExportReqVO reqVO)
|
||||
throws IOException;
|
||||
|
||||
void exportProjectLeadQuarterOutputExcel(HttpServletResponse response,
|
||||
ProjectLeadQuarterOutputExportReqVO reqVO)
|
||||
throws IOException;
|
||||
|
||||
void exportSpecialtyPersonOutputExcel(HttpServletResponse response, SpecialtyPersonOutputExportReqVO reqVO)
|
||||
throws IOException;
|
||||
|
||||
void exportProjectOverviewExcel(HttpServletResponse response, ProjectOverviewExportReqVO reqVO)
|
||||
throws IOException;
|
||||
|
||||
void exportEmployeeOutputSummaryExcel(HttpServletResponse response, EmployeeOutputSummaryExportReqVO reqVO)
|
||||
throws IOException;
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,207 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.report.builder;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.util.http.HttpUtils;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
public abstract class AbstractProjectOutputExcelBuilder {
|
||||
|
||||
private static final BigDecimal ZERO_AMOUNT = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
||||
private static final BigDecimal ZERO_RATIO = BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP);
|
||||
|
||||
protected Workbook createWorkbook() {
|
||||
return new XSSFWorkbook();
|
||||
}
|
||||
|
||||
protected Sheet createSheet(Workbook workbook, String preferredName, String fallbackName) {
|
||||
return workbook.createSheet(buildSheetName(preferredName, fallbackName));
|
||||
}
|
||||
|
||||
protected CellStyle createTitleStyle(Workbook workbook) {
|
||||
CellStyle style = createBaseStyle(workbook);
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
font.setFontHeightInPoints((short) 14);
|
||||
style.setFont(font);
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
return style;
|
||||
}
|
||||
|
||||
protected CellStyle createInfoStyle(Workbook workbook) {
|
||||
CellStyle style = createBaseStyle(workbook);
|
||||
Font font = workbook.createFont();
|
||||
font.setFontHeightInPoints((short) 10);
|
||||
style.setFont(font);
|
||||
return style;
|
||||
}
|
||||
|
||||
protected CellStyle createHeaderStyle(Workbook workbook) {
|
||||
CellStyle style = createBaseStyle(workbook);
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
font.setFontHeightInPoints((short) 10);
|
||||
style.setFont(font);
|
||||
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
return style;
|
||||
}
|
||||
|
||||
protected CellStyle createCellStyle(Workbook workbook) {
|
||||
CellStyle style = createBaseStyle(workbook);
|
||||
Font font = workbook.createFont();
|
||||
font.setFontHeightInPoints((short) 10);
|
||||
style.setFont(font);
|
||||
return style;
|
||||
}
|
||||
|
||||
protected CellStyle createDerivedStyle(Workbook workbook, CellStyle sourceStyle,
|
||||
IndexedColors fillColor, HorizontalAlignment alignment,
|
||||
boolean bold, short fontHeightInPoints) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.cloneStyleFrom(sourceStyle);
|
||||
if (fillColor != null) {
|
||||
style.setFillForegroundColor(fillColor.getIndex());
|
||||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
}
|
||||
if (alignment != null) {
|
||||
style.setAlignment(alignment);
|
||||
}
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(bold);
|
||||
font.setFontHeightInPoints(fontHeightInPoints);
|
||||
style.setFont(font);
|
||||
return style;
|
||||
}
|
||||
|
||||
protected void setText(Row row, int cellIndex, Object value, CellStyle style) {
|
||||
Cell cell = row.createCell(cellIndex);
|
||||
cell.setCellValue(value == null ? "" : String.valueOf(value));
|
||||
if (style != null) {
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
}
|
||||
|
||||
protected Row getOrCreateRow(Sheet sheet, int rowIndex) {
|
||||
Row row = sheet.getRow(rowIndex);
|
||||
return row != null ? row : sheet.createRow(rowIndex);
|
||||
}
|
||||
|
||||
protected int writeMergedTitleRow(Sheet sheet, int rowIndex, String title, CellStyle style, int lastCol) {
|
||||
Row row = getOrCreateRow(sheet, rowIndex);
|
||||
setText(row, 0, title, style);
|
||||
merge(sheet, rowIndex, rowIndex, 0, lastCol);
|
||||
return rowIndex + 1;
|
||||
}
|
||||
|
||||
protected int writeRow(Sheet sheet, int rowIndex, CellStyle style, Object... values) {
|
||||
Row row = getOrCreateRow(sheet, rowIndex);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
setText(row, i, values[i], style);
|
||||
}
|
||||
return rowIndex + 1;
|
||||
}
|
||||
|
||||
protected void writeLabelValue(Row row, int labelCellIndex, int valueCellIndex,
|
||||
Object label, Object value, CellStyle style) {
|
||||
setText(row, labelCellIndex, label, style);
|
||||
setText(row, valueCellIndex, value, style);
|
||||
}
|
||||
|
||||
protected void merge(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
|
||||
}
|
||||
|
||||
protected void setMergedRegionText(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol,
|
||||
String text, CellStyle style) {
|
||||
for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
|
||||
Row row = getOrCreateRow(sheet, rowIndex);
|
||||
for (int cellIndex = firstCol; cellIndex <= lastCol; cellIndex++) {
|
||||
setText(row, cellIndex, rowIndex == firstRow && cellIndex == firstCol ? text : "", style);
|
||||
}
|
||||
}
|
||||
if (firstRow != lastRow || firstCol != lastCol) {
|
||||
merge(sheet, firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setColumnWidths(Sheet sheet, int... widths) {
|
||||
for (int i = 0; i < widths.length; i++) {
|
||||
sheet.setColumnWidth(i, widths[i] * 256);
|
||||
}
|
||||
}
|
||||
|
||||
protected BigDecimal amount(BigDecimal value) {
|
||||
return value == null ? ZERO_AMOUNT : value.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
protected BigDecimal ratio(BigDecimal value) {
|
||||
return value == null ? ZERO_RATIO : value.setScale(4, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
protected String percentText(BigDecimal value) {
|
||||
return ratio(value).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP) + "%";
|
||||
}
|
||||
|
||||
protected String text(BigDecimal value) {
|
||||
return amount(value).toPlainString();
|
||||
}
|
||||
|
||||
protected String safeText(String value) {
|
||||
return value == null ? "" : value.trim();
|
||||
}
|
||||
|
||||
public void writeWorkbook(HttpServletResponse response, String fileName, Workbook workbook) throws IOException {
|
||||
try {
|
||||
response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(fileName));
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
workbook.write(response.getOutputStream());
|
||||
response.flushBuffer();
|
||||
} finally {
|
||||
workbook.close();
|
||||
}
|
||||
}
|
||||
|
||||
private CellStyle createBaseStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setWrapText(true);
|
||||
return style;
|
||||
}
|
||||
|
||||
private String buildSheetName(String preferred, String fallback) {
|
||||
String sheetName = sanitizeSheetName(preferred);
|
||||
if (sheetName.isEmpty()) {
|
||||
sheetName = sanitizeSheetName(fallback);
|
||||
}
|
||||
if (sheetName.length() > 31) {
|
||||
sheetName = sheetName.substring(0, 31);
|
||||
}
|
||||
return sheetName.isEmpty() ? "Sheet1" : sheetName;
|
||||
}
|
||||
|
||||
private String sanitizeSheetName(String value) {
|
||||
return safeText(value).replaceAll("[\\\\/?*\\[\\]:]", "_");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.report.builder;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ProjectBudgetExcelBuilder extends AbstractProjectOutputExcelBuilder {
|
||||
|
||||
private static final String SUMMARY_PLACEHOLDER = "/";
|
||||
private static final String BUDGET_SHEET_NAME = "建筑(装饰)工程项目考核产值预算表";
|
||||
private static final String BUDGET_SHEET_FALLBACK_NAME = "项目考核产值预算表";
|
||||
private static final String BUDGET_SHEET_TITLE = "附件4 建筑(装饰)工程项目考核产值预算表";
|
||||
private static final String QUARTER_BUDGET_SHEET_NAME = "项目考核产值年度季度预算计取表";
|
||||
private static final String QUARTER_BUDGET_SHEET_FALLBACK_NAME = "年度季度预算计取表";
|
||||
private static final String QUARTER_BUDGET_SHEET_TITLE = "项目考核产值年度/季度预算计取表";
|
||||
|
||||
public Workbook build(ExportData data) {
|
||||
Workbook workbook = createWorkbook();
|
||||
buildBudgetSheet(workbook, data);
|
||||
buildQuarterBudgetSheet(workbook, data);
|
||||
return workbook;
|
||||
}
|
||||
|
||||
private void buildBudgetSheet(Workbook workbook, ExportData data) {
|
||||
Sheet sheet = createSheet(workbook, BUDGET_SHEET_NAME, BUDGET_SHEET_FALLBACK_NAME);
|
||||
setColumnWidths(sheet, 16, 14, 18, 16, 18, 14, 12, 12, 12, 18, 12, 14, 16);
|
||||
|
||||
CellStyle titleStyle = createTitleStyle(workbook);
|
||||
CellStyle infoStyle = createInfoStyle(workbook);
|
||||
CellStyle infoValueStyle = createDerivedStyle(workbook, infoStyle,
|
||||
null, HorizontalAlignment.LEFT, false, (short) 10);
|
||||
CellStyle baseHeaderStyle = createHeaderStyle(workbook);
|
||||
CellStyle headerStyle = createDerivedStyle(workbook, baseHeaderStyle,
|
||||
IndexedColors.LEMON_CHIFFON, HorizontalAlignment.CENTER, true, (short) 10);
|
||||
CellStyle cellStyle = createCellStyle(workbook);
|
||||
CellStyle subtotalStyle = headerStyle;
|
||||
CellStyle totalStyle = createDerivedStyle(workbook, baseHeaderStyle,
|
||||
IndexedColors.GOLD, HorizontalAlignment.CENTER, true, (short) 10);
|
||||
|
||||
int rowIndex = 0;
|
||||
rowIndex = writeMergedTitleRow(sheet, rowIndex, BUDGET_SHEET_TITLE, titleStyle, 12);
|
||||
rowIndex = buildBudgetHeader(sheet, rowIndex, headerStyle);
|
||||
|
||||
if (data.getBudgetRows() != null) {
|
||||
for (BudgetRow rowData : data.getBudgetRows()) {
|
||||
if (rowData == null || rowData.getRowType() == null) {
|
||||
continue;
|
||||
}
|
||||
if (BudgetRowType.DETAIL.equals(rowData.getRowType())) {
|
||||
writeBudgetDetailRow(sheet, rowIndex++, rowData, cellStyle);
|
||||
continue;
|
||||
}
|
||||
if (BudgetRowType.PART_EMPTY.equals(rowData.getRowType())) {
|
||||
writeBudgetEmptyRow(sheet, rowIndex++, rowData, cellStyle);
|
||||
continue;
|
||||
}
|
||||
if (BudgetRowType.PART_SUBTOTAL.equals(rowData.getRowType())) {
|
||||
writeBudgetSummaryRow(sheet, rowIndex++, rowData, subtotalStyle);
|
||||
continue;
|
||||
}
|
||||
if (BudgetRowType.PLANNING_TOTAL.equals(rowData.getRowType())) {
|
||||
writeBudgetSummaryRow(sheet, rowIndex++, rowData, totalStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row remarkRow = sheet.createRow(rowIndex++);
|
||||
setMergedRegionText(sheet, remarkRow.getRowNum(), remarkRow.getRowNum(), 0, 12,
|
||||
"备注:" + safeText(data.getRemark()), infoValueStyle);
|
||||
|
||||
Row signRow = sheet.createRow(rowIndex);
|
||||
setMergedRegionText(sheet, signRow.getRowNum(), signRow.getRowNum(), 0, 3,
|
||||
"项目经理/工程负责人:", infoValueStyle);
|
||||
setMergedRegionText(sheet, signRow.getRowNum(), signRow.getRowNum(), 4, 7,
|
||||
"设计中心负责人:", infoValueStyle);
|
||||
setMergedRegionText(sheet, signRow.getRowNum(), signRow.getRowNum(), 8, 12,
|
||||
"市场运营中心负责人:", infoValueStyle);
|
||||
}
|
||||
|
||||
private int buildBudgetHeader(Sheet sheet, int rowIndex, CellStyle headerStyle) {
|
||||
int firstRow = rowIndex;
|
||||
sheet.createRow(firstRow);
|
||||
sheet.createRow(firstRow + 1);
|
||||
sheet.createRow(firstRow + 2);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 0, 0, "项目规模", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 1, 2, "建筑工程(㎡)\n精装工程(㎡)", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 3, 3, "内部指导单价(元 /㎡)", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow, 4, 10, "考核产值面积", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 2, 10, 10, "小计(㎡)", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 11, 11, "设计阶段占比", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 12, 12, "考核产值小计(万元)", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 2, 4, 4, "建筑(装饰)设计面积(㎡)", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 1, 5, 6, "套图系数", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 1, 7, 9, "调整系数", headerStyle);
|
||||
|
||||
writeRow(sheet, firstRow + 2, headerStyle, (Object[]) new String[]{
|
||||
"规划内容", "设计部位", "建筑类型", "", "", "栋数 / 户型数",
|
||||
"套图系数", "规模系数", "修改系数", "复杂系数 / 复杂等级", "", "", ""
|
||||
});
|
||||
return rowIndex + 3;
|
||||
}
|
||||
|
||||
private void writeBudgetDetailRow(Sheet sheet, int rowIndex, BudgetRow rowData, CellStyle style) {
|
||||
Row row = sheet.createRow(rowIndex);
|
||||
setText(row, 0, "", style);
|
||||
setText(row, 1, safeText(rowData.getDisplayDesignPart()), style);
|
||||
setText(row, 2, safeText(rowData.getDisplayBuildingType()), style);
|
||||
setText(row, 3, textOrBlank(rowData.getInternalGuidanceUnitPrice()), style);
|
||||
setText(row, 4, textOrBlank(rowData.getDesignArea()), style);
|
||||
setText(row, 5, integerText(rowData.getBuildingOrUnitCount()), style);
|
||||
setText(row, 6, factorTextOrBlank(rowData.getDrawingSetFactor(), 2), style);
|
||||
setText(row, 7, factorTextOrBlank(rowData.getScaleFactor(), 2), style);
|
||||
setText(row, 8, factorTextOrBlank(rowData.getModificationFactor(), 2), style);
|
||||
setText(row, 9, factorTextOrBlank(rowData.getComplexityFactor(), 2), style);
|
||||
setText(row, 10, textOrBlank(rowData.getSubtotalArea()), style);
|
||||
setText(row, 11, percentTextOrBlank(rowData.getCurrentDesignStageRatio()), style);
|
||||
setText(row, 12, textOrBlank(rowData.getAssessmentOutputValueWan()), style);
|
||||
}
|
||||
|
||||
private void writeBudgetEmptyRow(Sheet sheet, int rowIndex, BudgetRow rowData, CellStyle style) {
|
||||
Row row = sheet.createRow(rowIndex);
|
||||
setText(row, 0, "", style);
|
||||
setText(row, 1, safeText(rowData.getDisplayDesignPart()), style);
|
||||
for (int i = 2; i <= 12; i++) {
|
||||
setText(row, i, "", style);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBudgetSummaryRow(Sheet sheet, int rowIndex, BudgetRow rowData, CellStyle style) {
|
||||
Row row = sheet.createRow(rowIndex);
|
||||
setText(row, 0, "", style);
|
||||
setText(row, 1, safeText(rowData.getDisplayDesignPart()), style);
|
||||
setMergedRegionText(sheet, rowIndex, rowIndex, 2, 3, SUMMARY_PLACEHOLDER, style);
|
||||
setText(row, 4, text(rowData.getDesignArea()), style);
|
||||
setMergedRegionText(sheet, rowIndex, rowIndex, 5, 9, SUMMARY_PLACEHOLDER, style);
|
||||
setText(row, 10, text(rowData.getSubtotalArea()), style);
|
||||
setText(row, 11, SUMMARY_PLACEHOLDER, style);
|
||||
setText(row, 12, text(rowData.getAssessmentOutputValueWan()), style);
|
||||
}
|
||||
|
||||
private void buildQuarterBudgetSheet(Workbook workbook, ExportData data) {
|
||||
Sheet sheet = createSheet(workbook, QUARTER_BUDGET_SHEET_NAME, QUARTER_BUDGET_SHEET_FALLBACK_NAME);
|
||||
setColumnWidths(sheet, 10, 20, 18, 24, 16, 16, 16, 12, 14, 14, 12, 12, 12, 12, 14, 14, 12, 12, 12, 12, 14, 24);
|
||||
|
||||
CellStyle titleStyle = createTitleStyle(workbook);
|
||||
CellStyle baseHeaderStyle = createHeaderStyle(workbook);
|
||||
CellStyle headerStyle = createDerivedStyle(workbook, baseHeaderStyle,
|
||||
IndexedColors.LEMON_CHIFFON, HorizontalAlignment.CENTER, true, (short) 10);
|
||||
CellStyle cellStyle = createCellStyle(workbook);
|
||||
CellStyle totalStyle = createDerivedStyle(workbook, baseHeaderStyle,
|
||||
IndexedColors.GOLD, HorizontalAlignment.CENTER, true, (short) 10);
|
||||
CellStyle centeredCellStyle = createDerivedStyle(workbook, cellStyle,
|
||||
null, HorizontalAlignment.CENTER, false, (short) 10);
|
||||
|
||||
int rowIndex = 0;
|
||||
rowIndex = writeMergedTitleRow(sheet, rowIndex, QUARTER_BUDGET_SHEET_TITLE, titleStyle, 21);
|
||||
rowIndex = buildQuarterBudgetHeader(sheet, rowIndex, data, headerStyle, centeredCellStyle);
|
||||
|
||||
for (QuarterBudgetRow rowData : data.getQuarterBudgetRows()) {
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
if (rowData.isTotalRow()) {
|
||||
writeQuarterBudgetTotalRow(sheet, row, rowData, totalStyle);
|
||||
continue;
|
||||
}
|
||||
|
||||
setText(row, 0, rowData.getSerialNo(), cellStyle);
|
||||
setText(row, 1, safeText(data.getProjectName()), cellStyle);
|
||||
setText(row, 2, safeText(rowData.getOutputType()), cellStyle);
|
||||
setText(row, 3, safeText(rowData.getDesignContent()), cellStyle);
|
||||
setText(row, 4, textOrBlank(rowData.getTotalDesignArea()), cellStyle);
|
||||
setText(row, 5, textOrBlank(rowData.getTotalAssessmentArea()), cellStyle);
|
||||
setText(row, 6, textOrBlank(rowData.getTotalAssessmentOutputWan()), cellStyle);
|
||||
setText(row, 7, percentTextOrBlank(rowData.getDesignStageRatio()), cellStyle);
|
||||
setText(row, 8, textOrBlank(rowData.getDesignStageOutputWan()), cellStyle);
|
||||
setText(row, 9, percentTextOrBlank(rowData.getHistoricalIssuedRatio()), cellStyle);
|
||||
setText(row, 10, percentTextOrBlank(rowData.getQuarterOneRatio()), cellStyle);
|
||||
setText(row, 11, percentTextOrBlank(rowData.getQuarterTwoRatio()), cellStyle);
|
||||
setText(row, 12, percentTextOrBlank(rowData.getQuarterThreeRatio()), cellStyle);
|
||||
setText(row, 13, percentTextOrBlank(rowData.getQuarterFourRatio()), cellStyle);
|
||||
setText(row, 14, percentTextOrBlank(rowData.getCurrentYearRatio()), cellStyle);
|
||||
setText(row, 15, percentTextOrBlank(rowData.getPendingRatio()), cellStyle);
|
||||
setText(row, 16, textOrBlank(rowData.getQuarterOneAmountWan()), cellStyle);
|
||||
setText(row, 17, textOrBlank(rowData.getQuarterTwoAmountWan()), cellStyle);
|
||||
setText(row, 18, textOrBlank(rowData.getQuarterThreeAmountWan()), cellStyle);
|
||||
setText(row, 19, textOrBlank(rowData.getQuarterFourAmountWan()), cellStyle);
|
||||
setText(row, 20, textOrBlank(rowData.getYearTotalAmountWan()), cellStyle);
|
||||
setText(row, 21, safeText(rowData.getRatioRemark()), cellStyle);
|
||||
}
|
||||
}
|
||||
|
||||
private int buildQuarterBudgetHeader(Sheet sheet, int rowIndex, ExportData data,
|
||||
CellStyle headerStyle, CellStyle valueStyle) {
|
||||
int firstRow = rowIndex;
|
||||
sheet.createRow(firstRow);
|
||||
sheet.createRow(firstRow + 1);
|
||||
sheet.createRow(firstRow + 2);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 0, 0, "工程编号", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 1, 1, safeText(data.getProjectCode()), valueStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 0, "序号", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 1, "项目名称", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 2, 3, "类别", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 2, "产值类型", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 3, "设计内容", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 4, 4, "总建筑(精装)设计面积(㎡)", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 5, 5, "总考核产值面积(㎡)", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 6, 6, "总考核产值(万元)", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 7, 8, "设计阶段考核产值分配", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 7, "阶段占比", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 8, "考核产值", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow, 9, 15, "发放情况", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 2, 9, 9, "往年已发放比例", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 1, 10, 14, "本年度发放比例", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 10, "一季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 11, "二季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 12, "三季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 13, "四季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 14, "本年度小计", headerStyle);
|
||||
setMergedRegionText(sheet, firstRow + 1, firstRow + 2, 15, 15, "未发放比例", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 1, 16, 20, "本年度项目考核产值(万元)", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 16, "一季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 17, "二季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 18, "三季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 19, "四季度", headerStyle);
|
||||
setText(sheet.getRow(firstRow + 2), 20, "本年度小计", headerStyle);
|
||||
|
||||
setMergedRegionText(sheet, firstRow, firstRow + 2, 21, 21, "备注(本年度比例说明)", headerStyle);
|
||||
return rowIndex + 3;
|
||||
}
|
||||
|
||||
private void writeQuarterBudgetTotalRow(Sheet sheet, Row row, QuarterBudgetRow rowData, CellStyle totalStyle) {
|
||||
int rowIndex = row.getRowNum();
|
||||
setMergedRegionText(sheet, rowIndex, rowIndex, 0, 3, "项目合计", totalStyle);
|
||||
setText(row, 4, textOrBlank(rowData.getTotalDesignArea()), totalStyle);
|
||||
setText(row, 5, textOrBlank(rowData.getTotalAssessmentArea()), totalStyle);
|
||||
setText(row, 6, textOrBlank(rowData.getTotalAssessmentOutputWan()), totalStyle);
|
||||
setText(row, 7, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 8, textOrBlank(rowData.getDesignStageOutputWan()), totalStyle);
|
||||
setText(row, 9, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 10, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 11, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 12, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 13, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 14, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 15, SUMMARY_PLACEHOLDER, totalStyle);
|
||||
setText(row, 16, textOrBlank(rowData.getQuarterOneAmountWan()), totalStyle);
|
||||
setText(row, 17, textOrBlank(rowData.getQuarterTwoAmountWan()), totalStyle);
|
||||
setText(row, 18, textOrBlank(rowData.getQuarterThreeAmountWan()), totalStyle);
|
||||
setText(row, 19, textOrBlank(rowData.getQuarterFourAmountWan()), totalStyle);
|
||||
setText(row, 20, textOrBlank(rowData.getYearTotalAmountWan()), totalStyle);
|
||||
setText(row, 21, "", totalStyle);
|
||||
}
|
||||
|
||||
private String factorTextOrBlank(BigDecimal value, int digits) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.setScale(digits, RoundingMode.HALF_UP).toPlainString();
|
||||
}
|
||||
|
||||
private String textOrBlank(BigDecimal value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.setScale(2, RoundingMode.HALF_UP).toPlainString();
|
||||
}
|
||||
|
||||
private String percentTextOrBlank(BigDecimal value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return percentText(value);
|
||||
}
|
||||
|
||||
private String integerText(Integer value) {
|
||||
return value == null ? "" : String.valueOf(value);
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ExportData {
|
||||
private String projectCode;
|
||||
private String projectName;
|
||||
private String projectManagerName;
|
||||
private String engineeringPrincipalName;
|
||||
private BigDecimal totalConstructionArea;
|
||||
private BigDecimal contractUnitPrice;
|
||||
private BigDecimal internalGuidanceUnitPrice;
|
||||
private BigDecimal totalAssessmentArea;
|
||||
private BigDecimal totalAssessmentOutputValue;
|
||||
private BigDecimal totalAssessmentOutputValueWan;
|
||||
private String remark;
|
||||
private String yearRangeText;
|
||||
private List<BudgetRow> budgetRows;
|
||||
private List<QuarterBudgetRow> quarterBudgetRows;
|
||||
}
|
||||
|
||||
public enum BudgetRowType {
|
||||
DETAIL,
|
||||
PART_EMPTY,
|
||||
PART_SUBTOTAL,
|
||||
PLANNING_TOTAL
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class BudgetRow {
|
||||
private BudgetRowType rowType;
|
||||
private String planningContent;
|
||||
private String displayDesignPart;
|
||||
private String displayBuildingType;
|
||||
private BigDecimal internalGuidanceUnitPrice;
|
||||
private BigDecimal designArea;
|
||||
private Integer buildingOrUnitCount;
|
||||
private BigDecimal drawingSetFactor;
|
||||
private BigDecimal scaleFactor;
|
||||
private BigDecimal modificationFactor;
|
||||
private BigDecimal complexityFactor;
|
||||
private BigDecimal subtotalArea;
|
||||
private BigDecimal currentDesignStageRatio;
|
||||
private BigDecimal assessmentOutputValueWan;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class QuarterBudgetRow {
|
||||
private Integer serialNo;
|
||||
private boolean totalRow;
|
||||
private String outputType;
|
||||
private String designContent;
|
||||
private Integer budgetYear;
|
||||
private BigDecimal totalDesignArea;
|
||||
private BigDecimal totalAssessmentArea;
|
||||
private BigDecimal totalAssessmentOutputWan;
|
||||
private BigDecimal designStageRatio;
|
||||
private BigDecimal designStageOutputWan;
|
||||
private BigDecimal historicalIssuedRatio;
|
||||
private BigDecimal quarterOneRatio;
|
||||
private BigDecimal quarterTwoRatio;
|
||||
private BigDecimal quarterThreeRatio;
|
||||
private BigDecimal quarterFourRatio;
|
||||
private BigDecimal currentYearRatio;
|
||||
private BigDecimal pendingRatio;
|
||||
private BigDecimal quarterOneAmountWan;
|
||||
private BigDecimal quarterTwoAmountWan;
|
||||
private BigDecimal quarterThreeAmountWan;
|
||||
private BigDecimal quarterFourAmountWan;
|
||||
private BigDecimal yearTotalAmountWan;
|
||||
private String ratioRemark;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.report.builder;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ProjectLeadQuarterOutputExcelBuilder extends AbstractProjectOutputExcelBuilder {
|
||||
|
||||
public Workbook build(ExportData data) {
|
||||
Workbook workbook = createWorkbook();
|
||||
Sheet sheet = createSheet(workbook, "项目负责人计取", "项目负责人计取");
|
||||
setColumnWidths(sheet, 8, 24, 14, 20, 12, 20, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12);
|
||||
|
||||
CellStyle titleStyle = createTitleStyle(workbook);
|
||||
CellStyle infoStyle = createInfoStyle(workbook);
|
||||
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||
CellStyle cellStyle = createCellStyle(workbook);
|
||||
|
||||
int rowIndex = 0;
|
||||
rowIndex = writeMergedTitleRow(sheet, rowIndex, "项目负责人年度/季度计取表", titleStyle, 16);
|
||||
|
||||
Row infoRow = sheet.createRow(rowIndex++);
|
||||
writeLabelValue(infoRow, 0, 1, "项目名称", data.getProjectName(), infoStyle);
|
||||
writeLabelValue(infoRow, 4, 5, "年度", data.getYear(), infoStyle);
|
||||
|
||||
rowIndex = writeRow(sheet, rowIndex, headerStyle, (Object[]) new String[]{
|
||||
"序号", "规划内容", "项目经理人员", "项目经理比例", "项目负责人人员", "项目负责人比例",
|
||||
"项目经理一季度", "项目经理二季度", "项目经理三季度", "项目经理四季度", "项目经理年度合计",
|
||||
"项目负责人一季度", "项目负责人二季度", "项目负责人三季度", "项目负责人四季度",
|
||||
"项目负责人年度合计", "项目经理/项目负责人合计"
|
||||
});
|
||||
|
||||
int serialNo = 1;
|
||||
for (LeadQuarterRow rowData : data.getRows()) {
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
setText(row, 0, serialNo++, cellStyle);
|
||||
setText(row, 1, rowData.getPlanningContent(), cellStyle);
|
||||
setText(row, 2, rowData.getProjectManagerNames(), cellStyle);
|
||||
setText(row, 3, percentText(rowData.getProjectManagerRatio()), cellStyle);
|
||||
setText(row, 4, rowData.getEngineeringPrincipalNames(), cellStyle);
|
||||
setText(row, 5, percentText(rowData.getEngineeringPrincipalRatio()), cellStyle);
|
||||
setText(row, 6, text(rowData.getProjectManagerQuarterOneAmount()), cellStyle);
|
||||
setText(row, 7, text(rowData.getProjectManagerQuarterTwoAmount()), cellStyle);
|
||||
setText(row, 8, text(rowData.getProjectManagerQuarterThreeAmount()), cellStyle);
|
||||
setText(row, 9, text(rowData.getProjectManagerQuarterFourAmount()), cellStyle);
|
||||
setText(row, 10, text(rowData.getProjectManagerYearTotalAmount()), cellStyle);
|
||||
setText(row, 11, text(rowData.getEngineeringPrincipalQuarterOneAmount()), cellStyle);
|
||||
setText(row, 12, text(rowData.getEngineeringPrincipalQuarterTwoAmount()), cellStyle);
|
||||
setText(row, 13, text(rowData.getEngineeringPrincipalQuarterThreeAmount()), cellStyle);
|
||||
setText(row, 14, text(rowData.getEngineeringPrincipalQuarterFourAmount()), cellStyle);
|
||||
setText(row, 15, text(rowData.getEngineeringPrincipalYearTotalAmount()), cellStyle);
|
||||
setText(row, 16, text(rowData.getTotalAmount()), cellStyle);
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ExportData {
|
||||
private String projectName;
|
||||
private Integer year;
|
||||
private List<LeadQuarterRow> rows;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class LeadQuarterRow {
|
||||
private String planningContent;
|
||||
private String projectManagerNames;
|
||||
private BigDecimal projectManagerRatio;
|
||||
private String engineeringPrincipalNames;
|
||||
private BigDecimal engineeringPrincipalRatio;
|
||||
private BigDecimal projectManagerQuarterOneAmount;
|
||||
private BigDecimal projectManagerQuarterTwoAmount;
|
||||
private BigDecimal projectManagerQuarterThreeAmount;
|
||||
private BigDecimal projectManagerQuarterFourAmount;
|
||||
private BigDecimal projectManagerYearTotalAmount;
|
||||
private BigDecimal engineeringPrincipalQuarterOneAmount;
|
||||
private BigDecimal engineeringPrincipalQuarterTwoAmount;
|
||||
private BigDecimal engineeringPrincipalQuarterThreeAmount;
|
||||
private BigDecimal engineeringPrincipalQuarterFourAmount;
|
||||
private BigDecimal engineeringPrincipalYearTotalAmount;
|
||||
private BigDecimal totalAmount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.report.builder;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ProjectQuarterOutputExcelBuilder extends AbstractProjectOutputExcelBuilder {
|
||||
|
||||
public Workbook build(ExportData data) {
|
||||
Workbook workbook = createWorkbook();
|
||||
Sheet sheet = createSheet(workbook, "年度季度计取", "年度季度计取");
|
||||
setColumnWidths(sheet, 8, 24, 12, 22, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12);
|
||||
|
||||
CellStyle titleStyle = createTitleStyle(workbook);
|
||||
CellStyle infoStyle = createInfoStyle(workbook);
|
||||
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||
CellStyle cellStyle = createCellStyle(workbook);
|
||||
|
||||
int rowIndex = 0;
|
||||
rowIndex = writeMergedTitleRow(sheet, rowIndex, "项目考核产值年度/季度计取表", titleStyle, 15);
|
||||
|
||||
Row infoRow = sheet.createRow(rowIndex++);
|
||||
writeLabelValue(infoRow, 0, 1, "项目名称", data.getProjectName(), infoStyle);
|
||||
writeLabelValue(infoRow, 4, 5, "年度", data.getYear(), infoStyle);
|
||||
|
||||
rowIndex = writeRow(sheet, rowIndex, headerStyle, (Object[]) new String[]{
|
||||
"序号", "项目名称", "归属类型", "规划内容", "往年已发放比例", "本年度发放比例",
|
||||
"未发放比例", "一季度", "二季度", "三季度", "四季度", "本年度小计",
|
||||
"项目经理/项目负责人", "专业所合计", "专业分配说明", "考核产值"
|
||||
});
|
||||
|
||||
int serialNo = 1;
|
||||
for (QuarterRow rowData : data.getRows()) {
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
setText(row, 0, serialNo++, cellStyle);
|
||||
setText(row, 1, data.getProjectName(), cellStyle);
|
||||
setText(row, 2, rowData.getOwnershipType(), cellStyle);
|
||||
setText(row, 3, rowData.getPlanningContent(), cellStyle);
|
||||
setText(row, 4, percentText(rowData.getHistoricalIssuedRatio()), cellStyle);
|
||||
setText(row, 5, percentText(rowData.getCurrentYearRatio()), cellStyle);
|
||||
setText(row, 6, percentText(rowData.getPendingRatio()), cellStyle);
|
||||
setText(row, 7, text(rowData.getQuarterOneAmount()), cellStyle);
|
||||
setText(row, 8, text(rowData.getQuarterTwoAmount()), cellStyle);
|
||||
setText(row, 9, text(rowData.getQuarterThreeAmount()), cellStyle);
|
||||
setText(row, 10, text(rowData.getQuarterFourAmount()), cellStyle);
|
||||
setText(row, 11, text(rowData.getYearTotalAmount()), cellStyle);
|
||||
setText(row, 12, text(rowData.getProjectLeadAmount()), cellStyle);
|
||||
setText(row, 13, text(rowData.getOfficeAmount()), cellStyle);
|
||||
setText(row, 14, rowData.getSpecialtySummaryText(), cellStyle);
|
||||
setText(row, 15, text(rowData.getAssessmentOutputValue()), cellStyle);
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ExportData {
|
||||
private String projectName;
|
||||
private Integer year;
|
||||
private List<QuarterRow> rows;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class QuarterRow {
|
||||
private String ownershipType;
|
||||
private String planningContent;
|
||||
private BigDecimal historicalIssuedRatio;
|
||||
private BigDecimal currentYearRatio;
|
||||
private BigDecimal pendingRatio;
|
||||
private BigDecimal quarterOneAmount;
|
||||
private BigDecimal quarterTwoAmount;
|
||||
private BigDecimal quarterThreeAmount;
|
||||
private BigDecimal quarterFourAmount;
|
||||
private BigDecimal yearTotalAmount;
|
||||
private BigDecimal projectLeadAmount;
|
||||
private BigDecimal officeAmount;
|
||||
private String specialtySummaryText;
|
||||
private BigDecimal assessmentOutputValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.report.builder;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SpecialtyPersonOutputExcelBuilder extends AbstractProjectOutputExcelBuilder {
|
||||
|
||||
public Workbook build(ExportData data) {
|
||||
Workbook workbook = createWorkbook();
|
||||
Sheet sheet = createSheet(workbook, "专业内人员计取", "专业内人员计取");
|
||||
setColumnWidths(sheet, 8, 20, 14, 16, 12, 12, 12, 12, 12, 12);
|
||||
|
||||
CellStyle titleStyle = createTitleStyle(workbook);
|
||||
CellStyle infoStyle = createInfoStyle(workbook);
|
||||
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||
CellStyle cellStyle = createCellStyle(workbook);
|
||||
|
||||
int rowIndex = 0;
|
||||
rowIndex = writeMergedTitleRow(sheet, rowIndex, "专业内人员项目考核产值年度/季度计取表", titleStyle, 9);
|
||||
|
||||
Row infoRowOne = sheet.createRow(rowIndex++);
|
||||
writeLabelValue(infoRowOne, 0, 1, "项目名称", data.getProjectName(), infoStyle);
|
||||
writeLabelValue(infoRowOne, 4, 5, "规划内容", data.getPlanningContent(), infoStyle);
|
||||
|
||||
Row infoRowTwo = sheet.createRow(rowIndex++);
|
||||
writeLabelValue(infoRowTwo, 0, 1, "专业", data.getSpecialtyName(), infoStyle);
|
||||
writeLabelValue(infoRowTwo, 4, 5, "年度", data.getYear(), infoStyle);
|
||||
|
||||
rowIndex = writeRow(sheet, rowIndex, headerStyle, (Object[]) new String[]{
|
||||
"序号", "角色", "员工姓名", "角色比例", "人员比例",
|
||||
"一季度", "二季度", "三季度", "四季度", "年度合计"
|
||||
});
|
||||
|
||||
int serialNo = 1;
|
||||
for (PersonQuarterRow rowData : data.getRows()) {
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
setText(row, 0, serialNo++, cellStyle);
|
||||
setText(row, 1, rowData.getRoleName(), cellStyle);
|
||||
setText(row, 2, rowData.getEmployeeName(), cellStyle);
|
||||
setText(row, 3, percentText(rowData.getRoleRatio()), cellStyle);
|
||||
setText(row, 4, percentText(rowData.getPersonRatio()), cellStyle);
|
||||
setText(row, 5, text(rowData.getQuarterOneAmount()), cellStyle);
|
||||
setText(row, 6, text(rowData.getQuarterTwoAmount()), cellStyle);
|
||||
setText(row, 7, text(rowData.getQuarterThreeAmount()), cellStyle);
|
||||
setText(row, 8, text(rowData.getQuarterFourAmount()), cellStyle);
|
||||
setText(row, 9, text(rowData.getYearTotalAmount()), cellStyle);
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ExportData {
|
||||
private String projectName;
|
||||
private String planningContent;
|
||||
private String specialtyName;
|
||||
private Integer year;
|
||||
private List<PersonQuarterRow> rows;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PersonQuarterRow {
|
||||
private String roleName;
|
||||
private String employeeName;
|
||||
private BigDecimal roleRatio;
|
||||
private BigDecimal personRatio;
|
||||
private BigDecimal quarterOneAmount;
|
||||
private BigDecimal quarterTwoAmount;
|
||||
private BigDecimal quarterThreeAmount;
|
||||
private BigDecimal quarterFourAmount;
|
||||
private BigDecimal yearTotalAmount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.specialtyrolesplit;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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;
|
||||
@@ -8,16 +7,19 @@ import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.Speci
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitBatchSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.specialtyrolesplit.vo.SpecialtyRoleSplitSaveItemReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.employee.EmployeeDO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.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.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.enums.OutputSplitBizConstants;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.employee.EmployeeService;
|
||||
import cn.iocoder.lyzsys.module.tjt.service.outputsplit.ProjectOutputSplitService;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@@ -25,9 +27,11 @@ 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.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@@ -40,21 +44,15 @@ import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.SPECIALTY_RO
|
||||
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;
|
||||
|
||||
/**
|
||||
* 页面5角色比例 Service 实现类
|
||||
*
|
||||
* @author Codex
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService {
|
||||
|
||||
private static final int RATIO_SCALE = 4;
|
||||
private static final int AMOUNT_SCALE = 2;
|
||||
private static final TypeReference<List<SpecialtyRolePersonSaveReqVO>> PERSON_LIST_TYPE =
|
||||
new TypeReference<List<SpecialtyRolePersonSaveReqVO>>() {};
|
||||
private static final BigDecimal ZERO_RATIO = BigDecimal.ZERO.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
private static final BigDecimal ONE_RATIO = BigDecimal.ONE.setScale(RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
private static final BigDecimal HALF_RATIO = new BigDecimal("0.5000");
|
||||
private static final BigDecimal ZERO_AMOUNT = BigDecimal.ZERO.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
|
||||
|
||||
@Resource
|
||||
@@ -65,6 +63,10 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
private ProjectPlanningMapper projectPlanningMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ProjectRolePersonMapper projectRolePersonMapper;
|
||||
@Resource
|
||||
private EmployeeService employeeService;
|
||||
|
||||
@Override
|
||||
public List<SpecialtyRoleSplitRespVO> getSpecialtyRoleSplitListByPlanningId(Long planningId) {
|
||||
@@ -74,22 +76,30 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
List<SpecialtyRoleSplitDO> dbList = specialtyRoleSplitMapper.selectListByOutputSplitId(outputSplit.getId());
|
||||
Map<String, SpecialtyRoleSplitDO> dbMap = dbList.stream().collect(Collectors.toMap(
|
||||
item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b));
|
||||
Map<String, List<ProjectRolePersonDO>> projectRolePersonMap = projectRolePersonMapper
|
||||
.selectListByProjectId(project.getId()).stream()
|
||||
.collect(Collectors.groupingBy(ProjectRolePersonDO::getRoleCode, LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
List<SpecialtyRoleSplitRespVO> result = new ArrayList<>();
|
||||
BigDecimal assessmentOutputValue = planning.getAssessmentOutputValue();
|
||||
for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.SPECIALTY_ITEMS) {
|
||||
BigDecimal specialtyAmount = projectOutputSplitService.getSpecialtyAmount(
|
||||
outputSplit, assessmentOutputValue, specialtyItem.getCode());
|
||||
for (OutputSplitBizConstants.RoleItem roleItem : OutputSplitBizConstants.ROLE_ITEMS) {
|
||||
for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) {
|
||||
BigDecimal specialtyAmount = getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyItem.getCode());
|
||||
Map<String, BigDecimal> defaultRoleRatioMap = buildDefaultRoleRatioMap(
|
||||
specialtyItem.getCode(), projectRolePersonMap);
|
||||
for (OutputSplitBizConstants.RoleItem roleItem : OutputSplitBizConstants.getRoleItems(specialtyItem.getCode())) {
|
||||
SpecialtyRoleSplitDO dbItem = dbMap.get(specialtyItem.getCode() + ":" + roleItem.getCode());
|
||||
BigDecimal roleRatio = getStoredRoleRatio(dbItem, roleItem.getCode());
|
||||
BigDecimal roleRatio = getStoredRoleRatio(
|
||||
dbItem, specialtyItem.getCode(), roleItem.getCode(), defaultRoleRatioMap);
|
||||
BigDecimal roleAmount = multiplyAmount(specialtyAmount, roleRatio);
|
||||
List<SpecialtyRolePersonRespVO> persons = buildRespPersons(dbItem, roleAmount, roleRatio);
|
||||
List<SpecialtyRolePersonRespVO> persons = buildRespPersons(
|
||||
dbItem, specialtyItem.getCode(), roleItem.getCode(), roleAmount, roleRatio, projectRolePersonMap);
|
||||
SpecialtyRoleSplitRespVO respVO = dbItem == null
|
||||
? new SpecialtyRoleSplitRespVO()
|
||||
: BeanUtils.toBean(dbItem, SpecialtyRoleSplitRespVO.class);
|
||||
if (respVO.getId() == null) {
|
||||
respVO.setOutputSplitId(outputSplit.getId());
|
||||
respVO.setSortNo(roleItem.getSortNo());
|
||||
respVO.setSortNo(OutputSplitBizConstants.getSpecialtySortNo(specialtyItem.getCode()) * 10
|
||||
+ OutputSplitBizConstants.getRoleSortNo(roleItem.getCode()));
|
||||
}
|
||||
respVO.setPlanningId(planning.getId());
|
||||
respVO.setProjectName(project.getProjectName());
|
||||
@@ -117,30 +127,25 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
item -> item.getSpecialtyCode() + ":" + item.getRoleCode(), item -> item, (a, b) -> b));
|
||||
Map<String, Map<String, SpecialtyRoleSplitSaveItemReqVO>> groupedMap = buildGroupedInput(reqVO.getItems());
|
||||
BigDecimal assessmentOutputValue = planning.getAssessmentOutputValue();
|
||||
for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.SPECIALTY_ITEMS) {
|
||||
|
||||
for (OutputSplitBizConstants.SpecialtyItem specialtyItem : OutputSplitBizConstants.ASSIGNMENT_SPECIALTY_ITEMS) {
|
||||
Map<String, SpecialtyRoleSplitSaveItemReqVO> roleMap = groupedMap.getOrDefault(
|
||||
specialtyItem.getCode(), new LinkedHashMap<>());
|
||||
Map<String, BigDecimal> ratioMap = new LinkedHashMap<>();
|
||||
Map<String, List<SpecialtyRolePersonSaveReqVO>> personMap = new LinkedHashMap<>();
|
||||
BigDecimal roleTotal = ZERO_RATIO;
|
||||
BigDecimal specialtyAmount = projectOutputSplitService.getSpecialtyAmount(
|
||||
outputSplit, assessmentOutputValue, specialtyItem.getCode());
|
||||
for (OutputSplitBizConstants.RoleItem roleItem : OutputSplitBizConstants.ROLE_ITEMS) {
|
||||
BigDecimal roleRatio = getSaveRoleRatio(roleMap, roleItem.getCode());
|
||||
BigDecimal specialtyAmount = getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyItem.getCode());
|
||||
for (OutputSplitBizConstants.RoleItem roleItem : OutputSplitBizConstants.getRoleItems(specialtyItem.getCode())) {
|
||||
BigDecimal roleRatio = getSaveRoleRatio(roleMap, specialtyItem.getCode(), roleItem.getCode());
|
||||
BigDecimal roleAmount = multiplyAmount(specialtyAmount, roleRatio);
|
||||
List<SpecialtyRolePersonSaveReqVO> persons = normalizePersons(
|
||||
getSavePersons(roleMap, roleItem.getCode()));
|
||||
validateRolePersons(roleItem.getCode(), roleAmount, persons);
|
||||
ratioMap.put(roleItem.getCode(), roleRatio);
|
||||
personMap.put(roleItem.getCode(), 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));
|
||||
}
|
||||
validateRoleTotal(roleTotal);
|
||||
for (OutputSplitBizConstants.RoleItem roleItem : OutputSplitBizConstants.ROLE_ITEMS) {
|
||||
upsertRole(dbMap, outputSplit.getId(), specialtyItem.getCode(), specialtyItem.getName(),
|
||||
roleItem.getCode(), ratioMap.get(roleItem.getCode()),
|
||||
toPersonJson(personMap.get(roleItem.getCode())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,11 +165,14 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
|
||||
private Map<String, Map<String, SpecialtyRoleSplitSaveItemReqVO>> buildGroupedInput(List<SpecialtyRoleSplitSaveItemReqVO> items) {
|
||||
Map<String, Map<String, SpecialtyRoleSplitSaveItemReqVO>> result = new LinkedHashMap<>();
|
||||
if (items == null || items.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
for (SpecialtyRoleSplitSaveItemReqVO item : items) {
|
||||
if (!OutputSplitBizConstants.isValidSpecialtyCode(item.getSpecialtyCode())) {
|
||||
throw exception(SPECIALTY_ROLE_SPLIT_SPECIALTY_INVALID);
|
||||
}
|
||||
if (!OutputSplitBizConstants.isValidRoleCode(item.getRoleCode())) {
|
||||
if (!OutputSplitBizConstants.isValidRoleCode(item.getSpecialtyCode(), item.getRoleCode())) {
|
||||
throw exception(SPECIALTY_ROLE_SPLIT_ROLE_INVALID);
|
||||
}
|
||||
result.computeIfAbsent(item.getSpecialtyCode(), key -> new LinkedHashMap<>())
|
||||
@@ -174,7 +182,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
}
|
||||
|
||||
private void upsertRole(Map<String, SpecialtyRoleSplitDO> dbMap, Long outputSplitId, String specialtyCode,
|
||||
String specialtyName, String roleCode, BigDecimal roleRatio, String personNames) {
|
||||
String specialtyName, String roleCode, BigDecimal roleRatio, String personsJson) {
|
||||
String key = specialtyCode + ":" + roleCode;
|
||||
SpecialtyRoleSplitDO dbItem = dbMap.get(key);
|
||||
Integer sortNo = dbItem != null && dbItem.getSortNo() != null
|
||||
@@ -189,7 +197,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
createObj.setRoleCode(roleCode);
|
||||
createObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode));
|
||||
createObj.setRoleRatio(ratio(roleRatio));
|
||||
createObj.setPersonNames(personNames);
|
||||
createObj.setPersonsJson(personsJson);
|
||||
createObj.setSortNo(sortNo);
|
||||
specialtyRoleSplitMapper.insert(createObj);
|
||||
return;
|
||||
@@ -202,7 +210,7 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
updateObj.setRoleCode(roleCode);
|
||||
updateObj.setRoleName(OutputSplitBizConstants.getRoleName(roleCode));
|
||||
updateObj.setRoleRatio(ratio(roleRatio));
|
||||
updateObj.setPersonNames(personNames);
|
||||
updateObj.setPersonsJson(personsJson);
|
||||
updateObj.setSortNo(sortNo);
|
||||
specialtyRoleSplitMapper.updateById(updateObj);
|
||||
}
|
||||
@@ -213,9 +221,13 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
return item == null ? new ArrayList<>() : item.getPersons();
|
||||
}
|
||||
|
||||
private BigDecimal getSaveRoleRatio(Map<String, SpecialtyRoleSplitSaveItemReqVO> roleMap, String roleCode) {
|
||||
private BigDecimal getSaveRoleRatio(Map<String, SpecialtyRoleSplitSaveItemReqVO> roleMap,
|
||||
String specialtyCode, String roleCode) {
|
||||
SpecialtyRoleSplitSaveItemReqVO item = roleMap.get(roleCode);
|
||||
BigDecimal roleRatio = item == null ? ZERO_RATIO : ratio(item.getRoleRatio());
|
||||
if (!OutputSplitBizConstants.isValidRoleCode(specialtyCode, roleCode)) {
|
||||
throw exception(SPECIALTY_ROLE_SPLIT_ROLE_INVALID);
|
||||
}
|
||||
if (roleRatio.compareTo(ZERO_RATIO) < 0 || roleRatio.compareTo(ONE_RATIO) > 0) {
|
||||
throw exception(SPECIALTY_ROLE_SPLIT_ROLE_RATIO_INVALID);
|
||||
}
|
||||
@@ -231,18 +243,20 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
if (person == null) {
|
||||
continue;
|
||||
}
|
||||
String personName = StrUtil.trim(person.getPersonName());
|
||||
Long employeeId = person.getEmployeeId();
|
||||
BigDecimal personRatio = person.getPersonRatio();
|
||||
boolean hasName = StrUtil.isNotBlank(personName);
|
||||
boolean hasEmployee = employeeId != null;
|
||||
boolean hasRatio = personRatio != null;
|
||||
if (!hasName && !hasRatio) {
|
||||
if (!hasEmployee && !hasRatio) {
|
||||
continue;
|
||||
}
|
||||
if (!hasName || !hasRatio) {
|
||||
if (!hasEmployee || !hasRatio) {
|
||||
throw exception(SPECIALTY_ROLE_SPLIT_PERSON_INVALID);
|
||||
}
|
||||
EmployeeDO employee = employeeService.validateEmployeeExists(employeeId);
|
||||
SpecialtyRolePersonSaveReqVO normalized = new SpecialtyRolePersonSaveReqVO();
|
||||
normalized.setPersonName(personName);
|
||||
normalized.setEmployeeId(employeeId);
|
||||
normalized.setEmployeeName(employee.getEmployeeName());
|
||||
BigDecimal normalizedRatio = ratio(personRatio);
|
||||
if (normalizedRatio.compareTo(ZERO_RATIO) < 0 || normalizedRatio.compareTo(ONE_RATIO) > 0) {
|
||||
throw exception(SPECIALTY_ROLE_SPLIT_PERSON_RATIO_INVALID);
|
||||
@@ -271,19 +285,32 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal getStoredRoleRatio(SpecialtyRoleSplitDO dbItem, String roleCode) {
|
||||
if (dbItem == null) {
|
||||
return OutputSplitBizConstants.ROLE_DESIGN.equals(roleCode) ? ONE_RATIO : ZERO_RATIO;
|
||||
private BigDecimal getStoredRoleRatio(SpecialtyRoleSplitDO dbItem, String specialtyCode, String roleCode,
|
||||
Map<String, BigDecimal> defaultRoleRatioMap) {
|
||||
if (dbItem != null) {
|
||||
return ratio(dbItem.getRoleRatio());
|
||||
}
|
||||
return ratio(dbItem.getRoleRatio());
|
||||
if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) {
|
||||
return ratio(defaultRoleRatioMap.get(roleCode));
|
||||
}
|
||||
return OutputSplitBizConstants.ROLE_DESIGN.equals(roleCode) ? ONE_RATIO : ZERO_RATIO;
|
||||
}
|
||||
|
||||
private List<SpecialtyRolePersonRespVO> buildRespPersons(SpecialtyRoleSplitDO dbItem, BigDecimal roleAmount,
|
||||
BigDecimal roleRatio) {
|
||||
private List<SpecialtyRolePersonRespVO> buildRespPersons(SpecialtyRoleSplitDO dbItem, String specialtyCode,
|
||||
String roleCode, BigDecimal roleAmount,
|
||||
BigDecimal roleRatio,
|
||||
Map<String, List<ProjectRolePersonDO>> projectRolePersonMap) {
|
||||
List<SpecialtyRolePersonSaveReqVO> sourcePersons;
|
||||
if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) {
|
||||
sourcePersons = buildDefaultProjectLeadPersons(projectRolePersonMap.get(roleCode));
|
||||
} else {
|
||||
sourcePersons = parseStoredPersons(dbItem);
|
||||
}
|
||||
List<SpecialtyRolePersonRespVO> result = new ArrayList<>();
|
||||
for (SpecialtyRolePersonSaveReqVO person : parseStoredPersons(dbItem, roleRatio)) {
|
||||
for (SpecialtyRolePersonSaveReqVO person : sourcePersons) {
|
||||
SpecialtyRolePersonRespVO respVO = new SpecialtyRolePersonRespVO();
|
||||
respVO.setPersonName(person.getPersonName());
|
||||
respVO.setEmployeeId(person.getEmployeeId());
|
||||
respVO.setEmployeeName(person.getEmployeeName());
|
||||
respVO.setPersonRatio(ratio(person.getPersonRatio()));
|
||||
respVO.setPersonAmount(multiplyAmount(roleAmount, respVO.getPersonRatio()));
|
||||
result.add(respVO);
|
||||
@@ -291,66 +318,87 @@ public class SpecialtyRoleSplitServiceImpl implements SpecialtyRoleSplitService
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<SpecialtyRolePersonSaveReqVO> parseStoredPersons(SpecialtyRoleSplitDO dbItem, BigDecimal roleRatio) {
|
||||
private List<SpecialtyRolePersonSaveReqVO> parseStoredPersons(SpecialtyRoleSplitDO dbItem) {
|
||||
if (dbItem == null || dbItem.getPersonsJson() == null || dbItem.getPersonsJson().trim().isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<SpecialtyRolePersonSaveReqVO> persons = JsonUtils.parseArray(dbItem.getPersonsJson(), SpecialtyRolePersonSaveReqVO.class);
|
||||
if (persons == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return persons.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(person -> {
|
||||
SpecialtyRolePersonSaveReqVO normalized = new SpecialtyRolePersonSaveReqVO();
|
||||
normalized.setEmployeeId(person.getEmployeeId());
|
||||
normalized.setEmployeeName(person.getEmployeeName());
|
||||
normalized.setPersonRatio(ratio(person.getPersonRatio()));
|
||||
return normalized;
|
||||
})
|
||||
.filter(person -> person.getEmployeeId() != null
|
||||
&& person.getEmployeeName() != null
|
||||
&& !person.getEmployeeName().trim().isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<SpecialtyRolePersonSaveReqVO> buildDefaultProjectLeadPersons(List<ProjectRolePersonDO> rolePersons) {
|
||||
if (rolePersons == null || rolePersons.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<SpecialtyRolePersonSaveReqVO> result = new ArrayList<>();
|
||||
if (dbItem == null) {
|
||||
return result;
|
||||
}
|
||||
String rawPersons = StrUtil.trimToEmpty(dbItem.getPersonNames());
|
||||
BigDecimal storedRoleRatio = ratio(roleRatio);
|
||||
if (StrUtil.isNotBlank(rawPersons) && JsonUtils.isJson(rawPersons)) {
|
||||
List<SpecialtyRolePersonSaveReqVO> jsonPersons = JsonUtils.parseObjectQuietly(rawPersons, PERSON_LIST_TYPE);
|
||||
if (jsonPersons != null) {
|
||||
for (SpecialtyRolePersonSaveReqVO jsonPerson : jsonPersons) {
|
||||
if (jsonPerson == null) {
|
||||
continue;
|
||||
}
|
||||
String personName = StrUtil.trimToEmpty(jsonPerson.getPersonName());
|
||||
BigDecimal personRatio = jsonPerson.getPersonRatio();
|
||||
if (StrUtil.isBlank(personName) && personRatio == null) {
|
||||
continue;
|
||||
}
|
||||
SpecialtyRolePersonSaveReqVO person = new SpecialtyRolePersonSaveReqVO();
|
||||
person.setPersonName(personName);
|
||||
person.setPersonRatio(ratio(personRatio));
|
||||
result.add(person);
|
||||
}
|
||||
if (!result.isEmpty()) {
|
||||
if (storedRoleRatio.compareTo(ZERO_RATIO) > 0
|
||||
&& sumPersonRatios(result).compareTo(storedRoleRatio) == 0) {
|
||||
return convertLegacyPersons(result, storedRoleRatio);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (StrUtil.isNotBlank(rawPersons)) {
|
||||
result.add(buildStoredPerson(rawPersons, storedRoleRatio.compareTo(ZERO_RATIO) > 0 ? ONE_RATIO : ZERO_RATIO));
|
||||
return result;
|
||||
BigDecimal perRatio = BigDecimal.ONE.divide(BigDecimal.valueOf(rolePersons.size()), RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
BigDecimal accumulated = ZERO_RATIO;
|
||||
for (int i = 0; i < rolePersons.size(); i++) {
|
||||
ProjectRolePersonDO rolePerson = rolePersons.get(i);
|
||||
SpecialtyRolePersonSaveReqVO person = new SpecialtyRolePersonSaveReqVO();
|
||||
person.setEmployeeId(rolePerson.getEmployeeId());
|
||||
person.setEmployeeName(rolePerson.getEmployeeName());
|
||||
BigDecimal personRatio = i == rolePersons.size() - 1
|
||||
? ONE_RATIO.subtract(accumulated).setScale(RATIO_SCALE, RoundingMode.HALF_UP)
|
||||
: perRatio;
|
||||
person.setPersonRatio(personRatio);
|
||||
accumulated = accumulated.add(personRatio).setScale(RATIO_SCALE, RoundingMode.HALF_UP);
|
||||
result.add(person);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<SpecialtyRolePersonSaveReqVO> convertLegacyPersons(List<SpecialtyRolePersonSaveReqVO> persons,
|
||||
BigDecimal roleRatio) {
|
||||
List<SpecialtyRolePersonSaveReqVO> result = new ArrayList<>();
|
||||
if (roleRatio.compareTo(ZERO_RATIO) <= 0) {
|
||||
return persons;
|
||||
private Map<String, BigDecimal> buildDefaultRoleRatioMap(String specialtyCode,
|
||||
Map<String, List<ProjectRolePersonDO>> projectRolePersonMap) {
|
||||
if (!OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
for (SpecialtyRolePersonSaveReqVO person : persons) {
|
||||
SpecialtyRolePersonSaveReqVO converted = new SpecialtyRolePersonSaveReqVO();
|
||||
converted.setPersonName(person.getPersonName());
|
||||
converted.setPersonRatio(ratio(person.getPersonRatio().divide(roleRatio, RATIO_SCALE, RoundingMode.HALF_UP)));
|
||||
result.add(converted);
|
||||
boolean hasProjectManager = projectRolePersonMap.containsKey(OutputSplitBizConstants.ROLE_PROJECT_MANAGER)
|
||||
&& !projectRolePersonMap.get(OutputSplitBizConstants.ROLE_PROJECT_MANAGER).isEmpty();
|
||||
boolean hasEngineeringPrincipal = projectRolePersonMap.containsKey(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL)
|
||||
&& !projectRolePersonMap.get(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL).isEmpty();
|
||||
Map<String, BigDecimal> result = new LinkedHashMap<>();
|
||||
if (hasProjectManager && hasEngineeringPrincipal) {
|
||||
result.put(OutputSplitBizConstants.ROLE_PROJECT_MANAGER, HALF_RATIO);
|
||||
result.put(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL, HALF_RATIO);
|
||||
return result;
|
||||
}
|
||||
if (hasProjectManager) {
|
||||
result.put(OutputSplitBizConstants.ROLE_PROJECT_MANAGER, ONE_RATIO);
|
||||
result.put(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL, ZERO_RATIO);
|
||||
return result;
|
||||
}
|
||||
if (hasEngineeringPrincipal) {
|
||||
result.put(OutputSplitBizConstants.ROLE_PROJECT_MANAGER, ZERO_RATIO);
|
||||
result.put(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL, ONE_RATIO);
|
||||
return result;
|
||||
}
|
||||
result.put(OutputSplitBizConstants.ROLE_PROJECT_MANAGER, HALF_RATIO);
|
||||
result.put(OutputSplitBizConstants.ROLE_ENGINEERING_PRINCIPAL, HALF_RATIO);
|
||||
return result;
|
||||
}
|
||||
|
||||
private SpecialtyRolePersonSaveReqVO buildStoredPerson(String personName, BigDecimal personRatio) {
|
||||
SpecialtyRolePersonSaveReqVO person = new SpecialtyRolePersonSaveReqVO();
|
||||
person.setPersonName(personName);
|
||||
person.setPersonRatio(ratio(personRatio));
|
||||
return person;
|
||||
private BigDecimal getSpecialtyAmount(ProjectOutputSplitDO outputSplit, BigDecimal assessmentOutputValue,
|
||||
String specialtyCode) {
|
||||
if (OutputSplitBizConstants.SPECIALTY_PROJECT_LEAD.equals(specialtyCode)) {
|
||||
return multiplyAmount(assessmentOutputValue, outputSplit.getProjectLeadRatio());
|
||||
}
|
||||
return projectOutputSplitService.getSpecialtyAmount(outputSplit, assessmentOutputValue, specialtyCode);
|
||||
}
|
||||
|
||||
private String toPersonJson(List<SpecialtyRolePersonSaveReqVO> persons) {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.yearkvalue;
|
||||
|
||||
import cn.iocoder.lyzsys.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValuePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValueRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValueSaveReqVO;
|
||||
|
||||
public interface YearKValueService {
|
||||
|
||||
Long createYearKValue(YearKValueSaveReqVO createReqVO);
|
||||
|
||||
void updateYearKValue(YearKValueSaveReqVO updateReqVO);
|
||||
|
||||
void deleteYearKValue(Long id);
|
||||
|
||||
YearKValueRespVO getYearKValue(Long id);
|
||||
|
||||
PageResult<YearKValueRespVO> getYearKValuePage(YearKValuePageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package cn.iocoder.lyzsys.module.tjt.service.yearkvalue;
|
||||
|
||||
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.yearkvalue.vo.YearKValuePageReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValueRespVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.controller.admin.yearkvalue.vo.YearKValueSaveReqVO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.dataobject.yearkvalue.YearKValueDO;
|
||||
import cn.iocoder.lyzsys.module.tjt.dal.mysql.yearkvalue.YearKValueMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.YEAR_K_VALUE_DUPLICATE;
|
||||
import static cn.iocoder.lyzsys.module.tjt.enums.ErrorCodeConstants.YEAR_K_VALUE_NOT_EXISTS;
|
||||
|
||||
@Service
|
||||
@Validated
|
||||
public class YearKValueServiceImpl implements YearKValueService {
|
||||
|
||||
@Resource
|
||||
private YearKValueMapper yearKValueMapper;
|
||||
|
||||
@Override
|
||||
public Long createYearKValue(YearKValueSaveReqVO createReqVO) {
|
||||
validateYearUnique(null, createReqVO.getKYear());
|
||||
YearKValueDO yearKValue = BeanUtils.toBean(createReqVO, YearKValueDO.class);
|
||||
if (yearKValue.getEnabledFlag() == null) {
|
||||
yearKValue.setEnabledFlag(Boolean.TRUE);
|
||||
}
|
||||
yearKValueMapper.insert(yearKValue);
|
||||
return yearKValue.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateYearKValue(YearKValueSaveReqVO updateReqVO) {
|
||||
validateYearKValueExists(updateReqVO.getId());
|
||||
validateYearUnique(updateReqVO.getId(), updateReqVO.getKYear());
|
||||
YearKValueDO updateObj = BeanUtils.toBean(updateReqVO, YearKValueDO.class);
|
||||
yearKValueMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteYearKValue(Long id) {
|
||||
validateYearKValueExists(id);
|
||||
yearKValueMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public YearKValueRespVO getYearKValue(Long id) {
|
||||
return BeanUtils.toBean(validateYearKValueExists(id), YearKValueRespVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<YearKValueRespVO> getYearKValuePage(YearKValuePageReqVO pageReqVO) {
|
||||
return BeanUtils.toBean(yearKValueMapper.selectPage(pageReqVO), YearKValueRespVO.class);
|
||||
}
|
||||
|
||||
private void validateYearUnique(Long id, Integer kYear) {
|
||||
YearKValueDO yearKValue = yearKValueMapper.selectByKYear(kYear);
|
||||
if (yearKValue == null) {
|
||||
return;
|
||||
}
|
||||
if (id == null || !yearKValue.getId().equals(id)) {
|
||||
throw exception(YEAR_K_VALUE_DUPLICATE);
|
||||
}
|
||||
}
|
||||
|
||||
private YearKValueDO validateYearKValueExists(Long id) {
|
||||
YearKValueDO yearKValue = yearKValueMapper.selectById(id);
|
||||
if (yearKValue == null) {
|
||||
throw exception(YEAR_K_VALUE_NOT_EXISTS);
|
||||
}
|
||||
return yearKValue;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user