考勤
This commit is contained in:
@ -91,4 +91,10 @@ public class SubConstructionUserQueryReq implements Serializable {
|
||||
*/
|
||||
private LocalDate entryDate;
|
||||
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
}
|
||||
|
@ -278,4 +278,8 @@ public class SubConstructionUserVo implements Serializable {
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 用户Id
|
||||
*/
|
||||
private Long sysUserId;
|
||||
}
|
||||
|
@ -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人机关联解绑
|
||||
*/
|
||||
|
@ -78,5 +78,10 @@ public class GpsEquipment extends BaseEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 存活状态 0-离线 1-在线
|
||||
*/
|
||||
private String alive;
|
||||
|
||||
|
||||
}
|
||||
|
@ -114,4 +114,5 @@ public class GpsEquipmentSon extends BaseEntity {
|
||||
private String remark;
|
||||
|
||||
|
||||
private Long projectId;
|
||||
}
|
||||
|
@ -114,4 +114,6 @@ public class GpsEquipmentSonBo extends BaseEntity {
|
||||
private String remark;
|
||||
|
||||
|
||||
private Long projectId;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package org.dromara.gps.domain.vo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ConstructionUser {
|
||||
|
||||
/**
|
||||
* 人员姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 系统用户id
|
||||
*/
|
||||
private Long sysUserId;
|
||||
}
|
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 提交补卡
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
|
||||
|
Reference in New Issue
Block a user