feat(oa): 新增工资数据看板功能
- 添加新工资看板相关的 VO 类 - 实现新工资看板的数据获取接口和业务逻辑 - 优化原有工资看板的代码结构 - 新增月度支出、工资构成、趋势分析等图表数据查询- 增加社保公积金统计和单位、部门统计功能
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
package com.ruoyi.oa.controller;
|
||||
|
||||
|
||||
import com.ruoyi.common.core.AjaxResult;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.oa.domain.vo.SalaryDashboardVo;
|
||||
import com.ruoyi.oa.domain.vo.dashboard.NewSalaryDashboardVo;
|
||||
import com.ruoyi.oa.service.ISalaryDashboardService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -12,6 +12,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 工资数据看板控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/oa/salary/dashboard")
|
||||
public class SalaryDashboardController extends BaseController {
|
||||
@@ -19,8 +22,11 @@ public class SalaryDashboardController extends BaseController {
|
||||
@Autowired
|
||||
private ISalaryDashboardService salaryDashboardService;
|
||||
|
||||
/**
|
||||
* 获取原有工资数据看板数据
|
||||
*/
|
||||
@GetMapping
|
||||
public R<SalaryDashboardVo>getDashboardData(
|
||||
public R<SalaryDashboardVo> getDashboardData(
|
||||
@RequestParam(required = true) Long payYear,
|
||||
@RequestParam(required = true) Long payMonth
|
||||
) {
|
||||
@@ -28,4 +34,17 @@ public class SalaryDashboardController extends BaseController {
|
||||
salaryDashboardService.getDashboardData(payYear, payMonth)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取新工资数据看板数据(基于新的工资表结构)
|
||||
*/
|
||||
@GetMapping("/new")
|
||||
public R<NewSalaryDashboardVo> getNewDashboardData(
|
||||
@RequestParam(required = true) String salaryPeriod
|
||||
) {
|
||||
return R.ok(
|
||||
salaryDashboardService.getNewDashboardData(salaryPeriod)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 部门工资统计VO
|
||||
*/
|
||||
@Data
|
||||
public class DeptSalaryStatVo {
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 员工数量
|
||||
*/
|
||||
private Integer employeeCount;
|
||||
|
||||
/**
|
||||
* 总实发工资
|
||||
*/
|
||||
private BigDecimal totalNetSalary;
|
||||
|
||||
/**
|
||||
* 总应发工资
|
||||
*/
|
||||
private BigDecimal totalGrossSalary;
|
||||
|
||||
/**
|
||||
* 人均实发工资
|
||||
*/
|
||||
private BigDecimal avgNetSalary;
|
||||
|
||||
/**
|
||||
* 人均应发工资
|
||||
*/
|
||||
private BigDecimal avgGrossSalary;
|
||||
|
||||
/**
|
||||
* 同比增长率
|
||||
*/
|
||||
private BigDecimal yearOnYearGrowthRate;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 社保公积金统计VO
|
||||
*/
|
||||
@Data
|
||||
public class InsuranceStatVo {
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String itemName;
|
||||
|
||||
/**
|
||||
* 个人缴纳总额
|
||||
*/
|
||||
private BigDecimal personalTotal;
|
||||
|
||||
/**
|
||||
* 企业缴纳总额
|
||||
*/
|
||||
private BigDecimal enterpriseTotal;
|
||||
|
||||
/**
|
||||
* 合计
|
||||
*/
|
||||
private BigDecimal total;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 月度支出VO
|
||||
*/
|
||||
@Data
|
||||
public class MonthlyExpenseVo {
|
||||
/**
|
||||
* 月份
|
||||
*/
|
||||
private Integer month;
|
||||
|
||||
/**
|
||||
* 实发工资总额
|
||||
*/
|
||||
private BigDecimal totalNetSalary;
|
||||
|
||||
/**
|
||||
* 应发工资总额
|
||||
*/
|
||||
private BigDecimal totalGrossSalary;
|
||||
|
||||
/**
|
||||
* 单位总支出
|
||||
*/
|
||||
private BigDecimal totalUnitExpense;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 新工资看板卡片数据VO
|
||||
*/
|
||||
@Data
|
||||
public class NewCardDataVo {
|
||||
/**
|
||||
* 总实发工资
|
||||
*/
|
||||
private BigDecimal totalNetSalary;
|
||||
|
||||
/**
|
||||
* 较上月总实发工资增长率
|
||||
*/
|
||||
private BigDecimal lastMonthNetSalaryRate;
|
||||
|
||||
/**
|
||||
* 总应发工资
|
||||
*/
|
||||
private BigDecimal totalGrossSalary;
|
||||
|
||||
/**
|
||||
* 较上月总应发工资增长率
|
||||
*/
|
||||
private BigDecimal lastMonthGrossSalaryRate;
|
||||
|
||||
/**
|
||||
* 单位总支出
|
||||
*/
|
||||
private BigDecimal totalUnitExpense;
|
||||
|
||||
/**
|
||||
* 较上月单位总支出增长率
|
||||
*/
|
||||
private BigDecimal lastMonthUnitExpenseRate;
|
||||
|
||||
/**
|
||||
* 人均实发工资
|
||||
*/
|
||||
private BigDecimal avgNetSalary;
|
||||
|
||||
/**
|
||||
* 较上月人均实发工资增长率
|
||||
*/
|
||||
private BigDecimal lastMonthAvgNetSalaryRate;
|
||||
|
||||
/**
|
||||
* 同比增长率(与去年同期相比)
|
||||
*/
|
||||
private BigDecimal yearOnYearGrowthRate;
|
||||
|
||||
/**
|
||||
* 员工总数
|
||||
*/
|
||||
private Integer totalEmployeeCount;
|
||||
|
||||
/**
|
||||
* 单位数量
|
||||
*/
|
||||
private Integer unitCount;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 新工资看板卡片指标VO
|
||||
*/
|
||||
@Data
|
||||
public class NewCardMetricsVo {
|
||||
/**
|
||||
* 总实发工资
|
||||
*/
|
||||
private BigDecimal totalNetSalary;
|
||||
|
||||
/**
|
||||
* 总应发工资
|
||||
*/
|
||||
private BigDecimal totalGrossSalary;
|
||||
|
||||
/**
|
||||
* 单位总支出
|
||||
*/
|
||||
private BigDecimal totalUnitExpense;
|
||||
|
||||
/**
|
||||
* 员工数量
|
||||
*/
|
||||
private Integer employeeCount;
|
||||
|
||||
/**
|
||||
* 单位数量
|
||||
*/
|
||||
private Integer unitCount;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 新工资看板图表数据VO
|
||||
*/
|
||||
@Data
|
||||
public class NewChartDataVo {
|
||||
/**
|
||||
* 月度支出数据(柱状图)
|
||||
*/
|
||||
private List<MonthlyExpenseVo> monthlyExpenses;
|
||||
|
||||
/**
|
||||
* 工资构成分析(饼图)
|
||||
*/
|
||||
private List<SalaryStructureVo> salaryStructures;
|
||||
|
||||
/**
|
||||
* 趋势分析(折线图)
|
||||
*/
|
||||
private SalaryTrendVo trendData;
|
||||
|
||||
/**
|
||||
* 社保公积金统计(柱状图)
|
||||
*/
|
||||
private List<InsuranceStatVo> insuranceStats;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 新工资数据看板VO
|
||||
*/
|
||||
@Data
|
||||
public class NewSalaryDashboardVo {
|
||||
/**
|
||||
* 卡片数据
|
||||
*/
|
||||
private NewCardDataVo cardData;
|
||||
|
||||
/**
|
||||
* 图表数据
|
||||
*/
|
||||
private NewChartDataVo chartData;
|
||||
|
||||
/**
|
||||
* 单位统计表格数据
|
||||
*/
|
||||
private TableDataInfo<UnitStatVo> unitStats;
|
||||
|
||||
/**
|
||||
* 部门统计表格数据
|
||||
*/
|
||||
private TableDataInfo<DeptSalaryStatVo> deptStats;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 工资构成VO
|
||||
*/
|
||||
@Data
|
||||
public class SalaryStructureVo {
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String itemName;
|
||||
|
||||
/**
|
||||
* 总金额
|
||||
*/
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/**
|
||||
* 占比
|
||||
*/
|
||||
private BigDecimal percentage;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 工资趋势点VO
|
||||
*/
|
||||
@Data
|
||||
public class SalaryTrendPointVo {
|
||||
/**
|
||||
* 月份
|
||||
*/
|
||||
private Integer month;
|
||||
|
||||
/**
|
||||
* 总实发工资
|
||||
*/
|
||||
private BigDecimal totalNetSalary;
|
||||
|
||||
/**
|
||||
* 总应发工资
|
||||
*/
|
||||
private BigDecimal totalGrossSalary;
|
||||
|
||||
/**
|
||||
* 人均实发工资
|
||||
*/
|
||||
private BigDecimal avgNetSalary;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 工资趋势VO
|
||||
*/
|
||||
@Data
|
||||
public class SalaryTrendVo {
|
||||
/**
|
||||
* 月份列表
|
||||
*/
|
||||
private List<Integer> months;
|
||||
|
||||
/**
|
||||
* 实发工资趋势
|
||||
*/
|
||||
private List<BigDecimal> netSalaryTrend;
|
||||
|
||||
/**
|
||||
* 应发工资趋势
|
||||
*/
|
||||
private List<BigDecimal> grossSalaryTrend;
|
||||
|
||||
/**
|
||||
* 人均实发工资趋势
|
||||
*/
|
||||
private List<BigDecimal> avgNetSalaryTrend;
|
||||
|
||||
public SalaryTrendVo(List<SalaryTrendPointVo> points) {
|
||||
this.months = new ArrayList<>();
|
||||
this.netSalaryTrend = new ArrayList<>();
|
||||
this.grossSalaryTrend = new ArrayList<>();
|
||||
this.avgNetSalaryTrend = new ArrayList<>();
|
||||
|
||||
for (SalaryTrendPointVo point : points) {
|
||||
this.months.add(point.getMonth());
|
||||
this.netSalaryTrend.add(point.getTotalNetSalary());
|
||||
this.grossSalaryTrend.add(point.getTotalGrossSalary());
|
||||
this.avgNetSalaryTrend.add(point.getAvgNetSalary());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.ruoyi.oa.domain.vo.dashboard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 单位统计VO
|
||||
*/
|
||||
@Data
|
||||
public class UnitStatVo {
|
||||
/**
|
||||
* 单位名称
|
||||
*/
|
||||
private String unitName;
|
||||
|
||||
/**
|
||||
* 员工数量
|
||||
*/
|
||||
private Integer employeeCount;
|
||||
|
||||
/**
|
||||
* 总实发工资
|
||||
*/
|
||||
private BigDecimal totalNetSalary;
|
||||
|
||||
/**
|
||||
* 总应发工资
|
||||
*/
|
||||
private BigDecimal totalGrossSalary;
|
||||
|
||||
/**
|
||||
* 单位总支出
|
||||
*/
|
||||
private BigDecimal totalUnitExpense;
|
||||
|
||||
/**
|
||||
* 人均实发工资
|
||||
*/
|
||||
private BigDecimal avgNetSalary;
|
||||
|
||||
/**
|
||||
* 同比增长率
|
||||
*/
|
||||
private BigDecimal yearOnYearGrowthRate;
|
||||
|
||||
/**
|
||||
* 工资期间
|
||||
*/
|
||||
private String salaryPeriod;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.oa.mapper;
|
||||
|
||||
import com.ruoyi.oa.domain.vo.*;
|
||||
import com.ruoyi.oa.domain.vo.dashboard.*;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@@ -18,4 +19,59 @@ public interface SalaryDashboardMapper {
|
||||
List<LineChartPointVo> queryLineChartData(@Param("year") Long year);
|
||||
|
||||
List<DepartmentStatVo> queryDepartmentStats(@Param("year") Long year, @Param("month") Long month);
|
||||
/**
|
||||
* 查询卡片指标数据
|
||||
*
|
||||
* @param salaryPeriod 工资期间
|
||||
* @return 卡片指标数据
|
||||
*/
|
||||
NewCardMetricsVo queryNewCardMetrics(@Param("salaryPeriod") String salaryPeriod);
|
||||
|
||||
/**
|
||||
* 查询月度支出数据
|
||||
*
|
||||
* @param year 年份
|
||||
* @return 月度支出列表
|
||||
*/
|
||||
List<MonthlyExpenseVo> queryMonthlyExpenses(@Param("year") Integer year);
|
||||
|
||||
/**
|
||||
* 查询工资构成数据
|
||||
*
|
||||
* @param salaryPeriod 工资期间
|
||||
* @return 工资构成列表
|
||||
*/
|
||||
List<SalaryStructureVo> querySalaryStructures(@Param("salaryPeriod") String salaryPeriod);
|
||||
|
||||
/**
|
||||
* 查询工资趋势数据
|
||||
*
|
||||
* @param year 年份
|
||||
* @return 工资趋势点列表
|
||||
*/
|
||||
List<SalaryTrendPointVo> querySalaryTrendData(@Param("year") Integer year);
|
||||
|
||||
/**
|
||||
* 查询社保公积金统计数据
|
||||
*
|
||||
* @param salaryPeriod 工资期间
|
||||
* @return 社保公积金统计列表
|
||||
*/
|
||||
List<InsuranceStatVo> queryInsuranceStats(@Param("salaryPeriod") String salaryPeriod);
|
||||
|
||||
/**
|
||||
* 查询单位统计数据
|
||||
*
|
||||
* @param salaryPeriod 工资期间
|
||||
* @return 单位统计列表
|
||||
*/
|
||||
List<UnitStatVo> queryUnitStats(@Param("salaryPeriod") String salaryPeriod);
|
||||
|
||||
/**
|
||||
* 查询部门统计数据
|
||||
*
|
||||
* @param salaryPeriod 工资期间
|
||||
* @return 部门统计列表
|
||||
*/
|
||||
List<DeptSalaryStatVo> queryDeptSalaryStats(@Param("salaryPeriod") String salaryPeriod);
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
package com.ruoyi.oa.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.oa.domain.vo.SalaryDashboardVo;
|
||||
import com.ruoyi.oa.domain.vo.dashboard.NewSalaryDashboardVo;
|
||||
|
||||
public interface ISalaryDashboardService {
|
||||
SalaryDashboardVo getDashboardData(Long payYear, Long payMonth);
|
||||
/**
|
||||
* 获取新工资数据看板数据
|
||||
*
|
||||
* @param salaryPeriod 工资期间,格式如:2023-08
|
||||
* @return 数据看板VO
|
||||
*/
|
||||
NewSalaryDashboardVo getNewDashboardData(String salaryPeriod);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.oa.service.impl;
|
||||
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.oa.domain.vo.*;
|
||||
import com.ruoyi.oa.domain.vo.dashboard.*;
|
||||
import com.ruoyi.oa.mapper.SalaryDashboardMapper;
|
||||
import com.ruoyi.oa.service.ISalaryDashboardService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -154,4 +155,210 @@ public class SalaryDashboardServiceImpl implements ISalaryDashboardService {
|
||||
|
||||
return chartData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NewSalaryDashboardVo getNewDashboardData(String salaryPeriod) {
|
||||
NewSalaryDashboardVo dashboardVo = new NewSalaryDashboardVo();
|
||||
|
||||
// 1. 获取卡片数据
|
||||
dashboardVo.setCardData(getNewCardData(salaryPeriod));
|
||||
|
||||
// 2. 获取图表数据
|
||||
String[] periodParts = salaryPeriod.split("-");
|
||||
Integer year = Integer.valueOf(periodParts[0]);
|
||||
dashboardVo.setChartData(getNewChartData(salaryPeriod, year));
|
||||
|
||||
// 3. 获取单位统计表格数据
|
||||
List<UnitStatVo> unitStats = dashboardMapper.queryUnitStats(salaryPeriod);
|
||||
TableDataInfo<UnitStatVo> unitTableData = new TableDataInfo<>(unitStats, unitStats.size());
|
||||
dashboardVo.setUnitStats(unitTableData);
|
||||
|
||||
// 4. 获取部门统计表格数据
|
||||
List<DeptSalaryStatVo> deptStats = dashboardMapper.queryDeptSalaryStats(salaryPeriod);
|
||||
TableDataInfo<DeptSalaryStatVo> deptTableData = new TableDataInfo<>(deptStats, deptStats.size());
|
||||
dashboardVo.setDeptStats(deptTableData);
|
||||
|
||||
return dashboardVo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取新卡片数据
|
||||
*/
|
||||
private NewCardDataVo getNewCardData(String salaryPeriod) {
|
||||
NewCardDataVo cardData = new NewCardDataVo();
|
||||
|
||||
// 初始化所有数值为0,避免NPE
|
||||
cardData.setTotalNetSalary(BigDecimal.ZERO);
|
||||
cardData.setLastMonthNetSalaryRate(BigDecimal.ZERO);
|
||||
cardData.setTotalGrossSalary(BigDecimal.ZERO);
|
||||
cardData.setLastMonthGrossSalaryRate(BigDecimal.ZERO);
|
||||
cardData.setTotalUnitExpense(BigDecimal.ZERO);
|
||||
cardData.setLastMonthUnitExpenseRate(BigDecimal.ZERO);
|
||||
cardData.setAvgNetSalary(BigDecimal.ZERO);
|
||||
cardData.setLastMonthAvgNetSalaryRate(BigDecimal.ZERO);
|
||||
cardData.setYearOnYearGrowthRate(BigDecimal.ZERO);
|
||||
cardData.setTotalEmployeeCount(0);
|
||||
cardData.setUnitCount(0);
|
||||
|
||||
// 获取当月数据
|
||||
NewCardMetricsVo currentMonthMetrics = dashboardMapper.queryNewCardMetrics(salaryPeriod);
|
||||
if (currentMonthMetrics == null) {
|
||||
return cardData; // 如果当月没有数据,直接返回零值
|
||||
}
|
||||
|
||||
// 设置当月数据
|
||||
cardData.setTotalNetSalary(currentMonthMetrics.getTotalNetSalary() != null ?
|
||||
currentMonthMetrics.getTotalNetSalary() : BigDecimal.ZERO);
|
||||
cardData.setTotalGrossSalary(currentMonthMetrics.getTotalGrossSalary() != null ?
|
||||
currentMonthMetrics.getTotalGrossSalary() : BigDecimal.ZERO);
|
||||
cardData.setTotalUnitExpense(currentMonthMetrics.getTotalUnitExpense() != null ?
|
||||
currentMonthMetrics.getTotalUnitExpense() : BigDecimal.ZERO);
|
||||
cardData.setTotalEmployeeCount(currentMonthMetrics.getEmployeeCount() != null ?
|
||||
currentMonthMetrics.getEmployeeCount() : 0);
|
||||
cardData.setUnitCount(currentMonthMetrics.getUnitCount() != null ?
|
||||
currentMonthMetrics.getUnitCount() : 0);
|
||||
|
||||
// 计算人均实发工资
|
||||
if (currentMonthMetrics.getEmployeeCount() != null &&
|
||||
currentMonthMetrics.getEmployeeCount() > 0 &&
|
||||
currentMonthMetrics.getTotalNetSalary() != null) {
|
||||
try {
|
||||
BigDecimal avgNetSalary = currentMonthMetrics.getTotalNetSalary()
|
||||
.divide(new BigDecimal(currentMonthMetrics.getEmployeeCount()), 2, RoundingMode.HALF_UP);
|
||||
cardData.setAvgNetSalary(avgNetSalary);
|
||||
} catch (Exception e) {
|
||||
cardData.setAvgNetSalary(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
// 计算上月对比数据
|
||||
String lastMonthPeriod = getLastMonthPeriod(salaryPeriod);
|
||||
NewCardMetricsVo lastMonthMetrics = dashboardMapper.queryNewCardMetrics(lastMonthPeriod);
|
||||
|
||||
if (lastMonthMetrics != null) {
|
||||
// 计算实发工资增长率
|
||||
if (lastMonthMetrics.getTotalNetSalary() != null &&
|
||||
lastMonthMetrics.getTotalNetSalary().compareTo(BigDecimal.ZERO) != 0) {
|
||||
try {
|
||||
BigDecimal netSalaryGrowth = currentMonthMetrics.getTotalNetSalary()
|
||||
.subtract(lastMonthMetrics.getTotalNetSalary())
|
||||
.divide(lastMonthMetrics.getTotalNetSalary(), 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"));
|
||||
cardData.setLastMonthNetSalaryRate(netSalaryGrowth);
|
||||
} catch (Exception e) {
|
||||
cardData.setLastMonthNetSalaryRate(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
// 计算应发工资增长率
|
||||
if (lastMonthMetrics.getTotalGrossSalary() != null &&
|
||||
lastMonthMetrics.getTotalGrossSalary().compareTo(BigDecimal.ZERO) != 0) {
|
||||
try {
|
||||
BigDecimal grossSalaryGrowth = currentMonthMetrics.getTotalGrossSalary()
|
||||
.subtract(lastMonthMetrics.getTotalGrossSalary())
|
||||
.divide(lastMonthMetrics.getTotalGrossSalary(), 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"));
|
||||
cardData.setLastMonthGrossSalaryRate(grossSalaryGrowth);
|
||||
} catch (Exception e) {
|
||||
cardData.setLastMonthGrossSalaryRate(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
// 计算单位总支出增长率
|
||||
if (lastMonthMetrics.getTotalUnitExpense() != null &&
|
||||
lastMonthMetrics.getTotalUnitExpense().compareTo(BigDecimal.ZERO) != 0) {
|
||||
try {
|
||||
BigDecimal unitExpenseGrowth = currentMonthMetrics.getTotalUnitExpense()
|
||||
.subtract(lastMonthMetrics.getTotalUnitExpense())
|
||||
.divide(lastMonthMetrics.getTotalUnitExpense(), 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"));
|
||||
cardData.setLastMonthUnitExpenseRate(unitExpenseGrowth);
|
||||
} catch (Exception e) {
|
||||
cardData.setLastMonthUnitExpenseRate(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算同比增长率(与去年同期相比)
|
||||
String lastYearPeriod = getLastYearPeriod(salaryPeriod);
|
||||
NewCardMetricsVo lastYearMetrics = dashboardMapper.queryNewCardMetrics(lastYearPeriod);
|
||||
|
||||
if (lastYearMetrics != null &&
|
||||
lastYearMetrics.getEmployeeCount() != null &&
|
||||
lastYearMetrics.getEmployeeCount() > 0 &&
|
||||
lastYearMetrics.getTotalNetSalary() != null) {
|
||||
try {
|
||||
BigDecimal lastYearAvgSalary = lastYearMetrics.getTotalNetSalary()
|
||||
.divide(new BigDecimal(lastYearMetrics.getEmployeeCount()), 2, RoundingMode.HALF_UP);
|
||||
if (lastYearAvgSalary.compareTo(BigDecimal.ZERO) != 0 &&
|
||||
cardData.getAvgNetSalary() != null) {
|
||||
BigDecimal yearGrowth = cardData.getAvgNetSalary()
|
||||
.subtract(lastYearAvgSalary)
|
||||
.divide(lastYearAvgSalary, 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"));
|
||||
cardData.setYearOnYearGrowthRate(yearGrowth);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
cardData.setYearOnYearGrowthRate(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
return cardData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取新图表数据
|
||||
*/
|
||||
private NewChartDataVo getNewChartData(String salaryPeriod, Integer year) {
|
||||
NewChartDataVo chartData = new NewChartDataVo();
|
||||
|
||||
// 1. 获取月度支出数据
|
||||
List<MonthlyExpenseVo> monthlyExpenses = dashboardMapper.queryMonthlyExpenses(year);
|
||||
chartData.setMonthlyExpenses(monthlyExpenses != null ? monthlyExpenses : new ArrayList<>());
|
||||
|
||||
// 2. 获取工资构成数据
|
||||
List<SalaryStructureVo> salaryStructures = dashboardMapper.querySalaryStructures(salaryPeriod);
|
||||
chartData.setSalaryStructures(salaryStructures != null ? salaryStructures : new ArrayList<>());
|
||||
|
||||
// 3. 获取趋势数据
|
||||
List<SalaryTrendPointVo> trendData = dashboardMapper.querySalaryTrendData(year);
|
||||
chartData.setTrendData(new SalaryTrendVo(trendData != null ? trendData : new ArrayList<>()));
|
||||
|
||||
// 4. 获取社保公积金统计数据
|
||||
List<InsuranceStatVo> insuranceStats = dashboardMapper.queryInsuranceStats(salaryPeriod);
|
||||
chartData.setInsuranceStats(insuranceStats != null ? insuranceStats : new ArrayList<>());
|
||||
|
||||
return chartData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上月期间
|
||||
*/
|
||||
private String getLastMonthPeriod(String salaryPeriod) {
|
||||
String[] parts = salaryPeriod.split("-");
|
||||
int year = Integer.parseInt(parts[0]);
|
||||
int month = Integer.parseInt(parts[1]);
|
||||
|
||||
if (month == 1) {
|
||||
year--;
|
||||
month = 12;
|
||||
} else {
|
||||
month--;
|
||||
}
|
||||
|
||||
return String.format("%d-%02d", year, month);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取去年同期
|
||||
*/
|
||||
private String getLastYearPeriod(String salaryPeriod) {
|
||||
String[] parts = salaryPeriod.split("-");
|
||||
int year = Integer.parseInt(parts[0]) - 1;
|
||||
int month = Integer.parseInt(parts[1]);
|
||||
|
||||
return String.format("%d-%02d", year, month);
|
||||
}
|
||||
}
|
||||
@@ -140,4 +140,277 @@
|
||||
ORDER BY
|
||||
totalExpenditure DESC
|
||||
</select>
|
||||
<!-- 查询卡片指标数据 -->
|
||||
<select id="queryNewCardMetrics" resultType="com.ruoyi.oa.domain.vo.dashboard.NewCardMetricsVo">
|
||||
SELECT
|
||||
COALESCE(SUM(d.net_salary), 0) as totalNetSalary,
|
||||
COALESCE(SUM(d.gross_salary), 0) as totalGrossSalary,
|
||||
COALESCE(SUM(d.unit_total_expense), 0) as totalUnitExpense,
|
||||
COUNT(DISTINCT d.detail_id) as employeeCount,
|
||||
COUNT(DISTINCT m.unit_name) as unitCount
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0
|
||||
AND d.del_flag = 0
|
||||
</select>
|
||||
|
||||
<!-- 查询月度支出数据 -->
|
||||
<select id="queryMonthlyExpenses" resultType="com.ruoyi.oa.domain.vo.dashboard.MonthlyExpenseVo">
|
||||
SELECT
|
||||
CAST(SUBSTRING(m.salary_period, 6, 2) AS UNSIGNED) as month,
|
||||
COALESCE(SUM(d.net_salary), 0) as totalNetSalary,
|
||||
COALESCE(SUM(d.gross_salary), 0) as totalGrossSalary,
|
||||
COALESCE(SUM(d.unit_total_expense), 0) as totalUnitExpense
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE SUBSTRING(m.salary_period, 1, 4) = #{year}
|
||||
AND m.del_flag = 0
|
||||
AND d.del_flag = 0
|
||||
GROUP BY CAST(SUBSTRING(m.salary_period, 6, 2) AS UNSIGNED)
|
||||
ORDER BY month
|
||||
</select>
|
||||
|
||||
<!-- 查询工资构成数据 -->
|
||||
<select id="querySalaryStructures" resultType="com.ruoyi.oa.domain.vo.dashboard.SalaryStructureVo">
|
||||
SELECT
|
||||
'基本工资' as itemName,
|
||||
COALESCE(SUM(d.basic_salary), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.basic_salary) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'岗位工资' as itemName,
|
||||
COALESCE(SUM(d.post_salary), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.post_salary) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'餐补' as itemName,
|
||||
COALESCE(SUM(d.meal_allowance), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.meal_allowance) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'住房补贴' as itemName,
|
||||
COALESCE(SUM(d.housing_allowance), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.housing_allowance) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'公交补贴' as itemName,
|
||||
COALESCE(SUM(d.bus_allowance), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.bus_allowance) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'出差补助' as itemName,
|
||||
COALESCE(SUM(d.business_allowance), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.business_allowance) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'加班工资' as itemName,
|
||||
COALESCE(SUM(d.overtime_total), 0) as totalAmount,
|
||||
CASE
|
||||
WHEN SUM(d.gross_salary) > 0 THEN ROUND((SUM(d.overtime_total) / SUM(d.gross_salary)) * 100, 2)
|
||||
ELSE 0
|
||||
END as percentage
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
ORDER BY totalAmount DESC
|
||||
</select>
|
||||
|
||||
<!-- 查询工资趋势数据 -->
|
||||
<select id="querySalaryTrendData" resultType="com.ruoyi.oa.domain.vo.dashboard.SalaryTrendPointVo">
|
||||
SELECT
|
||||
CAST(SUBSTRING(m.salary_period, 6, 2) AS UNSIGNED) as month,
|
||||
COALESCE(SUM(d.net_salary), 0) as totalNetSalary,
|
||||
COALESCE(SUM(d.gross_salary), 0) as totalGrossSalary,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT d.detail_id) > 0 THEN ROUND(SUM(d.net_salary) / COUNT(DISTINCT d.detail_id), 2)
|
||||
ELSE 0
|
||||
END as avgNetSalary
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE SUBSTRING(m.salary_period, 1, 4) = #{year}
|
||||
AND m.del_flag = 0
|
||||
AND d.del_flag = 0
|
||||
GROUP BY CAST(SUBSTRING(m.salary_period, 6, 2) AS UNSIGNED)
|
||||
ORDER BY month
|
||||
</select>
|
||||
|
||||
<!-- 查询社保公积金统计数据 -->
|
||||
<select id="queryInsuranceStats" resultType="com.ruoyi.oa.domain.vo.dashboard.InsuranceStatVo">
|
||||
SELECT
|
||||
'养老保险' as itemName,
|
||||
COALESCE(SUM(d.personal_pension), 0) as personalTotal,
|
||||
COALESCE(SUM(d.enterprise_pension), 0) as enterpriseTotal,
|
||||
COALESCE(SUM(d.personal_pension) + SUM(d.enterprise_pension), 0) as total
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'医疗保险' as itemName,
|
||||
COALESCE(SUM(d.personal_medical), 0) as personalTotal,
|
||||
COALESCE(SUM(d.enterprise_medical), 0) as enterpriseTotal,
|
||||
COALESCE(SUM(d.personal_medical) + SUM(d.enterprise_medical), 0) as total
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'失业保险' as itemName,
|
||||
COALESCE(SUM(d.personal_unemployment), 0) as personalTotal,
|
||||
COALESCE(SUM(d.enterprise_unemployment), 0) as enterpriseTotal,
|
||||
COALESCE(SUM(d.personal_unemployment) + SUM(d.enterprise_unemployment), 0) as total
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'住房公积金' as itemName,
|
||||
COALESCE(SUM(d.personal_housing_fund), 0) as personalTotal,
|
||||
COALESCE(SUM(d.enterprise_housing_fund), 0) as enterpriseTotal,
|
||||
COALESCE(SUM(d.personal_housing_fund) + SUM(d.enterprise_housing_fund), 0) as total
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'工伤保险' as itemName,
|
||||
0 as personalTotal,
|
||||
COALESCE(SUM(d.enterprise_injury), 0) as enterpriseTotal,
|
||||
COALESCE(SUM(d.enterprise_injury), 0) as total
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'生育保险' as itemName,
|
||||
0 as personalTotal,
|
||||
COALESCE(SUM(d.enterprise_maternity), 0) as enterpriseTotal,
|
||||
COALESCE(SUM(d.enterprise_maternity), 0) as total
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0 AND d.del_flag = 0
|
||||
|
||||
ORDER BY total DESC
|
||||
</select>
|
||||
|
||||
<!-- 查询单位统计数据 -->
|
||||
<select id="queryUnitStats" resultType="com.ruoyi.oa.domain.vo.dashboard.UnitStatVo">
|
||||
SELECT
|
||||
m.unit_name as unitName,
|
||||
COUNT(DISTINCT d.detail_id) as employeeCount,
|
||||
COALESCE(SUM(d.net_salary), 0) as totalNetSalary,
|
||||
COALESCE(SUM(d.gross_salary), 0) as totalGrossSalary,
|
||||
COALESCE(SUM(d.unit_total_expense), 0) as totalUnitExpense,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT d.detail_id) > 0 THEN ROUND(SUM(d.net_salary) / COUNT(DISTINCT d.detail_id), 2)
|
||||
ELSE 0
|
||||
END as avgNetSalary,
|
||||
m.salary_period as salaryPeriod,
|
||||
0 as yearOnYearGrowthRate
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0
|
||||
AND d.del_flag = 0
|
||||
GROUP BY m.unit_name, m.salary_period
|
||||
ORDER BY totalNetSalary DESC
|
||||
</select>
|
||||
|
||||
<!-- 查询部门统计数据 -->
|
||||
<select id="queryDeptSalaryStats" resultType="com.ruoyi.oa.domain.vo.dashboard.DeptSalaryStatVo">
|
||||
SELECT
|
||||
COALESCE(d.dept, '未分配部门') as deptName,
|
||||
COUNT(DISTINCT d.detail_id) as employeeCount,
|
||||
COALESCE(SUM(d.net_salary), 0) as totalNetSalary,
|
||||
COALESCE(SUM(d.gross_salary), 0) as totalGrossSalary,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT d.detail_id) > 0 THEN ROUND(SUM(d.net_salary) / COUNT(DISTINCT d.detail_id), 2)
|
||||
ELSE 0
|
||||
END as avgNetSalary,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT d.detail_id) > 0 THEN ROUND(SUM(d.gross_salary) / COUNT(DISTINCT d.detail_id), 2)
|
||||
ELSE 0
|
||||
END as avgGrossSalary,
|
||||
0 as yearOnYearGrowthRate
|
||||
FROM oa_salary_master m
|
||||
LEFT JOIN oa_salary_detail d ON m.master_id = d.main_id
|
||||
WHERE m.salary_period = #{salaryPeriod}
|
||||
AND m.del_flag = 0
|
||||
AND d.del_flag = 0
|
||||
GROUP BY d.dept
|
||||
ORDER BY totalNetSalary DESC
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user