doc/20260209_create_personal_attendance_records.sql
@@ -13,5 +13,6 @@ tenant_id bigint not null comment '租户id', create_time datetime null comment '录入时间', update_time datetime null comment '更新时间', index idx_staff_on_job_id (staff_on_job_id) index idx_staff_on_job_id (staff_on_job_id), unique idx_staff_on_job_id_date (staff_on_job_id, date) ); src/main/java/com/ruoyi/staff/mapper/PersonalAttendanceRecordsMapper.java
@@ -11,6 +11,7 @@ import org.apache.ibatis.annotations.Param; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; /** @@ -25,5 +26,7 @@ public interface PersonalAttendanceRecordsMapper extends BaseMapper<PersonalAttendanceRecords> { IPage<PersonalAttendanceRecordsDto> listPage(Page page, @Param("params") PersonalAttendanceRecordsDto personalAttendanceRecordsDto); List<StaffOnJob> selectStaffWithoutAttendanceRecord(@Param("date") LocalDate date); List<StaffOnJob> selectStaffWithoutAttendanceRecordBeforeTime(@Param("date") LocalDate date, @Param("entryDeadline") LocalDateTime entryDeadline); boolean existsAttendanceRecord(@Param("staffOnJobId") Long staffOnJobId, @Param("date") LocalDate date); } src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
@@ -18,6 +18,7 @@ import com.ruoyi.staff.pojo.StaffOnJob; import com.ruoyi.staff.service.PersonalAttendanceRecordsService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.staff.task.PersonalAttendanceRecordsTask; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -48,6 +49,9 @@ private StaffOnJobMapper staffOnJobMapper; @Autowired private PersonalAttendanceRecordsTask personalAttendanceRecordsTask; @Autowired private ISysDictDataService dictDataService; @Autowired src/main/java/com/ruoyi/staff/task/PersonalAttendanceRecordsTask.java
@@ -35,32 +35,31 @@ * 定时任务:每天凌晨1点执行 * 排除今天刚入职的员工 */ // @Scheduled(cron = "0 0 1 * * ?") @Scheduled(cron = "0/30 * * * * ?") @Scheduled(cron = "0 0 1 * * ?") public void generateAbsenceRecords() { try { // 获取昨日日期 LocalDate yesterday = LocalDate.now().minusDays(1); log.info("生成日期:{} 的缺勤记录", yesterday); // 直接查询昨天没有考勤记录的在职员工(排除今天刚入职的) List<StaffOnJob> staffWithoutAttendance = personalAttendanceRecordsMapper.selectStaffWithoutAttendanceRecord(yesterday); LocalDateTime todayStart = LocalDate.now().atStartOfDay(); List<StaffOnJob> staffWithoutAttendance = personalAttendanceRecordsMapper.selectStaffWithoutAttendanceRecordBeforeTime(yesterday, todayStart); // 遍历没有考勤记录的员工,生成缺勤记录 for (StaffOnJob staff : staffWithoutAttendance) { try { boolean exists = personalAttendanceRecordsMapper.existsAttendanceRecord(staff.getId(), yesterday); if (exists) { log.debug("员工{}在{}的考勤记录已存在,跳过生成", staff.getStaffName(), yesterday); continue; } PersonalAttendanceRecords absenceRecord = new PersonalAttendanceRecords(); absenceRecord.setStaffOnJobId(staff.getId()); absenceRecord.setDate(yesterday); absenceRecord.setWorkStartAt(null); absenceRecord.setWorkEndAt(null); absenceRecord.setWorkHours(BigDecimal.ZERO); absenceRecord.setStatus(4); // 设置状态为缺勤 absenceRecord.setRemark("系统自动生成-缺勤"); absenceRecord.setTenantId(staff.getTenantId()); absenceRecord.setCreateTime(LocalDateTime.now()); absenceRecord.setUpdateTime(LocalDateTime.now()); personalAttendanceRecordsService.save(absenceRecord); } catch (Exception e) { src/main/resources/mapper/staff/PersonalAttendanceRecordsMapper.xml
@@ -41,11 +41,12 @@ </if> </select> <select id="selectStaffWithoutAttendanceRecord" resultType="com.ruoyi.staff.pojo.StaffOnJob"> <!-- 查询指定日期没有考勤记录的在职员工(在指定时间之前入职的) --> <select id="selectStaffWithoutAttendanceRecordBeforeTime" resultType="com.ruoyi.staff.pojo.StaffOnJob"> SELECT soj.* FROM staff_on_job soj WHERE soj.status = 1 AND DATE(soj.create_time) < #{date} WHERE soj.staff_state = 1 AND soj.create_time < #{entryDeadline} AND NOT EXISTS ( SELECT 1 FROM personal_attendance_records par @@ -53,4 +54,14 @@ AND par.date = #{date} ) </select> <!-- 检查指定员工在指定日期是否已存在考勤记录 --> <select id="existsAttendanceRecord" resultType="boolean"> SELECT EXISTS ( SELECT 1 FROM personal_attendance_records WHERE staff_on_job_id = #{staffOnJobId} AND date = #{date} ) </select> </mapper>