feat(oa): 新增工资数据看板功能

- 添加新工资看板相关的 VO 类
- 实现新工资看板的数据获取接口和业务逻辑
- 优化原有工资看板的代码结构
- 新增月度支出、工资构成、趋势分析等图表数据查询- 增加社保公积金统计和单位、部门统计功能
This commit is contained in:
2025-09-08 15:33:33 +08:00
parent fdd7489102
commit 655540c20b
16 changed files with 993 additions and 3 deletions

View File

@@ -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);
}

View File

@@ -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);
}
}