This commit is contained in:
zt
2025-03-06 16:22:37 +08:00
parent 4570788d5e
commit c286edf99f
18 changed files with 208 additions and 163 deletions

View File

@ -6,6 +6,7 @@ import com.ruoyi.bgt.domain.dto.BgtAttendanceDayDTO;
import com.ruoyi.bgt.domain.dto.BgtAttendanceDetailDTO; import com.ruoyi.bgt.domain.dto.BgtAttendanceDetailDTO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceDetailVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceDetailVO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceVO;
import com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO;
import com.ruoyi.bgt.domain.vo.BgtProjectRecruitApplyVO; import com.ruoyi.bgt.domain.vo.BgtProjectRecruitApplyVO;
import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService; import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
@ -20,6 +21,8 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(value = "App包工头考勤控制器", tags = {"App包工头考勤管理"}) @Api(value = "App包工头考勤控制器", tags = {"App包工头考勤管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired) @RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController @RestController
@ -31,22 +34,29 @@ public class AppBgtAttendanceController {
private final IBgtProjectRecruitApplyService iBgtProjectRecruitApplyService; private final IBgtProjectRecruitApplyService iBgtProjectRecruitApplyService;
@ApiOperation("App包工头总体考勤情况") @ApiOperation("App包工头总体考勤情况-统计")
@GetMapping("attendance") @GetMapping("attendance")
public AjaxResult<BgtAttendanceVO> attendanceDetail(@Validated BgtAttendanceDTO dto) { public AjaxResult<BgtAttendanceVO> attendanceDetail(@Validated BgtAttendanceDTO dto) {
return AjaxResult.success(attendanceService.attendanceDetail(dto)); return AjaxResult.success(attendanceService.attendanceDetail(dto));
} }
@ApiOperation("App包工头总体考勤情况-柱状图")
@GetMapping("attendanceList")
public AjaxResult<List<BgtDayAttendanceCountVO>> attendanceList(@Validated BgtAttendanceDTO dto) {
return AjaxResult.success(attendanceService.attendanceList(dto));
}
@ApiOperation("App包工头总体考勤情况-人员出勤情况")
@GetMapping("/todayAttendanceList")
public TableDataInfo<BgtProjectRecruitApplyVO> todayAttendanceList(@Validated BgtAttendanceDayDTO req) {
return iBgtProjectRecruitApplyService.dayAttendanceList(req);
}
@ApiOperation("App包工头考勤统计详情") @ApiOperation("App包工头考勤统计详情")
@GetMapping("attendanceDetail") @GetMapping("attendanceDetail")
public AjaxResult<BgtAttendanceDetailVO> attendanceDetail(@Validated BgtAttendanceDetailDTO dto) { public AjaxResult<BgtAttendanceDetailVO> attendanceDetail(@Validated BgtAttendanceDetailDTO dto) {
return AjaxResult.success(attendanceService.bgtAttendanceDetail(dto)); return AjaxResult.success(attendanceService.bgtAttendanceDetail(dto));
} }
@ApiOperation("总体考勤情况-人员出勤情况")
@GetMapping("/todayAttendanceList")
public TableDataInfo<BgtProjectRecruitApplyVO> todayAttendanceList(@Validated BgtAttendanceDayDTO req) {
return iBgtProjectRecruitApplyService.dayAttendanceList(req);
}
} }

View File

@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDate; import java.time.LocalDate;
@Data @Data
@ -17,6 +18,7 @@ import java.time.LocalDate;
public class BgtAttendanceDTO { public class BgtAttendanceDTO {
@ApiModelProperty("任务ID") @ApiModelProperty("任务ID")
@NotNull(message = "任务ID不能为空")
private Long taskId; private Long taskId;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")

View File

@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDate; import java.time.LocalDate;
@Data @Data
@ -27,9 +28,10 @@ public class BgtAttendanceDayDTO {
@ApiModelProperty("日期") @ApiModelProperty("日期")
private LocalDate date; private LocalDate date;
@ApiModelProperty("考勤类型1出勤 2缺勤 3迟到") @ApiModelProperty("考勤类型1正常 2异常 3请假")
private Integer attendanceType; private Integer attendanceType;
@ApiModelProperty("任务ID") @ApiModelProperty("任务ID")
@NotNull(message = "任务ID不能为空")
private Long taskId; private Long taskId;
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.bgt.domain.vo; package com.ruoyi.bgt.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -16,6 +17,7 @@ import java.util.List;
public class BgtAttendanceDetailVO { public class BgtAttendanceDetailVO {
@ApiModelProperty("务工者Id") @ApiModelProperty("务工者Id")
@JsonFormat(shape = JsonFormat.Shape.STRING)
private Long userId; private Long userId;
@ApiModelProperty("姓名") @ApiModelProperty("姓名")

View File

@ -1,5 +1,6 @@
package com.ruoyi.bgt.domain.vo; package com.ruoyi.bgt.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -25,6 +26,7 @@ public class BgtDailyClockDetailVO {
private String recruitName; private String recruitName;
/** 人员ID */ /** 人员ID */
@ApiModelProperty("人员ID") @ApiModelProperty("人员ID")
@JsonFormat(shape = JsonFormat.Shape.STRING)
private Long userId; private Long userId;
@ApiModelProperty("头像地址") @ApiModelProperty("头像地址")

View File

@ -0,0 +1,33 @@
package com.ruoyi.bgt.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.time.LocalDate;
/**
* 考勤打卡对象 wgz_attendance
*
* @author ruoyi
* @date 2025-02-20
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel("务工者每天考勤打卡统计对象")
public class BgtDayAttendanceCountVO {
@ApiModelProperty("到岗人数")
private Integer reportToDutyNum;
@ApiModelProperty("日期")
private LocalDate date;
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.bgt.domain.vo; package com.ruoyi.bgt.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -30,6 +31,7 @@ public class BgtMessageVO implements Serializable {
private Long tableId; private Long tableId;
@ApiModelProperty("发送人") @ApiModelProperty("发送人")
@JsonFormat(shape = JsonFormat.Shape.STRING)
private Long senderId; private Long senderId;
@ApiModelProperty("标题") @ApiModelProperty("标题")

View File

@ -90,6 +90,7 @@ public class BgtProjectRecruitDetailVO implements Serializable {
private String typeOfWork; private String typeOfWork;
@ApiModelProperty("创建者ID") @ApiModelProperty("创建者ID")
@JsonFormat(shape = JsonFormat.Shape.STRING)
private Long userId; private Long userId;
@ApiModelProperty("发布时间") @ApiModelProperty("发布时间")

View File

@ -28,7 +28,7 @@ public interface BgtProjectRecruitApplyMapper extends BaseMapperPlus<BgtProjectR
List<BgtProjectRecruitApplyVO> appQueryList(@Param("dto") BgtProjectRecruitApplyQueryDTO dto); List<BgtProjectRecruitApplyVO> appQueryList(@Param("dto") BgtProjectRecruitApplyQueryDTO dto);
Page<BgtProjectRecruitApplyVO> dayAttendanceList(@Param("page")Page<BgtAttendanceDayDTO> queryDTOPage,@Param("dto") BgtAttendanceDayDTO dto); // Page<BgtProjectRecruitApplyVO> dayAttendanceList(@Param("page")Page<BgtAttendanceDayDTO> queryDTOPage,@Param("dto") BgtAttendanceDayDTO dto);
Page<BgtProjectRecruitApplyVO> todayAttendanceList(@Param("page")Page<BgtAttendanceDayDTO> queryDTOPage,@Param("dto") BgtAttendanceDayDTO dto); Page<BgtProjectRecruitApplyVO> todayAttendanceList(@Param("page")Page<BgtAttendanceDayDTO> queryDTOPage,@Param("dto") BgtAttendanceDayDTO dto);
// 获取指定项目下的所有成员(分页) // 获取指定项目下的所有成员(分页)

View File

@ -47,7 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalAdjusters;
import java.util.*; import java.util.*;
@ -326,20 +325,8 @@ public class BgtProjectRecruitApplyServiceImpl extends ServicePlusImpl<BgtProjec
Page<BgtAttendanceDayDTO> queryDTOPage = new Page<>(); Page<BgtAttendanceDayDTO> queryDTOPage = new Page<>();
queryDTOPage.setCurrent(dto.getPageNum()); queryDTOPage.setCurrent(dto.getPageNum());
queryDTOPage.setSize(dto.getPageSize()); queryDTOPage.setSize(dto.getPageSize());
Page<BgtProjectRecruitApplyVO> queryVOPage = baseMapper.todayAttendanceList(queryDTOPage, dto);
// 获取当前时间
LocalTime currentTime = LocalTime.now();
// 定义目标时间12:10 12点才会录入当天所有人的考勤数据
LocalTime targetTime = LocalTime.of(12, 10);
// 判断当前时间是否在12:10之后
Page<BgtProjectRecruitApplyVO> queryVOPage;
if (currentTime.isAfter(targetTime)) {
queryVOPage = baseMapper.dayAttendanceList(queryDTOPage, dto);
} else {
queryVOPage = baseMapper.todayAttendanceList(queryDTOPage, dto);
}
return PageUtils.buildDataInfo(queryVOPage); return PageUtils.buildDataInfo(queryVOPage);
} }
@Override @Override

View File

@ -2,6 +2,7 @@ package com.ruoyi.common.util;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO;
import com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
@ -11,29 +12,29 @@ import java.util.*;
public class DataUtil { public class DataUtil {
public static List<BgtAttendanceCountVO> fillMissingDates(List<BgtAttendanceCountVO> countVOS, LocalDate startDate, LocalDate endDate) { public static List<BgtDayAttendanceCountVO> fillMissingDates(List<BgtDayAttendanceCountVO> countVOS, LocalDate startDate, LocalDate endDate) {
// 使用 HashSet 存储已有的日期,方便快速查找 // 使用 HashSet 存储已有的日期,方便快速查找
Set<LocalDate> existingDates = new HashSet<>(); Set<LocalDate> existingDates = new HashSet<>();
for (BgtAttendanceCountVO vo : countVOS) { for (BgtDayAttendanceCountVO vo : countVOS) {
existingDates.add(vo.getDate()); existingDates.add(vo.getDate());
} }
// 创建一个新的列表,用于存储补充后的结果 // 创建一个新的列表,用于存储补充后的结果
List<BgtAttendanceCountVO> filledList = new ArrayList<>(countVOS); List<BgtDayAttendanceCountVO> filledList = new ArrayList<>(countVOS);
// 遍历日期范围,补充缺失的日期 // 遍历日期范围,补充缺失的日期
LocalDate currentDate = startDate; LocalDate currentDate = startDate;
while (!currentDate.isAfter(endDate)) { while (!currentDate.isAfter(endDate)) {
if (!existingDates.contains(currentDate)) { if (!existingDates.contains(currentDate)) {
// 如果当前日期不在已有日期集合中,创建一个新的 BgtAttendanceCountVO 对象并添加到结果列表中 // 如果当前日期不在已有日期集合中,创建一个新的 BgtAttendanceCountVO 对象并添加到结果列表中
filledList.add(new BgtAttendanceCountVO(0,0,currentDate,0,0,0)); filledList.add(new BgtDayAttendanceCountVO(0,currentDate));
} }
// 日期递增一天 // 日期递增一天
currentDate = currentDate.plusDays(1); currentDate = currentDate.plusDays(1);
} }
// 对结果列表按日期排序 // 对结果列表按日期排序
filledList.sort(Comparator.comparing(BgtAttendanceCountVO::getDate)); filledList.sort(Comparator.comparing(BgtDayAttendanceCountVO::getDate));
return filledList; return filledList;
} }

View File

@ -1,6 +1,7 @@
package com.ruoyi.fbs.domain.vo; package com.ruoyi.fbs.domain.vo;
import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO;
import com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -27,7 +28,7 @@ public class AppTaskDetailAttendanceVO {
private Integer reportToDutyRate= 0; private Integer reportToDutyRate= 0;
@ApiModelProperty("考勤列表") @ApiModelProperty("考勤列表")
List<BgtAttendanceCountVO> countVOS; List<BgtDayAttendanceCountVO> countVOS;

View File

@ -10,7 +10,7 @@ import com.ruoyi.bgt.bo.BgtProjectRecruitQueryBo;
import com.ruoyi.bgt.domain.BgtProjectRecruit; import com.ruoyi.bgt.domain.BgtProjectRecruit;
import com.ruoyi.bgt.domain.dto.BgtProjectRecruitApplyQueryDTO; import com.ruoyi.bgt.domain.dto.BgtProjectRecruitApplyQueryDTO;
import com.ruoyi.bgt.domain.dto.BgtWageApplicationQueryDTO; import com.ruoyi.bgt.domain.dto.BgtWageApplicationQueryDTO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO; import com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO;
import com.ruoyi.bgt.domain.vo.BgtProjectRecruitApplyVO; import com.ruoyi.bgt.domain.vo.BgtProjectRecruitApplyVO;
import com.ruoyi.bgt.domain.vo.BgtWageApplicationListVO; import com.ruoyi.bgt.domain.vo.BgtWageApplicationListVO;
import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService; import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService;
@ -209,19 +209,18 @@ public class FbsProjectTaskServiceImpl extends ServicePlusImpl<FbsProjectTaskMap
if (taskBeginTime!=null &&taskBeginTime.isAfter(startTime)){ if (taskBeginTime!=null &&taskBeginTime.isAfter(startTime)){
startTime = taskBeginTime; startTime = taskBeginTime;
} }
List<BgtAttendanceCountVO> List<BgtDayAttendanceCountVO> countVOS = attendanceService.countDayByTaskId(id, startTime, date);
countVOS = attendanceService.countByTaskId(id, startTime, date); // 补充缺失的天数
if(CollectionUtil.isNotEmpty(countVOS)){ List<BgtDayAttendanceCountVO> bgtDayAttendanceCountVOS = DataUtil.fillMissingDates(countVOS, startTime, date);
BgtAttendanceCountVO vo = countVOS.get(0); //查询当天的总人数
appTaskDetailVO.setCountVOS(DataUtil.fillMissingDates(countVOS, startTime, date)); Integer totalNum = attendanceService.dayTotalNum(id, date);
appTaskDetailVO.setTotalNum(vo.getTotalNum()); appTaskDetailVO.setTotalNum(totalNum);
appTaskDetailVO.setReportToDutyNum(vo.getReportToDutyNum()); //计算到岗率
if(vo.getTotalNum()!=0){ if(totalNum!=0){
int rate = new BigDecimal(vo.getReportToDutyNum()).divide(new BigDecimal(vo.getTotalNum()), 2, RoundingMode.HALF_UP) BgtDayAttendanceCountVO bgtDayAttendanceCountVO = bgtDayAttendanceCountVOS.get(bgtDayAttendanceCountVOS.size() - 1);
.multiply(new BigDecimal(100)).intValue(); int rate = new BigDecimal(bgtDayAttendanceCountVO.getReportToDutyNum()).divide(new BigDecimal(totalNum), 2, RoundingMode.HALF_UP)
appTaskDetailVO.setReportToDutyRate(rate); .multiply(new BigDecimal(100)).intValue();
} appTaskDetailVO.setReportToDutyRate(rate);
} }
return appTaskDetailVO; return appTaskDetailVO;
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.wgz.mapper; package com.ruoyi.wgz.mapper;
import com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO;
import com.ruoyi.wgz.domain.WgzAttendance; import com.ruoyi.wgz.domain.WgzAttendance;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache; import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
@ -24,6 +25,9 @@ public interface WgzAttendanceMapper extends BaseMapperPlus<WgzAttendance> {
List<BgtAttendanceCountVO> countByTaskId(@Param("taskId") Long taskId, @Param("beginDate")LocalDate beginDate List<BgtAttendanceCountVO> countByTaskId(@Param("taskId") Long taskId, @Param("beginDate")LocalDate beginDate
, @Param("endDate")LocalDate endDate); , @Param("endDate")LocalDate endDate);
List<BgtDayAttendanceCountVO> countDayByTaskId(@Param("taskId") Long taskId, @Param("beginDate")LocalDate beginDate
, @Param("endDate")LocalDate endDate);
Integer dayTotalNum(@Param("taskId") Long taskId, @Param("date")LocalDate date); Integer dayTotalNum(@Param("taskId") Long taskId, @Param("date")LocalDate date);
Integer monthTotalNum(@Param("taskId") Long taskId, @Param("beginDate")LocalDate beginDate Integer monthTotalNum(@Param("taskId") Long taskId, @Param("beginDate")LocalDate beginDate

View File

@ -5,6 +5,7 @@ import com.ruoyi.bgt.domain.dto.BgtAttendanceDetailDTO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceDetailVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceDetailVO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceVO; import com.ruoyi.bgt.domain.vo.BgtAttendanceVO;
import com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO;
import com.ruoyi.common.core.mybatisplus.core.IServicePlus; import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.wgz.bo.WgzAttendanceQueryBo; import com.ruoyi.wgz.bo.WgzAttendanceQueryBo;
@ -106,6 +107,11 @@ public interface IWgzAttendanceService extends IServicePlus<WgzAttendance> {
*/ */
List<BgtAttendanceCountVO> countByTaskId(Long taskId, LocalDate beginDate, LocalDate endDate); List<BgtAttendanceCountVO> countByTaskId(Long taskId, LocalDate beginDate, LocalDate endDate);
/**
* 统计任务每天打卡情况
*/
List<BgtDayAttendanceCountVO> countDayByTaskId(Long taskId, LocalDate beginDate, LocalDate endDate);
/** /**
* 统计某天应打卡人数 * 统计某天应打卡人数
*/ */
@ -113,10 +119,12 @@ public interface IWgzAttendanceService extends IServicePlus<WgzAttendance> {
Integer monthTotalNum(Long taskId,LocalDate beginDate, LocalDate endDate); Integer monthTotalNum(Long taskId,LocalDate beginDate, LocalDate endDate);
/** /**
* 总体考勤情况 * 总体考勤情况-统计
*/ */
BgtAttendanceVO attendanceDetail(BgtAttendanceDTO dto); BgtAttendanceVO attendanceDetail(BgtAttendanceDTO dto);
List<BgtDayAttendanceCountVO> attendanceList(BgtAttendanceDTO dto);
/** /**
* 考勤详情,查询指定用户指定项目的指定天数考勤情况统计如若用户输入20但实际只有2天出勤 * 考勤详情,查询指定用户指定项目的指定天数考勤情况统计如若用户输入20但实际只有2天出勤
* 如若num为0,那么表示查询所有天数的考勤情况统计; * 如若num为0,那么表示查询所有天数的考勤情况统计;

View File

@ -10,14 +10,12 @@ import com.ruoyi.bgt.domain.BgtProjectRecruit;
import com.ruoyi.bgt.domain.BgtProjectRecruitApply; import com.ruoyi.bgt.domain.BgtProjectRecruitApply;
import com.ruoyi.bgt.domain.dto.BgtAttendanceDTO; import com.ruoyi.bgt.domain.dto.BgtAttendanceDTO;
import com.ruoyi.bgt.domain.dto.BgtAttendanceDetailDTO; import com.ruoyi.bgt.domain.dto.BgtAttendanceDetailDTO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceCountVO; import com.ruoyi.bgt.domain.vo.*;
import com.ruoyi.bgt.domain.vo.BgtAttendanceDetailVO;
import com.ruoyi.bgt.domain.vo.BgtAttendanceVO;
import com.ruoyi.bgt.domain.vo.WgzAttendanceRecordVO;
import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService; import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService;
import com.ruoyi.bgt.service.IBgtProjectRecruitService; import com.ruoyi.bgt.service.IBgtProjectRecruitService;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.util.DataUtil; import com.ruoyi.common.util.DataUtil;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.PageUtils;
@ -42,8 +40,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.*; import java.time.*;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -402,6 +398,11 @@ public class WgzAttendanceServiceImpl extends ServicePlusImpl<WgzAttendanceMappe
return baseMapper.countByTaskId(taskId, beginDate, endDate); return baseMapper.countByTaskId(taskId, beginDate, endDate);
} }
@Override
public List<BgtDayAttendanceCountVO> countDayByTaskId(Long taskId, LocalDate beginDate, LocalDate endDate){
return baseMapper.countDayByTaskId(taskId, beginDate, endDate);
}
@Override @Override
public Integer dayTotalNum(Long taskId,LocalDate date){ public Integer dayTotalNum(Long taskId,LocalDate date){
return baseMapper.dayTotalNum(taskId,date); return baseMapper.dayTotalNum(taskId,date);
@ -414,110 +415,83 @@ public class WgzAttendanceServiceImpl extends ServicePlusImpl<WgzAttendanceMappe
@Override @Override
public BgtAttendanceVO attendanceDetail(BgtAttendanceDTO dto) { public BgtAttendanceVO attendanceDetail(BgtAttendanceDTO dto) {
BgtAttendanceVO bgtAttendanceVO = new BgtAttendanceVO(); BgtAttendanceVO bgtAttendanceVO = new BgtAttendanceVO();
FbsProjectTask task = taskService.getById(dto.getTaskId()); FbsProjectTask task = taskService.getById(dto.getTaskId());
validTaskTime(task, dto.getDate());
bgtAttendanceVO.setTaskId(task.getId()); bgtAttendanceVO.setTaskId(task.getId());
bgtAttendanceVO.setTaskName(task.getTaskName()); bgtAttendanceVO.setTaskName(task.getTaskName());
LocalDate date = dto.getDate(); LocalDate date = dto.getDate();
LocalDate startData = null; //当天总人数
LocalDate endData = null; Integer totalNum = dayTotalNum(task.getId(), date);
LocalDate now = LocalDate.now(); bgtAttendanceVO.setTotalNum(totalNum);
if (dto.getDateType().equals(DateUtils.DAY)) { //今日到岗人数
// 获取本月开始日期 List<BgtDayAttendanceCountVO> countVOS = countDayByTaskId(dto.getTaskId(), date, date);
startData = date.with(TemporalAdjusters.firstDayOfMonth()); if(CollectionUtil.isNotEmpty(countVOS)){
endData = date; bgtAttendanceVO.setReportToDutyNum(countVOS.get(0).getReportToDutyNum());
}
List<BgtAttendanceCountVO> countVOS = countByTaskId(dto.getTaskId(), startData, endData);
List<BgtAttendanceCountVO> bgtAttendanceCountVOS = DataUtil.fillMissingDates(countVOS, startData, endData); //缺勤人数
bgtAttendanceVO.setAbsenceDutyNum(totalNum-bgtAttendanceVO.getReportToDutyNum());
// 因为当天可能还没有生成所有人的考勤数据,所以应到的总人数需要单独查询
// 判断当天是否在开始日期和结束日期之间(包含开始和结束日期) //任务拥有的所有招工
boolean isBetween = (now.isAfter(startData) || now.isEqual(startData)) List<BgtProjectRecruit> bgtProjectRecruits = iBgtProjectRecruitService.getBaseMapper().selectList(Wrappers.<BgtProjectRecruit>lambdaQuery()
&& (now.isBefore(endData) || now.isEqual(endData)); .eq(BgtProjectRecruit::getTaskId, dto.getTaskId()));
if (isBetween) { List<Long> recruitIds = bgtProjectRecruits.stream().map(BgtProjectRecruit::getId).collect(Collectors.toList());
Integer i = dayTotalNum(task.getId(), now); if (CollectionUtil.isNotEmpty(recruitIds)) {
BgtAttendanceCountVO countVO = bgtAttendanceCountVOS.stream() //请假人数
.filter(vo -> vo.getDate().isEqual(now)) Integer leaveNum = baseMapper.selectCount(Wrappers.<WgzAttendance>lambdaQuery().isNotNull(WgzAttendance::getLeaveMarkId)
.findFirst().orElse(null); .in(WgzAttendance::getRecruitId, recruitIds).eq(WgzAttendance::getDate, date));
countVO.setTotalNum(i); bgtAttendanceVO.setLeaveNum(leaveNum);
}
//迟到人数
bgtAttendanceVO.setCountVOs(bgtAttendanceCountVOS); Integer lateNum = baseMapper.selectCount(Wrappers.<WgzAttendance>lambdaQuery().eq(WgzAttendance::getLate, 1)
// 找出查询日期的考勤数据 .eq(WgzAttendance::getRecruitId, recruitIds).eq(WgzAttendance::getDate, date));
BgtAttendanceCountVO countVO = bgtAttendanceCountVOS.stream() bgtAttendanceVO.setLateNum(lateNum);
.filter(vo -> vo.getDate().isEqual(date))
.findFirst().orElse(null); //早退人数
if (countVO != null) { Integer earlyLeaveNum = baseMapper.selectCount(Wrappers.<WgzAttendance>lambdaQuery().eq(WgzAttendance::getEarlyLeave, 1)
bgtAttendanceVO.setReportToDutyNum(countVO.getReportToDutyNum()); .in(WgzAttendance::getRecruitId, recruitIds).eq(WgzAttendance::getDate, date));
bgtAttendanceVO.setTotalNum(countVO.getTotalNum()); bgtAttendanceVO.setEarlyLeaveNum(earlyLeaveNum);
bgtAttendanceVO.setAbsenceDutyNum(countVO.getTotalNum() - countVO.getReportToDutyNum());
if (bgtAttendanceVO.getTotalNum() != 0) {
int rate = new BigDecimal(bgtAttendanceVO.getReportToDutyNum()).divide(new BigDecimal(bgtAttendanceVO.getTotalNum()), 2, RoundingMode.HALF_UP)
.multiply(new BigDecimal(100)).intValue();
bgtAttendanceVO.setReportToDutyRate(rate);
}
}
} else if (dto.getDateType().equals(DateUtils.MONTH)) {
// 获取本年开始日期
startData = date.with(TemporalAdjusters.firstDayOfYear());
endData = date.with(TemporalAdjusters.lastDayOfMonth());
if(endData.isAfter(now)){
endData= now;
}
List<BgtAttendanceCountVO> countVOS = countByTaskId(dto.getTaskId(), startData, endData);
// 因为当天可能还没有生成所有人的考勤数据,所以应到的总人数需要单独查询
// 判断当天是否在开始日期和结束日期之间(包含开始和结束日期)
boolean isBetween = (now.isAfter(startData) || now.isEqual(startData))
&& (now.isBefore(endData) || now.isEqual(endData));
if (isBetween) {
Integer i = dayTotalNum(task.getId(), now);
BgtAttendanceCountVO countVO = countVOS.stream()
.filter(vo -> vo.getDate().isEqual(now))
.findFirst().orElse(null);
if (countVO != null) {
countVO.setTotalNum(i);
}else {
BgtAttendanceCountVO bgtAttendanceCountVO = new BgtAttendanceCountVO(0, i, now, 0, 0, 0);
countVOS.add(bgtAttendanceCountVO);
}
}
List<BgtAttendanceCountVO> bgtAttendanceCountVOS = DataUtil.statisticsByMonth(countVOS, startData, endData);
bgtAttendanceVO.setCountVOs(bgtAttendanceCountVOS);
BgtAttendanceCountVO countVO = bgtAttendanceCountVOS.stream()
.filter(vo -> YearMonth.from(vo.getDate()).equals(YearMonth.from(date)))
.findFirst().orElse(null);
if (countVO != null) {
bgtAttendanceVO.setReportToDutyNum(countVO.getReportToDutyNum());
bgtAttendanceVO.setTotalNum(countVO.getTotalNum());
bgtAttendanceVO.setAbsenceDutyNum(countVO.getAbsenceDutyNum());
int rate = new BigDecimal(countVO.getRateSum()).divide(new BigDecimal(countVO.getRateDay()), 2, RoundingMode.HALF_UP).intValue();
bgtAttendanceVO.setReportToDutyRate(rate);
}
//设置本月的总人数
bgtAttendanceVO.setTotalNum(monthTotalNum(task.getId(), date.with(TemporalAdjusters.firstDayOfMonth()), endData));
} }
getLateAndLeave(bgtAttendanceVO, startData, endData);
return bgtAttendanceVO; return bgtAttendanceVO;
} }
public void getLateAndLeave(BgtAttendanceVO vo, LocalDate startDate, LocalDate endDate) { @Override
List<BgtProjectRecruit> bgtProjectRecruits = iBgtProjectRecruitService.getBaseMapper().selectList(Wrappers.<BgtProjectRecruit>lambdaQuery() public List<BgtDayAttendanceCountVO> attendanceList(BgtAttendanceDTO dto) {
.eq(BgtProjectRecruit::getTaskId, vo.getTaskId())); FbsProjectTask task = taskService.getById(dto.getTaskId());
List<Long> recruitIds = bgtProjectRecruits.stream().map(BgtProjectRecruit::getId).collect(Collectors.toList()); validTaskTime(task, dto.getDate());
if (CollectionUtil.isNotEmpty(recruitIds)) {
Integer late = baseMapper.selectCount(Wrappers.<WgzAttendance>lambdaQuery().eq(WgzAttendance::getLate, 1) LocalDate taskBeginTime = DateUtils.str2Localdate(task.getTaskBeginTime(), DateUtils.YYYY_MM_DD);
.eq(WgzAttendance::getRecruitId, recruitIds).between(WgzAttendance::getDate, startDate, endDate)); LocalDate date = dto.getDate();
Integer leave = baseMapper.selectCount(Wrappers.<WgzAttendance>lambdaQuery().isNotNull(WgzAttendance::getLeaveMarkId)
.in(WgzAttendance::getRecruitId, recruitIds).between(WgzAttendance::getDate, startDate, endDate)); LocalDate startTime = date.minusDays(7);
vo.setLateNum(late); if (taskBeginTime!=null &&taskBeginTime.isAfter(startTime)){
vo.setLeaveNum(leave); startTime = taskBeginTime;
}
return countDayByTaskId(dto.getTaskId(), startTime, date);
}
public void validTaskTime(FbsProjectTask task,LocalDate date){
LocalDate taskBeginTime = DateUtils.str2Localdate(task.getTaskBeginTime(), DateUtils.YYYY_MM_DD);
LocalDate taskEndTime = DateUtils.str2Localdate(task.getTaskEndTime(), DateUtils.YYYY_MM_DD);
if(taskEndTime == null){
taskEndTime = LocalDate.now();
}
if(date.isBefore(taskBeginTime) || date.isAfter(taskEndTime)){
throw new BaseException("当前日期不在任务时间范围内");
} }
} }
// @Override // @Override
// public WgzAttendance findByUserIdWait(Long appUserId, Long recruitId, String date) { // public WgzAttendance findByUserIdWait(Long appUserId, Long recruitId, String date) {
// LambdaQueryWrapper<WgzAttendance> qw = new LambdaQueryWrapper<>(); // LambdaQueryWrapper<WgzAttendance> qw = new LambdaQueryWrapper<>();
// qw.eq(WgzAttendance::getRecruitId,recruitId); // qw.eq(WgzAttendance::getRecruitId,recruitId);

View File

@ -98,30 +98,37 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="todayAttendanceList" resultType="com.ruoyi.bgt.domain.vo.BgtProjectRecruitApplyVO"> <select id="todayAttendanceList" resultType="com.ruoyi.bgt.domain.vo.BgtProjectRecruitApplyVO">
SELECT bpra.id, SELECT bpra.id,
bpra.entry_time, bpra.entry_time,
wu.user_id, bpra.user_id,
wu.phone, wu.phone,
wu.score, wu.score,
wu.avatar_name, wu.avatar_name,
wu.username, wu.username,
wu.type_of_work, wu.type_of_work,
bpr.recruit_name, bpr.recruit_name,
fpt.task_name, fpt.task_name,
CASE CASE
WHEN wa.leave_mark_id IS NOT NULL THEN '请假' WHEN wa.leave_mark_id = 1 THEN '请假'
WHEN wa.late = 1 THEN '迟到' WHEN wa.late = 0 and wa.early_leave = 0 and wa.missed_in = 0 and wa.missed_out = 0 THEN '正常'
WHEN wa.early_leave = 1 THEN '早退' WHEN wa.late = 1 or wa.early_leave = 1 or wa.missed_in = 1 or wa.missed_out = 1 THEN '异常'
WHEN wa.missed_in = 0 OR wa.missed_out = 0 THEN '出勤' ELSE '异常'
ELSE '缺勤' END AS attendance_status
END AS attendance_status
FROM bgt_project_recruit_apply bpra FROM bgt_project_recruit_apply bpra
LEFT JOIN wgz_user wu ON bpra.user_id = wu.user_id LEFT JOIN bgt_project_recruit bpr ON bpr.id = bpra.recruit_id
LEFT JOIN wgz_attendance wa ON wa.user_id = wu.user_id AND wa.recruit_id = bpra.recruit_id AND wa.date = #{dto.date} LEFT JOIN fbs_project_task fpt ON fpt.id = bpr.task_id
LEFT JOIN bgt_project_recruit bpr ON bpr.id = bpra.recruit_id LEFT JOIN wgz_user wu ON bpra.user_id = wu.user_id
LEFT JOIN fbs_project_task fpt ON fpt.id = bpr.task_id LEFT JOIN wgz_attendance wa ON wa.user_id = wu.user_id AND wa.recruit_id = bpra.recruit_id AND wa.date = #{dto.date}
WHERE bpra.status = '5' and bpra.recruit_id IN (SELECT id WHERE bpra.entry_time &lt;= #{dto.date} and ((bpra.leave_time is null and bpra.status = '5')or leave_time>=#{dto.date})
FROM bgt_project_recruit and bpra.recruit_id IN (SELECT id FROM bgt_project_recruit WHERE task_id = #{dto.taskId})
WHERE task_id = #{dto.taskId}) <if test="dto.attendanceType !=null and dto.attendanceType ==1 ">
and (wa.late = 0 and wa.early_leave = 0 and wa.missed_in = 0 and wa.missed_out = 0) and leave_mark_id is null
</if>
<if test="dto.attendanceType !=null and dto.attendanceType ==2 ">
(wa.late = 1 or wa.early_leave = 1 or wa.missed_in = 1 or wa.missed_out = 1) and leave_mark_id is null
</if>
<if test="dto.attendanceType !=null and dto.attendanceType ==3 ">
and wa.leave_mark_id = 1
</if>
</select> </select>
<select id="underwayPage" resultType="com.ruoyi.wgz.bo.res.WgzAppUnderwayRes"> <select id="underwayPage" resultType="com.ruoyi.wgz.bo.res.WgzAppUnderwayRes">

View File

@ -42,6 +42,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
group by date order by date group by date order by date
</select> </select>
<select id="countDayByTaskId" resultType="com.ruoyi.bgt.domain.vo.BgtDayAttendanceCountVO">
select count(1) as reportToDutyNum,
date
from wgz_attendance
where date between #{beginDate} and #{endDate}
and (clock_in_time is not null or clock_out_time is not null)
and recruit_id in (select id from bgt_project_recruit where task_id = #{taskId} )
group by date order by date
</select>
<select id="dayTotalNum" resultType="Integer"> <select id="dayTotalNum" resultType="Integer">
select count(1) from bgt_project_recruit_apply where entry_time &lt;= #{date} and ((leave_time is null and status = '5')or leave_time>=#{date}) select count(1) from bgt_project_recruit_apply where entry_time &lt;= #{date} and ((leave_time is null and status = '5')or leave_time>=#{date})