| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.date.DateTime; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.project.system.domain.SysDictData; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.staff.dto.PerformanceShiftAddDto; |
| | | import com.ruoyi.staff.dto.PerformanceShiftMapDto; |
| | | import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper; |
| | | import com.ruoyi.staff.mapper.PersonalShiftMapper; |
| | | import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig; |
| | | import com.ruoyi.staff.pojo.PersonalShift; |
| | | import com.ruoyi.staff.mapper.PersonalShiftMapper; |
| | | import com.ruoyi.staff.service.PersonalAttendanceLocationConfigService; |
| | | import com.ruoyi.staff.service.PersonalShiftService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.staff.utils.JackSonUtil; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.ObjectUtils; |
| | | |
| | |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.YearMonth; |
| | | import java.time.ZoneId; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.time.temporal.TemporalAdjusters; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Service |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @RequiredArgsConstructor |
| | | public class PersonalShiftServiceImpl extends ServiceImpl<PersonalShiftMapper, PersonalShift> implements PersonalShiftService { |
| | | |
| | | @Autowired |
| | | private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper; |
| | | private final PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper; |
| | | |
| | | @Override |
| | | public int performanceShiftAdd(PerformanceShiftAddDto performanceShiftAddDto) { |
| | |
| | | IPage<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftPage(page, time, userName, sysDeptId); |
| | | //查询所有班次(打卡规则) |
| | | List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null); |
| | | |
| | | // 获取当月时间范围 |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | LocalDateTime localDateTime = LocalDateTime.parse(time, formatters); |
| | | LocalDate firstDayOfMonth = localDateTime.toLocalDate().withDayOfMonth(1); |
| | | LocalDate lastDayOfMonth = localDateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth()); |
| | | |
| | | // 收集所有员工ID |
| | | List<Long> staffIds = mapIPage.getRecords().stream() |
| | | .filter(dto -> dto.getUserId() != null) |
| | | .map(dto -> Long.valueOf(dto.getUserId())) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 查询当月审核通过的请假记录(从approval_instance的form_config解析) |
| | | Map<Long, List<String>> staffHolidayMap = new HashMap<>(); |
| | | if (!staffIds.isEmpty()) { |
| | | // 通过关联查询获取员工请假信息 |
| | | List<Map<String, Object>> holidayRecords = baseMapper.selectStaffHolidayDates(staffIds); |
| | | |
| | | // 构建员工-请假日期映射(从form_config JSON解析) |
| | | for (Map<String, Object> record : holidayRecords) { |
| | | Long staffId = ((Number) record.get("staff_id")).longValue(); |
| | | String formConfig = (String) record.get("form_config"); |
| | | |
| | | if (formConfig != null && !formConfig.isEmpty()) { |
| | | try { |
| | | // 解析form_config JSON |
| | | Map<String, Object> formMap = JackSonUtil.unmarshal(formConfig, Map.class); |
| | | Object formPayloadObj = formMap.get("formPayload"); |
| | | |
| | | if (formPayloadObj instanceof Map) { |
| | | Map<String, Object> formPayload = (Map<String, Object>) formPayloadObj; |
| | | Object dateRangeObj = formPayload.get("00"); // 请假日期字段key为"00" |
| | | |
| | | if (dateRangeObj instanceof List) { |
| | | List<String> dateRange = (List<String>) dateRangeObj; |
| | | if (dateRange.size() >= 2) { |
| | | String startDateTime = dateRange.get(0); |
| | | String endDateTime = dateRange.get(1); |
| | | |
| | | // 解析日期(格式:yyyy-MM-dd HH:mm:ss) |
| | | LocalDate startDate = LocalDate.parse(startDateTime.substring(0, 10)); |
| | | LocalDate endDate = LocalDate.parse(endDateTime.substring(0, 10)); |
| | | |
| | | // 过滤当月范围内的请假日期 |
| | | List<String> dates = getDatesBetween(startDate, endDate).stream() |
| | | .filter(date -> { |
| | | LocalDate d = LocalDate.parse(date); |
| | | return !d.isBefore(firstDayOfMonth) && !d.isAfter(lastDayOfMonth); |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!dates.isEmpty()) { |
| | | staffHolidayMap.computeIfAbsent(staffId, k -> new ArrayList<>()).addAll(dates); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | // JSON解析失败,跳过此记录 |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (PerformanceShiftMapDto i : mapIPage.getRecords()) { |
| | | // 设置请假日期列表 |
| | | if (i.getUserId() != null) { |
| | | Long staffId = Long.valueOf(i.getUserId()); |
| | | List<String> holidayDates = staffHolidayMap.getOrDefault(staffId, new ArrayList<>()); |
| | | i.setHolidayDates(holidayDates); |
| | | } |
| | | |
| | | List<String> shiftTimes = StrUtil.split(i.getShiftTime(), ";"); |
| | | if(CollUtil.isEmpty(shiftTimes)){ |
| | | continue; |
| | | } |
| | | double totalAttendance = 0;//总出勤天数 |
| | | List<Map<String, Object>> map = new ArrayList<>(); |
| | | // 获取该员工的请假日期集合 |
| | | Set<String> holidayDateSet = new HashSet<>(i.getHolidayDates()); |
| | | // 分割日期 |
| | | for (String shiftTime : shiftTimes) { |
| | | i.setShiftTime(null); |
| | |
| | | hashMap.put("id", shiftTimeAndShift.get(2)); |
| | | hashMap.put("shift", shiftTimeAndShift.get(1)); |
| | | hashMap.put("time", shiftTimeAndShift.get(0)); |
| | | |
| | | // 提取日期部分(格式:yyyy-MM-dd HH:mm:ss -> yyyy-MM-dd) |
| | | String workTimeStr = shiftTimeAndShift.get(0); |
| | | String workDate = workTimeStr.length() >= 10 ? workTimeStr.substring(0, 10) : workTimeStr; |
| | | |
| | | // 如果该日期有审核通过的请假记录,设置isHoliday为true,并将班次设为休息 |
| | | if (holidayDateSet.contains(workDate)) { |
| | | hashMap.put("isHoliday", true); |
| | | hashMap.put("shift", "休息"); |
| | | } else { |
| | | hashMap.put("isHoliday", false); |
| | | } |
| | | |
| | | map.add(hashMap); |
| | | i.setList(map); |
| | | //汇总的各班次统计数据 |
| | | for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) { |
| | | if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())){ |
| | | i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0); |
| | | |
| | | // 统计班次数据 |
| | | if (holidayDateSet.contains(workDate)) { |
| | | // 如果是请假日期,统计为休息(只统计一次) |
| | | if (!i.getMonthlyAttendance().containsKey("休息")){ |
| | | i.getMonthlyAttendance().put("休息", 0); |
| | | } |
| | | if (personalAttendanceLocationConfig.getShift().equals(shiftTimeAndShift.get(1))) { |
| | | BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(personalAttendanceLocationConfig.getShift()).toString()); |
| | | i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), bigDecimal.add(new BigDecimal("1"))); |
| | | i.getMonthlyAttendance().put("休息", new BigDecimal(i.getMonthlyAttendance().get("休息").toString()).add(new BigDecimal("1"))); |
| | | } else { |
| | | // 不是请假日期,统计原班次 |
| | | for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) { |
| | | if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())){ |
| | | i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0); |
| | | } |
| | | if (personalAttendanceLocationConfig.getShift().equals(shiftTimeAndShift.get(1))) { |
| | | BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(personalAttendanceLocationConfig.getShift()).toString()); |
| | | i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), bigDecimal.add(new BigDecimal("1"))); |
| | | } |
| | | } |
| | | } |
| | | //统计总出勤天数(早/中/晚/夜)都算出勤,其余都是休息 |
| | | if (shiftTimeAndShift.get(1).contains("早") || |
| | | // 统计总出勤天数(早/中/晚/夜)都算出勤 |
| | | if (shiftTimeAndShift.get(1).contains("早") || |
| | | shiftTimeAndShift.get(1).contains("中") || |
| | | shiftTimeAndShift.get(1).contains("晚") || |
| | | shiftTimeAndShift.get(1).contains("夜")) { |
| | | i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1); |
| | | i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 获取header时间 |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | // 将字符串时间转换为 LocalDateTime 类型时间 |
| | | LocalDateTime localDateTime = LocalDateTime.parse(time, formatters); |
| | | LocalDate firstDayOfMonth = localDateTime.toLocalDate().withDayOfMonth(1); |
| | | LocalDate lastDayOfMonth = localDateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth()); |
| | | List<LocalDateTime> localDateTimesBetween = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay()); |
| | | List<Object> list1 = new ArrayList<>(); |
| | | for (LocalDateTime dateTime : localDateTimesBetween) { |
| | |
| | | return resultMap; |
| | | } |
| | | |
| | | /** |
| | | * 获取两个日期之间的所有日期(格式:yyyy-MM-dd) |
| | | * 注意:结束日期不包含在内(请假日期范围是开始日期到结束日期,不含结束日期) |
| | | */ |
| | | private List<String> getDatesBetween(LocalDate startDate, LocalDate endDate) { |
| | | List<String> dates = new ArrayList<>(); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | LocalDate current = startDate; |
| | | while (current.isBefore(endDate)) { |
| | | dates.add(current.format(formatter)); |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | @Override |
| | | public void performanceShiftUpdate(PersonalShift personalShift) { |
| | | baseMapper.update(new PersonalShift(), Wrappers.<PersonalShift>lambdaUpdate() |