From 70553dff79a3be3eea328139705ae5ee51572e3d Mon Sep 17 00:00:00 2001 From: zt Date: Tue, 23 Sep 2025 11:38:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/SubUserSalaryDetailMapper.java | 15 + .../impl/SubUserSalaryDetailServiceImpl.java | 131 +++++-- .../impl/BusAttendanceServiceImpl.java | 339 +++++++++--------- 3 files changed, 286 insertions(+), 199 deletions(-) diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/mapper/SubUserSalaryDetailMapper.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/mapper/SubUserSalaryDetailMapper.java index f6e1136f..dbcc06b7 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/mapper/SubUserSalaryDetailMapper.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/mapper/SubUserSalaryDetailMapper.java @@ -1,9 +1,13 @@ package org.dromara.contractor.mapper; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; import org.dromara.contractor.domain.SubUserSalaryDetail; import org.dromara.contractor.domain.vo.usersalarydetail.SubUserSalaryDetailVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import java.util.List; + /** * 员工每日工资Mapper接口 * @@ -12,4 +16,15 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; */ public interface SubUserSalaryDetailMapper extends BaseMapperPlus { + + + @Insert({ + "" + }) + Boolean insertAll(@Param("list")List list, @Param("userId") Long userId); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubUserSalaryDetailServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubUserSalaryDetailServiceImpl.java index a1d44d63..980a5881 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubUserSalaryDetailServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubUserSalaryDetailServiceImpl.java @@ -18,6 +18,7 @@ import jakarta.annotation.Resource; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.pdfbox.io.IOUtils; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; @@ -30,6 +31,7 @@ import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.utils.IdCardEncryptorUtil; import org.dromara.contractor.domain.SubConstructionUser; import org.dromara.contractor.domain.SubUserSalaryDetail; @@ -58,6 +60,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import software.amazon.awssdk.utils.CollectionUtils; @@ -72,6 +75,7 @@ import java.time.LocalDate; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import org.dromara.contractor.excel.SalaryExcelReader; @@ -83,6 +87,7 @@ import org.dromara.contractor.excel.SalaryExcelReader; */ @RequiredArgsConstructor @Service +@Slf4j public class SubUserSalaryDetailServiceImpl extends ServiceImpl implements ISubUserSalaryDetailService { @@ -525,19 +530,21 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl dataList; try { - // 2. 将 MultipartFile 转为 InputStream,传给工具类解析 dataList = SalaryExcelReader.readAllAttendanceByStream(file.getInputStream(), month); } catch (Exception e) { throw new RuntimeException("Excel流解析失败:" + e.getMessage(), e); @@ -546,42 +553,79 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl> dataMap = dataList.stream().collect(Collectors.toMap(vo -> idCardEncryptorUtil.encrypt(vo.getIdCard()), DynamicSalaryData::getDailyAttendance)); - Set cards = dataMap.keySet(); + // 2. 数据预处理 - 使用并行流提高处理速度 + Map> dataMap = dataList.parallelStream() + .collect(Collectors.toMap( + vo -> idCardEncryptorUtil.encrypt(vo.getIdCard()), + DynamicSalaryData::getDailyAttendance + )); + Set cards = dataMap.keySet(); month = dataList.getFirst().getMonth(); YearMonth parse = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyy-MM")); LocalDate start = parse.atDay(1); LocalDate end = parse.atEndOfMonth(); - //人员数据 - List list = constructionUserService.list(Wrappers.lambdaQuery() - .in(SubConstructionUser::getSfzNumber, cards)); + // 3. 分批处理人员数据 - 避免一次性加载大量数据 + List allUsers = new ArrayList<>(); + int batchSize = 1000; // 批量查询大小 - List userIds = list.stream().map(SubConstructionUser::getSysUserId).toList(); - //考勤数据 - List attendanceList = attendanceService - .list(Wrappers.lambdaQuery() - .in(BusAttendance::getUserId, userIds) - .between(BusAttendance::getClockDate, start, end) + // 分批查询用户数据 + List> cardBatches = new ArrayList<>(); + List cardList = new ArrayList<>(cards); + for (int i = 0; i < cardList.size(); i += batchSize) { + int endIndex = Math.min(i + batchSize, cardList.size()); + cardBatches.add(cardList.subList(i, endIndex)); + } + + for (List batchCards : cardBatches) { + List batchUsers = constructionUserService.list( + Wrappers.lambdaQuery() + .in(SubConstructionUser::getSfzNumber, batchCards) ); - // 将 attendanceList 转换为 Map 格式 - Map attendanceSalaryMap = new HashMap<>(); + allUsers.addAll(batchUsers); + } - // 按 userId+日期 分组,只保留每组的第一条记录的salary - attendanceList.stream() - .collect(Collectors.groupingBy( - attendance -> attendance.getUserId() + "_" + attendance.getClockDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), - Collectors.toList() - )) - .forEach((key, dateList) -> attendanceSalaryMap.put(key, dateList.getFirst().getSalary())); + if (CollUtil.isEmpty(allUsers)) { + throw new ServiceException("未找到匹配的人员信息"); + } + // 4. 分批处理考勤数据 - 避免内存溢出 + List userIds = allUsers.stream() + .map(SubConstructionUser::getSysUserId) + .distinct() + .collect(Collectors.toList()); - List addList = new ArrayList<>(); - for(SubConstructionUser constructionUser : list){ - Map stringIntegerMap = dataMap.get(constructionUser.getSfzNumber()); - if(stringIntegerMap != null){ - for(Map.Entry entry : stringIntegerMap.entrySet()){ + Map attendanceSalaryMap = new ConcurrentHashMap<>(); + + // 分批查询考勤数据 + for (int i = 0; i < userIds.size(); i += batchSize) { + int endIndex = Math.min(i + batchSize, userIds.size()); + List batchUserIds = userIds.subList(i, endIndex); + + List batchAttendanceList = attendanceService.list( + Wrappers.lambdaQuery() + .in(BusAttendance::getUserId, batchUserIds) + .between(BusAttendance::getClockDate, start, end) + ); + + // 并行处理考勤数据 + batchAttendanceList.parallelStream() + .collect(Collectors.groupingBy( + attendance -> attendance.getUserId() + "_" + attendance.getClockDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), + Collectors.toList() + )) + .forEach((key, dateList) -> attendanceSalaryMap.put(key, dateList.getFirst().getSalary())); + } + + // 5. 批量构建数据 - 使用并行处理 + List allAddList = Collections.synchronizedList(new ArrayList<>()); + + // 并行处理用户数据构建 + allUsers.parallelStream().forEach(constructionUser -> { + Map userAttendanceMap = dataMap.get(constructionUser.getSfzNumber()); + if(userAttendanceMap != null){ + userAttendanceMap.entrySet().parallelStream().forEach(entry -> { String key = entry.getKey(); Double value = entry.getValue(); @@ -600,16 +644,35 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl deleteUserIds = userIds.subList(i, endIndex); + + baseMapper.delete(Wrappers.lambdaQuery() + .in(SubUserSalaryDetail::getUserId, deleteUserIds) + .between(SubUserSalaryDetail::getReportDate, start, end) + ); } + // 批量插入新数据 - 使用自定义批量插入方法 + for (int i = 0; i < allAddList.size(); i += batchSize) { + int endIndex = Math.min(i + batchSize, allAddList.size()); + List insertBatch = allAddList.subList(i, endIndex); + baseMapper.insertAll(insertBatch,LoginHelper.getUserId()); + } } - baseMapper.delete(Wrappers.lambdaQuery() - .in(SubUserSalaryDetail::getUserId, userIds) - .between(SubUserSalaryDetail::getReportDate, start, end) - ); - baseMapper.insertBatch(addList); + + long endTime = System.currentTimeMillis(); + log.info("工资数据导入完成,耗时: {} ms,处理数据: {} 条", (endTime - startTime), allAddList.size()); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java index 0e160a73..6ce91ef2 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java @@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.dromara.common.core.constant.DateConstant; import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.exception.ServiceException; @@ -1041,7 +1042,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl list = constructionUserService.list(Wrappers.lambdaQuery(SubConstructionUser.class) - .eq(SubConstructionUser::getProjectId, dto.getProjectId()) - .eq(dto.getTeamId() != null, SubConstructionUser::getTeamId, dto.getTeamId()) - .eq(StrUtil.isNotBlank(dto.getTypeOfWork()), SubConstructionUser::getTypeOfWork, dto.getTypeOfWork()) - .like(StringUtils.isNotBlank(dto.getUserName()), SubConstructionUser::getUserName, dto.getUserName()) - ); - - if (list.isEmpty()) { - throw new ServiceException("未查询到相关人员"); - } - - List userIds = list.stream().map(SubConstructionUser::getSysUserId).toList(); - String clockDate = dto.getClockDate(); - - YearMonth yearMonth = YearMonth.parse(clockDate, DateTimeFormatter.ofPattern("yyyy-MM")); - LocalDate start = yearMonth.atDay(1); - LocalDate end = yearMonth.atEndOfMonth(); - - int daysInMonth = yearMonth.lengthOfMonth(); // 动态获取天数 - - List attendanceList = list(Wrappers.lambdaQuery(BusAttendance.class) - .in(BusAttendance::getUserId, userIds) - .between(BusAttendance::getClockDate, start, end) - ); - - Map> teamUserMap = list.stream() - .collect(Collectors.groupingBy(user -> - user.getTeamId() != null ? user.getTeamId() : 0L)); - Workbook workbook = new HSSFWorkbook(); - - for (Map.Entry> entry : teamUserMap.entrySet()) { - Long teamId = entry.getKey(); - System.out.println("teamId:" + teamId); - List users = entry.getValue(); - SubConstructionUser constructionUser = users.getFirst(); - String teamName = constructionUser.getTeamName(); - if (teamId == 0) { - teamName = "无班组"; + if (project == null) { + throw new ServiceException("项目不存在"); } - if (StringUtils.isBlank(teamName)) { - teamName = teamId.toString(); - } - System.out.println("name:" + teamName); - Sheet sheet = workbook.createSheet(teamName); + String clockDate = dto.getClockDate(); + YearMonth yearMonth = YearMonth.parse(clockDate, DateTimeFormatter.ofPattern("yyyy-MM")); + LocalDate start = yearMonth.atDay(1); + LocalDate end = yearMonth.atEndOfMonth(); - // ==================== 设置列宽 ==================== - sheet.setColumnWidth(0, 5 * 256); // 序号 - sheet.setColumnWidth(1, 10 * 256); // 姓名/日期 - sheet.setColumnWidth(2, 30 * 256); // 身份证号 + LocalDateTime startTime = LocalDateTime.of(yearMonth.atDay(1), LocalTime.MIN); // 00:00:00 + LocalDateTime endTime = LocalDateTime.of(yearMonth.atEndOfMonth(), LocalTime.MAX); - // 日期列(每天一列) - for (int i = 3; i < 3 + daysInMonth; i++) { - sheet.setColumnWidth(i, 5 * 256); // 每天列宽 15 字符 + List list = constructionUserService.list(Wrappers.lambdaQuery(SubConstructionUser.class) + .eq(SubConstructionUser::getProjectId, dto.getProjectId()) + .isNotNull(SubConstructionUser::getEntryDate) + .and(wrapper -> wrapper.between(SubConstructionUser::getLeaveDate, startTime, endTime).or() + .isNull(SubConstructionUser::getLeaveDate)) + .eq(dto.getTeamId() != null, SubConstructionUser::getTeamId, dto.getTeamId()) + .eq(StrUtil.isNotBlank(dto.getTypeOfWork()), SubConstructionUser::getTypeOfWork, dto.getTypeOfWork()) + .like(StringUtils.isNotBlank(dto.getUserName()), SubConstructionUser::getUserName, dto.getUserName()) + ); + + if (list.isEmpty()) { + throw new ServiceException("未查询到相关人员"); } - sheet.setColumnWidth(3 + daysInMonth, 5 * 256); // 合计 - sheet.setColumnWidth(3 + daysInMonth + 1, 10 * 256); // 是否离场 - sheet.setColumnWidth(3 + daysInMonth + 2, 15 * 256); // 签字 + List userIds = list.stream().map(SubConstructionUser::getSysUserId).toList(); - // ==================== 创建样式 ==================== - CellStyle borderStyle = createBorderStyle(workbook); + int daysInMonth = yearMonth.lengthOfMonth(); // 动态获取天数 + + List attendanceList = list(Wrappers.lambdaQuery(BusAttendance.class) + .in(BusAttendance::getUserId, userIds) + .between(BusAttendance::getClockDate, start, end) + ); + + Map> teamUserMap = list.stream() + .collect(Collectors.groupingBy(user -> + user.getTeamId() != null ? user.getTeamId() : 0L)); + + Workbook workbook = new XSSFWorkbook(); + + for (Map.Entry> entry : teamUserMap.entrySet()) { + Long teamId = entry.getKey(); + System.out.println("teamId:" + teamId); + List users = entry.getValue(); + SubConstructionUser constructionUser = users.getFirst(); + String teamName = constructionUser.getTeamName(); + if (teamId == 0) { + teamName = "无班组"; + } + if (StringUtils.isBlank(teamName)) { + teamName = teamId.toString(); + } + System.out.println("name:" + teamName); + Sheet sheet = workbook.createSheet(teamName); + + // ==================== 设置列宽 ==================== + sheet.setColumnWidth(0, 5 * 256); // 序号 + sheet.setColumnWidth(1, 10 * 256); // 姓名/日期 + sheet.setColumnWidth(2, 30 * 256); // 身份证号 + + // 日期列(每天一列) + for (int i = 3; i < 3 + daysInMonth; i++) { + sheet.setColumnWidth(i, 5 * 256); // 每天列宽 15 字符 + } + + sheet.setColumnWidth(3 + daysInMonth, 5 * 256); // 合计 + sheet.setColumnWidth(3 + daysInMonth + 1, 10 * 256); // 是否离场 + sheet.setColumnWidth(3 + daysInMonth + 2, 15 * 256); // 签字 + + // ==================== 创建样式 ==================== + CellStyle borderStyle = createBorderStyle(workbook); // CellStyle numberStyle = createNumberStyle(workbook); - // ==================== 表头部分 ==================== - Row titleRow = sheet.createRow(0); - Cell titleCell = titleRow.createCell(0); - titleCell.setCellValue("建筑施工企业现场人员考勤表(" + clockDate + ")"); - titleCell.setCellStyle(createTitleCellStyle(workbook)); + // ==================== 表头部分 ==================== + Row titleRow = sheet.createRow(0); + Cell titleCell = titleRow.createCell(0); + titleCell.setCellValue("建筑施工企业现场人员考勤表(" + clockDate + ")"); + titleCell.setCellStyle(createTitleCellStyle(workbook)); - // 合并标题行,横跨所有列 - int totalColumns = 3 + daysInMonth + 3; // 总列数 - sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, totalColumns - 1)); + // 合并标题行,横跨所有列 + int totalColumns = 3 + daysInMonth + 3; // 总列数 + sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, totalColumns - 1)); - // ==================== 第二行:项目名称和班组类别 ==================== - Row projectRow = sheet.createRow(1); + // ==================== 第二行:项目名称和班组类别 ==================== + Row projectRow = sheet.createRow(1); - // 设置项目名称(左对齐,占据前半部分) - Cell projectNameCell = projectRow.createCell(0); - projectNameCell.setCellValue("项目名称:" + project.getProjectName()); - projectNameCell.setCellStyle(createProjectCellStyle(workbook)); // 可选:设置样式 + // 设置项目名称(左对齐,占据前半部分) + Cell projectNameCell = projectRow.createCell(0); + projectNameCell.setCellValue("项目名称:" + project.getProjectName()); + projectNameCell.setCellStyle(createProjectCellStyle(workbook)); // 可选:设置样式 - int midColumn = (totalColumns / 2) - 1; + int midColumn = (totalColumns / 2) - 1; - // 设置班组类别(右对齐,占据后半部分) - int teamCol = midColumn + 1; // - Cell teamNameCell = projectRow.createCell(teamCol); - teamNameCell.setCellValue("班组类别:" + teamName); - teamNameCell.setCellStyle(createProjectCellStyle(workbook)); + // 设置班组类别(右对齐,占据后半部分) + int teamCol = midColumn + 1; // + Cell teamNameCell = projectRow.createCell(teamCol); + teamNameCell.setCellValue("班组类别:" + teamName); + teamNameCell.setCellStyle(createProjectCellStyle(workbook)); - // 合并项目名称区域(从第 0 列到中间) - if (midColumn >= 0) { - sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, midColumn)); - } - - // 合并班组类别区域(从 teamCol 开始,到最后一列) - if (teamCol < totalColumns) { - sheet.addMergedRegion(new CellRangeAddress(1, 1, teamCol, totalColumns - 1)); - } - - // ==================== 数据表头 ==================== - Row headerRow = sheet.createRow(2); - writeHeaderRow(headerRow, daysInMonth); - // 设置表头边框 - for (int i = 0; i < totalColumns; i++) { - Cell cell = headerRow.getCell(i); - if (cell != null) { - cell.setCellStyle(borderStyle); + // 合并项目名称区域(从第 0 列到中间) + if (midColumn >= 0) { + sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, midColumn)); } - } - // ==================== 数据行 ==================== - CellStyle numberBorderStyle = createNumberBorderStyle(workbook); + // 合并班组类别区域(从 teamCol 开始,到最后一列) + if (teamCol < totalColumns) { + sheet.addMergedRegion(new CellRangeAddress(1, 1, teamCol, totalColumns - 1)); + } - int rowIndex = 3; - for (SubConstructionUser user : users) { - Row row = sheet.createRow(rowIndex++); - writeDataRow(row, user, attendanceList, start, end, daysInMonth,borderStyle,numberBorderStyle); - - // 设置数据行边框 + // ==================== 数据表头 ==================== + Row headerRow = sheet.createRow(2); + writeHeaderRow(headerRow, daysInMonth); + // 设置表头边框 for (int i = 0; i < totalColumns; i++) { - Cell cell = row.getCell(i); + Cell cell = headerRow.getCell(i); if (cell != null) { cell.setCellStyle(borderStyle); } } - } - // ==================== 设置月份天数列为数字格式 + 边框 ==================== + // ==================== 数据行 ==================== + CellStyle numberBorderStyle = createNumberBorderStyle(workbook); - // 表头 - for (int i = 3; i < 3 + daysInMonth; i++) { - Cell headerCell = headerRow.getCell(i); - if (headerCell != null) { - headerCell.setCellStyle(numberBorderStyle); - } - } + int rowIndex = 3; + for (SubConstructionUser user : users) { + Row row = sheet.createRow(rowIndex++); + writeDataRow(row, user, attendanceList, start, end, daysInMonth, borderStyle, numberBorderStyle); - // 数据行 - for (int i = 3; i < 3 + daysInMonth; i++) { - for (int j = 3; j < rowIndex; j++) { - Row dataRow = sheet.getRow(j); - if (dataRow != null) { - Cell dataCell = dataRow.getCell(i); - if (dataCell != null) { - dataCell.setCellStyle(numberBorderStyle); + // 设置数据行边框 + for (int i = 0; i < totalColumns; i++) { + Cell cell = row.getCell(i); + if (cell != null) { + cell.setCellStyle(borderStyle); } } } - } - // ==================== 设置合计列公式 ==================== + // ==================== 设置月份天数列为数字格式 + 边框 ==================== + + + // 表头 + for (int i = 3; i < 3 + daysInMonth; i++) { + Cell headerCell = headerRow.getCell(i); + if (headerCell != null) { + headerCell.setCellStyle(numberBorderStyle); + } + } + + // 数据行 + for (int i = 3; i < 3 + daysInMonth; i++) { + for (int j = 3; j < rowIndex; j++) { + Row dataRow = sheet.getRow(j); + if (dataRow != null) { + Cell dataCell = dataRow.getCell(i); + if (dataCell != null) { + dataCell.setCellStyle(numberBorderStyle); + } + } + } + } + // ==================== 设置合计列公式 ==================== // for (int i = 4; i < rowIndex; i++) { // Row dataRow = sheet.getRow(i); // if (dataRow != null) { @@ -1358,47 +1365,47 @@ public class BusAttendanceServiceImpl extends ServiceImpl attendanceList, LocalDate start, LocalDate end, int daysInMonth,CellStyle borderStyle,CellStyle numberBorderStyle) { - int index = row.getRowNum()-2; + private void writeDataRow(Row row, SubConstructionUser user, List attendanceList, LocalDate start, LocalDate end, int daysInMonth, CellStyle borderStyle, CellStyle numberBorderStyle) { + int index = row.getRowNum() - 2; row.createCell(0).setCellValue(index); row.createCell(1).setCellValue(user.getUserName()); row.createCell(2).setCellValue(idCardEncryptorUtil.decrypt(user.getSfzNumber())); @@ -1502,7 +1511,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl