feat(hrm): 请假批量导入、加班代申请人、批量排班与节假日区间联动
- 请假申请支持 Excel 批量导入,按手机号匹配员工档案,逐行独立提示失败原因
- 加班申请改为选择申请人,自动带出工号/部门/岗位
- 排班管理新增按部门+岗位+在职状态批量排班
- 节假日配置按区间新增/编辑/删除,列表按连续日期合并展示
- 排班批量生成与自动排班以节假日为准:休息日强制休息、工作日强制排班
- 考勤统计查询时按最新节假日重算应出勤天数并回写
Co-Authored-By: Claude Code <noreply@anthropic.com>
| | |
| | | ErrorCode LEAVE_APPLICATION_NO_EXISTS = new ErrorCode(1_030_001_004, "çæè¯·åç³è¯·åå·éå¤ï¼è¯·éè¯"); |
| | | ErrorCode LEAVE_APPLICATION_DURATION_EXCEED = new ErrorCode(1_030_001_005, "è¯·åæ¶é¿è¶
åºå¹´åä½é¢"); |
| | | ErrorCode LEAVE_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_001_006, "请åå®¡æ¹æµç¨ä¸åå¨"); |
| | | ErrorCode LEAVE_APPLICATION_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_030_001_007, "导å
¥è¯·åæ°æ®ä¸è½ä¸ºç©º"); |
| | | ErrorCode LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED = new ErrorCode(1_030_001_008, "导å
¥å段ã{}ãä¸è½ä¸ºç©º"); |
| | | ErrorCode LEAVE_APPLICATION_IMPORT_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_030_001_009, "ç³è¯·äººææºå·ã{}ãæªæ¾å°å工档æ¡ï¼è¯·å
ç»´æ¤å工档æ¡"); |
| | | ErrorCode LEAVE_APPLICATION_IMPORT_EMPLOYEE_NO_USER = new ErrorCode(1_030_001_010, "åå·¥ã{}ãæªå
³èç³»ç»è´¦å·ï¼æ æ³å建请åç³è¯·ï¼è¯·å
å¨ãç³»ç»ç®¡ç-ç¨æ·ç®¡çãä¸ç»å®è´¦å·"); |
| | | ErrorCode LEAVE_APPLICATION_IMPORT_TIME_INVALID = new ErrorCode(1_030_001_011, "å¼å§æ¶é´ã{}ãå¿
é¡»æ©äºç»ææ¶é´ã{}ã"); |
| | | ErrorCode LEAVE_APPLICATION_IMPORT_FIELD_INVALID = new ErrorCode(1_030_001_012, "导å
¥å段ã{}ãçå¼ã{}ãä¸åæ³ï¼è¯·å¡«åï¼{}"); |
| | | |
| | | // ========== è°å²ç³è¯· 1-030-002-000 ========== |
| | | ErrorCode TRANSFER_APPLICATION_NOT_EXISTS = new ErrorCode(1_030_002_000, "è°å²ç³è¯·ä¸åå¨"); |
| | |
| | | ErrorCode OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_008_004, "å çå®¡æ¹æµç¨ä¸åå¨ï¼è¯·å
å¨åååå
¬ä¸é
置并å叿µç¨"); |
| | | ErrorCode OVERTIME_APPLICATION_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_030_008_005, "å½åè´¦å·æªå
³èå工档æ¡"); |
| | | ErrorCode OVERTIME_APPLICATION_TIME_INVALID = new ErrorCode(1_030_008_006, "å çæ¶æ®µææ£é¤æ¶é¿ä¸åæ³"); |
| | | ErrorCode OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_030_008_007, "æéå ç人åä¸åå¨æå·²è¢«å é¤ï¼è¯·éæ°éæ©"); |
| | | ErrorCode OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NO_USER = new ErrorCode(1_030_008_008, "æéåå·¥ã{}ãæªå
³èç³»ç»è´¦å·ï¼æ æ³æäº¤å çç³è¯·ï¼è¯·å
å¨ãç³»ç»ç®¡ç-ç¨æ·ç®¡çãä¸ç»å®è´¦å·"); |
| | | |
| | | // ========== ç¨æ·æ°æ®äº¤æ¥ 1-030-007-000 ========== |
| | | ErrorCode USER_HANDOVER_NOT_EXISTS = new ErrorCode(1_030_007_000, "ç¨æ·äº¤æ¥è®°å½ä¸åå¨"); |
| | |
| | | ErrorCode ATTENDANCE_RULE_DEPT_EXISTS = new ErrorCode(1_030_004_007, "该é¨é¨å·²é
ç½®èå¤è§å"); |
| | | ErrorCode ATTENDANCE_HOLIDAY_NOT_EXISTS = new ErrorCode(1_030_004_008, "è忥é
ç½®ä¸åå¨"); |
| | | ErrorCode ATTENDANCE_HOLIDAY_DATE_EXISTS = new ErrorCode(1_030_004_009, "è¯¥æ¥æè忥é
置已åå¨"); |
| | | ErrorCode ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID = new ErrorCode(1_030_004_012, "èåæ¥ç»ææ¥æä¸è½æ©äºå¼å§æ¥æ"); |
| | | ErrorCode ATTENDANCE_HOLIDAY_RANGE_DATE_EXISTS = new ErrorCode(1_030_004_013, "æ¥æã{}ãå·²åå¨è忥é
ç½®ã{}ãï¼æ¬æ¬¡æªä¿åï¼è¯·å
å é¤è¯¥æ¥æé
ç½®ææ¹ä¸ºç¼è¾"); |
| | | ErrorCode ATTENDANCE_HOLIDAY_RANGE_IDS_EMPTY = new ErrorCode(1_030_004_014, "è¯·éæ©è¦ç¼è¾æå é¤çè忥åºé´"); |
| | | ErrorCode ATTENDANCE_HOLIDAY_RANGE_NOT_EXISTS = new ErrorCode(1_030_004_015, "é¨åè忥é
置已ä¸åå¨ï¼å¯è½å·²è¢«å é¤ï¼ï¼è¯·å·æ°å表åéæ°æä½"); |
| | | ErrorCode ATTENDANCE_CLOCK_FAIL_NO_RULE = new ErrorCode(1_030_004_010, "æå¡å¤±è´¥ï¼æªæ¾å°èå¤è§å"); |
| | | ErrorCode ATTENDANCE_CLOCK_FAIL_HOLIDAY = new ErrorCode(1_030_004_011, "æå¡å¤±è´¥ï¼å½æ¥ä¸ºä¼æ¯æ¥"); |
| | | ErrorCode ATTENDANCE_CLOCK_FAIL_NOT_WORKDAY = new ErrorCode(1_030_004_012, "æå¡å¤±è´¥ï¼å½æ¥ä¸æ¯å·¥ä½æ¥"); |
| | |
| | | ErrorCode SCHEDULE_ITEM_LIST_EMPTY = new ErrorCode(1_030_010_000, "æçæ°æ®ä¸è½ä¸ºç©º"); |
| | | ErrorCode SCHEDULE_SHIFT_NOT_EXISTS = new ErrorCode(1_030_010_001, "æçå¼ç¨ççæ¬¡ä¸åå¨"); |
| | | ErrorCode SCHEDULE_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_030_010_002, "æçå¼ç¨çåå·¥ä¸åå¨"); |
| | | ErrorCode SCHEDULE_BATCH_DATE_RANGE_INVALID = new ErrorCode(1_030_010_003, "æ¹éæççç»ææ¥æä¸è½æ©äºå¼å§æ¥æ"); |
| | | ErrorCode SCHEDULE_BATCH_EMPLOYEE_EMPTY = new ErrorCode(1_030_010_004, "æéé¨é¨ã{}ã䏿²¡æç¬¦åæ¡ä»¶çåå·¥ï¼è¯·æ£æ¥é¨é¨ãå²ä½ååå·¥ç¶æ"); |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportExcelVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationSaveReqVO; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | |
| | | return success(leaveApplicationService.getApproveProcessDefinitionList()); |
| | | } |
| | | |
| | | @GetMapping("/get-import-template") |
| | | @Operation(summary = "ä¸è½½è¯·åç³è¯·å¯¼å
¥æ¨¡æ¿") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave:import')") |
| | | public void getImportTemplate(HttpServletResponse response) throws IOException { |
| | | List<HrmLeaveApplicationImportExcelVO> list = List.of( |
| | | HrmLeaveApplicationImportExcelVO.builder() |
| | | .phone("13800138000") |
| | | .leaveType("å¹´å") |
| | | .startTime(LocalDateTime.of(2026, 10, 8, 9, 0, 0)) |
| | | .endTime(LocalDateTime.of(2026, 10, 8, 18, 0, 0)) |
| | | .duration(new BigDecimal("1")) |
| | | .reason("家䏿äº") |
| | | .remark("示ä¾è¡ï¼å¯¼å
¥å请å é¤") |
| | | .build() |
| | | ); |
| | | ExcelUtils.write(response, "请åç³è¯·å¯¼å
¥æ¨¡æ¿.xls", "请åç³è¯·å表", |
| | | HrmLeaveApplicationImportExcelVO.class, list); |
| | | } |
| | | |
| | | @PostMapping("/import") |
| | | @Operation(summary = "æ¹é导å
¥è¯·åç³è¯·") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave:import')") |
| | | public CommonResult<HrmLeaveApplicationImportRespVO> importLeaveApplication( |
| | | @Valid HrmLeaveApplicationImportReqVO importReqVO) throws IOException { |
| | | List<HrmLeaveApplicationImportExcelVO> list = ExcelUtils.read( |
| | | importReqVO.getFile(), HrmLeaveApplicationImportExcelVO.class); |
| | | return success(leaveApplicationService.importLeaveApplicationList(list)); |
| | | } |
| | | |
| | | @GetMapping("/export-excel") |
| | | @Operation(summary = "导åºè¯·åç³è¯· Excel") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave:export')") |
| | |
| | | } |
| | | @PutMapping("/update") @PreAuthorize("@ss.hasPermission('hrm:overtime:update')") |
| | | public CommonResult<Boolean> update(@Valid @RequestBody HrmOvertimeApplicationSaveReqVO reqVO) { |
| | | service.update(reqVO, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | service.update(reqVO, SecurityFrameworkUtils.getLoginUserId(), canManage()); return success(true); |
| | | } |
| | | @DeleteMapping("/delete") @PreAuthorize("@ss.hasPermission('hrm:overtime:delete')") |
| | | public CommonResult<Boolean> delete(@RequestParam Long id) { |
| | | service.delete(id, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | service.delete(id, SecurityFrameworkUtils.getLoginUserId(), canManage()); return success(true); |
| | | } |
| | | @GetMapping("/get") @PreAuthorize("@ss.hasAnyPermissions('hrm:overtime:query', 'bpm:task:query')") |
| | | public CommonResult<HrmOvertimeApplicationRespVO> get(@RequestParam Long id) { |
| | |
| | | } |
| | | @PostMapping("/submit") @PreAuthorize("@ss.hasPermission('hrm:overtime:submit')") |
| | | public CommonResult<Boolean> submit(@RequestParam Long id, @RequestParam String processDefinitionKey) { |
| | | service.submit(id, processDefinitionKey, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | service.submit(id, processDefinitionKey, SecurityFrameworkUtils.getLoginUserId(), canManage()); return success(true); |
| | | } |
| | | @PostMapping("/cancel") @PreAuthorize("@ss.hasPermission('hrm:overtime:cancel')") |
| | | public CommonResult<Boolean> cancel(@RequestParam Long id) { |
| | | service.cancel(id, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | service.cancel(id, SecurityFrameworkUtils.getLoginUserId(), canManage()); return success(true); |
| | | } |
| | | @GetMapping("/approve-process-definition-list") @PreAuthorize("@ss.hasPermission('hrm:overtime:query')") |
| | | public CommonResult<List<Map<String, Object>>> processes() { return success(service.getApproveProcessDefinitionList()); } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo; |
| | | |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * 请åç³è¯· Excel 导å
¥ VO |
| | | * |
| | | * 请åç±»åæåç§°å¡«åï¼å¦ãå¹´åããäºåãï¼ï¼ä¹å
¼å®¹å¡«ååå
¸å¼ï¼1~6ï¼ï¼ |
| | | * è¿æ ·å¡«åé误æ¶è½ç»åºãä½ å¡«çå¼ + å¯å¡«å¼æ¸
åãç精确æç¤ºã |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class HrmLeaveApplicationImportExcelVO { |
| | | |
| | | @ExcelProperty("ç³è¯·äººææºå·") |
| | | private String phone; |
| | | |
| | | @ExcelProperty("请åç±»å") |
| | | private String leaveType; |
| | | |
| | | @ExcelProperty("å¼å§æ¶é´") |
| | | private LocalDateTime startTime; |
| | | |
| | | @ExcelProperty("ç»ææ¶é´") |
| | | private LocalDateTime endTime; |
| | | |
| | | @ExcelProperty("è¯·åæ¶é¿ï¼å¤©ï¼") |
| | | private BigDecimal duration; |
| | | |
| | | @ExcelProperty("请ååå ") |
| | | private String reason; |
| | | |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | @Schema(description = "管çåå° - 请åç³è¯·å¯¼å
¥ Request VO") |
| | | @Data |
| | | public class HrmLeaveApplicationImportReqVO { |
| | | |
| | | @Schema(description = "Excel æä»¶", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "Excel æä»¶ä¸è½ä¸ºç©º") |
| | | private MultipartFile file; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Schema(description = "管çåå° - 请åç³è¯·å¯¼å
¥ Response VO") |
| | | @Data |
| | | @Builder |
| | | public class HrmLeaveApplicationImportRespVO { |
| | | |
| | | @Schema(description = "å建æåçç³è¯·äººåæ¥ææ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> createNames; |
| | | |
| | | @Schema(description = "导å
¥å¤±è´¥çéåï¼key 为è¡å·ï¼value 为失败åå ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private Map<String, String> failureNames; |
| | | |
| | | } |
| | |
| | | @Data |
| | | public class HrmOvertimeApplicationSaveReqVO { |
| | | private Long id; |
| | | @Schema(description = "å ç人åIDï¼éæ©ç³è¯·äººä¸ºç©ºæ¶æå½åç»å½è´¦å·å
³èçåå·¥ï¼", example = "66") |
| | | private Long employeeId; |
| | | @NotNull(message = "å çæ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate overtimeDate; |
| | | @NotNull(message = "å¼å§æ¶é´ä¸è½ä¸ºç©º") |
| | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayGroupRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeCreateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeUpdateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidaySaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; |
| | |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; |
| | |
| | | return success(attendanceHolidayService.createAttendanceHoliday(createReqVO)); |
| | | } |
| | | |
| | | @PostMapping("/create-range") |
| | | @Operation(summary = "ææ¥æèå´æ°å¢è忥é
ç½®ï¼å«ä¸é´æ¯ä¸å¤©ï¼") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:create')") |
| | | public CommonResult<Integer> createAttendanceHolidayRange( |
| | | @Valid @RequestBody HrmAttendanceHolidayRangeCreateReqVO createReqVO) { |
| | | return success(attendanceHolidayService.createAttendanceHolidayRange(createReqVO)); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "æ´æ°è忥é
ç½®") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:update')") |
| | | public CommonResult<Boolean> updateAttendanceHoliday(@Valid @RequestBody HrmAttendanceHolidaySaveReqVO updateReqVO) { |
| | | attendanceHolidayService.updateAttendanceHoliday(updateReqVO); |
| | | return success(true); |
| | | } |
| | | |
| | | @PutMapping("/update-range") |
| | | @Operation(summary = "ææ¥æåºé´æ´æ°è忥é
ç½®ï¼å é¤ååºé´è®°å½åææ°èµ·æ¢æ¥æéåï¼") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:update')") |
| | | public CommonResult<Boolean> updateAttendanceHolidayRange( |
| | | @Valid @RequestBody HrmAttendanceHolidayRangeUpdateReqVO updateReqVO) { |
| | | attendanceHolidayService.updateAttendanceHolidayRange(updateReqVO); |
| | | return success(true); |
| | | } |
| | | |
| | |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:delete')") |
| | | public CommonResult<Boolean> deleteAttendanceHoliday(@RequestParam("id") Long id) { |
| | | attendanceHolidayService.deleteAttendanceHoliday(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/delete-range") |
| | | @Operation(summary = "ææ¥æåºé´å é¤è忥é
ç½®ï¼å é¤åºé´å
å
¨é¨æ¥æï¼") |
| | | @Parameter(name = "ids", description = "åºé´å
è忥IDå表", required = true) |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:delete')") |
| | | public CommonResult<Boolean> deleteAttendanceHolidayRange(@RequestParam("ids") List<Long> ids) { |
| | | attendanceHolidayService.deleteAttendanceHolidayRange(ids); |
| | | return success(true); |
| | | } |
| | | |
| | |
| | | return success(BeanUtils.toBean(pageResult, HrmAttendanceHolidayRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/page-grouped") |
| | | @Operation(summary = "è·å¾è忥é
ç½®åé¡µï¼æè¿ç»æ¥æåºé´åå¹¶å±ç¤ºï¼") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:query')") |
| | | public CommonResult<PageResult<HrmAttendanceHolidayGroupRespVO>> getAttendanceHolidayGroupPage( |
| | | @Valid HrmAttendanceHolidayPageReqVO pageReqVO) { |
| | | return success(attendanceHolidayService.getAttendanceHolidayGroupPage(pageReqVO)); |
| | | } |
| | | |
| | | @GetMapping("/list") |
| | | @Operation(summary = "è·å¾æå®æ¥æèå´çè忥å表ï¼éæ¥ï¼æçæ¥å使ç¨ï¼") |
| | | @Parameter(name = "startDate", description = "å¼å§æ¥æ", required = true) |
| | | @Parameter(name = "endDate", description = "ç»ææ¥æ", required = true) |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:query')") |
| | | public CommonResult<List<HrmAttendanceHolidayRespVO>> getAttendanceHolidayList( |
| | | @RequestParam("startDate") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate, |
| | | @RequestParam("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) { |
| | | List<HrmAttendanceHolidayDO> list = attendanceHolidayService.getAttendanceHolidayListByDateRange(startDate, endDate); |
| | | return success(BeanUtils.toBean(list, HrmAttendanceHolidayRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/export-excel") |
| | | @Operation(summary = "导åºè忥é
ç½® Excel") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:export')") |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleListReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleSaveReqVO; |
| | |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/batch-save") |
| | | @Operation(summary = "æé¨é¨+å²ä½æ¹éæçï¼ä¸ç±»äººä¸æ¬¡æå®ï¼") |
| | | @PreAuthorize("@ss.hasPermission('hrm:employee-schedule:save')") |
| | | public CommonResult<HrmEmployeeScheduleBatchSaveRespVO> batchSaveEmployeeSchedule( |
| | | @Valid @RequestBody HrmEmployeeScheduleBatchSaveReqVO reqVO) { |
| | | return success(employeeScheduleService.batchSaveSchedule(reqVO)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 管çåå° - èå¤è忥æåºé´åç»åç Response VO |
| | | * |
| | | * åºéæèªç¶æ¥åå¨ï¼å表æãè¿ç»æ¥æ + åç§°/ç±»å/æ¯å¦æ³å®/夿³¨ä¸è´ãåå¹¶æä¸è¡å±ç¤ºï¼ |
| | | * ä¾å¦ 2026-10-01 ~ 2026-10-03 çå½åºèå¨å表ä¸åªå ä¸è¡ã |
| | | */ |
| | | @Schema(description = "管çåå° - èå¤è忥åç» Response VO") |
| | | @Data |
| | | public class HrmAttendanceHolidayGroupRespVO { |
| | | |
| | | @Schema(description = "èµ·å§æ¥æå¯¹åºçè®°å½IDï¼è¡ keyï¼", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "åºé´å
å
¨é¨è®°å½IDï¼ç¨äºåºé´ç¼è¾/å é¤") |
| | | private List<Long> ids; |
| | | |
| | | @Schema(description = "è忥åç§°", example = "å½åºè") |
| | | private String name; |
| | | |
| | | @Schema(description = "å¼å§æ¥æ", example = "2026-10-01") |
| | | private LocalDate date; |
| | | |
| | | @Schema(description = "ç»ææ¥æ", example = "2026-10-03") |
| | | private LocalDate endDate; |
| | | |
| | | @Schema(description = "åºé´å¤©æ°", example = "3") |
| | | private Integer dayCount; |
| | | |
| | | @Schema(description = "ç±»åï¼1-伿¯æ¥ï¼2-工使¥", example = "1") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "æ¯å¦æ³å®è忥ï¼0-å¦ï¼1-æ¯", example = "1") |
| | | private Integer isLegal; |
| | | |
| | | @Schema(description = "夿³¨", example = "å½åºèæ³å®åæ") |
| | | private String remark; |
| | | |
| | | @Schema(description = "å建æ¶é´") |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
| | |
| | | @Schema(description = "ç±»åï¼1-伿¯æ¥ï¼2-工使¥", example = "1") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "æ¯å¦æ³å®è忥ï¼0-å¦ï¼1-æ¯", example = "1") |
| | | private Integer isLegal; |
| | | |
| | | @Schema(description = "å¼å§æ¥æ", example = "2024-01-01") |
| | | private LocalDate startDate; |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * 管çåå° - ææ¥æèå´æ°å¢è忥é
ç½® Request VO |
| | | * |
| | | * åç«¯éæ©ã10æ1æ¥ ~ 10æ3æ¥ãæ¶ï¼åç«¯ä¸æ¬¡æ§åå
¥ 3 天ï¼é¿å
åªåèµ·æ¢ä¸¤å¤©ã |
| | | */ |
| | | @Schema(description = "管çåå° - ææ¥æèå´æ°å¢è忥é
ç½® Request VO") |
| | | @Data |
| | | public class HrmAttendanceHolidayRangeCreateReqVO { |
| | | |
| | | @Schema(description = "è忥åç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "å½åºè") |
| | | @NotBlank(message = "è忥åç§°ä¸è½ä¸ºç©º") |
| | | private String name; |
| | | |
| | | @Schema(description = "å¼å§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-10-01") |
| | | @NotNull(message = "å¼å§æ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate startDate; |
| | | |
| | | @Schema(description = "ç»ææ¥æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-10-03") |
| | | @NotNull(message = "ç»ææ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate endDate; |
| | | |
| | | @Schema(description = "ç±»åï¼1-伿¯æ¥ï¼2-工使¥", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "ç±»åä¸è½ä¸ºç©º") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "æ¯å¦æ³å®è忥ï¼false-å¦ï¼true-æ¯", example = "true") |
| | | private Boolean isLegal; |
| | | |
| | | @Schema(description = "夿³¨", example = "å½åºèæ³å®åæ") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 管çåå° - ææ¥æåºé´æ´æ°è忥é
ç½® Request VO |
| | | * |
| | | * å表æè¿ç»åºé´åå¹¶å±ç¤ºï¼ç¼è¾æ¶æè¯¥åºé´å
çå
¨é¨è®°å½ ID ä¸èµ·æäº¤ï¼ |
| | | * å端å
å 餿§è®°å½åææ°çèµ·æ¢æ¥æéæ°åå
¥ï¼é¿å
åªæ¹å°æä¸å¤©å¯¼è´åºé´æè£ã |
| | | */ |
| | | @Schema(description = "管çåå° - ææ¥æåºé´æ´æ°è忥é
ç½® Request VO") |
| | | @Data |
| | | public class HrmAttendanceHolidayRangeUpdateReqVO { |
| | | |
| | | @Schema(description = "åºé´å
åæè®°å½IDå表", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotEmpty(message = "åºé´è®°å½IDä¸è½ä¸ºç©º") |
| | | private List<Long> ids; |
| | | |
| | | @Schema(description = "è忥åç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "å½åºè") |
| | | @NotBlank(message = "è忥åç§°ä¸è½ä¸ºç©º") |
| | | private String name; |
| | | |
| | | @Schema(description = "å¼å§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-10-01") |
| | | @NotNull(message = "å¼å§æ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate startDate; |
| | | |
| | | @Schema(description = "ç»ææ¥æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-10-03") |
| | | @NotNull(message = "ç»ææ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate endDate; |
| | | |
| | | @Schema(description = "ç±»åï¼1-伿¯æ¥ï¼2-工使¥", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "ç±»åä¸è½ä¸ºç©º") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "æ¯å¦æ³å®è忥ï¼false-å¦ï¼true-æ¯", example = "true") |
| | | private Boolean isLegal; |
| | | |
| | | @Schema(description = "夿³¨", example = "å½åºèæ³å®åæ") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * 管çåå° - åå·¥æçæç¾¤ä½æ¹éä¿å Request VO |
| | | * |
| | | * 䏿¬¡ä¸ºãé¨é¨ + å²ä½ãçéåºçä¸ç±»åå·¥ï¼ææ¥æèå´ç»ä¸æçã |
| | | */ |
| | | @Schema(description = "管çåå° - åå·¥æçæç¾¤ä½æ¹éä¿å Request VO") |
| | | @Data |
| | | public class HrmEmployeeScheduleBatchSaveReqVO { |
| | | |
| | | @Schema(description = "é¨é¨IDï¼å«ä¸çº§é¨é¨ï¼", requiredMode = Schema.RequiredMode.REQUIRED, example = "119") |
| | | @NotNull(message = "é¨é¨ä¸è½ä¸ºç©º") |
| | | private Long deptId; |
| | | |
| | | @Schema(description = "å²ä½IDï¼ä¸ºç©ºè¡¨ç¤ºä¸éå²ä½", example = "48") |
| | | private Long postId; |
| | | |
| | | @Schema(description = "åå·¥ç¶æï¼1-å¨èï¼2-è¯ç¨ï¼3-离èï¼ä¸ºç©ºè¡¨ç¤ºå¨èåè¯ç¨", example = "1") |
| | | private Integer employeeStatus; |
| | | |
| | | @Schema(description = "æçå¼å§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-10-01") |
| | | @NotNull(message = "æçå¼å§æ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate startDate; |
| | | |
| | | @Schema(description = "æçç»ææ¥æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-10-31") |
| | | @NotNull(message = "æçç»ææ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate endDate; |
| | | |
| | | @Schema(description = "çæ¬¡IDï¼ä¸ºç©ºè¡¨ç¤ºä¼æ¯ï¼æ¸
餿çï¼", example = "1") |
| | | private Long shiftId; |
| | | |
| | | @Schema(description = "伿¯æ¨¡å¼ï¼none-ä¸ä¼æ¯ï¼single-卿¥ä¼æ¯ï¼double-å¨å
æ¥ä¼æ¯ï¼ä¸ºç©ºæä¸ä¼æ¯å¤ç", |
| | | example = "double") |
| | | private String restMode; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | @Schema(description = "管çåå° - åå·¥æçæç¾¤ä½æ¹éä¿å Response VO") |
| | | @Data |
| | | public class HrmEmployeeScheduleBatchSaveRespVO { |
| | | |
| | | @Schema(description = "æ¬æ¬¡æçè¦ççåå·¥æ°é", example = "50") |
| | | private Integer employeeCount; |
| | | |
| | | @Schema(description = "æ¬æ¬¡æçåå
¥/æ¸
é¤çæçæ¡ç®æ°é", example = "1550") |
| | | private Integer itemCount; |
| | | |
| | | } |
| | |
| | | @Schema(description = "é¨é¨åç§°") |
| | | private String deptName; |
| | | |
| | | @Schema(description = "å²ä½åç§°ï¼å¤ä¸ªç¨éå·åéï¼") |
| | | private String postName; |
| | | |
| | | @Schema(description = "åå·¥ç¶æ") |
| | | private Integer employeeStatus; |
| | | |
| | |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayPageReqVO; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import org.apache.ibatis.annotations.Delete; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | |
| | | return selectPage(reqVO, new LambdaQueryWrapperX<HrmAttendanceHolidayDO>() |
| | | .likeIfPresent(HrmAttendanceHolidayDO::getName, reqVO.getName()) |
| | | .eqIfPresent(HrmAttendanceHolidayDO::getType, reqVO.getType()) |
| | | .eqIfPresent(HrmAttendanceHolidayDO::getIsLegal, reqVO.getIsLegal()) |
| | | .betweenIfPresent(HrmAttendanceHolidayDO::getDate, reqVO.getStartDate(), reqVO.getEndDate()) |
| | | .orderByDesc(HrmAttendanceHolidayDO::getDate)); |
| | | } |
| | | |
| | | /** |
| | | * ææ¥è¯¢æ¡ä»¶åå
¨é¨è忥ï¼ååºï¼ï¼ç¨äºå表æè¿ç»åºé´åå¹¶å±ç¤º |
| | | */ |
| | | default List<HrmAttendanceHolidayDO> selectListByCondition(HrmAttendanceHolidayPageReqVO reqVO) { |
| | | return selectList(new LambdaQueryWrapperX<HrmAttendanceHolidayDO>() |
| | | .likeIfPresent(HrmAttendanceHolidayDO::getName, reqVO.getName()) |
| | | .eqIfPresent(HrmAttendanceHolidayDO::getType, reqVO.getType()) |
| | | .eqIfPresent(HrmAttendanceHolidayDO::getIsLegal, reqVO.getIsLegal()) |
| | | .betweenIfPresent(HrmAttendanceHolidayDO::getDate, reqVO.getStartDate(), reqVO.getEndDate()) |
| | | .orderByAsc(HrmAttendanceHolidayDO::getDate)); |
| | | } |
| | | |
| | | default HrmAttendanceHolidayDO selectByDate(LocalDate date) { |
| | |
| | | .orderByAsc(HrmAttendanceHolidayDO::getDate)); |
| | | } |
| | | |
| | | /** |
| | | * ç©çå é¤è忥é
ç½® |
| | | * |
| | | * å¯ä¸ç´¢å¼ä¸º (date, deleted)ï¼é»è¾å é¤ä¸¤æ¬¡åä¸å¤©ä¼äº§ç deleted=1 ç主é®å²çªï¼ |
| | | * å æ¤è忥é
ç½®çå é¤ç»ä¸èµ°ç©çå é¤ã |
| | | */ |
| | | @Delete("<script>DELETE FROM hrm_attendance_holiday WHERE id IN " + |
| | | "<foreach collection='ids' item='id' open='(' separator=',' close=')'>#{id}</foreach></script>") |
| | | int physicalDeleteByIds(@Param("ids") List<Long> ids); |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.hrm.dal.mysql.attendance; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceSummaryDO; |
| | |
| | | .orderByAsc(HrmAttendanceSummaryDO::getUserId)); |
| | | } |
| | | |
| | | /** |
| | | * æå¹´ææ¹éå·æ°åºåºå¤å¤©æ°ï¼è忥é
ç½®åååè°ç¨ï¼ |
| | | * |
| | | * @return æ´æ°çè®°å½æ° |
| | | */ |
| | | default int updateWorkDaysByYearMonth(String yearMonth, Integer workDays) { |
| | | return update(new HrmAttendanceSummaryDO(), new LambdaUpdateWrapper<HrmAttendanceSummaryDO>() |
| | | .set(HrmAttendanceSummaryDO::getWorkDays, workDays) |
| | | .eq(HrmAttendanceSummaryDO::getYearMonth, yearMonth)); |
| | | } |
| | | |
| | | } |
| | |
| | | return selectList(HrmEmployeeDO::getDeptId, deptId); |
| | | } |
| | | |
| | | default List<HrmEmployeeDO> selectListByDeptIds(Collection<Long> deptIds) { |
| | | if (deptIds == null || deptIds.isEmpty()) { |
| | | return List.of(); |
| | | } |
| | | return selectList(new LambdaQueryWrapperX<HrmEmployeeDO>() |
| | | .in(HrmEmployeeDO::getDeptId, deptIds) |
| | | .orderByAsc(HrmEmployeeDO::getId)); |
| | | } |
| | | |
| | | default List<HrmEmployeeDO> selectByEmployeeStatus(Integer employeeStatus) { |
| | | return selectList(HrmEmployeeDO::getEmployeeStatus, employeeStatus); |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.approval; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportExcelVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationSaveReqVO; |
| | |
| | | */ |
| | | HrmLeaveApplicationDO getLeaveApplicationByProcessInstanceId(String processInstanceId); |
| | | |
| | | /** |
| | | * æ¹é导å
¥è¯·åç³è¯·ï¼å¯¼å
¥å为èç¨¿ç¶æï¼éå¨é¡µé¢æäº¤å®¡æ¹ï¼ |
| | | * |
| | | * @param importList 导å
¥æ°æ® |
| | | * @return 导å
¥ç»æ |
| | | */ |
| | | HrmLeaveApplicationImportRespVO importLeaveApplicationList(List<HrmLeaveApplicationImportExcelVO> importList); |
| | | |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| | |
| | | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportExcelVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmLeaveApplicationDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmLeaveApplicationMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmLeaveTypeEnum; |
| | |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | @Resource |
| | | private HrmEmployeeMapper employeeMapper; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | return leaveApplicationMapper.selectByProcessInstanceId(processInstanceId); |
| | | } |
| | | |
| | | @Override |
| | | public HrmLeaveApplicationImportRespVO importLeaveApplicationList(List<HrmLeaveApplicationImportExcelVO> importList) { |
| | | // 1. è¿æ»¤ç©ºè¡ï¼ææºå·ä¸ºç©ºç Excel è¡è§ä¸ºç©ºè¡ï¼ |
| | | importList = filterList(importList, item -> StrUtil.isNotBlank(item.getPhone())); |
| | | if (CollUtil.isEmpty(importList)) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | |
| | | // 2. éè¡å¯¼å
¥ï¼åè¡å¤±è´¥ä¸å½±åå
¶ä»è¡ |
| | | HrmLeaveApplicationImportRespVO respVO = HrmLeaveApplicationImportRespVO.builder() |
| | | .createNames(new ArrayList<>()) |
| | | .failureNames(new LinkedHashMap<>()) |
| | | .build(); |
| | | for (int i = 0; i < importList.size(); i++) { |
| | | HrmLeaveApplicationImportExcelVO row = importList.get(i); |
| | | // Excel 第 1 è¡æ¯è¡¨å¤´ï¼æ°æ®ä»ç¬¬ 2 è¡å¼å§ |
| | | String rowKey = "第" + (i + 2) + "è¡"; |
| | | try { |
| | | HrmLeaveApplicationSaveReqVO saveReqVO = buildImportSaveReqVO(row); |
| | | createLeaveApplication(saveReqVO); |
| | | respVO.getCreateNames().add(row.getPhone() + " " + row.getStartTime().toLocalDate()); |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureNames().put(rowKey, ex.getMessage()); |
| | | } catch (Exception ex) { |
| | | respVO.getFailureNames().put(rowKey, "导å
¥å¤±è´¥ï¼" + ex.getMessage()); |
| | | } |
| | | } |
| | | return respVO; |
| | | } |
| | | |
| | | private HrmLeaveApplicationSaveReqVO buildImportSaveReqVO(HrmLeaveApplicationImportExcelVO row) { |
| | | String phone = row.getPhone().trim(); |
| | | HrmEmployeeDO employee = employeeMapper.selectByPhone(phone); |
| | | if (employee == null) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_EMPLOYEE_NOT_EXISTS, phone); |
| | | } |
| | | if (employee.getUserId() == null) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_EMPLOYEE_NO_USER, employee.getName()); |
| | | } |
| | | // 请åç±»åï¼æåç§°å¹é
ï¼å
¼å®¹ç´æ¥å¡«åå
¸å¼ï¼ï¼å¹é
ä¸å°æ¶ååºå¯å¡«å¼ |
| | | List<String> leaveTypeNames = Arrays.stream(HrmLeaveTypeEnum.values()) |
| | | .map(HrmLeaveTypeEnum::getName).toList(); |
| | | String leaveTypeText = StrUtil.trim(row.getLeaveType()); |
| | | if (StrUtil.isBlank(leaveTypeText)) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, |
| | | "请åç±»åï¼å¯éï¼" + String.join("ã", leaveTypeNames) + "ï¼"); |
| | | } |
| | | Integer leaveType = Arrays.stream(HrmLeaveTypeEnum.values()) |
| | | .filter(item -> item.getName().equals(leaveTypeText) |
| | | || String.valueOf(item.getType()).equals(leaveTypeText)) |
| | | .map(HrmLeaveTypeEnum::getType) |
| | | .findFirst().orElse(null); |
| | | if (leaveType == null) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_FIELD_INVALID, |
| | | "请åç±»å", leaveTypeText, String.join("ã", leaveTypeNames)); |
| | | } |
| | | if (row.getStartTime() == null) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "å¼å§æ¶é´"); |
| | | } |
| | | if (row.getEndTime() == null) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "ç»ææ¶é´"); |
| | | } |
| | | if (!row.getStartTime().isBefore(row.getEndTime())) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_TIME_INVALID, |
| | | row.getStartTime(), row.getEndTime()); |
| | | } |
| | | if (row.getDuration() == null || row.getDuration().signum() <= 0) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "è¯·åæ¶é¿ï¼å¤©ï¼å¿
é¡»å¤§äº 0ï¼"); |
| | | } |
| | | if (StrUtil.isBlank(row.getReason())) { |
| | | throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "请ååå "); |
| | | } |
| | | |
| | | HrmLeaveApplicationSaveReqVO saveReqVO = new HrmLeaveApplicationSaveReqVO(); |
| | | saveReqVO.setUserId(employee.getUserId()); |
| | | saveReqVO.setDeptId(employee.getDeptId()); |
| | | saveReqVO.setLeaveType(leaveType); |
| | | saveReqVO.setStartTime(row.getStartTime()); |
| | | saveReqVO.setEndTime(row.getEndTime()); |
| | | saveReqVO.setDuration(row.getDuration()); |
| | | saveReqVO.setReason(row.getReason().trim()); |
| | | saveReqVO.setRemark(row.getRemark()); |
| | | return saveReqVO; |
| | | } |
| | | |
| | | } |
| | |
| | | String APPROVE_CATEGORY_CODE = "overtime_approve"; |
| | | |
| | | Long create(@Valid HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId); |
| | | void update(@Valid HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId); |
| | | void delete(Long id, Long loginUserId); |
| | | void update(@Valid HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId, boolean canManage); |
| | | void delete(Long id, Long loginUserId, boolean canManage); |
| | | HrmOvertimeApplicationRespVO getDetail(Long id, Long loginUserId, boolean canManage); |
| | | HrmOvertimeApplicationRespVO getCurrentApplicant(Long loginUserId); |
| | | PageResult<HrmOvertimeApplicationRespVO> getPage(HrmOvertimeApplicationPageReqVO reqVO); |
| | | void submit(Long id, String processDefinitionKey, Long loginUserId); |
| | | void cancel(Long id, Long loginUserId); |
| | | void submit(Long id, String processDefinitionKey, Long loginUserId, boolean canManage); |
| | | void cancel(Long id, Long loginUserId, boolean canManage); |
| | | List<Map<String, Object>> getApproveProcessDefinitionList(); |
| | | void updateAuditStatus(Long id, Integer status); |
| | | } |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long create(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) { |
| | | HrmEmployeeDO employee = requireEmployee(loginUserId); |
| | | HrmEmployeeDO employee = resolveEmployee(reqVO.getEmployeeId(), loginUserId); |
| | | HrmOvertimeApplicationDO application = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class); |
| | | applyApplicantAndCalculatedTime(application, employee); |
| | | application.setNo(noRedisDAO.generateOvertimeApplicationNo()); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void update(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) { |
| | | HrmOvertimeApplicationDO existing = requireOwnedDraft(reqVO.getId(), loginUserId); |
| | | public void update(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId, boolean canManage) { |
| | | HrmOvertimeApplicationDO existing = requireManageableDraft(reqVO.getId(), loginUserId, canManage); |
| | | HrmOvertimeApplicationDO update = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class); |
| | | applyApplicantAndCalculatedTime(update, requireEmployee(loginUserId)); |
| | | applyApplicantAndCalculatedTime(update, resolveEmployee(reqVO.getEmployeeId(), loginUserId)); |
| | | update.setId(existing.getId()); |
| | | mapper.updateById(update); |
| | | } |
| | | |
| | | @Override |
| | | public void delete(Long id, Long loginUserId) { |
| | | public void delete(Long id, Long loginUserId, boolean canManage) { |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | boolean deletable = Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus()) |
| | | || Objects.equals(application.getStatus(), HrmAuditStatusEnum.CANCEL.getStatus()); |
| | | if (!Objects.equals(application.getUserId(), loginUserId) || !deletable) { |
| | | if ((!canManage && !Objects.equals(application.getUserId(), loginUserId)) || !deletable) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | mapper.deleteById(id); |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void submit(Long id, String processDefinitionKey, Long loginUserId) { |
| | | HrmOvertimeApplicationDO application = requireOwnedDraft(id, loginUserId); |
| | | public void submit(Long id, String processDefinitionKey, Long loginUserId, boolean canManage) { |
| | | HrmOvertimeApplicationDO application = requireManageableDraft(id, loginUserId, canManage); |
| | | validateProcessDefinitions(); |
| | | ProcessDefinition definition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey); |
| | | if (definition == null || !BPM_PROCESS_DEFINITION_KEY.equals(definition.getKey())) { |
| | | throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(loginUserId, |
| | | // 代åå·¥æäº¤æ¶ï¼æµç¨å起人ä»åºä¸ºç³è¯·è¡¨ä¸çç³è¯·äºº |
| | | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(application.getUserId(), |
| | | new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(processDefinitionKey) |
| | | .setBusinessKey(String.valueOf(id))); |
| | | mapper.updateById(HrmOvertimeApplicationDO.builder().id(id).processInstanceId(processInstanceId) |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void cancel(Long id, Long loginUserId) { |
| | | public void cancel(Long id, Long loginUserId, boolean canManage) { |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | if (!Objects.equals(application.getUserId(), loginUserId) |
| | | if ((!canManage && !Objects.equals(application.getUserId(), loginUserId)) |
| | | || !Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); |
| | | } |
| | | bpmProcessInstanceService.cancelProcessInstanceByStartUser(loginUserId, |
| | | bpmProcessInstanceService.cancelProcessInstanceByStartUser(application.getUserId(), |
| | | new BpmProcessInstanceCancelReqVO().setId(application.getProcessInstanceId()).setReason("ç³è¯·äººæ¤éå çç³è¯·")); |
| | | } |
| | | |
| | |
| | | return value; |
| | | } |
| | | |
| | | private HrmOvertimeApplicationDO requireOwnedDraft(Long id, Long userId) { |
| | | private HrmOvertimeApplicationDO requireManageableDraft(Long id, Long userId, boolean canManage) { |
| | | HrmOvertimeApplicationDO value = require(id); |
| | | if (!Objects.equals(value.getUserId(), userId) |
| | | if ((!canManage && !Objects.equals(value.getUserId(), userId)) |
| | | || !Objects.equals(value.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | |
| | | return employee; |
| | | } |
| | | |
| | | /** |
| | | * ç³è¯·äººä¸ºç©ºæ¶åéå°å½åç»å½è´¦å·å
³èçåå·¥ï¼éæ©ä»äººæ¶æåå·¥IDå è½½ |
| | | */ |
| | | private HrmEmployeeDO resolveEmployee(Long employeeId, Long loginUserId) { |
| | | if (employeeId == null) { |
| | | return requireEmployee(loginUserId); |
| | | } |
| | | HrmEmployeeDO employee = employeeMapper.selectById(employeeId); |
| | | if (employee == null) { |
| | | throw exception(OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NOT_EXISTS); |
| | | } |
| | | if (employee.getUserId() == null) { |
| | | throw exception(OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NO_USER, employee.getName()); |
| | | } |
| | | return employee; |
| | | } |
| | | |
| | | /** å½åå¾
å审æ¹äººææ¾å¤çè¿è¯¥æµç¨ç审æ¹äººå¯æ¥çä¸å¡è¯¦æ
ã */ |
| | | private boolean isProcessParticipant(String processInstanceId, Long userId) { |
| | | if (processInstanceId == null || userId == null) { |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.attendance; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayGroupRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeCreateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeUpdateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidaySaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; |
| | | import jakarta.validation.Valid; |
| | |
| | | Long createAttendanceHoliday(@Valid HrmAttendanceHolidaySaveReqVO createReqVO); |
| | | |
| | | /** |
| | | * ææ¥æèå´æ°å¢è忥é
ç½®ï¼å«èµ·æ¢æ¥æä¹é´çæ¯ä¸å¤©ï¼ |
| | | * |
| | | * @param createReqVO æ°å¢ä¿¡æ¯ |
| | | * @return æ°å¢çè忥æ°é |
| | | */ |
| | | Integer createAttendanceHolidayRange(@Valid HrmAttendanceHolidayRangeCreateReqVO createReqVO); |
| | | |
| | | /** |
| | | * æ´æ°è忥é
ç½® |
| | | * |
| | | * @param updateReqVO æ´æ°ä¿¡æ¯ |
| | | */ |
| | | void updateAttendanceHoliday(@Valid HrmAttendanceHolidaySaveReqVO updateReqVO); |
| | | |
| | | /** |
| | | * ææ¥æåºé´æ´æ°è忥é
ç½®ï¼å é¤åºé´å
åè®°å½ï¼åææ°èµ·æ¢æ¥æéæ°åå
¥æ¯ä¸å¤© |
| | | * |
| | | * @param updateReqVO æ´æ°ä¿¡æ¯ |
| | | */ |
| | | void updateAttendanceHolidayRange(@Valid HrmAttendanceHolidayRangeUpdateReqVO updateReqVO); |
| | | |
| | | /** |
| | | * ææ¥æåºé´å é¤è忥é
ç½®ï¼å é¤åºé´å
å
¨é¨è®°å½ï¼ |
| | | * |
| | | * @param ids åºé´å
è®°å½IDå表 |
| | | */ |
| | | void deleteAttendanceHolidayRange(List<Long> ids); |
| | | |
| | | /** |
| | | * å é¤è忥é
ç½® |
| | |
| | | PageResult<HrmAttendanceHolidayDO> getAttendanceHolidayPage(HrmAttendanceHolidayPageReqVO pageReqVO); |
| | | |
| | | /** |
| | | * è·å¾æè¿ç»æ¥æåºé´åå¹¶åçè忥å页 |
| | | * |
| | | * åºéæèªç¶æ¥åå¨ï¼å表侧æãæ¥æè¿ç» + åç§°/ç±»å/æ¯å¦æ³å®/夿³¨ä¸è´ãåå¹¶æä¸è¡å±ç¤ºã |
| | | * |
| | | * @param pageReqVO å页æ¥è¯¢åæ° |
| | | * @return åå¹¶åçè忥å页 |
| | | */ |
| | | PageResult<HrmAttendanceHolidayGroupRespVO> getAttendanceHolidayGroupPage(HrmAttendanceHolidayPageReqVO pageReqVO); |
| | | |
| | | /** |
| | | * è·å¾æå®æ¥æèå´çè忥å表 |
| | | * |
| | | * @param startDate å¼å§æ¥æ |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.attendance; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayGroupRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeCreateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeUpdateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidaySaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceHolidayMapper; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.time.DayOfWeek; |
| | | import java.time.LocalDate; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*; |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Integer createAttendanceHolidayRange(HrmAttendanceHolidayRangeCreateReqVO createReqVO) { |
| | | if (createReqVO.getEndDate().isBefore(createReqVO.getStartDate())) { |
| | | throw exception(ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID); |
| | | } |
| | | return insertDays(createReqVO.getName(), createReqVO.getStartDate(), createReqVO.getEndDate(), |
| | | createReqVO.getType(), createReqVO.getIsLegal(), createReqVO.getRemark()); |
| | | } |
| | | |
| | | /** |
| | | * æå¤©åå
¥è忥ï¼åå
¥åæ´ä½æ¥éï¼ä»»ä¸æ¥æå·²åå¨åæ´ä½ä¸åå
¥ |
| | | */ |
| | | private int insertDays(String name, LocalDate startDate, LocalDate endDate, |
| | | Integer type, Boolean isLegal, String remark) { |
| | | // å
æ´ä½æ ¡éªï¼åºé´å
å·²åå¨ä»»ä¸æ¥ææ¶ä¸åé¨ååå
¥ |
| | | List<HrmAttendanceHolidayDO> existingList = attendanceHolidayMapper.selectListByDateBetween(startDate, endDate); |
| | | if (!existingList.isEmpty()) { |
| | | HrmAttendanceHolidayDO existing = existingList.get(0); |
| | | throw exception(ATTENDANCE_HOLIDAY_RANGE_DATE_EXISTS, existing.getDate(), existing.getName()); |
| | | } |
| | | int count = 0; |
| | | for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) { |
| | | HrmAttendanceHolidayDO attendanceHoliday = HrmAttendanceHolidayDO.builder() |
| | | .name(name) |
| | | .date(date) |
| | | .type(type) |
| | | .isLegal(Boolean.TRUE.equals(isLegal) ? 1 : 0) |
| | | .remark(remark) |
| | | .build(); |
| | | attendanceHolidayMapper.insert(attendanceHoliday); |
| | | count++; |
| | | } |
| | | return count; |
| | | } |
| | | |
| | | @Override |
| | | public void updateAttendanceHoliday(HrmAttendanceHolidaySaveReqVO updateReqVO) { |
| | | validateAttendanceHolidayExists(updateReqVO.getId()); |
| | | // å¦ææ¥æåæ´ï¼æ ¡éªæ°æ¥ææ¯å¦å·²åå¨é
ç½® |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateAttendanceHolidayRange(HrmAttendanceHolidayRangeUpdateReqVO updateReqVO) { |
| | | // 1. æ ¡éªæ¶é´èå´ä¸åºé´è®°å½ |
| | | if (updateReqVO.getEndDate().isBefore(updateReqVO.getStartDate())) { |
| | | throw exception(ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID); |
| | | } |
| | | List<Long> ids = updateReqVO.getIds().stream().filter(Objects::nonNull).distinct().toList(); |
| | | if (ids.isEmpty()) { |
| | | throw exception(ATTENDANCE_HOLIDAY_RANGE_IDS_EMPTY); |
| | | } |
| | | List<HrmAttendanceHolidayDO> oldList = attendanceHolidayMapper.selectBatchIds(ids); |
| | | if (oldList.size() != ids.size()) { |
| | | throw exception(ATTENDANCE_HOLIDAY_RANGE_NOT_EXISTS); |
| | | } |
| | | // 2. å é¤åºé´å
åè®°å½ï¼åææ°çèµ·æ¢æ¥ææ´ä½éåï¼åä¸äºå¡ï¼å¼å¸¸ä¼åæ»ï¼ |
| | | attendanceHolidayMapper.physicalDeleteByIds(ids); |
| | | insertDays(updateReqVO.getName(), updateReqVO.getStartDate(), updateReqVO.getEndDate(), |
| | | updateReqVO.getType(), updateReqVO.getIsLegal(), updateReqVO.getRemark()); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteAttendanceHolidayRange(List<Long> ids) { |
| | | List<Long> cleanIds = ids == null ? Collections.emptyList() |
| | | : ids.stream().filter(Objects::nonNull).distinct().toList(); |
| | | if (cleanIds.isEmpty()) { |
| | | throw exception(ATTENDANCE_HOLIDAY_RANGE_IDS_EMPTY); |
| | | } |
| | | attendanceHolidayMapper.physicalDeleteByIds(cleanIds); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteAttendanceHoliday(Long id) { |
| | | validateAttendanceHolidayExists(id); |
| | | attendanceHolidayMapper.deleteById(id); |
| | | attendanceHolidayMapper.physicalDeleteByIds(Collections.singletonList(id)); |
| | | } |
| | | |
| | | private void validateAttendanceHolidayExists(Long id) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<HrmAttendanceHolidayGroupRespVO> getAttendanceHolidayGroupPage( |
| | | HrmAttendanceHolidayPageReqVO pageReqVO) { |
| | | List<HrmAttendanceHolidayDO> list = attendanceHolidayMapper.selectListByCondition(pageReqVO); |
| | | if (list.isEmpty()) { |
| | | return new PageResult<>(Collections.emptyList(), 0L); |
| | | } |
| | | // 1. è¿ç»æ¥æ + åç§°/ç±»å/æ¯å¦æ³å®/夿³¨ä¸è´çè®°å½å并为ä¸è¡ |
| | | List<HrmAttendanceHolidayGroupRespVO> groups = new ArrayList<>(); |
| | | HrmAttendanceHolidayDO previous = null; |
| | | for (HrmAttendanceHolidayDO current : list) { |
| | | HrmAttendanceHolidayGroupRespVO last = groups.isEmpty() ? null : groups.get(groups.size() - 1); |
| | | boolean sameGroup = last != null && previous != null |
| | | && previous.getDate().plusDays(1).equals(current.getDate()) |
| | | && sameHoliday(previous, current); |
| | | if (sameGroup) { |
| | | last.setEndDate(current.getDate()); |
| | | last.getIds().add(current.getId()); |
| | | last.setDayCount(last.getDayCount() + 1); |
| | | } else { |
| | | HrmAttendanceHolidayGroupRespVO group = new HrmAttendanceHolidayGroupRespVO(); |
| | | group.setId(current.getId()); |
| | | List<Long> ids = new ArrayList<>(); |
| | | ids.add(current.getId()); |
| | | group.setIds(ids); |
| | | group.setName(current.getName()); |
| | | group.setDate(current.getDate()); |
| | | group.setEndDate(current.getDate()); |
| | | group.setDayCount(1); |
| | | group.setType(current.getType()); |
| | | group.setIsLegal(current.getIsLegal()); |
| | | group.setRemark(current.getRemark()); |
| | | group.setCreateTime(current.getCreateTime()); |
| | | groups.add(group); |
| | | } |
| | | previous = current; |
| | | } |
| | | // 2. ææ¥æååºï¼ä¸éæ¥åè¡¨ä¿æä¸è´ |
| | | groups.sort(Comparator.comparing(HrmAttendanceHolidayGroupRespVO::getDate).reversed()); |
| | | // 3. åç»åå
åå页 |
| | | return pageGroups(groups, pageReqVO); |
| | | } |
| | | |
| | | private boolean sameHoliday(HrmAttendanceHolidayDO a, HrmAttendanceHolidayDO b) { |
| | | return StrUtil.equals(a.getName(), b.getName()) |
| | | && Objects.equals(a.getType(), b.getType()) |
| | | && Objects.equals(a.getIsLegal(), b.getIsLegal()) |
| | | && StrUtil.equals(a.getRemark(), b.getRemark()); |
| | | } |
| | | |
| | | private PageResult<HrmAttendanceHolidayGroupRespVO> pageGroups( |
| | | List<HrmAttendanceHolidayGroupRespVO> groups, HrmAttendanceHolidayPageReqVO pageReqVO) { |
| | | long total = groups.size(); |
| | | if (Objects.equals(PageParam.PAGE_SIZE_NONE, pageReqVO.getPageSize())) { |
| | | return new PageResult<>(groups, total); |
| | | } |
| | | int pageNo = pageReqVO.getPageNo() == null ? 1 : pageReqVO.getPageNo(); |
| | | int pageSize = pageReqVO.getPageSize() == null ? 10 : pageReqVO.getPageSize(); |
| | | int from = Math.max(0, (pageNo - 1) * pageSize); |
| | | if (from >= groups.size()) { |
| | | return new PageResult<>(Collections.emptyList(), total); |
| | | } |
| | | int to = Math.min(groups.size(), from + pageSize); |
| | | return new PageResult<>(new ArrayList<>(groups.subList(from, to)), total); |
| | | } |
| | | |
| | | @Override |
| | | public List<HrmAttendanceHolidayDO> getAttendanceHolidayListByDateRange(LocalDate startDate, LocalDate endDate) { |
| | | return attendanceHolidayMapper.selectListByDateBetween(startDate, endDate); |
| | | } |
| | |
| | | return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.attendance; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceSummaryPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceSummaryDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceRecordMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceSummaryMapper; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceClockTypeEnum; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum; |
| | | import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.DayOfWeek; |
| | | import java.time.LocalDate; |
| | | import java.time.YearMonth; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * èå¤ç»è®¡æ±æ» Service å®ç°ç±» |
| | |
| | | |
| | | /** |
| | | * 计ç®åºåºå¤å¤©æ°ï¼å·¥ä½æ¥æ°éï¼ |
| | | * |
| | | * 䏿¬¡ååºåºé´å
è忥é
ç½®ï¼é¿å
鿥æ¥è¯¢ã |
| | | */ |
| | | private int calculateWorkDays(LocalDate startDate, LocalDate endDate) { |
| | | Map<LocalDate, Integer> holidayTypeMap = attendanceHolidayService |
| | | .getAttendanceHolidayListByDateRange(startDate, endDate) |
| | | .stream() |
| | | .collect(Collectors.toMap(HrmAttendanceHolidayDO::getDate, HrmAttendanceHolidayDO::getType, |
| | | (a, b) -> a)); |
| | | int workDays = 0; |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | if (attendanceHolidayService.isWorkDay(current)) { |
| | | Integer holidayType = holidayTypeMap.get(current); |
| | | boolean work; |
| | | if (holidayType != null) { |
| | | // æè忥é
ç½®æ¶æé
ç½®å¤æï¼ä¼æ¯æ¥ä¸ç®åºåºå¤ï¼å·¥ä½æ¥è®¡å
¥ï¼å«è°ä¼ä¸çç卿«ï¼ |
| | | work = HrmAttendanceHolidayTypeEnum.WORK_DAY.getType().equals(holidayType); |
| | | } else { |
| | | DayOfWeek dayOfWeek = current.getDayOfWeek(); |
| | | work = dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; |
| | | } |
| | | if (work) { |
| | | workDays++; |
| | | } |
| | | current = current.plusDays(1); |
| | |
| | | return workDays; |
| | | } |
| | | |
| | | /** |
| | | * è忥é
ç½®åæ´åï¼å·²ææ±æ»çåºåºå¤å¤©æ°ä¼ä¸ææ°é
ç½®ä¸ä¸è´ã |
| | | * æ¥è¯¢æ±æ»æ¶æææ°è忥éç®ä¸æ¬¡å¹¶ååï¼ä¿è¯ãåºåºå¤å¤©æ°ãå§ç»å
³èè忥é
ç½®ã |
| | | */ |
| | | private void refreshWorkDaysOfMonth(String yearMonth) { |
| | | if (StrUtil.isBlank(yearMonth)) { |
| | | return; |
| | | } |
| | | try { |
| | | YearMonth ym = YearMonth.parse(yearMonth); |
| | | attendanceSummaryMapper.updateWorkDaysByYearMonth(yearMonth, |
| | | calculateWorkDays(ym.atDay(1), ym.atEndOfMonth())); |
| | | } catch (Exception ex) { |
| | | // å·æ°å¤±è´¥ä¸å½±åæ¥è¯¢æ¬èº«ï¼è®°å½æ¥å¿å³å¯ |
| | | log.warn("[refreshWorkDaysOfMonth][yearMonth({}) å·æ°åºåºå¤å¤©æ°å¤±è´¥]", yearMonth, ex); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<HrmAttendanceSummaryDO> getAttendanceSummaryPage(HrmAttendanceSummaryPageReqVO pageReqVO) { |
| | | // æ¥è¯¢åæææ°è忥éç®è¯¥æåºåºå¤å¤©æ° |
| | | refreshWorkDaysOfMonth(pageReqVO.getYearMonth()); |
| | | return attendanceSummaryMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<HrmAttendanceSummaryDO>() |
| | | .eqIfPresent(HrmAttendanceSummaryDO::getUserId, pageReqVO.getUserId()) |
| | | .eqIfPresent(HrmAttendanceSummaryDO::getDeptId, pageReqVO.getDeptId()) |
| | |
| | | |
| | | @Override |
| | | public List<HrmAttendanceSummaryDO> getDeptMonthlySummaryList(Long deptId, String yearMonth) { |
| | | // æ¥è¯¢åæææ°è忥éç®è¯¥æåºåºå¤å¤©æ° |
| | | refreshWorkDaysOfMonth(yearMonth); |
| | | return attendanceSummaryMapper.selectListByDeptIdAndYearMonth(deptId, yearMonth); |
| | | } |
| | | |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.attendance; |
| | | |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleListReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleSaveReqVO; |
| | |
| | | */ |
| | | void saveSchedule(List<HrmEmployeeScheduleSaveReqVO> saveReqVOList); |
| | | |
| | | /** |
| | | * æãé¨é¨ + å²ä½ãæ¹éæçï¼ä¸ºçéåºçä¸ç±»åå·¥ï¼ææ¥æèå´ç»ä¸è®¾ç½®ç次æä¼æ¯æ¥ |
| | | */ |
| | | HrmEmployeeScheduleBatchSaveRespVO batchSaveSchedule(HrmEmployeeScheduleBatchSaveReqVO reqVO); |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.attendance; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleBatchSaveRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleListReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmEmployeeScheduleSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmEmployeeScheduleDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmShiftDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmEmployeeScheduleMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmShiftMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.time.DayOfWeek; |
| | | import java.time.LocalDate; |
| | | import java.time.YearMonth; |
| | | import java.util.*; |
| | |
| | | private HrmEmployeeMapper employeeMapper; |
| | | @Resource |
| | | private HrmShiftMapper shiftMapper; |
| | | @Resource |
| | | private DeptApi deptApi; |
| | | @Resource |
| | | private HrmAttendanceHolidayService attendanceHolidayService; |
| | | |
| | | @Override |
| | | public List<HrmEmployeeScheduleRespVO> getScheduleList(HrmEmployeeScheduleListReqVO reqVO) { |
| | |
| | | if (reqVO.getEmployeeId() != null) { |
| | | list = employeeScheduleMapper.selectListByEmployeeIdAndPeriod(reqVO.getEmployeeId(), startDate, endDate); |
| | | } else if (reqVO.getDeptId() != null) { |
| | | List<HrmEmployeeDO> employees = employeeMapper.selectByDeptId(reqVO.getDeptId()); |
| | | // ä¸åå·¥åé¡µä¿æä¸è´ï¼éä¸é¨é¨æ¶è¿å¸¦æ¥è¯¢ææä¸çº§é¨é¨çåå·¥ |
| | | Set<Long> deptIds = getSelfAndChildDeptIds(reqVO.getDeptId()); |
| | | List<HrmEmployeeDO> employees = employeeMapper.selectListByDeptIds(deptIds); |
| | | Set<Long> employeeIds = employees.stream().map(HrmEmployeeDO::getId).collect(Collectors.toSet()); |
| | | list = CollUtil.isEmpty(employeeIds) ? Collections.emptyList() |
| | | : employeeScheduleMapper.selectListByEmployeeIdsAndPeriod(employeeIds, startDate, endDate); |
| | |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public HrmEmployeeScheduleBatchSaveRespVO batchSaveSchedule(HrmEmployeeScheduleBatchSaveReqVO reqVO) { |
| | | // 1. æ ¡éªæ¥æèå´åçæ¬¡ |
| | | if (reqVO.getEndDate().isBefore(reqVO.getStartDate())) { |
| | | throw exception(SCHEDULE_BATCH_DATE_RANGE_INVALID); |
| | | } |
| | | if (reqVO.getShiftId() != null && shiftMapper.selectById(reqVO.getShiftId()) == null) { |
| | | throw exception(SCHEDULE_SHIFT_NOT_EXISTS); |
| | | } |
| | | // 2. æé¨é¨ï¼å«ä¸çº§ï¼+ å²ä½ + åå·¥ç¶æçéç®æ åå·¥ |
| | | Set<Long> deptIds = getSelfAndChildDeptIds(reqVO.getDeptId()); |
| | | List<HrmEmployeeDO> employees = employeeMapper.selectListByDeptIds(deptIds).stream() |
| | | .filter(employee -> matchEmployeeStatus(employee, reqVO.getEmployeeStatus())) |
| | | .filter(employee -> matchPost(employee, reqVO.getPostId())) |
| | | .collect(Collectors.toList()); |
| | | if (CollUtil.isEmpty(employees)) { |
| | | DeptRespDTO dept = deptApi.getDept(reqVO.getDeptId()); |
| | | throw exception(SCHEDULE_BATCH_EMPLOYEE_EMPTY, dept == null ? String.valueOf(reqVO.getDeptId()) : dept.getName()); |
| | | } |
| | | |
| | | // 3. é¢å è½½èå´å
å·²ææçï¼é¿å
éæ¡æ¥è¯¢ |
| | | Set<Long> employeeIds = employees.stream().map(HrmEmployeeDO::getId).collect(Collectors.toSet()); |
| | | Map<String, HrmEmployeeScheduleDO> existingMap = employeeScheduleMapper |
| | | .selectListByEmployeeIdsAndPeriod(employeeIds, reqVO.getStartDate(), reqVO.getEndDate()) |
| | | .stream() |
| | | .collect(Collectors.toMap(item -> scheduleKey(item.getEmployeeId(), item.getDate()), |
| | | Function.identity(), (a, b) -> a)); |
| | | |
| | | // 4. é¢å è½½åºé´å
è忥é
ç½®ï¼é
ç½®ä¸ºä¼æ¯æ¥çå½å¤©å¼ºå¶ä¼æ¯ï¼é
ç½®ä¸ºå·¥ä½æ¥çå½å¤©å¼ºå¶æçï¼å¯è¦ç卿«ï¼ |
| | | Map<LocalDate, Integer> holidayTypeMap = attendanceHolidayService |
| | | .getAttendanceHolidayListByDateRange(reqVO.getStartDate(), reqVO.getEndDate()) |
| | | .stream() |
| | | .collect(Collectors.toMap(HrmAttendanceHolidayDO::getDate, HrmAttendanceHolidayDO::getType, |
| | | (a, b) -> a)); |
| | | |
| | | // 5. ææ¥æéå¤©çææçï¼ä¼æ¯æ¥å é¤åçæ¬¡ï¼å·¥ä½æ¥ upsert |
| | | int itemCount = 0; |
| | | for (LocalDate date = reqVO.getStartDate(); !date.isAfter(reqVO.getEndDate()); date = date.plusDays(1)) { |
| | | boolean rest = isRestDay(date, reqVO.getRestMode(), holidayTypeMap.get(date)) |
| | | || reqVO.getShiftId() == null; |
| | | for (HrmEmployeeDO employee : employees) { |
| | | HrmEmployeeScheduleDO existing = existingMap.get(scheduleKey(employee.getId(), date)); |
| | | if (rest) { |
| | | if (existing != null) { |
| | | employeeScheduleMapper.deleteById(existing.getId()); |
| | | itemCount++; |
| | | } |
| | | continue; |
| | | } |
| | | if (existing == null) { |
| | | HrmEmployeeScheduleDO schedule = new HrmEmployeeScheduleDO(); |
| | | schedule.setEmployeeId(employee.getId()); |
| | | schedule.setDate(date); |
| | | schedule.setShiftId(reqVO.getShiftId()); |
| | | employeeScheduleMapper.insert(schedule); |
| | | itemCount++; |
| | | } else if (!Objects.equals(existing.getShiftId(), reqVO.getShiftId())) { |
| | | existing.setShiftId(reqVO.getShiftId()); |
| | | employeeScheduleMapper.updateById(existing); |
| | | itemCount++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | HrmEmployeeScheduleBatchSaveRespVO respVO = new HrmEmployeeScheduleBatchSaveRespVO(); |
| | | respVO.setEmployeeCount(employees.size()); |
| | | respVO.setItemCount(itemCount); |
| | | return respVO; |
| | | } |
| | | |
| | | private Set<Long> getSelfAndChildDeptIds(Long deptId) { |
| | | Set<Long> deptIds = new LinkedHashSet<>(); |
| | | deptIds.add(deptId); |
| | | List<DeptRespDTO> childDepts = deptApi.getChildDeptList(deptId); |
| | | if (CollUtil.isNotEmpty(childDepts)) { |
| | | childDepts.forEach(dept -> deptIds.add(dept.getId())); |
| | | } |
| | | return deptIds; |
| | | } |
| | | |
| | | /** employeeStatus 为空æ¶å
å«å¨èåè¯ç¨ï¼æé¤ç¦»è */ |
| | | private boolean matchEmployeeStatus(HrmEmployeeDO employee, Integer employeeStatus) { |
| | | if (employeeStatus != null) { |
| | | return Objects.equals(employee.getEmployeeStatus(), employeeStatus); |
| | | } |
| | | return !Objects.equals(employee.getEmployeeStatus(), 3); |
| | | } |
| | | |
| | | private boolean matchPost(HrmEmployeeDO employee, Long postId) { |
| | | if (postId == null) { |
| | | return true; |
| | | } |
| | | if (StrUtil.isBlank(employee.getPostIds())) { |
| | | return false; |
| | | } |
| | | return JSONUtil.toList(employee.getPostIds(), Long.class).contains(postId); |
| | | } |
| | | |
| | | private boolean isRestDay(LocalDate date, String restMode, Integer holidayType) { |
| | | // è忥é
ç½®ä¼å
ï¼ä¼æ¯æ¥å¼ºå¶ä¼æ¯ï¼å·¥ä½æ¥å¼ºå¶ä¸çï¼å«è°ä¼ä¸çç卿«ï¼ |
| | | if (holidayType != null) { |
| | | return HrmAttendanceHolidayTypeEnum.REST_DAY.getType().equals(holidayType); |
| | | } |
| | | if ("double".equals(restMode)) { |
| | | return date.getDayOfWeek() == DayOfWeek.SATURDAY || date.getDayOfWeek() == DayOfWeek.SUNDAY; |
| | | } |
| | | if ("single".equals(restMode)) { |
| | | return date.getDayOfWeek() == DayOfWeek.SUNDAY; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private String scheduleKey(Long employeeId, LocalDate date) { |
| | | return employeeId + "_" + date; |
| | | } |
| | | |
| | | } |
| | |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(deptIds); |
| | | // å¡«å
å²ä½åç§° |
| | | Set<Long> postIds = list.stream() |
| | | .map(HrmEmployeeDO::getPostIds) |
| | | .filter(StrUtil::isNotBlank) |
| | | .flatMap(json -> JSONUtil.toList(json, Long.class).stream()) |
| | | .collect(Collectors.toSet()); |
| | | Map<Long, PostRespDTO> postMap = CollUtil.isEmpty(postIds) |
| | | ? Collections.emptyMap() : postApi.getPostMap(postIds); |
| | | return list.stream().map(emp -> { |
| | | HrmEmployeeSimpleRespVO vo = new HrmEmployeeSimpleRespVO(); |
| | | vo.setId(emp.getId()); |
| | |
| | | if (emp.getDeptId() != null && deptMap.containsKey(emp.getDeptId())) { |
| | | vo.setDeptName(deptMap.get(emp.getDeptId()).getName()); |
| | | } |
| | | if (StrUtil.isNotBlank(emp.getPostIds())) { |
| | | vo.setPostName(JSONUtil.toList(emp.getPostIds(), Long.class).stream() |
| | | .filter(postMap::containsKey) |
| | | .map(id -> postMap.get(id).getName()) |
| | | .collect(Collectors.joining(","))); |
| | | } |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | } |