diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/constant/RoleIdConstant.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/constant/RoleIdConstant.java new file mode 100644 index 00000000..26c4b953 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/constant/RoleIdConstant.java @@ -0,0 +1,14 @@ +package org.dromara.common.constant; + +public class RoleIdConstant { + + /** + * 分包管理审核 + */ + public static final Long FB_SH = 6L; + + /** + * 管理审核 + */ + public static final Long SYS_SH = 7L; +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/controller/SubConstructionUserController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/controller/SubConstructionUserController.java index e76d943d..b462775b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/controller/SubConstructionUserController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/controller/SubConstructionUserController.java @@ -211,6 +211,13 @@ public class SubConstructionUserController extends BaseController { return toAjax(constructionUserService.batchUpdateStatus(req)); } + @SaCheckPermission("contractor:constructionUser:updateClock") + @PutMapping("updateClockBatch") + @RepeatSubmit() + public R updateClockBatch(@Validated(EditGroup.class) @RequestBody updateClockBatchDto dto) { + return toAjax(constructionUserService.updateClockBatch(dto)); + } + /** * 根据项目id批量修改施工人员打卡状态 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/updateClockBatchDto.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/updateClockBatchDto.java new file mode 100644 index 00000000..70716697 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/updateClockBatchDto.java @@ -0,0 +1,23 @@ +package org.dromara.contractor.domain.dto.constructionuser; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Data +public class updateClockBatchDto { + /** + * 用户id + */ + private List sysUserIds; + + /** + * 打卡(0启用打卡 1禁止打卡) + */ + @NotNull(message = "打卡状态不能为空") + private String clock; + + @NotNull(message = "项目id不能为空") + private Long projectId; +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/ISubConstructionUserService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/ISubConstructionUserService.java index 47a8872b..fe836c55 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/ISubConstructionUserService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/ISubConstructionUserService.java @@ -109,6 +109,14 @@ public interface ISubConstructionUserService extends IService recognizeRecords) { + public void transmitViolationRecord(List recognizeRecords) { List records = new ArrayList<>(); for (HseRecognizeRecord record : recognizeRecords) { String violationType = record.getViolationType(); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceRuleController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceRuleController.java index 1cd0618d..5fa360b4 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceRuleController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceRuleController.java @@ -115,4 +115,16 @@ public class BusAttendanceRuleController extends BaseController { return R.ok(busAttendanceRuleService.queryByProjectId(projectId)); } + /** + * 获取考勤打卡规则详细信息 + * + * @param projectId 主键 + */ + @SaCheckPermission("project:attendanceRule:query") + @GetMapping("/byProjectIdV1/{projectId}") + public R> getInfoByProjectIdV1(@NotNull(message = "项目Id不能为空") + @PathVariable Long projectId) { + return R.ok(busAttendanceRuleService.queryListByProjectId(projectId)); + } + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java index 12e89db6..467be81d 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java @@ -70,6 +70,15 @@ public class BusAttendanceAppController extends BaseController { return R.ok(attendanceService.punchCardByFace(file, req)); } + /** + * 人脸坐标打卡 + */ + @RepeatSubmit(interval = 3, timeUnit = TimeUnit.MINUTES,message = "3分钟内禁止重复打卡") + @PostMapping("/punch/card/faceV1") + public R punchCardByFaceV1(@RequestPart("file") MultipartFile file, BusAttendancePunchCardByFaceReq req) { + return R.ok(attendanceService.punchCardByFaceV1(file, req)); + } + /** * 获取考勤打卡规则详细信息 */ @@ -79,6 +88,15 @@ public class BusAttendanceAppController extends BaseController { return R.ok(attendanceRuleService.queryByProjectId(projectId)); } + /** + * 获取考勤打卡规则详细信息 + */ + @GetMapping("/ruleInfoV1/{projectId}") + public R getInfoV1(@NotNull(message = "项目不能为空") + @PathVariable Long projectId) { + return R.ok(attendanceRuleService.queryByProjectIdV1(projectId,LoginHelper.getUserId())); + } + /** * 查询项目考勤范围列表 */ @@ -107,6 +125,14 @@ public class BusAttendanceAppController extends BaseController { return R.ok(attendanceService.checkInRange(req)); } + /** + * 判断是否在打卡范围内 + */ + @PostMapping("/checkInRangeV1") + public R checkInRangeV1(@RequestBody BusAttendancePunchCardByFaceReq req) { + return R.ok(attendanceService.checkInRangeV1(req)); + } + /** * 获取用户当天打卡记录 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendanceRule.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendanceRule.java index b9286e95..7376fb5c 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendanceRule.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendanceRule.java @@ -102,4 +102,9 @@ public class BusAttendanceRule extends BaseEntity { */ private Long clockOutJobId; + /** + * 适用人群(0-施工人员 1-管理人员 2-分包人员) + */ + private String personType; + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/bo/BusAttendanceRuleBo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/bo/BusAttendanceRuleBo.java index 377ba7f8..9e449148 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/bo/BusAttendanceRuleBo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/bo/BusAttendanceRuleBo.java @@ -94,5 +94,9 @@ public class BusAttendanceRuleBo extends BaseEntity { */ private String type; + /** + * 适用人群(0-施工人员 1-管理人员 2-分包人员) + */ + private String personType; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceRuleService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceRuleService.java index e09e6330..f8096f5c 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceRuleService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceRuleService.java @@ -76,4 +76,19 @@ public interface IBusAttendanceRuleService extends IService{ */ BusAttendanceRuleVo queryByProjectId(Long projectId); + /** + * 根据项目id查询 + */ + BusAttendanceRuleVo queryByProjectIdV1(Long projectId,Long userId); + + /** + * 根据项目id和type查询 + */ + BusAttendanceRuleVo queryByProjectIdAndType(Long projectId,String type); + + /** + * 根据项目id和type查询 + */ + List queryListByProjectId(Long projectId); + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java index 0e390caa..6fbd57d3 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java @@ -95,6 +95,15 @@ public interface IBusAttendanceService extends IService{ */ Boolean punchCardByFace(MultipartFile file, BusAttendancePunchCardByFaceReq req); + /** + * 人脸打卡V1 + * + * @param file 人脸图片 + * @param req 人脸打卡请求 + * @return 是否打卡成功 + */ + Boolean punchCardByFaceV1(MultipartFile file, BusAttendancePunchCardByFaceReq req); + /** * 根据项目id查询出勤人列表 @@ -118,11 +127,18 @@ public interface IBusAttendanceService extends IService{ */ Boolean checkInRange(BusAttendancePunchCardByFaceReq req); + Boolean checkInRangeV1(BusAttendancePunchCardByFaceReq req); + /** * 获取用户当天打卡记录 */ List getTodayAttendance(Long projectId,Long userId); + /** + * 获取用户当天打卡记录 + */ + List getTodayAttendanceV1(Long projectId,Long userId); + /** * 获取用户指定月份的打卡记录 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceRuleServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceRuleServiceImpl.java index 36c6ffdd..26e08f2f 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceRuleServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceRuleServiceImpl.java @@ -10,6 +10,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.contractor.domain.SubConstructionUser; +import org.dromara.contractor.service.ISubConstructionUserService; +import org.dromara.contractor.service.impl.SubConstructionUserServiceImpl; import org.dromara.job.attendance.AttendanceJobUtil; import org.springframework.stereotype.Service; import org.dromara.project.domain.bo.BusAttendanceRuleBo; @@ -37,6 +41,8 @@ public class BusAttendanceRuleServiceImpl extends ServiceImpl busAttendanceRules = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(BusAttendanceRule::getProjectId, entity.getProjectId()) + .eq(BusAttendanceRule::getPersonType, entity.getPersonType()) + .ne(entity.getId() != null, BusAttendanceRule::getId, entity.getId()) + ); + if (!busAttendanceRules.isEmpty()) { + throw new ServiceException("该项目已存在打卡规则"); + } + } + + private void setResultTime(BusAttendanceRule entity) { if (entity.getClockInEndTime() != null) { @@ -224,4 +244,28 @@ public class BusAttendanceRuleServiceImpl extends ServiceImpllambdaQuery() .eq(BusAttendanceRule::getProjectId, projectId)); } + + @Override + public BusAttendanceRuleVo queryByProjectIdV1(Long projectId,Long userId) { + SubConstructionUser constructionUser = constructionUserService.getBySysUserId(userId); + if(constructionUser == null){ + throw new ServiceException("请先进行实名认证"); + } + return baseMapper.selectVoOne(Wrappers.lambdaQuery() + .eq(BusAttendanceRule::getProjectId, projectId) + .eq(BusAttendanceRule::getPersonType, constructionUser.getUserRole())); + } + + @Override + public BusAttendanceRuleVo queryByProjectIdAndType(Long projectId, String type) { + return baseMapper.selectVoOne(Wrappers.lambdaQuery() + .eq(BusAttendanceRule::getProjectId, projectId) + .eq(BusAttendanceRule::getPersonType, type)); + } + + @Override + public List queryListByProjectId(Long projectId) { + return baseMapper.selectVoList(Wrappers.lambdaQuery() + .eq(BusAttendanceRule::getProjectId, projectId)); + } } 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 15bc0785..27daad4c 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 @@ -566,6 +566,257 @@ public class BusAttendanceServiceImpl extends ServiceImpl attendances = this.lambdaQuery() + .eq(BusAttendance::getUserId, userId) + .eq(BusAttendance::getClockDate, localDate) + .list(); + List inAttendances = attendances.stream().filter(attendance -> + BusAttendanceCommuterEnum.CLOCKIN.getValue().equals(attendance.getClockType())).toList(); + List outAttendances = attendances.stream().filter(attendance -> + BusAttendanceCommuterEnum.CLOCKOUT.getValue().equals(attendance.getClockType())).toList(); + + if (clockTypeByTime == 1) { + if(CollectionUtils.isEmpty(inAttendances)){ + BusAttendance attendance = new BusAttendance(); + // 上班打卡 + attendance.setClockType(BusAttendanceCommuterEnum.CLOCKIN.getValue()); + //打卡时间 + attendance.setRuleTime(busAttendanceRuleVo.getClockInTime()); + // 判断是否为迟到 + if (isLate(now, busAttendanceRuleVo)) { + attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue()); + attendance.setMinuteCount(getMinutesDifference(now, busAttendanceRuleVo.getClockInTime())); + } else { + attendance.setClockStatus(BusAttendanceClockStatusEnum.NORMAL.getValue()); + } + //只要请假,直接归为请假 + LocalDateTime localDateTime = localDate.atTime(busAttendanceRuleVo.getClockInTime()); + if (leaveService.isLeave(localDateTime, userId)) { + attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); + } + + // 填充信息 + attendance.setUserId(userId); + attendance.setProjectId(req.getProjectId()); + attendance.setClockDate(localDate); + attendance.setClockTime(now); + attendance.setUserName(constructionUser.getUserName()); + attendance.setReplaceId(replaceId); + if(req.getSource() != null){ + attendance.setSource(req.getSource()); + attendance.setSn(req.getSn()); + } + // 记录打卡坐标 + attendance.setLat(req.getLat()); + attendance.setLng(req.getLng()); + try { + attendance.setClockLocation(JSTUtil.getLocationName(req.getLat(), req.getLng())); + } catch (Exception e) { + log.error("获取打卡位置失败", e); + } + + // 上传人脸照 + SysOssVo upload = ossService.upload(file); + attendance.setFacePic(upload.getOssId().toString()); + Long finalUserId = userId; + CompletableFuture.runAsync(() -> { + try { + chatServerHandler.sendSystemMessageToUser(finalUserId, "打卡成功", "1"); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", finalUserId, "打卡成功", e); + } + }); + //计算工资 + attendance.setSalary(computeSalary(constructionUser, inAttendances)); + return this.save(attendance); + } + //考勤机打卡会有历史记录,需要更新状态 + if(CollectionUtil.isNotEmpty(outAttendances) && "1".equals(req.getSource())){ + BusAttendance busAttendance = outAttendances.getFirst(); + String oldStatus = busAttendance.getClockStatus(); + //更新打卡时间 + busAttendance.setClockTime(now); + // 判断是否为迟到 + if (isLate(now, busAttendanceRuleVo)) { + busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue()); + busAttendance.setMinuteCount(getMinutesDifference(now, busAttendanceRuleVo.getClockInTime())); + } else { + busAttendance.setClockStatus(BusAttendanceClockStatusEnum.NORMAL.getValue()); + } + //只要请假,直接归为请假 + LocalDateTime localDateTime = localDate.atTime(busAttendanceRuleVo.getClockInTime()); + if (leaveService.isLeave(localDateTime, userId)) { + busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); + } + + busAttendance.setSource(req.getSource()); + busAttendance.setSn(req.getSn()); + //如果是缺卡需要上传人脸 + if(oldStatus.equals(BusAttendanceClockStatusEnum.UNCLOCK.getValue())){ + SysOssVo upload = ossService.upload(file); + busAttendance.setFacePic(upload.getOssId().toString()); + } + updateById(busAttendance); + } + + + } else if (clockTypeByTime == 2 || CollectionUtils.isNotEmpty(inAttendances)) { + + if (CollectionUtil.isNotEmpty(outAttendances)) { + BusAttendance busAttendance = outAttendances.getFirst(); + if("1".equals(req.getSource())){ + busAttendance.setSource(req.getSource()); + busAttendance.setSn(req.getSn()); + if(busAttendance.getClockStatus().equals(BusAttendanceClockStatusEnum.UNCLOCK.getValue())){ + SysOssVo upload = ossService.upload(file); + busAttendance.setFacePic(upload.getOssId().toString()); + } + }else { + if (busAttendance.getClockStatus().equals(BusAttendanceClockStatusEnum.UNCLOCK.getValue())) { + throw new ServiceException("下班缺卡记录已生成,不能更新"); + } + } + + //更新打卡时间 + busAttendance.setClockTime(now); + // 判断是否为早退 + if (isLeaveEarly(now, busAttendanceRuleVo, localDate)) { + busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVEEARLY.getValue()); + busAttendance.setMinuteCount(getMinutesDifference(now, busAttendanceRuleVo.getClockOutTime())); + } else { + busAttendance.setClockStatus(BusAttendanceClockStatusEnum.NORMAL.getValue()); + busAttendance.setMinuteCount(0); + } + //只要请假,直接归为请假 + LocalDateTime localDateTime = localDate.atTime(busAttendanceRuleVo.getClockInTime()); + if (leaveService.isLeave(localDateTime, userId)) { + busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); + } + updateById(busAttendance); + } else { + BusAttendance attendance = new BusAttendance(); + // 下班打卡 + attendance.setClockType(BusAttendanceCommuterEnum.CLOCKOUT.getValue()); + attendance.setRuleTime(busAttendanceRuleVo.getClockOutTime()); + // 判断是否为早退 + if (isLeaveEarly(now, busAttendanceRuleVo, localDate)) { + attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVEEARLY.getValue()); + attendance.setMinuteCount(getMinutesDifference(now, busAttendanceRuleVo.getClockOutTime())); + } else { + attendance.setClockStatus(BusAttendanceClockStatusEnum.NORMAL.getValue()); + } + //只要请假,直接归为请假 + LocalDateTime localDateTime = localDate.atTime(busAttendanceRuleVo.getClockInTime()); + if (leaveService.isLeave(localDateTime, userId)) { + attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); + } + // 填充信息 + attendance.setUserId(userId); + attendance.setProjectId(req.getProjectId()); + attendance.setClockDate(localDate); + attendance.setClockTime(now); + attendance.setUserName(constructionUser.getUserName()); + attendance.setReplaceId(replaceId); + if(req.getSource() != null){ + attendance.setSource(req.getSource()); + attendance.setSn(req.getSn()); + } + // 记录打卡坐标 + attendance.setLat(req.getLat()); + attendance.setLng(req.getLng()); + try { + attendance.setClockLocation(JSTUtil.getLocationName(req.getLat(), req.getLng())); + } catch (Exception e) { + log.error("获取打卡位置失败", e); + } + // 上传人脸照 + SysOssVo upload = ossService.upload(file); + attendance.setFacePic(upload.getOssId().toString()); + + Long finalUserId1 = userId; + CompletableFuture.runAsync(() -> { + try { + chatServerHandler.sendSystemMessageToUser(finalUserId1, "打卡成功", "1"); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", finalUserId1, "打卡成功", e); + } + }); + //计算工资 + attendance.setSalary(computeSalary(constructionUser, inAttendances)); + return this.save(attendance); + } + } + } + return false; + } + /** * 根据项目id查询出勤人列表 @@ -731,6 +982,70 @@ public class BusAttendanceServiceImpl extends ServiceImpl rangeIds = new ArrayList<>(); + if (isConstruct) { + BusProjectTeamMember one = projectTeamMemberService.getOne(Wrappers.lambdaQuery(BusProjectTeamMember.class) + .eq(BusProjectTeamMember::getMemberId, userId) + .eq(BusProjectTeamMember::getProjectId, projectId) + .last("limit 1")); + if (one == null) { + throw new ServiceException("当前用户未加入班组", HttpStatus.BAD_REQUEST); + } + + BusProjectTeam team = projectTeamService.getById(one.getTeamId()); + //需要考虑班组不设置考勤范围 + if ("1".equals(team.getIsClockIn())) { + return true; + } + try { + JSONArray jsonArray = JSONUtil.parseArray(team.getPunchRange()); + rangeIds = jsonArray.toList(Long.class); + } catch (Exception e) { + + } + } + // 再获取项目的规则 + BusAttendanceRuleVo busAttendanceRuleVo = attendanceRuleService.queryByProjectIdAndType(projectId,"0"); + if (busAttendanceRuleVo != null && "2".equals(busAttendanceRuleVo.getType())) { + return true; + } + + List punchRangeList = projectPunchrangeService.lambdaQuery() + .in(CollectionUtil.isNotEmpty(rangeIds), BusProjectPunchrange::getId, rangeIds) + .eq(BusProjectPunchrange::getProjectId, projectId) + .list() + .stream() + .map(BusProjectPunchrange::getPunchRange) + .toList(); + + if (CollUtil.isEmpty(punchRangeList)) { + throw new ServiceException(isConstruct ? "班组未配置考勤范围" : "项目未配置考勤范围", HttpStatus.ERROR); + } + List matchingRange = JSTUtil.findMatchingRange(req.getLat(), req.getLng(), punchRangeList); + return matchingRange != null; + } + @Override public List getTodayAttendance(Long projectId, Long userId) { @@ -752,6 +1067,28 @@ public class BusAttendanceServiceImpl extends ServiceImpl getTodayAttendanceV1(Long projectId, Long userId) { + + if (userId == null) { + userId = LoginHelper.getUserId(); + } + + BusAttendanceRuleVo busAttendanceRuleVo = attendanceRuleService.queryByProjectIdV1(projectId,userId); + + if (busAttendanceRuleVo == null) { + return List.of(); + } + + // 考勤时间 + //确定考勤日期 + LocalDate localDate = calculateAttendanceDate(LocalDateTime.now(), busAttendanceRuleVo); + + return baseMapper.selectVoList(new LambdaQueryWrapper() + .eq(BusAttendance::getUserId, userId) + .eq(BusAttendance::getClockDate, localDate) + ); + } @Override public List getMonthAttendance(Long projectId, String month) { diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusLeaveServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusLeaveServiceImpl.java index 96bbc16c..c7d3653e 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusLeaveServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusLeaveServiceImpl.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.constant.RoleIdConstant; import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.event.ProcessDeleteEvent; @@ -24,6 +25,7 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.enums.AppUserTypeEnum; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; @@ -45,6 +47,7 @@ import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.service.ISysOssService; import org.dromara.system.service.ISysRoleService; import org.dromara.system.service.ISysUserService; +import org.dromara.websocket.ChatServerHandler; import org.dromara.workflow.domain.TestLeave; import org.springframework.beans.BeanUtils; import org.springframework.context.annotation.Lazy; @@ -56,6 +59,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -97,6 +101,9 @@ public class BusLeaveServiceImpl extends ServiceImpl @Resource private ISysOssService ossService; + @Resource + private ChatServerHandler chatServerHandler; + /** * 查询施工人员请假申请 * @@ -112,9 +119,9 @@ public class BusLeaveServiceImpl extends ServiceImpl List sysUsers = new ArrayList<>(); if(busLeaveVo.getGangerId()==null){ if("1".equals(userType)){ - sysUsers = userService.selectUserByRoleIdAndProjectId(6L, busLeaveVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.FB_SH, busLeaveVo.getProjectId()); } else if ("2".equals(userType)) { - sysUsers = userService.selectUserByRoleIdAndProjectId(7L, busLeaveVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.SYS_SH, busLeaveVo.getProjectId()); } }else { SysUserVo sysUserVo = userService.selectUserById(busLeaveVo.getGangerId()); @@ -434,9 +441,9 @@ public class BusLeaveServiceImpl extends ServiceImpl List sysUsers = new ArrayList<>(); if(leaveVo.getGangerId()==null){ if("1".equals(userType)){ - sysUsers = userService.selectUserByRoleIdAndProjectId(6L, leaveVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.FB_SH, leaveVo.getProjectId()); } else if ("2".equals(userType)) { - sysUsers = userService.selectUserByRoleIdAndProjectId(7L, leaveVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.SYS_SH, leaveVo.getProjectId()); } }else { SysUserVo sysUserVo = userService.selectUserById(leaveVo.getGangerId()); @@ -500,6 +507,30 @@ public class BusLeaveServiceImpl extends ServiceImpl leave.setContractorId(bySysUserId.getContractorId()); } this.save(leave); + //发送通知 - 异步执行 + CompletableFuture.runAsync(() -> { + try { + SysUserVo sysUserVo = userService.selectUserById(leave.getUserId()); + String appUserType = sysUserVo.getAppUserType(); + + if(AppUserTypeEnum.SG.getType().equals(appUserType)){ + chatServerHandler.sendSystemMessageToUser(leave.getGangerId(),"["+leave.getUserName()+ "]"+"提交了新的请假申请","1"); + }else if(AppUserTypeEnum.GL.getType().equals(appUserType)){ + List longs = roleService.selectUserIdsByRoleId(RoleIdConstant.SYS_SH); + for (Long aLong : longs) { + chatServerHandler.sendSystemMessageToUser(aLong,"["+leave.getUserName()+ "]"+"提交了新的请假申请","1"); + } + }else if(AppUserTypeEnum.FB.getType().equals(appUserType)){ + List longs = roleService.selectUserIdsByRoleId(RoleIdConstant.FB_SH); + for (Long aLong : longs) { + chatServerHandler.sendSystemMessageToUser(aLong,"["+leave.getUserName()+ "]"+"提交了新的请假申请","1"); + } + } + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", leave.getGangerId(), "提交了新的请假申请", e); + } + }); + return leave.getId(); } @@ -551,10 +582,10 @@ public class BusLeaveServiceImpl extends ServiceImpl List roleIds = roleService.selectRoleIdsByUserIdAndProjectId(userId, req.getProjectId()); List type = new ArrayList<>(); - if(roleIds.contains(7L)){ + if(roleIds.contains(RoleIdConstant.SYS_SH)){ type.add("1"); } - if(roleIds.contains(6L)){ + if(roleIds.contains(RoleIdConstant.FB_SH)){ type.add("2"); } if(CollUtil.isEmpty(type)){ @@ -643,6 +674,21 @@ public class BusLeaveServiceImpl extends ServiceImpl } } } + CompletableFuture.runAsync(() -> { + try { + chatServerHandler.sendSystemMessageToUser(busLeave.getUserId(),"请假申请已通过","1"); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", busLeave.getUserId(), "请假申请已通过", e); + } + }); + }else if(gangerOpinion.equals("3")){ + CompletableFuture.runAsync(() -> { + try { + chatServerHandler.sendSystemMessageToUser(busLeave.getUserId(),"请假申请未通过","1"); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", busLeave.getUserId(), "请假申请未通过", e); + } + }); } return i>0; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java index 1db35ad8..dabd068b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.constant.RoleIdConstant; import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.domain.event.ProcessDeleteEvent; import org.dromara.common.core.domain.event.ProcessEvent; @@ -21,6 +22,7 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.enums.AppUserTypeEnum; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; @@ -101,6 +103,7 @@ public class BusReissueCardServiceImpl extends ServiceImpl sysUsers = new ArrayList<>(); if(busReissueCardVo.getGangerId()==null){ if("1".equals(userType)){ - sysUsers = userService.selectUserByRoleIdAndProjectId(6L, busReissueCardVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.FB_SH, busReissueCardVo.getProjectId()); } else if ("2".equals(userType)) { - sysUsers = userService.selectUserByRoleIdAndProjectId(7L, busReissueCardVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.SYS_SH, busReissueCardVo.getProjectId()); } }else { SysUserVo sysUserVo = userService.selectUserById(busReissueCardVo.getGangerId()); @@ -366,9 +369,9 @@ public class BusReissueCardServiceImpl extends ServiceImpl sysUsers = new ArrayList<>(); if(reissueCardVo.getGangerId()==null){ if("1".equals(userType)){ - sysUsers = userService.selectUserByRoleIdAndProjectId(6L, reissueCardVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.FB_SH, reissueCardVo.getProjectId()); } else if ("2".equals(userType)) { - sysUsers = userService.selectUserByRoleIdAndProjectId(7L, reissueCardVo.getProjectId()); + sysUsers = userService.selectUserByRoleIdAndProjectId(RoleIdConstant.SYS_SH, reissueCardVo.getProjectId()); } }else { SysUserVo sysUserVo = userService.selectUserById(reissueCardVo.getGangerId()); @@ -433,10 +436,10 @@ public class BusReissueCardServiceImpl extends ServiceImpl type = new ArrayList<>(); - if(roleIds.contains(7L)){ + if(roleIds.contains(RoleIdConstant.SYS_SH)){ type.add("1"); } - if(roleIds.contains(6L)){ + if(roleIds.contains(RoleIdConstant.FB_SH)){ type.add("2"); } if(CollUtil.isEmpty(type)){ @@ -477,7 +480,22 @@ public class BusReissueCardServiceImpl extends ServiceImpl { try { - chatServerHandler.sendSystemMessageToUser(bean.getGangerId(),"["+bean.getUserName()+ "]"+"提交了新的补卡申请","1"); + Long userId = bean.getUserId(); + SysUserVo sysUserVo = userService.selectUserById(userId); + String appUserType = sysUserVo.getAppUserType(); + if(AppUserTypeEnum.SG.getType().equals(appUserType)){ + chatServerHandler.sendSystemMessageToUser(bean.getGangerId(),"["+bean.getUserName()+ "]"+"提交了新的补卡申请","1"); + }else if(AppUserTypeEnum.GL.getType().equals(appUserType)){ + List longs = roleService.selectUserIdsByRoleId(RoleIdConstant.SYS_SH); + for (Long aLong : longs) { + chatServerHandler.sendSystemMessageToUser(aLong,"["+bean.getUserName()+ "]"+"提交了新的补卡申请","1"); + } + }else if(AppUserTypeEnum.FB.getType().equals(appUserType)){ + List longs = roleService.selectUserIdsByRoleId(RoleIdConstant.FB_SH); + for (Long aLong : longs) { + chatServerHandler.sendSystemMessageToUser(aLong,"["+bean.getUserName()+ "]"+"提交了新的补卡申请","1"); + } + } } catch (Exception e) { log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", bean.getGangerId(), "提交了新的补卡申请", e); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java index 0d3e7d8c..31eeb5af 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java @@ -162,4 +162,8 @@ public class SysUserVo implements Serializable { */ private String contractorName; + /** + * 打卡(0启用打卡 1禁止打卡) + */ + private String clock; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java index d20ffca5..e791823b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java @@ -221,4 +221,6 @@ public interface ISysRoleService { List selectRoleIdsByName(String roleName); + + List selectUserIdsByRoleId(Long roleId); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 68152a96..c2d7b418 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -660,4 +660,9 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService { .eq(SysRole::getRoleName, roleName) ).stream().map(SysRole::getRoleId).toList(); } + + @Override + public List selectUserIdsByRoleId(Long roleId) { + return userRoleMapper.selectUserIdsByRoleId(roleId); + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index bc3525eb..96c24343 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -163,9 +163,19 @@ public class SysUserServiceImpl implements ISysUserService, UserService { List list1 = userVoList.stream().map(SysUserVo::getContractorId).toList(); List subContractors = contractorService.listByIds(list1); Map collect = subContractors.stream().collect(Collectors.toMap(SubContractor::getId, SubContractor::getName)); + + List sysUserIds = userVoList.stream().map(SysUserVo::getUserId).toList(); + List constructionUsers = constructionUserService.lambdaQuery() + .select(SubConstructionUser::getSysUserId, SubConstructionUser::getClock) + .in(SubConstructionUser::getSysUserId, sysUserIds) + .list(); + + Map collect2 = constructionUsers.stream().collect(Collectors.toMap(SubConstructionUser::getSysUserId, SubConstructionUser::getClock)); + userVoList.forEach(userVo -> { Long contractorId = userVo.getContractorId(); userVo.setContractorName(collect.get(contractorId)); + userVo.setClock(collect2.get(userVo.getUserId())); }); page.setRecords(userVoList); }