Compare commits

...

2 Commits

Author SHA1 Message Date
zt
127059e934 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 17:45:42 +08:00
zt
742e67af23 考勤 2025-09-04 17:45:21 +08:00
22 changed files with 526 additions and 4 deletions

View File

@ -95,4 +95,10 @@ public class SubConstructionUserQueryReq implements Serializable {
*/
private String workStatus;
/**
* 创建人
*/
private String userId;
}

View File

@ -289,4 +289,8 @@ public class SubConstructionUserVo implements Serializable {
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 用户Id
*/
private Long sysUserId;
}

View File

@ -2,12 +2,22 @@ package org.dromara.gps.controller;
import java.util.List;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.extern.slf4j.Slf4j;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.domain.dto.constructionuser.SubConstructionUserQueryReq;
import org.dromara.contractor.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.gps.domain.vo.ConstructionUser;
import org.dromara.gps.domain.vo.GpsUserVo;
import org.dromara.project.service.IBusProjectService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -39,6 +49,12 @@ public class GpsEquipmentController extends BaseController {
private final IGpsEquipmentService gpsEquipmentService;
private final ISubConstructionUserService constructionUserService;
private final IBusProjectService projectService;
/**
* 接收设备数据
* @param jsonData
@ -64,7 +80,7 @@ public class GpsEquipmentController extends BaseController {
/**
* 查询GPS设备用户列表
*/
@SaCheckPermission("gps:equipment:list")
@SaCheckPermission("gps:equipment:getUserList")
@GetMapping("/getUserList")
public R<List<GpsUserVo>> getUserList(GpsEquipmentBo bo) {
return R.ok(gpsEquipmentService.getUserList(bo));
@ -115,6 +131,12 @@ public class GpsEquipmentController extends BaseController {
return toAjax(gpsEquipmentService.updateByBo(bo));
}
/**
* 项目列表
*/
/**
* GPS人机关联绑定
*/
@ -125,6 +147,21 @@ public class GpsEquipmentController extends BaseController {
public R<Void> bindManmachine(@RequestBody GpsEquipmentBo bo) {
return toAjax(gpsEquipmentService.bindManmachine(bo));
}
/**
* 查询施工人员列表
*/
@SaCheckPermission("gps:equipment:bindManmachine")
@GetMapping("/userList")
public R<List<ConstructionUser>> list(SubConstructionUserQueryReq req) {
List<SubConstructionUser> list = constructionUserService.list(Wrappers.<SubConstructionUser>lambdaQuery()
.eq(SubConstructionUser::getProjectId, req.getProjectId())
);
return R.ok(BeanUtil.copyToList(list,ConstructionUser.class ));
}
/**
* GPS人机关联解绑
*/

View File

@ -78,5 +78,10 @@ public class GpsEquipment extends BaseEntity {
*/
private String remark;
/**
* 存活状态 0-离线 1-在线
*/
private String alive;
}

View File

@ -114,4 +114,5 @@ public class GpsEquipmentSon extends BaseEntity {
private String remark;
private Long projectId;
}

View File

@ -114,4 +114,6 @@ public class GpsEquipmentSonBo extends BaseEntity {
private String remark;
private Long projectId;
}

View File

@ -0,0 +1,18 @@
package org.dromara.gps.domain.vo;
import lombok.Data;
@Data
public class ConstructionUser {
/**
* 人员姓名
*/
private String userName;
/**
* 系统用户id
*/
private Long sysUserId;
}

View File

@ -1,10 +1,13 @@
package org.dromara.gps.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -13,6 +16,7 @@ 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.redis.utils.RedisUtils;
import org.dromara.gps.domain.GpsEquipmentSon;
import org.dromara.gps.domain.GpsManmachine;
import org.dromara.gps.domain.bo.GpsEquipmentSonBo;
@ -21,6 +25,7 @@ import org.dromara.gps.mapper.GpsManmachineMapper;
import org.dromara.gps.service.IGpsEquipmentSonService;
import org.dromara.gps.service.IGpsManmachineService;
import org.plutext.jaxb.svg11.G;
import org.redisson.api.ObjectListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.gps.domain.bo.GpsEquipmentBo;
@ -30,6 +35,7 @@ import org.dromara.gps.mapper.GpsEquipmentMapper;
import org.dromara.gps.service.IGpsEquipmentService;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
/**
@ -40,6 +46,7 @@ import java.util.*;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, GpsEquipment> implements IGpsEquipmentService {
private final GpsEquipmentMapper baseMapper;
@ -164,6 +171,9 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
JSONObject location = device.getJSONObject("location");
gpsEquipmentSon.setLocLatitude(location.getBigDecimal("latitude"));
gpsEquipmentSon.setLocLongitude(location.getBigDecimal("longitude"));
if (equipment != null) {
gpsEquipmentSon.setProjectId(equipment.getProjectId());
}
if (!(gpsEquipmentSon.getLocLatitude().compareTo(BigDecimal.ZERO) == 0) || !(gpsEquipmentSon.getLocLongitude().compareTo(BigDecimal.ZERO) == 0)) {
gpsEquipmentSon.setLocAltitude(location.getLong("altitude"));
gpsEquipmentSon.setLocSpeed(location.getLong("speed"));
@ -180,14 +190,79 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
}
gpsEquipmentSonService.insertByBo(gpsEquipmentSon);
//保存到redis如果存在则更新存活时间
}
// 保存到Redis并设置过期监听
updateDeviceAliveStatus(gpsEquipment.getClientId());
}
private static final int DEVICE_ALIVE_TIMEOUT = 180; // 5分钟
/**
* 更新设备存活状态到Redis并添加过期监听
* @param clientId 设备ID
*/
private void updateDeviceAliveStatus(String clientId) {
// String key = "gps_device_alive:" + clientId;
//
// // 先删除可能存在的旧监听器
// if (RedisUtils.isExistsObject(key)) {
// RedisUtils.deleteObject(key);
// }
//
// // 设置缓存对象和过期时间
// RedisUtils.setCacheObject(key, "ALIVE", Duration.ofSeconds(DEVICE_ALIVE_TIMEOUT));
//
// // 添加过期监听器
// RedisUtils.addObjectListener(key, new ObjectListener() {
// @Override
// public void onExpired(String name) {
// log.info("Device {} is offline due to key expiration", clientId);
// handleDeviceOffline(clientId);
// }
//
// @Override
// public void onDeleted(String name) {
// // 可选:处理手动删除的情况
// }
// });
}
/**
* 处理设备离线
* @param clientId 设备ID
*/
private void handleDeviceOffline(String clientId) {
try {
// 更新设备状态为离线
LambdaUpdateWrapper<GpsEquipment> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(GpsEquipment::getClientId, clientId)
.set(GpsEquipment::getAlive, "0"); // 0表示离线
this.update(null, updateWrapper);
log.info("Device {} status updated to offline", clientId);
} catch (Exception e) {
log.error("Failed to handle device offline for client: {}", clientId, e);
}
}
@Override
public Boolean bindManmachine(GpsEquipmentBo bo) {
baseMapper.update(new LambdaUpdateWrapper<GpsEquipment>()
.set(GpsEquipment::getUserId,bo.getUserId())
.eq(GpsEquipment::getId,bo.getId()));
//只能绑定一个设备
List<GpsManmachine> gpsManmachines = gpsManmachineMapper.selectList(Wrappers.<GpsManmachine>lambdaQuery()
.eq(GpsManmachine::getUserId, bo.getUserId()));
if(CollectionUtil.isNotEmpty(gpsManmachines)){
throw new ServiceException("选中用户已绑定设备");
}
GpsManmachine gpsManmachine = new GpsManmachine();
gpsManmachine.setClientId(bo.getClientId());
gpsManmachine.setUserId(bo.getUserId());

View File

@ -145,6 +145,7 @@ public class AttendanceJob {
busAttendance.setClockDate(date);
busAttendance.setClockType(BusAttendanceCommuterEnum.CLOCKIN.getValue());
busAttendance.setRuleTime(rule.getClockInTime());
if(leaveService.isLeave(date, relevancy.getUserId())){
busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
}else {
@ -257,6 +258,7 @@ public class AttendanceJob {
busAttendance.setClockDate(date);
busAttendance.setClockType(BusAttendanceCommuterEnum.CLOCKOUT.getValue());
busAttendance.setRuleTime(rule.getClockOutTime());
if(leaveService.isLeave(date, relevancy.getUserId())){
busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
}else {

View File

@ -4,21 +4,28 @@ import cn.hutool.core.collection.CollectionUtil;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
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.web.core.BaseController;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.project.domain.BusProjectPunchrange;
import org.dromara.project.domain.dto.attendance.AttendanceCountDto;
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
import org.dromara.project.domain.vo.BusAttendanceRuleVo;
import org.dromara.project.domain.vo.BusAttendanceVo;
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
import org.dromara.project.domain.vo.attendance.AttendanceCountVo;
import org.dromara.project.domain.vo.attendance.AttendanceUserVo;
import org.dromara.project.service.IBusAttendanceRuleService;
import org.dromara.project.service.IBusAttendanceService;
import org.dromara.project.service.IBusProjectPunchrangeService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.util.List;
/**
@ -94,9 +101,9 @@ public class BusAttendanceAppController extends BaseController {
@GetMapping("/getTodayAttendance/{projectId}")
public R<List<BusAttendanceVo>> getTodayAttendance(@NotNull @PathVariable("projectId") Long projectId){
return R.ok(attendanceService.getTodayAttendance(projectId));
}
/**
* 获取用户指定月份打卡记录
*/
@ -115,6 +122,22 @@ public class BusAttendanceAppController extends BaseController {
}
/**
* 统计指定日期的打卡人员
*/
@GetMapping("/count")
public R<AttendanceCountVo> getAttendanceCount(AttendanceCountDto dto){
return R.ok(attendanceService.getAttendanceCount(dto));
}
/**
* 指定日期的打卡人员列表
*/
@GetMapping("/getAttendanceCount")
public TableDataInfo<AttendanceUserVo> getAttendanceUser(AttendanceCountDto dto,PageQuery pageQuery){
return attendanceService.getAttendanceUser(dto,pageQuery);
}
}

View File

@ -3,8 +3,11 @@ package org.dromara.project.controller.app;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.project.domain.vo.project.BusProjectContractorTeamListVo;
import org.dromara.project.domain.vo.userprojectrelevancy.BusLoginUserProjectRelevancyVo;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusUserProjectRelevancyService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -27,6 +30,9 @@ public class BusProjectAppController {
@Resource
private IBusProjectService projectService;
@Resource
private IBusUserProjectRelevancyService userProjectRelevancyService;
/**
* 查询项目以及项目下的分包公司、班组列表
*/
@ -43,4 +49,13 @@ public class BusProjectAppController {
@PathVariable Long id) {
return R.ok(projectService.queryContractorTeamListById(id));
}
/**
* 查询登录用户与项目关联列表
*/
@GetMapping("/login/list")
public R<List<BusLoginUserProjectRelevancyVo>> listByLoginUser() {
Long userId = LoginHelper.getUserId();
return R.ok(userProjectRelevancyService.queryListByUserId(userId));
}
}

View File

@ -1,10 +1,12 @@
package org.dromara.project.controller.app;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -20,6 +22,7 @@ import org.dromara.project.domain.BusProjectTeamMember;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardUpdateReq;
import org.dromara.project.domain.enums.BusProjectTeamMemberPostEnum;
import org.dromara.project.domain.vo.projectteam.BusForemanVo;
import org.dromara.project.domain.vo.projectteam.BusProjectTeamForemanVo;
@ -67,6 +70,38 @@ public class BusReissueCardAppController extends BaseController {
return reissueCardService.listByLoginUser(req, pageQuery);
}
/**
* 查询当前登录用户补卡审批列表
*/
@GetMapping("/list/auditUser")
public TableDataInfo<BusReissueCardVo> listByAuditUser(BusReissueCardQueryReq req, PageQuery pageQuery) {
// SubConstructionUser constructionUser = constructionUserService.getBySysUserId(LoginHelper.getUserId());
req.setGangerId(LoginHelper.getUserId());
return reissueCardService.listByAuditUser(req, pageQuery);
}
/**
* 获取施工人员补卡申请详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<BusReissueCardVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(reissueCardService.queryById(id));
}
/**
* 修改补卡申请
*/
@Log(title = "施工人员补卡申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("")
public R<Void> managerReview(@RequestBody BusReissueCardUpdateReq req) {
return toAjax(reissueCardService.updateCard(req));
}
/**
* 提交补卡
*/

View File

@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
@ -92,5 +93,8 @@ public class BusAttendance extends BaseEntity {
*/
private String lat;
/**
* 规定时间
*/
private LocalTime ruleTime;
}

View File

@ -0,0 +1,36 @@
package org.dromara.project.domain.dto.attendance;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
@Data
public class AttendanceCountDto {
/**
* 项目id
*/
private Long projectId;
/**
* 查询日期
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
/**
* 考勤状态 1-出勤 2-缺勤
*/
private String clockStatus;
/**
* 工种
*/
private String typeOfWork;
/**
* 班组
*/
private Long teamId;
}

View File

@ -0,0 +1,81 @@
package org.dromara.project.domain.dto.reissuecard;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author lilemy
* @date 2025/4/8 9:58
*/
@Data
public class BusReissueCardUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -3708280254564807491L;
/**
* 主键id
*/
private Long id;
/**
* 申请人id
*/
private Long userId;
/**
* 申请人名字
*/
private String userName;
/**
* 班组长
*/
private Long gangerId;
/**
* 班组长名字
*/
private String gangerName;
/**
* 班组长意见1未读 2同意 3拒绝
*/
private String gangerOpinion;
/**
* 管理员意见1未读 2同意 3拒绝
*/
private String managerOpinion;
/**
* 项目id
*/
private Long projectId;
/**
* 班组id
*/
private Long teamId;
/**
* 补卡类型1上班 2下班
*/
private String reissueCardType;
/**
* 考勤表主键id
*/
private Long attendanceId;
/**
* 日期
*/
private LocalDate date;
}

View File

@ -2,6 +2,7 @@ package org.dromara.project.domain.vo;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.project.domain.BusAttendance;
@ -113,4 +114,10 @@ public class BusAttendanceVo implements Serializable {
@ExcelProperty(value = "纬度")
private Integer week;
/**
* 规定时间
*/
private LocalTime ruleTime;
}

View File

@ -0,0 +1,23 @@
package org.dromara.project.domain.vo.attendance;
import lombok.Data;
import org.dromara.project.domain.dto.attendance.AttendanceCountDto;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.util.List;
@Data
public class AttendanceCountVo {
/**
* 总人数
*/
private Integer totalCount;
/**
* 出勤人数
*/
private Integer workCount;
}

View File

@ -0,0 +1,33 @@
package org.dromara.project.domain.vo.attendance;
import lombok.Data;
@Data
public class AttendanceUserVo {
/**
* 用户昵称
*/
private String nickName;
/**
* 用户头像
*/
private Long avatar;
/**
* 工种(字典type_of_work)
*/
private String typeOfWork;
/**
* 班组名称
*/
private String teamName;
/**
* 考勤状态 1-出勤 2-缺勤
*/
private String clockStatus;
}

View File

@ -1,6 +1,7 @@
package org.dromara.project.service;
import jakarta.validation.constraints.NotNull;
import org.dromara.project.domain.dto.attendance.AttendanceCountDto;
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
import org.dromara.project.domain.vo.BusAttendanceVo;
import org.dromara.project.domain.bo.BusAttendanceBo;
@ -10,9 +11,14 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
import org.dromara.project.domain.vo.attendance.AttendanceCountVo;
import org.dromara.project.domain.vo.attendance.AttendanceUserVo;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
@ -121,4 +127,14 @@ public interface IBusAttendanceService extends IService<BusAttendance>{
* 获取用户指定月份的打卡记录
*/
List<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId);
/**
* 统计指定日期的打卡人员
*/
AttendanceCountVo getAttendanceCount(AttendanceCountDto dto);
/**
* 指定日期的打卡人员列表
*/
TableDataInfo<AttendanceUserVo> getAttendanceUser(AttendanceCountDto dto, PageQuery pageQuery);
}

View File

@ -9,6 +9,7 @@ import org.dromara.project.domain.BusReissueCard;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardUpdateReq;
import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo;
import org.springframework.web.bind.annotation.RequestBody;
@ -95,8 +96,20 @@ public interface IBusReissueCardService extends IService<BusReissueCard> {
*/
TableDataInfo<BusReissueCardVo> listByLoginUser(BusReissueCardQueryReq req, PageQuery pageQuery);
/**
* 审批列表
*/
TableDataInfo<BusReissueCardVo> listByAuditUser(BusReissueCardQueryReq req, PageQuery pageQuery);
/**
* 新增施工人员补卡申请
*/
Long add(BusReissueCardAddReq req);
/**
* 修改施工人员补卡申请
*/
Boolean updateCard(BusReissueCardUpdateReq req);
}

View File

@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -23,12 +24,15 @@ import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.project.domain.*;
import org.dromara.project.domain.bo.BusAttendanceBo;
import org.dromara.project.domain.dto.attendance.AttendanceCountDto;
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import org.dromara.project.domain.vo.BusAttendanceRuleVo;
import org.dromara.project.domain.vo.BusAttendanceVo;
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
import org.dromara.project.domain.vo.attendance.AttendanceCountVo;
import org.dromara.project.domain.vo.attendance.AttendanceUserVo;
import org.dromara.project.mapper.BusAttendanceMapper;
import org.dromara.project.service.*;
import org.dromara.system.domain.vo.SysOssVo;
@ -36,6 +40,7 @@ import org.dromara.system.service.ISysOssService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@ -254,18 +259,23 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
if (CollUtil.isEmpty(attendances)) {
// 上班打卡
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());
}
} else if (attendances.size() == 1) {
// 下班打卡
attendance.setClockType(BusAttendanceCommuterEnum.CLOCKOUT.getValue());
attendance.setRuleTime(busAttendanceRuleVo.getClockOutTime());
// 判断是否为早退
if (isLeaveEarly(now, busAttendanceRuleVo)) {
attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVEEARLY.getValue());
attendance.setMinuteCount(getMinutesDifference(now, busAttendanceRuleVo.getClockOutTime()));
} else {
attendance.setClockStatus(BusAttendanceClockStatusEnum.NORMAL.getValue());
}
@ -323,6 +333,19 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
return attendedUserIds;
}
/**
* 计算实际打卡时间与规定时间的分钟差
*
* @param actualTime 实际打卡时间
* @param expectedTime 规定打卡时间
* @return 时间差(分钟)
*/
private int getMinutesDifference(LocalDateTime actualTime, LocalTime expectedTime) {
LocalDateTime expectedDateTime = LocalDateTime.of(actualTime.toLocalDate(), expectedTime);
return (int) Duration.between(expectedDateTime, actualTime).toMinutes();
}
@Override
public List<String> getPunchRangeByProjectIdAndUserId(Long projectId, Long userId) {
@ -528,4 +551,38 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
}
@Override
public AttendanceCountVo getAttendanceCount(AttendanceCountDto dto) {
//查询今天打卡人员
AttendanceCountVo attendanceCountVo = new AttendanceCountVo();
List<BusAttendance> attendanceList = baseMapper.selectList(Wrappers.<BusAttendance>lambdaQuery()
.eq(BusAttendance::getProjectId, dto.getProjectId())
.in(BusAttendance::getClockStatus,Arrays.asList("1","2","3","5","7"))
.eq(BusAttendance::getClockDate, dto.getDate())
);
List<Long> attendanceUserIds = attendanceList.stream().map(BusAttendance::getUserId).toList();
//总人数
long count = constructionUserService.count(Wrappers.<SubConstructionUser>lambdaQuery()
.eq(SubConstructionUser::getProjectId, dto.getProjectId()));
attendanceCountVo.setTotalCount((int)count);
//出勤人数
HashSet<Long> longs = new HashSet<>(attendanceUserIds);
int size = longs.size();
attendanceCountVo.setWorkCount(size);
return attendanceCountVo;
}
@Override
public TableDataInfo<AttendanceUserVo> getAttendanceUser(AttendanceCountDto dto, PageQuery pageQuery) {
// constructionUserService.queryPageList(dto.getProjectId());
return null;
}
}

View File

@ -3,6 +3,7 @@ package org.dromara.project.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -22,6 +23,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.project.domain.*;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardUpdateReq;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import org.dromara.project.domain.enums.BusOpinionStatusEnum;
@ -291,7 +293,7 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
LambdaQueryWrapper<BusReissueCard> lqw = new LambdaQueryWrapper<>();
lqw.eq(ObjectUtils.isNotEmpty(req.getUserId()), BusReissueCard::getUserId, req.getUserId());
lqw.orderByDesc(BusReissueCard::getCreateTime);
List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(
Wrappers.lambdaQuery(BusUserProjectRelevancy.class)
.eq(BusUserProjectRelevancy::getProjectId, req.getProjectId())
@ -313,6 +315,15 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
return TableDataInfo.build(this.getVoPage(result));
}
@Override
public TableDataInfo<BusReissueCardVo> listByAuditUser(BusReissueCardQueryReq req, PageQuery pageQuery) {
LambdaQueryWrapper<BusReissueCard> lqw = new LambdaQueryWrapper<>();
lqw.orderByDesc(BusReissueCard::getCreateTime);
lqw.eq(ObjectUtils.isNotEmpty(req.getGangerId()), BusReissueCard::getGangerId, req.getGangerId());
lqw.like(StrUtil.isNotBlank(req.getUserName()), BusReissueCard::getUserName, req.getUserName());
Page<BusReissueCard> result = this.page(pageQuery.build(), lqw);
return TableDataInfo.build(this.getVoPage(result));
}
@Override
public Long add(BusReissueCardAddReq req) {
@ -324,10 +335,28 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
if (CollUtil.isNotEmpty(busReissueCards)) {
throw new ServiceException("已提交该申请");
}
save(bean);
return bean.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateCard(BusReissueCardUpdateReq req) {
BusReissueCard bean = getById(req.getId());
if (bean == null) {
throw new ServiceException("未找到该申请");
}
BeanUtil.copyProperties(req, bean);
boolean b = updateById(bean);
if("2".equals(bean.getGangerOpinion())){
BusAttendance byId = attendanceService.getById(bean.getAttendanceId());
byId.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
}
return b;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)