From 875a3ff40667c007e5eb95ef9c91c8aae957673e Mon Sep 17 00:00:00 2001 From: aikai Date: Thu, 17 Jul 2025 14:23:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(smartfactory):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=B7=A5=E7=A7=8D=E7=AD=9B=E9=80=89=E5=8A=9F=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=80=83=E5=8B=A4=E8=AE=B0=E5=BD=95=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 StaffAttendanceRecordReqVO 中添加 workTypeId 字段,用于工种筛选 - 修改 StaffService 接口,增加按工种筛选的 getListByFactory 方法 - 重构 StaffAttendanceRecordServiceImpl 中的 convertRecord 方法,提高代码可读性和维护性 - 优化 StaffSalaryServiceImpl 中的扣款金额计算逻辑 - 在 StaffMapper 和 StaffSalaryMapper 中添加创建时间降序排序 --- .../StaffAttendanceRecordController.java | 13 +- .../vo/StaffAttendanceRecordReqVO.java | 5 +- .../dal/mysql/staff/StaffMapper.java | 2 +- .../mysql/staffsalary/StaffSalaryMapper.java | 4 +- .../StaffAttendanceRecordServiceImpl.java | 151 +++++++++--------- .../service/staff/StaffService.java | 2 + .../service/staff/StaffServiceImpl.java | 8 +- .../staffsalary/StaffSalaryServiceImpl.java | 27 ++-- 8 files changed, 117 insertions(+), 95 deletions(-) diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/StaffAttendanceRecordController.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/StaffAttendanceRecordController.java index 4267ba1c..588e294d 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/StaffAttendanceRecordController.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/StaffAttendanceRecordController.java @@ -149,8 +149,9 @@ public class StaffAttendanceRecordController { // 查询该厂区员工在 其他厂区得考勤记录 List otherRecordDOS = staffAttendanceRecordService.getOtherRecord(reqVO); - // 获取工厂员工列表 - List staffDOS = staffService.getListByFactory(reqVO.getFactoryId(), true); + // 获取工厂员工列表,支持工种筛选 + List workTypeIds = reqVO.getWorkTypeId() != null ? Collections.singletonList(reqVO.getWorkTypeId()) : null; + List staffDOS = staffService.getListByFactory(reqVO.getFactoryId(), true, workTypeIds); Map staffMap = convertMap(staffDOS, StaffDO::getId); if (CollUtil.isNotEmpty(recordDOS)) { @@ -180,7 +181,7 @@ public class StaffAttendanceRecordController { recordRespVO.addAll(otherRespVO); return success(recordRespVO); - }else { + } else { // 判断是否 新增考勤情况 if (reqVO.getFactoryId() != null && reqVO.getMonth() != null && reqVO.getType() != null) { @@ -196,7 +197,7 @@ public class StaffAttendanceRecordController { .setStaffName(staffDO.getNickName()) .setWorkTypeId(staffDO.getWorkTypeId()); return success(Collections.singletonList(respVO)); - }else { + } else { List respVO = staffDOS.stream() .map(staffDO -> new StaffAttendanceRecordRespVO() .setStaffId(staffDO.getId()) @@ -220,7 +221,7 @@ public class StaffAttendanceRecordController { @PreAuthorize("@ss.hasPermission('smartfactory:staff-attendance-record:export')") @OperateLog(type = EXPORT) public void exportStaffAttendanceRecordExcel(@Valid StaffAttendanceRecordReqVO reqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { List recordDOS = staffAttendanceRecordService.getStaffAttendanceRecordList(reqVO); // 导出 Excel @@ -239,4 +240,4 @@ public class StaffAttendanceRecordController { staffAttendanceRecordService.updateReview(factoryId, month); return success(true); } -} \ No newline at end of file +} diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/vo/StaffAttendanceRecordReqVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/vo/StaffAttendanceRecordReqVO.java index 1ff0c438..298f0a00 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/vo/StaffAttendanceRecordReqVO.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/attendance/vo/StaffAttendanceRecordReqVO.java @@ -20,4 +20,7 @@ public class StaffAttendanceRecordReqVO { @Schema(description = "考勤方式 | 1.正常月份 2.25号开始计算至下个月24号", example = "1") private Integer type; -} \ No newline at end of file + + @Schema(description = "工种id", example = "1") + private Integer workTypeId; +} diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java index 91b254e2..d84200d3 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java @@ -76,7 +76,7 @@ public interface StaffMapper extends BaseMapperX { query.eqIfPresent(StaffDO::getFactoryId, pageReqVO.getFactoryId()); query.eqIfPresent(StaffDO::getWorkTypeId, pageReqVO.getWorkTypeId()); query.eqIfPresent(StaffDO::getId, pageReqVO.getStaffId()); - + query.orderByDesc(StaffSalaryDO::getCreateTime); return selectJoinPage(pageReqVO, StaffSalaryRespVO.class, query); } diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java index 7c2ee213..614deef5 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java @@ -41,7 +41,7 @@ public interface StaffSalaryMapper extends BaseMapperX { query.eqIfPresent(StaffSalaryDO::getStatus, reqVO.getStatus()); query.eqIfPresent(StaffSalaryDO::getIsGrant, reqVO.getIsGrant()); query.apply(Objects.nonNull(reqVO.getWorkTypeId()), "staff.work_type_id = {0} ", reqVO.getWorkTypeId()); - + query.orderByDesc(StaffSalaryDO::getCreateTime); return selectJoinPage(reqVO, StaffSalaryRespVO.class, query); } @@ -60,4 +60,4 @@ public interface StaffSalaryMapper extends BaseMapperX { return selectJoinList(StaffSalaryRespVO.class, query); } -} \ No newline at end of file +} diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/attendance/StaffAttendanceRecordServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/attendance/StaffAttendanceRecordServiceImpl.java index 8d03329a..7420da6b 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/attendance/StaffAttendanceRecordServiceImpl.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/attendance/StaffAttendanceRecordServiceImpl.java @@ -124,7 +124,7 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe List lastMonthRecord = staffAttendanceRecordMapper.selectList(new LambdaQueryWrapperX() .eq(StaffAttendanceRecordDO::getStaffId, staffId) - .betweenIfPresent(StaffAttendanceRecordDO::getPunchTime, new LocalDate[]{ beginDate, lastMonthEnd })); + .betweenIfPresent(StaffAttendanceRecordDO::getPunchTime, new LocalDate[]{beginDate, lastMonthEnd})); recordDOS.addAll(lastMonthRecord); } @@ -176,7 +176,7 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe // 获取查询月份得第25日日期 LocalDate lastMonthEnd = now.withDayOfMonth(25); - date = new LocalDate[]{ beginDate, lastMonthEnd }; + date = new LocalDate[]{beginDate, lastMonthEnd}; } return staffAttendanceRecordMapper.selectRecordList(reqVO, date); } @@ -216,48 +216,20 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe public List convertRecord(StaffAttendanceRecordReqVO reqVO, List recordDOS, List otherRecordDOS) { - // 根据考勤类型 生成对应得日期数据 - List punchTimeList = new ArrayList<>(); + // 根据考勤类型生成对应的日期列表 + List punchTimeList = generatePunchTimeList(reqVO); - // 获取所选月份的第一天 - LocalDate now = LocalDate.parse(reqVO.getMonth() + "-01", DateTimeFormatter.ISO_LOCAL_DATE); - if (reqVO.getType() == 1) { - - // 获取上月26日日期 - LocalDate beginDate = now.minusMonths(1).withDayOfMonth(26); - // 本月25日日期 - LocalDate lastMonthEnd = now.withDayOfMonth(25); - - while (!beginDate.isAfter(lastMonthEnd)) { - AttendanceRecordVO attendanceRecordVO = new AttendanceRecordVO() - .setPunchTime(beginDate); - punchTimeList.add(attendanceRecordVO); - - beginDate = beginDate.plusDays(1); - } - } - if (reqVO.getType() == 2) { - // 获取所选月份的第一天 - LocalDate firstDayOfMonth = LocalDate.parse(reqVO.getMonth() + "-01", DateTimeFormatter.ISO_LOCAL_DATE); - - // 生成当月每一天的 LocalDate - for (int i = 0; i < firstDayOfMonth.lengthOfMonth(); i++) { - AttendanceRecordVO attendanceRecordVO = new AttendanceRecordVO() - .setPunchTime(firstDayOfMonth.plusDays(i)); - punchTimeList.add(attendanceRecordVO); - } - } - // 获取员工信息 + // 获取员工信息 - 在当前厂区打卡的员工信息 List staffDOS = staffService.getList(convertSet(recordDOS, StaffAttendanceRecordDO::getStaffId)); Map staffMap = convertMap(staffDOS, StaffDO::getId); - // 获取厂区信息 + // 获取厂区信息 - 获取员工所打卡的所有厂区ids - 获取所有厂区信息 Set factoryIds = convertSet(recordDOS, StaffAttendanceRecordDO::getFactoryId); factoryIds.addAll(convertList(otherRecordDOS, StaffAttendanceRecordDO::getFactoryId)); List factoryDOS = factoryInfoService.getFactoryList(factoryIds); Map factoryMap = convertMap(factoryDOS, FactoryInfoDO::getId); - // 根据用户 分组打卡记录 + // 根据用户分组打卡记录 Map> recordMap = convertMultiMap(recordDOS, StaffAttendanceRecordDO::getStaffId); // 重组数据 @@ -275,10 +247,12 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe reqVO.getType(), reqVO.getMonth()); + // 筛选同一个工厂打卡数据并按日期建立映射 Map records = entry.getValue().stream() - .filter(record -> record.getFactoryId().equals(reqVO.getFactoryId())) // 筛选同一个工厂打卡数据 + .filter(record -> record.getFactoryId().equals(reqVO.getFactoryId())) .map(item -> BeanUtils.toBean(item, AttendanceRecordVO.class)) .collect(Collectors.toMap(AttendanceRecordVO::getPunchTime, value -> value)); + // 设置打卡数据 List recordVOS = punchTimeList.stream() .map(record -> { @@ -289,44 +263,16 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe return recordVO; }).collect(Collectors.toList()); respVO.setRecords(recordVOS); - // 设置员工名称 - respVO.setStaffName(staffMap.get(entry.getKey()).getNickName()); - // 设置工种 - respVO.setWorkTypeId(staffMap.get(entry.getKey()).getWorkTypeId()); - // 设置厂区名称 + + // 设置员工名称、工种、厂区名称 + StaffDO staffDO = staffMap.get(entry.getKey()); + respVO.setStaffName(staffDO.getNickName()); + respVO.setWorkTypeId(staffDO.getWorkTypeId()); respVO.setFactoryName(factoryMap.get(reqVO.getFactoryId()) != null ? factoryMap.get(reqVO.getFactoryId()).getName() : null); + // 处理其他厂区的考勤记录 if (CollUtil.isNotEmpty(otherRecordDOS)) { - // 获得该员工 在其他工厂的考勤记录 - Map> factoryRecordMap = convertMultiMap(otherRecordDOS, StaffAttendanceRecordDO::getFactoryId); - - List childRespVO = otherRecordDOS.stream() - .map(recordDO -> new StaffAttendanceRecordRespVO( - recordDO.getStaffId(), - recordDO.getFactoryId(), - recordDO.getType(), - recordDO.getMonth())) - .distinct() - .collect(Collectors.toList()); - - childRespVO.forEach(vo -> { - if (!staffMap.containsKey(vo.getStaffId())) { - return; - } - // 设置员工名称 - vo.setStaffName(staffMap.get(vo.getStaffId()).getNickName()); - // 设置工种 - vo.setWorkTypeId(staffMap.get(vo.getStaffId()).getWorkTypeId()); - // 设置厂区名称 - vo.setFactoryName(factoryMap.get(vo.getFactoryId()) != null ? factoryMap.get(vo.getFactoryId()).getName() : null); - - if (factoryRecordMap.containsKey(vo.getFactoryId())) { - - // 设置打卡记录 - vo.setRecords(BeanUtils.toBean(factoryRecordMap.get(vo.getFactoryId()), AttendanceRecordVO.class)); - } - }); - // 插入其他考勤记录 + List childRespVO = processOtherFactoryRecords(otherRecordDOS, staffMap, factoryMap); respVO.setChildRecords(childRespVO); } @@ -336,4 +282,65 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe return respVOs; } -} \ No newline at end of file + + /** + * 根据考勤类型生成对应的日期列表 + */ + private List generatePunchTimeList(StaffAttendanceRecordReqVO reqVO) { + List punchTimeList = new ArrayList<>(); + + LocalDate now = LocalDate.parse(reqVO.getMonth() + "-01", DateTimeFormatter.ISO_LOCAL_DATE); + if (reqVO.getType() == 1) { + LocalDate beginDate = now.minusMonths(1).withDayOfMonth(26); + LocalDate lastMonthEnd = now.withDayOfMonth(25); + + while (!beginDate.isAfter(lastMonthEnd)) { + punchTimeList.add(new AttendanceRecordVO().setPunchTime(beginDate)); + beginDate = beginDate.plusDays(1); + } + } else if (reqVO.getType() == 2) { + LocalDate firstDayOfMonth = now; + int lengthOfMonth = firstDayOfMonth.lengthOfMonth(); + for (int i = 0; i < lengthOfMonth; i++) { + punchTimeList.add(new AttendanceRecordVO().setPunchTime(firstDayOfMonth.plusDays(i))); + } + } + + return punchTimeList; + } + + /** + * 处理其他厂区的考勤记录 + */ + private List processOtherFactoryRecords(List otherRecordDOS, + Map staffMap, + Map factoryMap) { + Map> factoryRecordMap = convertMultiMap(otherRecordDOS, StaffAttendanceRecordDO::getFactoryId); + + return otherRecordDOS.stream() + .map(recordDO -> new StaffAttendanceRecordRespVO( + recordDO.getStaffId(), + recordDO.getFactoryId(), + recordDO.getType(), + recordDO.getMonth())) + .distinct() + .peek(vo -> { + if (staffMap.containsKey(vo.getStaffId())) { + StaffDO staffDO = staffMap.get(vo.getStaffId()); + vo.setStaffName(staffDO.getNickName()); + vo.setWorkTypeId(staffDO.getWorkTypeId()); + + if (factoryMap.containsKey(vo.getFactoryId())) { + vo.setFactoryName(factoryMap.get(vo.getFactoryId()).getName()); + } + + if (factoryRecordMap.containsKey(vo.getFactoryId())) { + vo.setRecords(BeanUtils.toBean(factoryRecordMap.get(vo.getFactoryId()), AttendanceRecordVO.class)); + } + } + }) + .filter(vo -> staffMap.containsKey(vo.getStaffId())) + .collect(Collectors.toList()); + } + +} diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffService.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffService.java index cd7e3b33..2246c9ca 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffService.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffService.java @@ -92,6 +92,8 @@ public interface StaffService { */ List getListByFactory(Long factoryId, Boolean isIn); + List getListByFactory(Long factoryId, Boolean isIn, List workTypeIds); + /** * 获取指定厂区得员工列表 * diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java index bfe27001..cc31986b 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java @@ -250,10 +250,16 @@ public class StaffServiceImpl implements StaffService { @Override public List getListByFactory(Long factoryId, Boolean isIn) { + return this.getListByFactory(factoryId, isIn, null); + } + + @Override + public List getListByFactory(Long factoryId, Boolean isIn, List workTypeIds) { return staffMapper.selectList(new LambdaQueryWrapperX() .eq(isIn, StaffDO::getFactoryId, factoryId) .ne(!isIn, StaffDO::getFactoryId, factoryId) - .ne(StaffDO::getStatus, 0)); + .ne(StaffDO::getStatus, 0) + .in(CollUtil.isNotEmpty(workTypeIds), StaffDO::getWorkTypeId, workTypeIds)); } @Override diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java index 43874333..65fcd1bb 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java @@ -111,7 +111,7 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { if (pageReqVO.getMonth() != null && pageReqVO.getStatus() == null) { return staffMapper.selectSalaryPage(pageReqVO); - }else { + } else { return staffSalaryMapper.selectSalaryPage(pageReqVO); } } @@ -154,7 +154,7 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { firstDayOfMonth.minusMonths(1).withDayOfMonth(26), firstDayOfMonth.withDayOfMonth(25) }; - }else if (type == 2) { + } else if (type == 2) { date = new LocalDate[]{ firstDayOfMonth, @@ -213,10 +213,12 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { // 设置扣款明细 默认扣除保险 50元 salaryDO.setDeductionItems(Collections.singletonList( - new DeductionItemsVO() - .setKey("insurance") - .setValue("50") - )); + new DeductionItemsVO() + .setKey("insurance") + .setValue("50") + )); + // 设置扣款金额 + salaryDO.setDeductionAmount(BigDecimal.valueOf(50)); // 计算应发工资 BigDecimal salary = staffDO.getSalary(); @@ -226,14 +228,14 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { // 设置应发工资 salaryDO.setPayableAmount(salary); // 设置实发工资 - salaryDO.setRealAmount(salary.subtract(BigDecimal.valueOf(50))); + salaryDO.setRealAmount(salary.subtract(salaryDO.getDeductionAmount())); } else { BigDecimal payableAmount = salary.divide(BigDecimal.valueOf(workDays), 0, RoundingMode.DOWN) .multiply(BigDecimal.valueOf(salaryDO.getAttendanceDays())); // 设置应发工资 salaryDO.setPayableAmount(payableAmount); // 设置实发工资 - salaryDO.setRealAmount(payableAmount.subtract(BigDecimal.valueOf(50))); + salaryDO.setRealAmount(payableAmount.subtract(salaryDO.getDeductionAmount())); } // 设置薪资主体数据 @@ -262,9 +264,10 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { .setId(id) .setIsGrant(isGrant)) .collect(Collectors.toList()); - - // 更新 - staffSalaryMapper.updateBatch(salaryDOS); + if (CollUtil.isNotEmpty(salaryDOS)) { + // 更新 + staffSalaryMapper.updateBatch(salaryDOS); + } } @Override @@ -300,4 +303,4 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { return salaryTotalVO; } -} \ No newline at end of file +}