buhuazhen
3 天以前 a60ba9317c84329c4cd43e0d13c55ec5fbddf253
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.ruoyi.staff.task;
 
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.staff.dto.PerformanceShiftAddDto;
import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper;
import com.ruoyi.staff.mapper.PersonalShiftMapper;
import com.ruoyi.staff.mapper.StaffOnJobMapper;
import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig;
import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
import com.ruoyi.staff.pojo.StaffOnJob;
import com.ruoyi.staff.service.PersonalAttendanceRecordsService;
import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
import com.ruoyi.staff.service.PersonalShiftService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
 
/**
 * 个人考勤记录定时任务
 *
 * @author 芯导软件(江苏)有限公司
 * @since 2026-02-09
 */
@Slf4j
@Component
public class PersonalAttendanceRecordsTask {
 
    @Autowired
    private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
 
    @Autowired
    private PersonalAttendanceRecordsService personalAttendanceRecordsService;
 
    @Autowired
    private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
 
    @Autowired
    private StaffOnJobMapper staffOnJobMapper;
 
    @Autowired
    private PersonalShiftService personalShiftService;
 
    /**
     * 每天凌晨生成昨日的缺勤记录
     * 定时任务:每天凌晨1点执行
     * 排除今天刚入职的员工
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void generateAbsenceRecords() {
        try {
            // 获取昨日日期
            LocalDate yesterday = LocalDate.now().minusDays(1);
 
            // 直接查询昨天没有考勤记录的在职员工(排除今天刚入职的)
            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) {
                        continue;
                    }
 
                    PersonalAttendanceRecords absenceRecord = new PersonalAttendanceRecords();
                    absenceRecord.setStaffOnJobId(staff.getId());
                    absenceRecord.setDate(yesterday);
                    absenceRecord.setStatus(4); // 设置状态为缺勤
                    absenceRecord.setRemark("系统自动生成-缺勤");
                    absenceRecord.setCreateTime(LocalDateTime.now());
                    absenceRecord.setUpdateTime(LocalDateTime.now());
                    absenceRecord.setTenantId(staff.getTenantId());
                    personalAttendanceRecordsService.save(absenceRecord);
 
                } catch (Exception e) {
                    log.error("为员工{}生成缺勤记录失败:{}", staff.getStaffName(), e.getMessage(), e);
                }
            }
 
            log.info("昨日缺勤记录生成完成");
        } catch (Exception e) {
            log.error("生成昨日缺勤记录任务执行失败:{}", e.getMessage(), e);
        }
    }
 
    /**
     * 定时任务,每个月1号的00:00:00给下一个月排班
     * 给每个人都进行排班(默认早班)
     */
    @Scheduled(cron = "0 10 0 1 * ?")
    private void timerCreateSchedule() {
        log.info("开始给每个人进行排班,默认早班======start");
        PerformanceShiftAddDto performanceShiftAddDto = new PerformanceShiftAddDto();
        //查询所有班次(打卡规则)
        List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null);
        if (CollectionUtil.isEmpty(personalAttendanceLocationConfigs)){
            return;
        }
        performanceShiftAddDto.setPersonalAttendanceLocationConfigId(personalAttendanceLocationConfigs.get(0).getId());
        //在职人员
        List<StaffOnJob> staffOnJobs = staffOnJobMapper.selectList(Wrappers.<StaffOnJob>lambdaQuery().eq(StaffOnJob::getStaffState, 1));
        if (CollectionUtil.isEmpty(staffOnJobs)){
            return;
        }
        String userIds = staffOnJobs.stream().map(user -> user.getId().toString()).distinct().collect(Collectors.joining(","));
        performanceShiftAddDto.setStaffOnJobId(userIds);
        //周次--当月所有
        // 获取当前日期
        LocalDate today = LocalDate.now(ZoneId.of(ZoneId.SHORT_IDS.get("CTT"))).plusMonths(1);
        // 获取本月的第一天和最后一天
        LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
        // 获取周字段信息(根据区域设置)
        WeekFields weekFields = WeekFields.of(Locale.getDefault());
        // 获取本月第一天的周一
        LocalDate startOfWeek = firstDayOfMonth.with(TemporalAdjusters.previousOrSame(weekFields.getFirstDayOfWeek()));
        // 遍历本月所有天数,找出每周的第一天和最后一天
        LocalDate endOfWeek;
        while (startOfWeek.isBefore(firstDayOfMonth.plusMonths(1))) {
            endOfWeek = startOfWeek.plusDays(6);
            LocalDateTime startDateTime = LocalDateTime.of(startOfWeek, LocalTime.MIDNIGHT);
            LocalDateTime endDateTime = LocalDateTime.of(endOfWeek, LocalTime.MIDNIGHT);
            log.info("Week starts on {} and ends on {}", startDateTime, endDateTime);
            performanceShiftAddDto.setStartWeek(startDateTime);
            performanceShiftAddDto.setEndWeek(endDateTime);
            personalShiftService.performanceShiftAdd(performanceShiftAddDto);
            startOfWeek = startOfWeek.plusWeeks(1);
        }
        log.info("排班结束======end");
    }
}