feat(hrm): 添加请假统计功能
- 在控制器中新增 /stats 接口用于获取请假统计数据 - 新增 HrmLeaveStatsVo 数据传输对象定义统计结构 - 在数据访问层添加多个统计查询方法,包括按类型、部门、月份统计 - 实现服务层统计业务逻辑,包括请假汇总、分类统计、员工状态统计 - 配置 MyBatis 映射文件实现各维度统计 SQL 查询 - 添加员工总数和请假中员工数的统计功能
This commit is contained in:
@@ -9,6 +9,7 @@ import com.ruoyi.common.enums.BusinessType;
|
|||||||
import com.ruoyi.hrm.domain.HrmLeaveReq;
|
import com.ruoyi.hrm.domain.HrmLeaveReq;
|
||||||
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
||||||
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
||||||
|
import com.ruoyi.hrm.domain.vo.HrmLeaveStatsVo;
|
||||||
import com.ruoyi.hrm.service.IHrmLeaveReqService;
|
import com.ruoyi.hrm.service.IHrmLeaveReqService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -59,4 +60,9 @@ public class HrmLeaveReqController extends BaseController {
|
|||||||
public R<List<HrmLeaveReqVo>> all(HrmLeaveReqBo bo) {
|
public R<List<HrmLeaveReqVo>> all(HrmLeaveReqBo bo) {
|
||||||
return R.ok(service.queryList(bo));
|
return R.ok(service.queryList(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/stats")
|
||||||
|
public R<HrmLeaveStatsVo> stats() {
|
||||||
|
return R.ok(service.getLeaveStats());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.ruoyi.hrm.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class HrmLeaveStatsVo implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总请假申请数
|
||||||
|
*/
|
||||||
|
private Integer totalLeaveRequests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总请假时长(小时)
|
||||||
|
*/
|
||||||
|
private BigDecimal totalLeaveHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按请假类型统计
|
||||||
|
*/
|
||||||
|
private List<LeaveTypeStats> leaveByType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按部门统计
|
||||||
|
*/
|
||||||
|
private List<DeptStats> leaveByDept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按月份统计(本年)
|
||||||
|
*/
|
||||||
|
private List<MonthStats> leaveByMonth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总员工数
|
||||||
|
*/
|
||||||
|
private Integer totalEmployees;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请假中员工数
|
||||||
|
*/
|
||||||
|
private Integer leavingEmployees;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class LeaveTypeStats {
|
||||||
|
private String leaveType;
|
||||||
|
private Integer count;
|
||||||
|
private BigDecimal totalHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class DeptStats {
|
||||||
|
private Long deptId;
|
||||||
|
private String deptName;
|
||||||
|
private Integer count;
|
||||||
|
private BigDecimal totalHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class MonthStats {
|
||||||
|
private String month; // YYYY-MM
|
||||||
|
private Integer count;
|
||||||
|
private BigDecimal totalHours;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,13 @@ import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
|||||||
import com.ruoyi.hrm.domain.HrmLeaveReq;
|
import com.ruoyi.hrm.domain.HrmLeaveReq;
|
||||||
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
||||||
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
||||||
|
import com.ruoyi.hrm.domain.vo.HrmLeaveStatsVo;
|
||||||
|
import org.apache.ibatis.annotations.MapKey;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.session.RowBounds;
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface HrmLeaveReqMapper extends BaseMapperPlus<HrmLeaveReqMapper, HrmLeaveReq, HrmLeaveReqVo> {
|
public interface HrmLeaveReqMapper extends BaseMapperPlus<HrmLeaveReqMapper, HrmLeaveReq, HrmLeaveReqVo> {
|
||||||
|
|
||||||
@@ -17,4 +20,17 @@ public interface HrmLeaveReqMapper extends BaseMapperPlus<HrmLeaveReqMapper, Hrm
|
|||||||
List<HrmLeaveReqVo> selectVoWithProjectByPage(IPage<HrmLeaveReqVo> page, @Param("bo") HrmLeaveReqBo bo);
|
List<HrmLeaveReqVo> selectVoWithProjectByPage(IPage<HrmLeaveReqVo> page, @Param("bo") HrmLeaveReqBo bo);
|
||||||
|
|
||||||
List<HrmLeaveReqVo> selectVoWithProjectList(@Param("bo") HrmLeaveReqBo bo);
|
List<HrmLeaveReqVo> selectVoWithProjectList(@Param("bo") HrmLeaveReqBo bo);
|
||||||
|
|
||||||
|
// 统计相关方法
|
||||||
|
Map<String, Object> selectLeaveSummary();
|
||||||
|
|
||||||
|
List<Map<String, Object>> selectLeaveByType();
|
||||||
|
|
||||||
|
List<Map<String, Object>> selectLeaveByDept();
|
||||||
|
|
||||||
|
List<Map<String, Object>> selectLeaveByMonth(@Param("year") Integer year);
|
||||||
|
|
||||||
|
Integer selectTotalEmployees();
|
||||||
|
|
||||||
|
Integer selectLeavingEmployees();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
|
|||||||
import com.ruoyi.hrm.domain.HrmLeaveReq;
|
import com.ruoyi.hrm.domain.HrmLeaveReq;
|
||||||
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
||||||
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
||||||
|
import com.ruoyi.hrm.domain.vo.HrmLeaveStatsVo;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -24,4 +25,7 @@ public interface IHrmLeaveReqService {
|
|||||||
Boolean updateByBo(HrmLeaveReqBo bo);
|
Boolean updateByBo(HrmLeaveReqBo bo);
|
||||||
|
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
// 统计方法
|
||||||
|
HrmLeaveStatsVo getLeaveStats();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ import com.ruoyi.hrm.domain.HrmLeaveReq;
|
|||||||
import com.ruoyi.hrm.domain.bo.HrmFlowStartBo;
|
import com.ruoyi.hrm.domain.bo.HrmFlowStartBo;
|
||||||
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
import com.ruoyi.hrm.domain.bo.HrmLeaveReqBo;
|
||||||
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
import com.ruoyi.hrm.domain.vo.HrmLeaveReqVo;
|
||||||
|
import com.ruoyi.hrm.domain.vo.HrmLeaveStatsVo;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import com.ruoyi.hrm.mapper.HrmFlowTemplateMapper;
|
import com.ruoyi.hrm.mapper.HrmFlowTemplateMapper;
|
||||||
import com.ruoyi.hrm.mapper.HrmLeaveReqMapper;
|
import com.ruoyi.hrm.mapper.HrmLeaveReqMapper;
|
||||||
import com.ruoyi.hrm.service.IHrmFlowInstanceService;
|
import com.ruoyi.hrm.service.IHrmFlowInstanceService;
|
||||||
@@ -117,6 +124,55 @@ public class HrmLeaveReqServiceImpl implements IHrmLeaveReqService {
|
|||||||
return baseMapper.deleteBatchIds(ids) > 0;
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HrmLeaveStatsVo getLeaveStats() {
|
||||||
|
HrmLeaveStatsVo stats = new HrmLeaveStatsVo();
|
||||||
|
|
||||||
|
// 获取汇总数据
|
||||||
|
Map<String, Object> summary = baseMapper.selectLeaveSummary();
|
||||||
|
stats.setTotalLeaveRequests(((Long) summary.get("totalRequests")).intValue());
|
||||||
|
stats.setTotalLeaveHours((BigDecimal) summary.get("totalHours"));
|
||||||
|
|
||||||
|
// 按类型统计
|
||||||
|
List<Map<String, Object>> leaveByType = baseMapper.selectLeaveByType();
|
||||||
|
stats.setLeaveByType(leaveByType.stream().map(map -> {
|
||||||
|
HrmLeaveStatsVo.LeaveTypeStats s = new HrmLeaveStatsVo.LeaveTypeStats();
|
||||||
|
s.setLeaveType((String) map.get("leaveType"));
|
||||||
|
s.setCount(((Long) map.get("count")).intValue());
|
||||||
|
s.setTotalHours((BigDecimal) map.get("totalHours"));
|
||||||
|
return s;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
// 按部门统计
|
||||||
|
List<Map<String, Object>> leaveByDept = baseMapper.selectLeaveByDept();
|
||||||
|
stats.setLeaveByDept(leaveByDept.stream().map(map -> {
|
||||||
|
HrmLeaveStatsVo.DeptStats s = new HrmLeaveStatsVo.DeptStats();
|
||||||
|
s.setDeptName((String) map.get("deptName"));
|
||||||
|
s.setCount(((Long) map.get("count")).intValue());
|
||||||
|
s.setTotalHours((BigDecimal) map.get("totalHours"));
|
||||||
|
return s;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
// 按月份统计(当前年)
|
||||||
|
int currentYear = LocalDate.now().getYear();
|
||||||
|
List<Map<String, Object>> leaveByMonth = baseMapper.selectLeaveByMonth(currentYear);
|
||||||
|
stats.setLeaveByMonth(leaveByMonth.stream().map(map -> {
|
||||||
|
HrmLeaveStatsVo.MonthStats s = new HrmLeaveStatsVo.MonthStats();
|
||||||
|
s.setMonth((String) map.get("month"));
|
||||||
|
s.setCount(((Long) map.get("count")).intValue());
|
||||||
|
s.setTotalHours((BigDecimal) map.get("totalHours"));
|
||||||
|
return s;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
// 总员工数
|
||||||
|
stats.setTotalEmployees(baseMapper.selectTotalEmployees());
|
||||||
|
|
||||||
|
// 请假中员工数
|
||||||
|
stats.setLeavingEmployees(baseMapper.selectLeavingEmployees());
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
private LambdaQueryWrapper<HrmLeaveReq> buildQueryWrapper(HrmLeaveReqBo bo) {
|
private LambdaQueryWrapper<HrmLeaveReq> buildQueryWrapper(HrmLeaveReqBo bo) {
|
||||||
LambdaQueryWrapper<HrmLeaveReq> lqw = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<HrmLeaveReq> lqw = Wrappers.lambdaQuery();
|
||||||
lqw.eq(bo.getBizId() != null, HrmLeaveReq::getBizId, bo.getBizId());
|
lqw.eq(bo.getBizId() != null, HrmLeaveReq::getBizId, bo.getBizId());
|
||||||
|
|||||||
@@ -149,4 +149,64 @@
|
|||||||
</if>
|
</if>
|
||||||
ORDER BY l.create_time DESC
|
ORDER BY l.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
<!-- 统计查询 -->
|
||||||
|
<select id="selectLeaveSummary" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
COUNT(*) as totalRequests,
|
||||||
|
SUM(hours) as totalHours
|
||||||
|
FROM hrm_leave_req
|
||||||
|
WHERE del_flag = 0
|
||||||
|
AND status = 'approved'
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectLeaveByType" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
leave_type as leaveType,
|
||||||
|
COUNT(*) as count,
|
||||||
|
SUM(hours) as totalHours
|
||||||
|
FROM hrm_leave_req
|
||||||
|
WHERE del_flag = 0
|
||||||
|
AND status = 'approved'
|
||||||
|
GROUP BY leave_type
|
||||||
|
ORDER BY totalHours DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectLeaveByDept" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
d.dept_name as deptName,
|
||||||
|
COUNT(l.biz_id) as count,
|
||||||
|
SUM(l.hours) as totalHours
|
||||||
|
FROM hrm_leave_req l
|
||||||
|
JOIN hrm_employee e ON l.emp_id = e.emp_id AND e.del_flag = 0
|
||||||
|
LEFT JOIN sys_dept d ON e.dept_id = d.dept_id AND d.del_flag = '0'
|
||||||
|
WHERE l.del_flag = 0
|
||||||
|
AND l.status = 'approved'
|
||||||
|
GROUP BY d.dept_id, d.dept_name
|
||||||
|
ORDER BY totalHours DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectLeaveByMonth" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
DATE_FORMAT(start_time, '%Y-%m') as month,
|
||||||
|
COUNT(*) as count,
|
||||||
|
SUM(hours) as totalHours
|
||||||
|
FROM hrm_leave_req
|
||||||
|
WHERE del_flag = 0
|
||||||
|
AND status = 'approved'
|
||||||
|
AND YEAR(start_time) = #{year}
|
||||||
|
GROUP BY DATE_FORMAT(start_time, '%Y-%m')
|
||||||
|
ORDER BY month
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTotalEmployees" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*) FROM hrm_employee WHERE del_flag = 0 AND status = 'onboard'
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectLeavingEmployees" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(DISTINCT l.emp_id)
|
||||||
|
FROM hrm_leave_req l
|
||||||
|
WHERE l.del_flag = 0
|
||||||
|
AND l.status = 'approved'
|
||||||
|
AND NOW() BETWEEN l.start_time AND l.end_time
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user