薪资分析
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.oa.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.oa.domain.vo.SalaryDashboardVo;
|
||||
|
||||
public interface ISalaryDashboardService {
|
||||
SalaryDashboardVo getDashboardData(Long payYear, Long payMonth);
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.ruoyi.oa.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.oa.domain.bo.OaEmployeeBo;
|
||||
@@ -18,6 +21,8 @@ import com.ruoyi.oa.service.IOaEmployeeService;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 员工基础信息Service业务层处理
|
||||
@@ -30,6 +35,7 @@ import java.util.Collection;
|
||||
public class OaEmployeeServiceImpl implements IOaEmployeeService {
|
||||
|
||||
private final OaEmployeeMapper baseMapper;
|
||||
private final SysDeptMapper deptMapper;
|
||||
|
||||
/**
|
||||
* 查询员工基础信息
|
||||
@@ -46,6 +52,35 @@ public class OaEmployeeServiceImpl implements IOaEmployeeService {
|
||||
public TableDataInfo<OaEmployeeVo> queryPageList(OaEmployeeBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<OaEmployee> lqw = buildQueryWrapper(bo);
|
||||
Page<OaEmployeeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
// 根据部门id查询部门名称
|
||||
if (CollectionUtils.isNotEmpty(result.getRecords())) {
|
||||
// 提取所有部门ID
|
||||
List<Long> deptIds = result.getRecords().stream()
|
||||
.map(OaEmployeeVo::getDeptId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 批量查询部门信息
|
||||
if (!deptIds.isEmpty()) {
|
||||
LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.in(SysDept::getDeptId, deptIds)
|
||||
.eq(SysDept::getDelFlag, '0'); // 只查询未删除的部门
|
||||
|
||||
List<SysDept> deptList = deptMapper.selectList(queryWrapper);
|
||||
Map<Long, String> deptNameMap = deptList.stream()
|
||||
.collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName, (k1, k2) -> k1));
|
||||
|
||||
// 将部门名称设置到对应的VO对象中
|
||||
for (OaEmployeeVo vo : result.getRecords()) {
|
||||
if (vo.getDeptId() != null) {
|
||||
vo.setDeptName(deptNameMap.getOrDefault(vo.getDeptId(), "未知部门"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.ruoyi.oa.service.impl;
|
||||
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.oa.domain.vo.*;
|
||||
import com.ruoyi.oa.mapper.SalaryDashboardMapper;
|
||||
import com.ruoyi.oa.service.ISalaryDashboardService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class SalaryDashboardServiceImpl implements ISalaryDashboardService {
|
||||
|
||||
@Autowired
|
||||
private SalaryDashboardMapper dashboardMapper;
|
||||
|
||||
@Override
|
||||
public SalaryDashboardVo getDashboardData(Long payYear, Long payMonth) {
|
||||
SalaryDashboardVo dashboardVo = new SalaryDashboardVo();
|
||||
|
||||
// 1. 获取卡片数据
|
||||
dashboardVo.setCardData(getCardData(payYear, payMonth));
|
||||
|
||||
// 2. 获取图表数据
|
||||
dashboardVo.setChartData(getChartData(payYear, payMonth));
|
||||
|
||||
// 3. 获取部门统计表格数据 (带分页)
|
||||
// PageHelper.startPage(pageNum, pageSize);
|
||||
List<DepartmentStatVo> deptStats = dashboardMapper.queryDepartmentStats(payYear, payMonth);
|
||||
TableDataInfo<DepartmentStatVo> tableData = new TableDataInfo<>(deptStats, deptStats.size());
|
||||
dashboardVo.setDepartmentStats(tableData);
|
||||
return dashboardVo;
|
||||
}
|
||||
|
||||
private CardDataVo getCardData(Long payYear, Long payMonth) {
|
||||
CardDataVo cardData = new CardDataVo();
|
||||
|
||||
// 获取当月数据
|
||||
CardMetricsVo currentMonthMetrics = dashboardMapper.queryCardMetrics(payYear, payMonth);
|
||||
|
||||
// 获取上月数据 (处理1月的情况)
|
||||
Long lastMonth = payMonth == 1 ? 12 : payMonth - 1;
|
||||
Long lastYear = payMonth == 1 ? payYear - 1 : payYear;
|
||||
CardMetricsVo lastMonthMetrics = dashboardMapper.queryCardMetrics(lastYear, lastMonth);
|
||||
|
||||
// 获取去年同期数据
|
||||
CardMetricsVo lastYearMetrics = dashboardMapper.queryCardMetrics(payYear - 1, payMonth);
|
||||
|
||||
// 计算各项指标
|
||||
cardData.setTotalSalaryExpenditure(currentMonthMetrics.getTotalSalaryExpenditure());
|
||||
|
||||
// 计算较上月增长率
|
||||
if (lastMonthMetrics.getTotalSalaryExpenditure().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal monthGrowth = currentMonthMetrics.getTotalSalaryExpenditure()
|
||||
.subtract(lastMonthMetrics.getTotalSalaryExpenditure())
|
||||
.divide(lastMonthMetrics.getTotalSalaryExpenditure(), 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"));
|
||||
cardData.setLastMonthTotalSalaryExpenditureRate(monthGrowth);
|
||||
}
|
||||
|
||||
// 计算部门平均支出
|
||||
if (currentMonthMetrics.getDepartmentCount() > 0) {
|
||||
cardData.setAvgDepartmentExpenditure(
|
||||
currentMonthMetrics.getTotalCompanyExpenditure()
|
||||
.divide(new BigDecimal(currentMonthMetrics.getDepartmentCount()), 2, RoundingMode.HALF_UP)
|
||||
);
|
||||
}
|
||||
|
||||
// 计算人均实发工资
|
||||
if (currentMonthMetrics.getEmployeeCount() > 0) {
|
||||
cardData.setAvgPersonSalary(
|
||||
currentMonthMetrics.getTotalSalaryExpenditure()
|
||||
.divide(new BigDecimal(currentMonthMetrics.getEmployeeCount()), 2, RoundingMode.HALF_UP)
|
||||
);
|
||||
}
|
||||
|
||||
// 计算同比增长率
|
||||
if (lastYearMetrics.getEmployeeCount() > 0) {
|
||||
BigDecimal lastYearAvgSalary = lastYearMetrics.getTotalSalaryExpenditure()
|
||||
.divide(new BigDecimal(lastYearMetrics.getEmployeeCount()), 2, RoundingMode.HALF_UP);
|
||||
if (lastYearAvgSalary.compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal yearGrowth = cardData.getAvgPersonSalary()
|
||||
.subtract(lastYearAvgSalary)
|
||||
.divide(lastYearAvgSalary, 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"));
|
||||
cardData.setYearOnYearGrowthRate(yearGrowth);
|
||||
}
|
||||
}
|
||||
|
||||
return cardData;
|
||||
}
|
||||
|
||||
private ChartDataVo getChartData(Long payYear, Long payMonth) {
|
||||
ChartDataVo chartData = new ChartDataVo();
|
||||
|
||||
// 1. 获取柱状图数据 (年度每月总支出)
|
||||
List<MonthlyExpenditureVo> monthlyExpenditures =
|
||||
dashboardMapper.queryMonthlyExpenditures(payYear);
|
||||
chartData.setMonthlyExpenditures(monthlyExpenditures);
|
||||
|
||||
// 2. 获取饼图数据 (薪资构成)
|
||||
List<SalaryComponentVo> salaryComponents =
|
||||
dashboardMapper.querySalaryComponents(payYear, payMonth);
|
||||
chartData.setSalaryComponents(salaryComponents);
|
||||
|
||||
// 3. 获取折线图数据 (总支出 vs 平均工资)
|
||||
List<LineChartPointVo> lineChartData =
|
||||
dashboardMapper.queryLineChartData(payYear);
|
||||
chartData.setLineChartData(new LineChartVo(lineChartData));
|
||||
|
||||
return chartData;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user