diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CommonConstant.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CommonConstant.java deleted file mode 100644 index 6281e7d8..00000000 --- a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CommonConstant.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.dromara.common.core.constant; - -/** - * 通用常量 - */ -public interface CommonConstant { - - /** - * 升序 - */ - String SORT_ORDER_ASC = "ascend"; - - /** - * 降序 - */ - String SORT_ORDER_DESC = " descend"; - -} diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/DateConstant.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/DateConstant.java new file mode 100644 index 00000000..edfc8f61 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/DateConstant.java @@ -0,0 +1,14 @@ +package org.dromara.common.core.constant; + +import java.util.regex.Pattern; + +/** + * @author lcj + * @date 2025/4/7 17:12 + */ +public interface DateConstant { + + // 匹配 "yyyy-MM",年四位,月 01~12 + Pattern YEAR_MONTH_PATTERN = Pattern.compile("^\\d{4}-(0[1-9]|1[0-2])$"); + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceController.java index b2e0d04d..4c93576f 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceController.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusAttendanceController.java @@ -2,22 +2,18 @@ package org.dromara.project.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; import org.dromara.common.excel.utils.ExcelUtil; -import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; -import org.dromara.project.domain.req.attendance.AttendanceCreateReq; import org.dromara.project.domain.req.attendance.AttendanceQueryReq; -import org.dromara.project.domain.req.attendance.AttendanceUpdateReq; +import org.dromara.project.domain.req.attendance.AttendanceQueryTwoWeekReq; +import org.dromara.project.domain.resp.attendance.AttendanceClockDateForTwoWeekResp; import org.dromara.project.domain.vo.BusAttendanceVo; import org.dromara.project.service.IBusAttendanceService; import org.springframework.validation.annotation.Validated; @@ -29,7 +25,7 @@ import java.util.List; * 考勤 * * @author lcj - * @date 2025-03-26 + * @date 2025-04-07 */ @Validated @RequiredArgsConstructor @@ -48,6 +44,15 @@ public class BusAttendanceController extends BaseController { return busAttendanceService.queryPageList(req, pageQuery); } + /** + * 查询近两周考勤列表 + */ + @SaCheckPermission("project:attendance:list") + @GetMapping("/list/clockDate/twoWeek") + public R> listClockDateForTwoWeek(AttendanceQueryTwoWeekReq req) { + return R.ok(busAttendanceService.listClockDateForTwoWeek(req)); + } + /** * 导出考勤列表 */ @@ -71,38 +76,4 @@ public class BusAttendanceController extends BaseController { return R.ok(busAttendanceService.queryById(id)); } - /** - * 新增考勤 - */ - @SaCheckPermission("project:attendance:add") - @Log(title = "考勤", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody AttendanceCreateReq req) { - return R.ok(busAttendanceService.insertByBo(req)); - } - - /** - * 修改考勤 - */ - @SaCheckPermission("project:attendance:edit") - @Log(title = "考勤", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody AttendanceUpdateReq req) { - return toAjax(busAttendanceService.updateByBo(req)); - } - - /** - * 删除考勤 - * - * @param ids 主键串 - */ - @SaCheckPermission("project:attendance:remove") - @Log(title = "考勤", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(busAttendanceService.deleteWithValidByIds(List.of(ids), true)); - } } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusConstructionUserController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusConstructionUserController.java index 48c64bda..2e5dbc0d 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusConstructionUserController.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusConstructionUserController.java @@ -17,6 +17,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; import org.dromara.project.domain.exportvo.BusConstructionUserExportVo; import org.dromara.project.domain.req.constructionuser.*; +import org.dromara.project.domain.resp.constructionuser.ConstructionUserAttendanceMonthResp; +import org.dromara.project.domain.resp.constructionuser.ConstructionUserAttendanceTotalResp; import org.dromara.project.domain.vo.BusConstructionUserVo; import org.dromara.project.service.IBusConstructionUserService; import org.springframework.validation.annotation.Validated; @@ -47,6 +49,25 @@ public class BusConstructionUserController extends BaseController { return busConstructionUserService.queryPageList(req, pageQuery); } + /** + * 查询每个施工人员总的考勤列表 + */ + @SaCheckPermission("project:attendance:list") + @GetMapping("/list/attendance/total") + public TableDataInfo listAttendanceTotal(ConstructionUserAttendanceQueryReq req, + PageQuery pageQuery) { + return busConstructionUserService.queryPageAttendanceList(req, pageQuery); + } + + /** + * 查询施工人员月份考勤列表 + */ + @SaCheckPermission("project:constructionUser:list") + @GetMapping("/list/attendance/month") + public R> listAttendanceMonth(ConstructionUserAttendanceMonthReq req) { + return R.ok(busConstructionUserService.queryAttendanceMonthList(req)); + } + /** * 导出施工人员列表 */ diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendance.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendance.java index becda69a..9b075034 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendance.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusAttendance.java @@ -14,7 +14,7 @@ import java.util.Date; * 考勤对象 bus_attendance * * @author lcj - * @date 2025-03-26 + * @date 2025-04-07 */ @Data @EqualsAndHashCode(callSuper = true) @@ -51,19 +51,24 @@ public class BusAttendance extends BaseEntity { private Long projectId; /** - * 打卡时间 + * 上班打卡时间 */ - private String clockTime; + private Date clockTime; /** - * 1正常,2迟到,3早退,4缺勤,5补卡 + * 打卡日期 + */ + private Date clockDate; + + /** + * 打卡状态(1正常,2迟到,3早退,4缺勤,5补卡) */ private String clockStatus; /** * 代打人员id */ - private String pinchUserId; + private Long pinchUserId; /** * 多次打卡时间记录 @@ -75,6 +80,26 @@ public class BusAttendance extends BaseEntity { */ private String commuter; + /** + * 打卡范围 + */ + private String punchRange; + + /** + * 日薪 + */ + private Long dailyWage; + + /** + * 经度 + */ + private String lng; + + /** + * 纬度 + */ + private String lat; + /** * 备注 */ diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceClockStatusEnum.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceClockStatusEnum.java new file mode 100644 index 00000000..81441ecd --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceClockStatusEnum.java @@ -0,0 +1,46 @@ +package org.dromara.project.domain.enums; + +import lombok.Getter; +import org.dromara.common.core.utils.ObjectUtils; + +/** + * @author lcj + * @date 2025/4/7 11:31 + */ +@Getter +public enum ConstructionUserAttendanceClockStatusEnum { + + NORMAL("正常", "1"), + LATE("迟到", "2"), + LEAVEEARLY("早退", "3"), + UNCLOCK("缺卡", "4"), + REISSUE("补卡", "5"); + + private final String text; + + private final String value; + + ConstructionUserAttendanceClockStatusEnum(String text, String value) { + this.text = text; + this.value = value; + } + + /** + * 根据 value 获取枚举 + * + * @param value 项目成员岗位枚举值 + * @return 项目成员岗位枚举 + */ + public static ConstructionUserAttendanceClockStatusEnum getEnumByValue(String value) { + if (ObjectUtils.isEmpty(value)) { + return null; + } + for (ConstructionUserAttendanceClockStatusEnum anEnum : ConstructionUserAttendanceClockStatusEnum.values()) { + if (anEnum.value.equals(value)) { + return anEnum; + } + } + return null; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceCommuterEnum.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceCommuterEnum.java new file mode 100644 index 00000000..4aad43c6 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceCommuterEnum.java @@ -0,0 +1,43 @@ +package org.dromara.project.domain.enums; + +import lombok.Getter; +import org.dromara.common.core.utils.ObjectUtils; + +/** + * @author lcj + * @date 2025/4/7 12:29 + */ +@Getter +public enum ConstructionUserAttendanceCommuterEnum { + + CLOCKIN("上班", "1"), + CLOCKOUT("下班", "2"); + + private final String text; + + private final String value; + + ConstructionUserAttendanceCommuterEnum(String text, String value) { + this.text = text; + this.value = value; + } + + /** + * 根据 value 获取枚举 + * + * @param value 项目成员岗位枚举值 + * @return 项目成员岗位枚举 + */ + public static ConstructionUserAttendanceCommuterEnum getEnumByValue(String value) { + if (ObjectUtils.isEmpty(value)) { + return null; + } + for (ConstructionUserAttendanceCommuterEnum anEnum : ConstructionUserAttendanceCommuterEnum.values()) { + if (anEnum.value.equals(value)) { + return anEnum; + } + } + return null; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceStatusEnum.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceStatusEnum.java new file mode 100644 index 00000000..304ba490 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/enums/ConstructionUserAttendanceStatusEnum.java @@ -0,0 +1,44 @@ +package org.dromara.project.domain.enums; + +import lombok.Getter; +import org.dromara.common.core.utils.ObjectUtils; + +/** + * @author lcj + * @date 2025/4/7 15:38 + */ +@Getter +public enum ConstructionUserAttendanceStatusEnum { + + NORMAL("全天考勤正常", "1"), + ERROR("当天存在异常迟到、早退、缺卡", "2"), + REISSUE("当天提交过补卡申请", "3"); + + private final String text; + + private final String value; + + ConstructionUserAttendanceStatusEnum(String text, String value) { + this.text = text; + this.value = value; + } + + /** + * 根据 value 获取枚举 + * + * @param value 项目成员岗位枚举值 + * @return 项目成员岗位枚举 + */ + public static ConstructionUserAttendanceStatusEnum getEnumByValue(String value) { + if (ObjectUtils.isEmpty(value)) { + return null; + } + for (ConstructionUserAttendanceStatusEnum anEnum : ConstructionUserAttendanceStatusEnum.values()) { + if (anEnum.value.equals(value)) { + return anEnum; + } + } + return null; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceCreateReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceCreateReq.java deleted file mode 100644 index dec58e04..00000000 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceCreateReq.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.dromara.project.domain.req.attendance; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * @author lcj - * @date 2025/3/26 9:46 - */ -@Data -public class AttendanceCreateReq implements Serializable { - - @Serial - private static final long serialVersionUID = 1906706006468828948L; - - /** - * 人员id - */ - private Long userId; - - /** - * 人脸照 - */ - private String facePic; - - /** - * 项目id - */ - private Long projectId; - - /** - * 1正常,2迟到,3早退,4缺勤,5补卡 - */ - private String clockStatus; - - /** - * 代打人员id - */ - private String pinchUserId; - - /** - * 多次打卡时间记录 - */ - private String clockRecord; - - /** - * 上下班(1上班,2下班) - */ - private String commuter; - - /** - * 备注 - */ - private String remark; -} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryReq.java index f7765736..11e3fd91 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryReq.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryReq.java @@ -1,9 +1,12 @@ package org.dromara.project.domain.req.attendance; +import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; import java.io.Serial; import java.io.Serializable; +import java.util.Date; /** * @author lcj @@ -15,16 +18,6 @@ public class AttendanceQueryReq implements Serializable { @Serial private static final long serialVersionUID = -7188085233824968862L; - /** - * 主键id - */ - private Long id; - - /** - * 人员id - */ - private Long userId; - /** * 人员姓名 */ @@ -33,26 +26,23 @@ public class AttendanceQueryReq implements Serializable { /** * 项目id */ + @NotNull(message = "项目id不能为空") private Long projectId; /** - * 1正常,2迟到,3早退,4缺勤,5补卡 + * 班组id + */ + private Long teamId; + + /** + * 打卡状态(1正常,2迟到,3早退,4缺勤,5补卡) */ private String clockStatus; /** - * 代打人员id + * 打卡日期 */ - private String pinchUserId; - - /** - * 上下班(1上班,2下班) - */ - private String commuter; - - /** - * 备注 - */ - private String remark; + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date clockDate; } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryTwoWeekReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryTwoWeekReq.java new file mode 100644 index 00000000..c3612ffc --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceQueryTwoWeekReq.java @@ -0,0 +1,25 @@ +package org.dromara.project.domain.req.attendance; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/7 9:53 + */ +@Data +public class AttendanceQueryTwoWeekReq implements Serializable { + + @Serial + private static final long serialVersionUID = 3193787736889938829L; + + /** + * 项目id + */ + @NotNull(message = "项目id不能为空") + private Long projectId; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceUpdateReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceUpdateReq.java deleted file mode 100644 index 63142e58..00000000 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/attendance/AttendanceUpdateReq.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.dromara.project.domain.req.attendance; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * @author lcj - * @date 2025/3/26 9:47 - */ -@Data -public class AttendanceUpdateReq implements Serializable { - - @Serial - private static final long serialVersionUID = 3159243618168476248L; - - /** - * 主键id - */ - private Long id; - - /** - * 人员id - */ - private Long userId; - - /** - * 人员姓名 - */ - private String userName; - - /** - * 人脸照 - */ - private String facePic; - - /** - * 项目id - */ - private Long projectId; - - /** - * 打卡时间 - */ - private String clockTime; - - /** - * 1正常,2迟到,3早退,4缺勤,5补卡 - */ - private String clockStatus; - - /** - * 代打人员id - */ - private String pinchUserId; - - /** - * 多次打卡时间记录 - */ - private String clockRecord; - - /** - * 上下班(1上班,2下班) - */ - private String commuter; - - /** - * 备注 - */ - private String remark; -} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/constructionuser/ConstructionUserAttendanceMonthReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/constructionuser/ConstructionUserAttendanceMonthReq.java new file mode 100644 index 00000000..c7495d02 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/constructionuser/ConstructionUserAttendanceMonthReq.java @@ -0,0 +1,30 @@ +package org.dromara.project.domain.req.constructionuser; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/7 15:04 + */ +@Data +public class ConstructionUserAttendanceMonthReq implements Serializable { + + @Serial + private static final long serialVersionUID = -1496942176392426636L; + + /** + * id + */ + @NotNull(message = "用户主键不能为空") + private Long id; + + /** + * 打卡月份 + */ + private String clockMonth; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/constructionuser/ConstructionUserAttendanceQueryReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/constructionuser/ConstructionUserAttendanceQueryReq.java new file mode 100644 index 00000000..f2743a94 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/constructionuser/ConstructionUserAttendanceQueryReq.java @@ -0,0 +1,45 @@ +package org.dromara.project.domain.req.constructionuser; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/7 10:52 + */ +@Data +public class ConstructionUserAttendanceQueryReq implements Serializable { + + @Serial + private static final long serialVersionUID = -6634291825924626633L; + + /** + * 人员姓名 + */ + private String userName; + + /** + * 项目id + */ + @NotNull(message = "项目id不能为空") + private Long projectId; + + /** + * 班组id + */ + private Long teamId; + + /** + * 工种 + */ + private String typeOfWork; + + /** + * 打卡月份 + */ + private String clockMonth; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/attendance/AttendanceClockDateForTwoWeekResp.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/attendance/AttendanceClockDateForTwoWeekResp.java new file mode 100644 index 00000000..2726d047 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/attendance/AttendanceClockDateForTwoWeekResp.java @@ -0,0 +1,43 @@ +package org.dromara.project.domain.resp.attendance; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * @author lcj + * @date 2025/4/7 9:55 + */ +@Data +public class AttendanceClockDateForTwoWeekResp implements Serializable { + + @Serial + private static final long serialVersionUID = -2762312533060742243L; + + /** + * 打卡日期 + */ + @JsonFormat(shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd", + timezone = "GMT+8") + private Date clockDate; + + /** + * 出勤人数 + */ + private Integer attendance; + + /** + * 半勤人数 + */ + private Integer halfAttendance; + + /** + * 缺勤人数 + */ + private Integer absenteeism; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/attendance/AttendanceListByDay.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/attendance/AttendanceListByDay.java new file mode 100644 index 00000000..75de790c --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/attendance/AttendanceListByDay.java @@ -0,0 +1,45 @@ +package org.dromara.project.domain.resp.attendance; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dromara.project.domain.BusAttendance; + +import java.util.Date; + +/** + * @author lcj + * @date 2025/4/7 15:27 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AttendanceListByDay { + + /** + * 上下班(1上班,2下班) + */ + private String commuter; + + /** + * 打卡时间 + */ + private Date clockTime; + + /** + * 打卡状态(1正常,2迟到,3早退,4缺勤,5补卡) + */ + private String clockStatus; + + public static AttendanceListByDay build(BusAttendance attendance) { + if (attendance == null) { + return null; + } + AttendanceListByDay attendanceListByDay = new AttendanceListByDay(); + attendanceListByDay.setCommuter(attendance.getCommuter()); + attendanceListByDay.setClockTime(attendance.getClockTime()); + attendanceListByDay.setClockStatus(attendance.getClockStatus()); + return attendanceListByDay; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/constructionuser/ConstructionUserAttendanceMonthResp.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/constructionuser/ConstructionUserAttendanceMonthResp.java new file mode 100644 index 00000000..0886757b --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/constructionuser/ConstructionUserAttendanceMonthResp.java @@ -0,0 +1,45 @@ +package org.dromara.project.domain.resp.constructionuser; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.dromara.project.domain.resp.attendance.AttendanceListByDay; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @author lcj + * @date 2025/4/7 15:06 + */ +@Data +public class ConstructionUserAttendanceMonthResp implements Serializable { + + @Serial + private static final long serialVersionUID = -413447291128760025L; + + /** + * 主键id + */ + private Long id; + + /** + * 打卡日期 + */ + @JsonFormat(shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd", + timezone = "GMT+8") + private Date clockDate; + + /** + * 当天打卡状态 + */ + private String Status; + + /** + * 当天打卡记录 + */ + private List attendanceList; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/constructionuser/ConstructionUserAttendanceTotalResp.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/constructionuser/ConstructionUserAttendanceTotalResp.java new file mode 100644 index 00000000..a631884f --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/constructionuser/ConstructionUserAttendanceTotalResp.java @@ -0,0 +1,64 @@ +package org.dromara.project.domain.resp.constructionuser; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * @author lcj + * @date 2025/4/7 10:16 + */ +@Data +public class ConstructionUserAttendanceTotalResp implements Serializable { + + @Serial + private static final long serialVersionUID = 1335094839733429171L; + + /** + * 主键id + */ + private Long id; + + /** + * 人员姓名 + */ + private String userName; + + /** + * 班组id + */ + private Long teamId; + + /** + * 班组名称 + */ + private String teamName; + + /** + * 工种 + */ + private String typeOfWork; + + /** + * 出勤天数 + */ + private Integer attendanceDays; + + /** + * 迟到天数 + */ + private Integer lateDays; + + /** + * 早退天数 + */ + private Integer leaveEarlyDays; + + /** + * 缺卡天数 + */ + private Integer unClockDays; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusAttendanceVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusAttendanceVo.java index 531af2f3..6227ed66 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusAttendanceVo.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusAttendanceVo.java @@ -2,6 +2,7 @@ package org.dromara.project.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; import org.dromara.common.excel.annotation.ExcelDictFormat; @@ -10,13 +11,14 @@ import org.dromara.project.domain.BusAttendance; import java.io.Serial; import java.io.Serializable; +import java.util.Date; /** * 考勤视图对象 bus_attendance * * @author lcj - * @date 2025-03-26 + * @date 2025-04-07 */ @Data @ExcelIgnoreUnannotated @@ -29,13 +31,11 @@ public class BusAttendanceVo implements Serializable { /** * 主键id */ - @ExcelProperty(value = "主键id") private Long id; /** * 人员id */ - @ExcelProperty(value = "人员id") private Long userId; /** @@ -44,10 +44,21 @@ public class BusAttendanceVo implements Serializable { @ExcelProperty(value = "人员姓名") private String userName; + /** + * 班组id + */ + private Long teamId; + + /** + * 工种 + */ + @ExcelProperty(value = "工种", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "type_of_work") + private String typeOfWork; + /** * 人脸照 */ - @ExcelProperty(value = "人脸照") private String facePic; /** @@ -60,20 +71,28 @@ public class BusAttendanceVo implements Serializable { * 打卡时间 */ @ExcelProperty(value = "打卡时间") - private String clockTime; + private Date clockTime; /** - * 1正常,2迟到,3早退,4缺勤,5补卡 + * 打卡日期 */ - @ExcelProperty(value = "1正常,2迟到,3早退,4缺勤,5补卡", converter = ExcelDictConvert.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd", + timezone = "GMT+8") + @ExcelProperty(value = "打卡日期") + private Date clockDate; + + /** + * 打卡状态(1正常,2迟到,3早退,4缺勤,5补卡) + */ + @ExcelProperty(value = "打卡状态", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "clock_status_type") private String clockStatus; /** * 代打人员id */ - @ExcelProperty(value = "代打人员id") - private String pinchUserId; + private Long pinchUserId; /** * 多次打卡时间记录 @@ -88,11 +107,34 @@ public class BusAttendanceVo implements Serializable { @ExcelDictFormat(dictType = "commuter_type") private String commuter; + /** + * 打卡范围 + */ + @ExcelProperty(value = "打卡范围") + private String punchRange; + + /** + * 日薪 + */ + @ExcelProperty(value = "日薪") + private Long dailyWage; + + /** + * 经度 + */ + @ExcelProperty(value = "经度") + private String lng; + + /** + * 纬度 + */ + @ExcelProperty(value = "纬度") + private String lat; + /** * 备注 */ @ExcelProperty(value = "备注") private String remark; - } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusAttendanceMapper.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusAttendanceMapper.java index 7ce03029..9a21b156 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusAttendanceMapper.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusAttendanceMapper.java @@ -8,7 +8,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; * 考勤Mapper接口 * * @author lcj - * @date 2025-03-26 + * @date 2025-04-07 */ public interface BusAttendanceMapper extends BaseMapperPlus { diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java index 0def8a11..01ffd875 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java @@ -6,19 +6,18 @@ import com.baomidou.mybatisplus.extension.service.IService; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.project.domain.BusAttendance; -import org.dromara.project.domain.req.attendance.AttendanceCreateReq; import org.dromara.project.domain.req.attendance.AttendanceQueryReq; -import org.dromara.project.domain.req.attendance.AttendanceUpdateReq; +import org.dromara.project.domain.req.attendance.AttendanceQueryTwoWeekReq; +import org.dromara.project.domain.resp.attendance.AttendanceClockDateForTwoWeekResp; import org.dromara.project.domain.vo.BusAttendanceVo; -import java.util.Collection; import java.util.List; /** * 考勤Service接口 * * @author lcj - * @date 2025-03-26 + * @date 2025-04-07 */ public interface IBusAttendanceService extends IService { @@ -39,6 +38,14 @@ public interface IBusAttendanceService extends IService { */ TableDataInfo queryPageList(AttendanceQueryReq req, PageQuery pageQuery); + /** + * 查询两周内的考勤列表 + * + * @param req 查询条件 + * @return 考勤列表 + */ + List listClockDateForTwoWeek(AttendanceQueryTwoWeekReq req); + /** * 查询符合条件的考勤列表 * @@ -47,31 +54,6 @@ public interface IBusAttendanceService extends IService { */ List queryList(AttendanceQueryReq req); - /** - * 新增考勤 - * - * @param req 考勤 - * @return 新增考勤id - */ - Long insertByBo(AttendanceCreateReq req); - - /** - * 修改考勤 - * - * @param req 考勤 - * @return 是否修改成功 - */ - Boolean updateByBo(AttendanceUpdateReq req); - - /** - * 校验并批量删除考勤信息 - * - * @param ids 待删除的主键集合 - * @param isValid 是否进行有效性校验 - * @return 是否删除成功 - */ - Boolean deleteWithValidByIds(Collection ids, Boolean isValid); - /** * 获取考勤视图对象 * @@ -95,4 +77,5 @@ public interface IBusAttendanceService extends IService { * @return 考勤分页对象视图 */ Page getVoPage(Page attendancePage); + } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusConstructionUserService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusConstructionUserService.java index f4048786..cbb2f34a 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusConstructionUserService.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusConstructionUserService.java @@ -8,6 +8,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.project.domain.BusConstructionUser; import org.dromara.project.domain.exportvo.BusConstructionUserExportVo; import org.dromara.project.domain.req.constructionuser.*; +import org.dromara.project.domain.resp.constructionuser.ConstructionUserAttendanceMonthResp; +import org.dromara.project.domain.resp.constructionuser.ConstructionUserAttendanceTotalResp; import org.dromara.project.domain.vo.BusConstructionUserVo; import java.util.Collection; @@ -38,6 +40,23 @@ public interface IBusConstructionUserService extends IService queryPageList(ConstructionUserQueryReq req, PageQuery pageQuery); + /** + * 分页查询施工人员考勤列表 + * + * @param req 查询条件 + * @param pageQuery 分页参数 + * @return 施工人员考勤分页列表 + */ + TableDataInfo queryPageAttendanceList(ConstructionUserAttendanceQueryReq req, PageQuery pageQuery); + + /** + * 查询施工人员月考勤列表 + * + * @param req 查询条件 + * @return 施工人员考勤月列表 + */ + List queryAttendanceMonthList(ConstructionUserAttendanceMonthReq req); + /** * 查询符合条件的施工人员列表 * @@ -134,4 +153,14 @@ public interface IBusConstructionUserService extends IService getVoPage(Page constructionUserPage); + + /** + * 获取施工人员考勤分页对象视图 + * + * @param req 施工人员考勤分页查询条件 + * @return 施工人员考勤分页对象视图 + */ + Page getAttendanceTotalVoPage(ConstructionUserAttendanceQueryReq req, + PageQuery pageQuery); + } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java index a7b26ad7..96b5b9db 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.ObjectUtils; @@ -11,29 +12,41 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.project.domain.BusAttendance; -import org.dromara.project.domain.req.attendance.AttendanceCreateReq; +import org.dromara.project.domain.BusProjectTeamMember; +import org.dromara.project.domain.enums.ConstructionUserAttendanceClockStatusEnum; +import org.dromara.project.domain.enums.ConstructionUserAttendanceCommuterEnum; import org.dromara.project.domain.req.attendance.AttendanceQueryReq; -import org.dromara.project.domain.req.attendance.AttendanceUpdateReq; +import org.dromara.project.domain.req.attendance.AttendanceQueryTwoWeekReq; +import org.dromara.project.domain.resp.attendance.AttendanceClockDateForTwoWeekResp; import org.dromara.project.domain.vo.BusAttendanceVo; import org.dromara.project.mapper.BusAttendanceMapper; import org.dromara.project.service.IBusAttendanceService; +import org.dromara.project.service.IBusProjectService; +import org.dromara.project.service.IBusProjectTeamMemberService; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.List; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.*; +import java.util.stream.Collectors; /** * 考勤Service业务层处理 * * @author lcj - * @date 2025-03-26 + * @date 2025-04-07 */ @Service public class BusAttendanceServiceImpl extends ServiceImpl implements IBusAttendanceService { + @Resource + private IBusProjectService projectService; + + @Resource + private IBusProjectTeamMemberService projectTeamMemberService; + /** * 查询考勤 * @@ -62,6 +75,75 @@ public class BusAttendanceServiceImpl extends ServiceImpl listClockDateForTwoWeek(AttendanceQueryTwoWeekReq req) { + Long projectId = req.getProjectId(); + if (projectService.getById(projectId) == null) { + throw new ServiceException("项目信息不存在", HttpStatus.NOT_FOUND); + } + // 获取两周前的日期 + LocalDate twoWeeksAgoLocal = LocalDate.now().minusWeeks(2); + // 2. 转成Date(时分秒会被置为 00:00:00) + Date twoWeeksDate = Date.from(twoWeeksAgoLocal.atStartOfDay(ZoneId.systemDefault()).toInstant()); + // 获取两周内的考勤记录 + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(BusAttendance::getProjectId, projectId) + .ge(BusAttendance::getClockDate, twoWeeksDate) + .orderByDesc(BusAttendance::getClockDate); + Map> dateListMap = this.list(lqw) + .stream().collect(Collectors.groupingBy(BusAttendance::getClockDate)); + // 遍历每个日期,计算考勤状态 + List respList = new ArrayList<>(); + dateListMap.forEach((date, attendanceList) -> { + AttendanceClockDateForTwoWeekResp resp = new AttendanceClockDateForTwoWeekResp(); + resp.setClockDate(date); + // 统计考勤状态数量 + int attendance = 0; + int halfAttendance = 0; + int absenteeism = 0; + // 遍历每个用户,统计考勤状态数量 + Map> userAttendanceMap = attendanceList.stream() + .collect(Collectors.groupingBy(BusAttendance::getUserId)); + if (CollUtil.isNotEmpty(userAttendanceMap)) { + for (List userAttendanceList : userAttendanceMap.values()) { + String clockInStatus = null; + String clockOutStatus = null; + // 获取上下班状态 + for (BusAttendance a : userAttendanceList) { + if (ConstructionUserAttendanceCommuterEnum.CLOCKIN.getValue().equals(a.getCommuter())) { + clockInStatus = a.getClockStatus(); + } else if (ConstructionUserAttendanceCommuterEnum.CLOCKOUT.getValue().equals(a.getCommuter())) { + clockOutStatus = a.getClockStatus(); + } + } + // 统计考勤状态 + if (ConstructionUserAttendanceClockStatusEnum.NORMAL.getValue().equals(clockInStatus) + && ConstructionUserAttendanceClockStatusEnum.NORMAL.getValue().equals(clockOutStatus)) { + attendance++; + } else if (ConstructionUserAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockInStatus) + && ConstructionUserAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockOutStatus)) { + absenteeism++; + } else { + halfAttendance++; + } + } + } + resp.setAttendance(attendance); + resp.setHalfAttendance(halfAttendance); + resp.setAbsenteeism(absenteeism); + respList.add(resp); + }); + // 按打卡日期正序排列 + respList.sort(Comparator.comparing(AttendanceClockDateForTwoWeekResp::getClockDate)); + return respList; + } + /** * 查询符合条件的考勤列表 * @@ -74,75 +156,6 @@ public class BusAttendanceServiceImpl extends ServiceImpl ids, Boolean isValid) { - if (isValid) { - // TODO 做一些业务上的校验,判断是否需要校验 - } - return this.removeBatchByIds(ids); - } - /** * 获取考勤视图对象 * @@ -172,24 +185,24 @@ public class BusAttendanceServiceImpl extends ServiceImpl projectTeamMemberList = projectTeamMemberService.lambdaQuery() + .eq(BusProjectTeamMember::getTeamId, teamId).list(); + List userIdList = projectTeamMemberList.stream().map(BusProjectTeamMember::getMemberId).toList(); + lqw.in(BusAttendance::getUserId, userIdList); + } // 模糊查询 lqw.like(StringUtils.isNotBlank(userName), BusAttendance::getUserName, userName); - lqw.like(StringUtils.isNotBlank(remark), BusAttendance::getRemark, remark); // 精确查询 - lqw.eq(ObjectUtils.isNotEmpty(id), BusAttendance::getId, id); - lqw.eq(ObjectUtils.isNotEmpty(userId), BusAttendance::getUserId, userId); lqw.eq(ObjectUtils.isNotEmpty(projectId), BusAttendance::getProjectId, projectId); lqw.eq(StringUtils.isNotBlank(clockStatus), BusAttendance::getClockStatus, clockStatus); - lqw.eq(StringUtils.isNotBlank(pinchUserId), BusAttendance::getPinchUserId, pinchUserId); - lqw.eq(StringUtils.isNotBlank(commuter), BusAttendance::getCommuter, commuter); + lqw.eq(ObjectUtils.isNotEmpty(clockDate), BusAttendance::getClockDate, clockDate); return lqw; } @@ -214,4 +227,5 @@ public class BusAttendanceServiceImpl extends ServiceImpl queryPageAttendanceList(ConstructionUserAttendanceQueryReq req, + PageQuery pageQuery) { + return TableDataInfo.build(getAttendanceTotalVoPage(req, pageQuery)); + } + + /** + * 查询施工人员月考勤列表 + * + * @param req 查询条件 + * @return 施工人员考勤月列表 + */ + @Override + public List queryAttendanceMonthList(ConstructionUserAttendanceMonthReq req) { + Long id = req.getId(); + String clockMonth = req.getClockMonth(); + if (this.getById(id) == null) { + throw new ServiceException("施工人员信息不存在", HttpStatus.NOT_FOUND); + } + // 解析月份 + YearMonth yearMonth; + if (StringUtils.isNotBlank(clockMonth)) { + // 校验月份格式 + if (!DateConstant.YEAR_MONTH_PATTERN.matcher(clockMonth).matches()) { + throw new ServiceException("月份格式不正确", HttpStatus.BAD_REQUEST); + } + yearMonth = YearMonth.parse(clockMonth); + } else { + // 如果月份为空,则默认查询当前月份 + yearMonth = YearMonth.now(); + } + // 计算当月第一天 / 最后一天 + Date start = DateUtils.toDate(yearMonth.atDay(1)); + Date end = DateUtils.toDate(yearMonth.atEndOfMonth()); + // 查询当月考勤记录 + Map> dateListMap = attendanceService.lambdaQuery() + .eq(BusAttendance::getUserId, id) + .between(BusAttendance::getClockDate, start, end) + .list() + .stream().collect(Collectors.groupingBy(BusAttendance::getClockDate)); + // 遍历每天,计算考勤状态 + List respList = new ArrayList<>(); + dateListMap.forEach((date, attendanceList) -> { + ConstructionUserAttendanceMonthResp resp = new ConstructionUserAttendanceMonthResp(); + resp.setId(id); + resp.setClockDate(date); + List attendanceListByDayList = new ArrayList<>(); + String clockInStatus = null; + String clockOutStatus = null; + String status; + for (BusAttendance attendance : attendanceList) { + // 获取考勤记录 + AttendanceListByDay day = AttendanceListByDay.build(attendance); + attendanceListByDayList.add(day); + // 获取上下班状态 + if (ConstructionUserAttendanceCommuterEnum.CLOCKIN.getValue().equals(attendance.getCommuter())) { + clockInStatus = attendance.getClockStatus(); + } else if (ConstructionUserAttendanceCommuterEnum.CLOCKOUT.getValue().equals(attendance.getCommuter())) { + clockOutStatus = attendance.getClockStatus(); + } + } + // 统计当天考勤状态 + if (ConstructionUserAttendanceClockStatusEnum.NORMAL.getValue().equals(clockInStatus) + && ConstructionUserAttendanceClockStatusEnum.NORMAL.getValue().equals(clockOutStatus)) { + status = ConstructionUserAttendanceStatusEnum.NORMAL.getValue(); + } else if (ConstructionUserAttendanceClockStatusEnum.REISSUE.getValue().equals(clockInStatus) + || ConstructionUserAttendanceClockStatusEnum.REISSUE.getValue().equals(clockOutStatus)) { + status = ConstructionUserAttendanceStatusEnum.REISSUE.getValue(); + } else { + status = ConstructionUserAttendanceStatusEnum.ERROR.getValue(); + } + resp.setStatus(status); + resp.setAttendanceList(attendanceListByDayList); + respList.add(resp); + }); + // 按打卡日期正序排列 + respList.sort(Comparator.comparing(ConstructionUserAttendanceMonthResp::getClockDate)); + return respList; + } + /** * 查询符合条件的施工人员列表 * @@ -653,4 +753,141 @@ public class BusConstructionUserServiceImpl extends ServiceImpl getAttendanceTotalVoPage(ConstructionUserAttendanceQueryReq req, + PageQuery pageQuery) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + // 从对象中取值 + String userName = req.getUserName(); + Long projectId = req.getProjectId(); + Long teamId = req.getTeamId(); + String typeOfWork = req.getTypeOfWork(); + String clockMonth = req.getClockMonth(); + // 联表查询 + LambdaQueryWrapper attendanceLqw = Wrappers.lambdaQuery(BusAttendance.class) + .eq(BusAttendance::getProjectId, projectId); + if (ObjectUtils.isNotEmpty(clockMonth)) { + // 校验月份格式 + if (!DateConstant.YEAR_MONTH_PATTERN.matcher(clockMonth).matches()) { + throw new ServiceException("月份格式不正确", HttpStatus.BAD_REQUEST); + } + // 解析月份 + YearMonth yearMonth = YearMonth.parse(clockMonth); + // 计算当月第一天 / 最后一天 + Date start = DateUtils.toDate(yearMonth.atDay(1)); + Date end = DateUtils.toDate(yearMonth.atEndOfMonth()); + attendanceLqw.between(BusAttendance::getClockDate, start, end); + List userIdList = attendanceService.list(attendanceLqw) + .stream().map(BusAttendance::getUserId).toList(); + if (CollUtil.isNotEmpty(userIdList)) { + lqw.in(BusConstructionUser::getId, userIdList); + } + } + // 模糊查询 + lqw.like(StringUtils.isNotBlank(userName), BusConstructionUser::getUserName, userName); + // 精确查询 + lqw.eq(ObjectUtils.isNotEmpty(projectId), BusConstructionUser::getProjectId, projectId); + lqw.eq(ObjectUtils.isNotEmpty(teamId), BusConstructionUser::getTeamId, teamId); + lqw.eq(StringUtils.isNotBlank(typeOfWork), BusConstructionUser::getTypeOfWork, typeOfWork); + // 查询当前项目下的黑名单人员 + List blackUserIdList = constructionBlacklistService.lambdaQuery() + .eq(BusConstructionBlacklist::getProjectId, projectId).list() + .stream().map(BusConstructionBlacklist::getUserId).toList(); + // 查询结果移除黑名单人员 + if (CollUtil.isNotEmpty(blackUserIdList)) { + lqw.notIn(BusConstructionUser::getId, blackUserIdList); + } + // 分页查询获取数据 + Page constructionUserPage = this.page(pageQuery.build(), lqw); + List constructionUserList = constructionUserPage.getRecords(); + Page constructionUserAttendanceTotalPage = new Page<>( + constructionUserPage.getCurrent(), + constructionUserPage.getSize(), + constructionUserPage.getTotal()); + if (CollUtil.isEmpty(constructionUserList)) { + return constructionUserAttendanceTotalPage; + } + // 获取施工人员id列表 + List userIdList = constructionUserList.stream().map(BusConstructionUser::getId).toList(); + // 关联查询施工人员考勤列表 + attendanceLqw.in(BusAttendance::getUserId, userIdList); + Map> userIdBusAttendanceListMap = attendanceService.list(attendanceLqw) + .stream().collect(Collectors.groupingBy(BusAttendance::getUserId)); + // 关联查询班组列表 + List teamIdList = constructionUserList.stream().map(BusConstructionUser::getTeamId).toList(); + Map> teamIdProjectTeamListMap = projectTeamService.lambdaQuery() + .in(BusProjectTeam::getId, teamIdList).list() + .stream().collect(Collectors.groupingBy(BusProjectTeam::getId)); + // 填充信息 + List userAttendanceTotalList = constructionUserList.stream().map(constructionUser -> { + ConstructionUserAttendanceTotalResp constructionUserAttendanceTotalResp = new ConstructionUserAttendanceTotalResp(); + Long id = constructionUser.getId(); + constructionUserAttendanceTotalResp.setId(id); + constructionUserAttendanceTotalResp.setUserName(constructionUser.getUserName()); + constructionUserAttendanceTotalResp.setTypeOfWork(constructionUser.getTypeOfWork()); + // 关联施工人员考勤信息 + int attendanceDays = 0; + int lateDays = 0; + int leaveEarlyDays = 0; + int unClockDays = 0; + if (userIdBusAttendanceListMap.containsKey(id)) { + List attendanceList = userIdBusAttendanceListMap.get(id); + if (CollUtil.isNotEmpty(attendanceList)) { + // 1. 按打卡日期分组 + Map> dailyMap = attendanceList.stream() + .collect(Collectors.groupingBy(BusAttendance::getClockDate)); + // 2. 对每一天的记录计算状态 + for (List dailyList : dailyMap.values()) { + String clockInStatus = null; + String clockOutStatus = null; + // 获取上下班状态 + for (BusAttendance attendance : dailyList) { + if (ConstructionUserAttendanceCommuterEnum.CLOCKIN.getValue().equals(attendance.getCommuter())) { + clockInStatus = attendance.getClockStatus(); + } else if (ConstructionUserAttendanceCommuterEnum.CLOCKOUT.getValue().equals(attendance.getCommuter())) { + clockOutStatus = attendance.getClockStatus(); + } + } + // 统计考勤状态 + if (ConstructionUserAttendanceClockStatusEnum.LATE.getValue().equals(clockInStatus)) { + lateDays++; + } + if (ConstructionUserAttendanceClockStatusEnum.LEAVEEARLY.getValue().equals(clockOutStatus)) { + leaveEarlyDays++; + } + if (clockInStatus == null || ConstructionUserAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockInStatus)) { + unClockDays++; + } + if (clockOutStatus == null || ConstructionUserAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockOutStatus)) { + unClockDays++; + } + } + attendanceDays = dailyMap.size(); + } + } + constructionUserAttendanceTotalResp.setAttendanceDays(attendanceDays); + constructionUserAttendanceTotalResp.setLateDays(lateDays); + constructionUserAttendanceTotalResp.setLeaveEarlyDays(leaveEarlyDays); + constructionUserAttendanceTotalResp.setUnClockDays(unClockDays); + // 关联班组信息 + Long userTeamId = constructionUser.getTeamId(); + String teamName = null; + if (teamIdProjectTeamListMap.containsKey(userTeamId)) { + teamName = teamIdProjectTeamListMap.get(userTeamId).get(0).getTeamName(); + } + constructionUserAttendanceTotalResp.setTeamId(userTeamId); + constructionUserAttendanceTotalResp.setTeamName(teamName); + return constructionUserAttendanceTotalResp; + }).toList(); + constructionUserAttendanceTotalPage.setRecords(userAttendanceTotalList); + return constructionUserAttendanceTotalPage; + } + } diff --git a/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql b/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql index 7b1d7e30..7cf17ccf 100644 --- a/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql +++ b/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql @@ -445,27 +445,32 @@ CREATE TABLE `bus_question_user_answer` DROP TABLE IF EXISTS `bus_attendance`; CREATE TABLE `bus_attendance` ( - `id` bigint not null auto_increment comment '主键id', - `user_id` bigint null comment '人员id', - `user_name` varchar(32) null comment '人员姓名', - `face_pic` varchar(512) null comment '人脸照', - `project_id` bigint null comment '项目id', - `on_clock_time` varchar(64) null comment '上班打卡时间', - `off_clock_time` varchar(64) null comment '下班打卡时间', - `clock_status` varchar(20) null comment '1正常,2迟到,3早退,4缺勤,5补卡', - `pinch_user_Id` varchar(64) null comment '代打人员id', - `clock_record` varchar(500) null comment '多次打卡时间记录', - `commuter` char(1) null comment '上下班(1上班,2下班)', - `remark` varchar(512) null comment '备注', - `create_by` varchar(64) null comment '创建者', - `update_by` varchar(64) null comment '更新者', - `create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间', - `update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间', - `deleted_at` datetime null comment '删除时间', - `is_delete` tinyint(4) default 0 not null comment '是否删除(0正常 1删除)', + `id` bigint not null auto_increment comment '主键id', + `user_id` bigint null comment '人员id', + `user_name` varchar(32) null comment '人员姓名', + `face_pic` varchar(512) null comment '人脸照', + `project_id` bigint null comment '项目id', + `clock_time` datetime null comment '打卡时间', + `clock_date` date null comment '打卡日期', + `clock_status` varchar(20) null comment '打卡状态(1正常,2迟到,3早退,4缺勤,5补卡)', + `pinch_user_id` bigint null comment '代打人员id', + `clock_record` varchar(500) null comment '多次打卡时间记录', + `commuter` char(1) null comment '上下班(1上班,2下班)', + `punch_range` varchar(64) null comment '打卡范围', + `daily_wage` decimal(10, 2) null comment '日薪', + `lng` varchar(255) null comment '经度', + `lat` varchar(255) null comment '纬度', + `remark` varchar(512) null comment '备注', + `create_by` varchar(64) null comment '创建者', + `update_by` varchar(64) null comment '更新者', + `create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间', + `update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间', + `deleted_at` datetime null comment '删除时间', + `is_delete` tinyint(4) default 0 not null comment '是否删除(0正常 1删除)', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id` (`user_id` ASC) USING BTREE comment '人员id', - INDEX `idx_project_id` (`project_id` ASC) USING BTREE comment '项目id' + INDEX `idx_project_id` (`project_id` ASC) USING BTREE comment '项目id', + INDEX `idx_clock_date` (`clock_date` ASC) USING BTREE comment '打卡日期' ) comment = '考勤表' COLLATE = utf8mb4_unicode_ci; DROP TABLE IF EXISTS `bus_work_wage`;