| | |
| | | |
| | | 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; |
| | |
| | | */ |
| | | @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) { |
| | |
| | | LocalDateTime endWeek = performanceShiftAddDto.getEndWeek();//结束日期 |
| | | |
| | | |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | String formattedDateTime = performanceShiftAddDto.getStartWeek().format(formatter); |
| | | String[] splitUserId = performanceShiftAddDto.getStaffOnJobId().split(","); |
| | | for (String userId : splitUserId) { |
| | | //判断是否跨月 |
| | | boolean isMonth = startWeek.getMonthValue() != endWeek.getMonthValue(); |
| | | if (isMonth){ |
| | | //如果跨月,则两个月都判断一下看数据库是哪个月份的数据没有 |
| | | LocalDateTime startMonthBegin = startWeek.toLocalDate().withDayOfMonth(1).atStartOfDay(); |
| | | LocalDateTime endMonthBegin = endWeek.toLocalDate().withDayOfMonth(1).atStartOfDay(); |
| | | boolean exists1 = baseMapper.exists(Wrappers.<PersonalShift>lambdaQuery() |
| | | .eq(PersonalShift::getWorkTime, startWeek) |
| | | .ge(PersonalShift::getWorkTime, startMonthBegin) |
| | | .lt(PersonalShift::getWorkTime, startMonthBegin.plusMonths(1)) |
| | | .eq(PersonalShift::getStaffOnJobId, userId)); |
| | | boolean exists2 = baseMapper.exists(Wrappers.<PersonalShift>lambdaQuery() |
| | | .eq(PersonalShift::getWorkTime, endWeek) |
| | | .ge(PersonalShift::getWorkTime, endMonthBegin) |
| | | .lt(PersonalShift::getWorkTime, endMonthBegin.plusMonths(1)) |
| | | .eq(PersonalShift::getStaffOnJobId, userId)); |
| | | if (!exists1 && !exists2){ |
| | | //两个月都不存在数据 |
| | |
| | | } |
| | | }else { |
| | | //不跨月 |
| | | LocalDateTime monthBegin = startWeek.toLocalDate().withDayOfMonth(1).atStartOfDay(); |
| | | boolean exists = baseMapper.exists(Wrappers.<PersonalShift>lambdaQuery() |
| | | .in(PersonalShift::getWorkTime, formattedDateTime) |
| | | .ge(PersonalShift::getWorkTime, monthBegin) |
| | | .lt(PersonalShift::getWorkTime, monthBegin.plusMonths(1)) |
| | | .eq(PersonalShift::getStaffOnJobId, userId)); |
| | | // 如果不存在添加数据 |
| | | if (!exists) { |
| | |
| | | // 再次更新 |
| | | List<LocalDateTime> datesBetween = getLocalDateTimesBetween(performanceShiftAddDto.getStartWeek(), performanceShiftAddDto.getEndWeek()); |
| | | for (LocalDateTime date : datesBetween) { |
| | | LocalDateTime dayBegin = date.toLocalDate().atStartOfDay(); |
| | | for (String s : splitUserId) { |
| | | PersonalShift personalShift = new PersonalShift(); |
| | | personalShift.setPersonalAttendanceLocationConfigId(performanceShiftAddDto.getPersonalAttendanceLocationConfigId()); |
| | | personalShift.setStaffOnJobId(Long.valueOf(s)); |
| | | personalShift.setWorkTime(date); |
| | | String formatterDateTime = date.format(formatter); |
| | | baseMapper.update(new PersonalShift(), Wrappers.<PersonalShift>lambdaUpdate() |
| | | .set(PersonalShift::getPersonalAttendanceLocationConfigId, performanceShiftAddDto.getPersonalAttendanceLocationConfigId()) |
| | | .eq(PersonalShift::getStaffOnJobId, s) |
| | | .eq(PersonalShift::getWorkTime, formatterDateTime)); |
| | | .ge(PersonalShift::getWorkTime, dayBegin) |
| | | .lt(PersonalShift::getWorkTime, dayBegin.plusDays(1))); |
| | | } |
| | | } |
| | | return 0; |
| | |
| | | } |
| | | } |
| | | } |
| | | // 合计出勤天数以实际打卡记录为准(排班只代表计划) |
| | | Map<String, Integer> attendanceDays = loadMonthAttendanceDays(time, userName, sysDeptId); |
| | | for (PerformanceShiftMapDto i : mapIPage.getRecords()) { |
| | | i.getMonthlyAttendance().put("totalAttendance", |
| | | attendanceDays.getOrDefault(i.getUserId(), 0)); |
| | | } |
| | | // 获取header时间 |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | |
| | | IPage<Map<String, Object>> mapYearIPage = baseMapper.performanceShiftYear(page, time, userName, sysDeptId); |
| | | //查询所有班次(打卡规则) |
| | | List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null); |
| | | mapYearIPage.setRecords(annualAttendanceProcessing(mapYearIPage.getRecords(), personalAttendanceLocationConfigs)); |
| | | Map<String, Map<Integer, Integer>> attendanceCounts = loadYearAttendanceDays(time, userName, sysDeptId); |
| | | mapYearIPage.setRecords(annualAttendanceProcessing(mapYearIPage.getRecords(), personalAttendanceLocationConfigs, attendanceCounts)); |
| | | return mapYearIPage; |
| | | } |
| | | |
| | |
| | | LocalDateTime localDateTime = LocalDateTime.parse(time, formatters); |
| | | map.put("header", getYearHeader(localDateTime.getYear() + " 年", personalAttendanceLocationConfigs)); |
| | | List<Map<String, Object>> mapYearList = baseMapper.performanceShiftYearList(time, userName, sysDeptId); |
| | | annualAttendanceProcessing(mapYearList, personalAttendanceLocationConfigs); |
| | | Map<String, Map<Integer, Integer>> attendanceCounts = loadYearAttendanceDays(time, userName, sysDeptId); |
| | | annualAttendanceProcessing(mapYearList, personalAttendanceLocationConfigs, attendanceCounts); |
| | | List<List<Object>> lists = dataRequiredForProcessingIntoExcel(mapYearList, personalAttendanceLocationConfigs); |
| | | map.put("data", lists); |
| | | return map; |
| | |
| | | //查询所有班次(打卡规则) |
| | | List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null); |
| | | List<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftList(time, userName, sysDeptId); |
| | | // 合计出勤天数以实际打卡记录为准(排班只代表计划) |
| | | Map<String, Integer> attendanceDays = loadMonthAttendanceDays(time, userName, sysDeptId); |
| | | mapIPage.forEach(i -> { |
| | | String[] shiftTimes = i.getShiftTime().split(";"); |
| | | double totalAttendance = 0; |
| | |
| | | for (String shiftTime : shiftTimes) { |
| | | Map<String, Object> hashMap = new HashMap<>(); |
| | | String[] shiftTimeAndShift = shiftTime.split(":"); |
| | | if(shiftTimeAndShift.length != 3){ |
| | | continue; |
| | | } |
| | | for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) { |
| | | if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())) { |
| | | i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0); |
| | |
| | | } |
| | | i.setList(map); |
| | | i.setShiftTime(null); |
| | | i.getMonthlyAttendance().put("totalAttendance", |
| | | attendanceDays.getOrDefault(i.getUserId(), 0)); |
| | | }); |
| | | Map<Object, Object> map = new HashMap<>(); |
| | | DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | |
| | | LocalDateTime localDateTime = LocalDateTime.parse(time, formatters); |
| | | map.put("header", getMonthHeader(localDateTime)); |
| | | List<List<Object>> lists = dataRequiredForProcessingIntoExcelMonth(mapIPage, personalAttendanceLocationConfigs); |
| | | int maxSize = lists.stream() |
| | | .mapToInt(List::size) |
| | | .max() |
| | | .orElse(0); |
| | | |
| | | for (List<Object> row : lists) { |
| | | while (row.size() < maxSize) { |
| | | row.add("-"); |
| | | } |
| | | } |
| | | map.put("data", lists); |
| | | return map; |
| | | } |
| | | |
| | | // 实际打卡出勤天数(按月) |
| | | private Map<String, Integer> loadMonthAttendanceDays(String time, String userName, Integer sysDeptId) { |
| | | Map<String, Integer> result = new HashMap<>(); |
| | | for (Map<String, Object> row : baseMapper.attendanceDayCountByMonth(time, userName, sysDeptId)) { |
| | | Object userId = row.get("user_id"); |
| | | Object days = row.get("days"); |
| | | if (userId != null && days != null) { |
| | | result.put(String.valueOf(userId), new BigDecimal(days.toString()).intValue()); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | // 实际打卡出勤天数(按年,每人每月) |
| | | private Map<String, Map<Integer, Integer>> loadYearAttendanceDays(String time, String userName, Integer sysDeptId) { |
| | | Map<String, Map<Integer, Integer>> result = new HashMap<>(); |
| | | for (Map<String, Object> row : baseMapper.attendanceMonthCountByYear(time, userName, sysDeptId)) { |
| | | Object userId = row.get("user_id"); |
| | | Object month = row.get("month"); |
| | | Object days = row.get("days"); |
| | | if (userId == null || month == null || days == null) { |
| | | continue; |
| | | } |
| | | result.computeIfAbsent(String.valueOf(userId), k -> new HashMap<>()) |
| | | .put(Integer.parseInt(month.toString()), new BigDecimal(days.toString()).intValue()); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | // 年分页与导出共同使用 |
| | | public List<Map<String, Object>> annualAttendanceProcessing(List<Map<String, Object>> mapYearList,List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs) { |
| | | public List<Map<String, Object>> annualAttendanceProcessing(List<Map<String, Object>> mapYearList, List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs, Map<String, Map<Integer, Integer>> attendanceCounts) { |
| | | for (Map<String, Object> map : mapYearList) { |
| | | Map<String, Object> resultMap = new LinkedHashMap<>(); |
| | | Map<String, Object> hashMapYear = new LinkedHashMap<>(); |
| | | double totalYearAttendance = 0; |
| | | // 每个月的合计出勤天数以实际打卡记录为准 |
| | | Map<Integer, Integer> staffMonthAttendance = attendanceCounts.getOrDefault(String.valueOf(map.get("user_id")), Collections.emptyMap()); |
| | | // 一年12个月 |
| | | for (int i = 1; i < 13; i++) { |
| | | Map<String, Object> hashMapMonth = new LinkedHashMap<>(); |
| | | double totalMonthAttendance = 0; |
| | | for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) { |
| | | // 初始化赋值 |
| | | if (!hashMapYear.containsKey(personalAttendanceLocationConfig.getShift())){ |
| | |
| | | int count = countOccurrences(charArray, i + ":" + personalAttendanceLocationConfig.getShift()); |
| | | hashMapMonth.put(personalAttendanceLocationConfig.getShift(), count); |
| | | hashMapYear.put(personalAttendanceLocationConfig.getShift(), new BigDecimal(hashMapYear.get(personalAttendanceLocationConfig.getShift()).toString()).add(new BigDecimal(count))); |
| | | // 早,中,夜,差 |
| | | if (personalAttendanceLocationConfig.getShift().contains("早") || |
| | | personalAttendanceLocationConfig.getShift().contains("中") || |
| | | personalAttendanceLocationConfig.getShift().contains("晚") || |
| | | personalAttendanceLocationConfig.getShift().contains("夜")) { |
| | | totalMonthAttendance += count; |
| | | totalYearAttendance += count; |
| | | } |
| | | } |
| | | // 空数据 |
| | | else { |
| | |
| | | hashMapMonth.put(personalAttendanceLocationConfig.getShift(), 0); |
| | | } |
| | | } |
| | | hashMapMonth.put("totalMonthAttendance", totalMonthAttendance); |
| | | int monthAttendance = staffMonthAttendance.getOrDefault(i, 0); |
| | | totalYearAttendance += monthAttendance; |
| | | hashMapMonth.put("totalMonthAttendance", monthAttendance); |
| | | hashMapYear.put("totalYearAttendance", totalYearAttendance); |
| | | resultMap.put(i + "", hashMapMonth); |
| | | } |