liu
12 小时以前 fc61c0a691600205ef6e7d7b1182afa825b1d550
feat(hrm): 新增我的考勤状态接口
已修改3个文件
已添加1个文件
150 ■■■■■ 文件已修改
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRecordController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceMyStatusRespVO.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRecordService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRecordServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRecordController.java
@@ -7,6 +7,7 @@
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceMyStatusRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordImportExcelVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordImportReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO;
@@ -54,6 +55,18 @@
    @Resource
    private AdminUserApi adminUserApi;
    @GetMapping("/my-status")
    @Operation(summary = "获取我的今日打卡状态")
    @PreAuthorize("@ss.hasPermission('hrm:attendance-record:clock')")
    public CommonResult<HrmAttendanceMyStatusRespVO> getMyStatus() {
        HrmEmployeeDO employee = employeeService.getEmployeeByUserId(getLoginUserId());
        if (employee == null) {
            // æœªå…³è”员工时返回 null,由前端提示,避免打卡页加载直接报错
            return success(null);
        }
        return success(attendanceRecordService.getMyStatus(employee.getId()));
    }
    @PostMapping("/clock-in")
    @Operation(summary = "上班打卡")
    @PreAuthorize("@ss.hasPermission('hrm:attendance-record:clock')")
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceMyStatusRespVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@Schema(description = "管理后台 - æˆ‘的今日打卡状态 Response VO")
@Data
public class HrmAttendanceMyStatusRespVO {
    @Schema(description = "考勤日期")
    private LocalDate date;
    @Schema(description = "是否工作日")
    private Boolean workDay;
    @Schema(description = "员工ID")
    private Long employeeId;
    @Schema(description = "员工姓名")
    private String userName;
    @Schema(description = "部门ID")
    private Long deptId;
    @Schema(description = "部门名称")
    private String deptName;
    @Schema(description = "考勤规则名称")
    private String ruleName;
    @Schema(description = "上班时间")
    private LocalTime workStartTime;
    @Schema(description = "下班时间")
    private LocalTime workEndTime;
    @Schema(description = "今日记录ID,未打卡时为空")
    private Long recordId;
    @Schema(description = "上班打卡时间")
    private LocalDateTime clockInTime;
    @Schema(description = "下班打卡时间")
    private LocalDateTime clockOutTime;
    @Schema(description = "上班打卡类型")
    private Integer clockInType;
    @Schema(description = "下班打卡类型")
    private Integer clockOutType;
    @Schema(description = "是否已上班打卡")
    private Boolean clockInDone;
    @Schema(description = "是否已下班打卡")
    private Boolean clockOutDone;
    @Schema(description = "是否可上班打卡")
    private Boolean canClockIn;
    @Schema(description = "是否可下班打卡")
    private Boolean canClockOut;
    @Schema(description = "工作时长(小时)")
    private BigDecimal workHours;
    @Schema(description = "加班时长(小时)")
    private BigDecimal overtimeHours;
    @Schema(description = "打卡地点")
    private String location;
    @Schema(description = "数据来源")
    private Integer dataSource;
}
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRecordService.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.hrm.service.attendance;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceMyStatusRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceExceptionDO;
@@ -64,6 +65,14 @@
    HrmAttendanceRecordDO clockOut(Long userId, LocalDateTime clockTime, String location);
    /**
     * èŽ·å–å‘˜å·¥ä»Šæ—¥æ‰“å¡çŠ¶æ€
     *
     * @param userId å‘˜å·¥ID
     * @return ä»Šæ—¥æ‰“卡状态,员工不存在时返回 null
     */
    HrmAttendanceMyStatusRespVO getMyStatus(Long userId);
    /**
     * è¡¥å¡å®¡æ‰¹é€šè¿‡åŽæ›´æ–°è€ƒå‹¤è®°å½•
     *
     * @param exception è€ƒå‹¤å¼‚常申请
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRecordServiceImpl.java
@@ -2,6 +2,7 @@
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceMyStatusRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRuleDO;
@@ -258,6 +259,52 @@
    }
    @Override
    public HrmAttendanceMyStatusRespVO getMyStatus(Long userId) {
        // 1. å‘˜å·¥ä¸å­˜åœ¨æ—¶è¿”回 null,由前端提示未关联员工,避免打卡页加载直接报错
        HrmEmployeeDO employee = employeeService.getEmployee(userId);
        if (employee == null) {
            return null;
        }
        LocalDate today = LocalDate.now();
        // 2. æŸ¥è¯¢ä»Šæ—¥è€ƒå‹¤è®°å½•与考勤规则
        HrmAttendanceRecordDO record = attendanceRecordMapper.selectByUserIdAndDate(userId, today);
        HrmAttendanceRuleDO rule = attendanceRuleService.getAttendanceRuleByDeptId(employee.getDeptId());
        boolean workDay = attendanceHolidayService.isWorkDay(today);
        boolean clockInDone = record != null && record.getClockInTime() != null;
        boolean clockOutDone = record != null && record.getClockOutTime() != null;
        // 3. ç»„装今日打卡状态
        HrmAttendanceMyStatusRespVO respVO = new HrmAttendanceMyStatusRespVO();
        respVO.setDate(today);
        respVO.setWorkDay(workDay);
        respVO.setEmployeeId(employee.getId());
        respVO.setUserName(employee.getName());
        respVO.setDeptId(employee.getDeptId());
        if (rule != null) {
            respVO.setRuleName(rule.getName());
            respVO.setWorkStartTime(rule.getWorkStartTime());
            respVO.setWorkEndTime(rule.getWorkEndTime());
        }
        if (record != null) {
            respVO.setRecordId(record.getId());
            respVO.setClockInTime(record.getClockInTime());
            respVO.setClockOutTime(record.getClockOutTime());
            respVO.setClockInType(record.getClockInType());
            respVO.setClockOutType(record.getClockOutType());
            respVO.setWorkHours(record.getWorkHours());
            respVO.setOvertimeHours(record.getOvertimeHours());
            respVO.setLocation(record.getLocation());
            respVO.setDataSource(record.getDataSource());
        }
        respVO.setClockInDone(clockInDone);
        respVO.setClockOutDone(clockOutDone);
        // éžå·¥ä½œæ—¥ä¸å¯æ‰“卡,与打卡接口的校验保持一致
        respVO.setCanClockIn(workDay && !clockInDone);
        respVO.setCanClockOut(workDay && !clockOutDone);
        return respVO;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void supplementClockIn(HrmAttendanceExceptionDO exception) {
        // ä»…处理补卡类型