Merge branch 'dev' of http://git.znkjfw.com/ak/zn-cloud into frx
# Conflicts: # yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java # yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApi.java # yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApiImpl.java # yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/attendance/punchrecord/AttendancePunchRecordDO.java # yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java # yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml
This commit is contained in:
commit
d8e1b6df5d
@ -46,9 +46,13 @@ public class Constants {
|
||||
*/
|
||||
public static final Integer ONE = 1;
|
||||
/**
|
||||
* 一
|
||||
* 二
|
||||
*/
|
||||
public static final Integer TWO = 2;
|
||||
/**
|
||||
* 三
|
||||
*/
|
||||
public static final Integer THREE = 3;
|
||||
/**
|
||||
* 中文1
|
||||
*/
|
||||
|
@ -249,6 +249,24 @@ public class CollectionUtils {
|
||||
return asList(createList, updateList, deleteList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对比老、新两个列表,找出新增、修改、删除的数据
|
||||
*
|
||||
* @param oldList 老列表
|
||||
* @param newList 新列表
|
||||
* @return [新增列表、修改列表、删除列表]
|
||||
*/
|
||||
public static <T> List<List<T>> diffList(Collection<T> oldList, Collection<T> newList) {
|
||||
List<T> createList = new LinkedList<>(newList); // 默认都认为是新增的,后续会进行移除
|
||||
List<T> updateList = new ArrayList<>();
|
||||
List<T> deleteList = new ArrayList<>();
|
||||
|
||||
// 通过以 oldList 为主遍历,找出 updateList 和 deleteList
|
||||
|
||||
return asList(createList, updateList, deleteList);
|
||||
}
|
||||
|
||||
public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
|
||||
return org.springframework.util.CollectionUtils.containsAny(source, candidates);
|
||||
}
|
||||
|
@ -163,6 +163,18 @@ public class DateUtils {
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建指定时间
|
||||
*
|
||||
* @param timeStr 时间字符串,格式为 HH:mm
|
||||
* @return 指定时间
|
||||
*/
|
||||
public static LocalDateTime buildHHmmLocalDateTime(String timeStr, LocalDateTime localDateTime) {
|
||||
String[] time = timeStr.split(":");
|
||||
return localDateTime.withHour(Integer.parseInt(time[0])).withMinute(Integer.parseInt(time[1])).withSecond(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建指定时间
|
||||
*
|
||||
@ -405,6 +417,7 @@ public class DateUtils {
|
||||
|
||||
/**
|
||||
* 毫秒转 **小时**分钟
|
||||
*
|
||||
* @param milliseconds
|
||||
* @return
|
||||
*/
|
||||
|
@ -7,11 +7,11 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 时间工具类,用于 {@link java.time.LocalDateTime}
|
||||
*
|
||||
|
||||
*/
|
||||
public class LocalDateTimeUtils {
|
||||
|
||||
@ -121,4 +121,97 @@ public class LocalDateTimeUtils {
|
||||
return date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前日期获取本季度最后一天
|
||||
*
|
||||
* @param dateTime
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime getQuarterEnd(LocalDateTime dateTime) {
|
||||
int month = dateTime.getMonthValue();
|
||||
int year = dateTime.getYear();
|
||||
|
||||
LocalDateTime quarterEnd = LocalDateTime.now();
|
||||
|
||||
if (month <= 3) {
|
||||
quarterEnd = LocalDateTime.of(year, 3, 31, 23, 59, 59);
|
||||
} else if (month <= 6) {
|
||||
quarterEnd = LocalDateTime.of(year, 6, 30, 23, 59, 59);
|
||||
} else if (month <= 9) {
|
||||
quarterEnd = LocalDateTime.of(year, 9, 30, 23, 59, 59);
|
||||
} else {
|
||||
quarterEnd = LocalDateTime.of(year, 12, 31, 23, 59, 59);
|
||||
}
|
||||
|
||||
return quarterEnd.with(TemporalAdjusters.lastDayOfMonth());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取至某一个时间每一个月的某一天
|
||||
*
|
||||
* @param beginTime
|
||||
* @param endTime
|
||||
* @param day
|
||||
*/
|
||||
public static List<LocalDateTime> getTheDayOfEachMonthSoFar(LocalDateTime beginTime, LocalDateTime endTime, int day) {
|
||||
List<LocalDateTime> monthlyFirstDays = new ArrayList<>();
|
||||
beginTime = beginTime.withDayOfMonth(day);
|
||||
while (!beginTime.isAfter(endTime)) {
|
||||
// 获取当月的1号
|
||||
LocalDateTime firstDayOfMonth = beginTime.withDayOfMonth(day);
|
||||
// 添加到列表
|
||||
monthlyFirstDays.add(firstDayOfMonth);
|
||||
|
||||
// 移动到下个月
|
||||
beginTime = beginTime.plusMonths(1);
|
||||
}
|
||||
return monthlyFirstDays;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取至某一个时间每年的一月一号
|
||||
*
|
||||
* @param beginTime
|
||||
* @param endTime
|
||||
*/
|
||||
public static List<LocalDateTime> getTheDayOfEachYeasSoFar(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
List<LocalDateTime> monthlyFirstDays = new ArrayList<>();
|
||||
while (!beginTime.isAfter(endTime)) {
|
||||
// 获取当月的1号
|
||||
LocalDateTime firstDayOfMonth = beginTime.withDayOfYear(1);
|
||||
// 添加到列表
|
||||
monthlyFirstDays.add(firstDayOfMonth);
|
||||
|
||||
// 移动到下个月
|
||||
beginTime = beginTime.plusYears(1);
|
||||
}
|
||||
return monthlyFirstDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取至某一个时间每年当前日期
|
||||
*
|
||||
* @param beginTime
|
||||
* @param endTime
|
||||
*/
|
||||
public static List<LocalDateTime> getTheCurrentDateOfEachYearToACertainTime(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
List<LocalDateTime> monthlyFirstDays = new ArrayList<>();
|
||||
while (!beginTime.isAfter(endTime)) {
|
||||
// 添加到列表
|
||||
monthlyFirstDays.add(beginTime);
|
||||
// 移动到下个年
|
||||
beginTime = beginTime.plusYears(1);
|
||||
}
|
||||
return monthlyFirstDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个时间范围是否相交 true 是 false 否
|
||||
*/
|
||||
public static boolean intersects(LocalDateTime start, LocalDateTime end, LocalDateTime otherStart, LocalDateTime otherEnd) {
|
||||
// 判断两个时间范围是否相交
|
||||
return !end.isBefore(otherStart) && !otherEnd.isBefore(start);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,16 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1_009_001_006, "HR岗位未设置");
|
||||
ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1_009_001_007, "请假天数必须>=1");
|
||||
ErrorCode FAILED_TO_APPLY_FOR_LEAVE = new ErrorCode(1_009_001_008, "请假失败");
|
||||
ErrorCode WRONG_TIME_FORMAT = new ErrorCode(1_009_001_009, "时间格式错误");
|
||||
ErrorCode THERE_IS_ALREADY_A_RECORD_OF_REQUESTING_LEAVE_DURING_THIS_TIME_PERIOD = new ErrorCode(1_009_001_010, "该时间段内已有请假记录,请调整");
|
||||
ErrorCode GET_USER_HOLIDAY_EXCEPTION = new ErrorCode(1_009_001_011, "获取用户假期异常");
|
||||
ErrorCode THE_USER_ATTENDANCE_INFORMATION_IS_ABNORMAL = new ErrorCode(1_009_001_012, "获取用户考勤信息异常");
|
||||
ErrorCode INSUFFICIENT_LEAVE_BALANCE = new ErrorCode(1_009_001_013, "假期余额不足");
|
||||
ErrorCode NO_NEED_TO_APPLY_FOR_OVERTIME_IF_NOT_IN_THE_ATTENDANCE_GROUP = new ErrorCode(1_009_001_014, "不在考勤组内无需申请加班");
|
||||
ErrorCode EXCEPTION_OCCURRED_WHILE_OBTAINING_OVERTIME_SETTINGS = new ErrorCode(1_009_001_015, "获取加班设置出现异常");
|
||||
ErrorCode ABNORMAL_ACCESS_TO_ATTENDANCE_RECORDS = new ErrorCode(1_009_001_016, "获取考勤记录异常");
|
||||
ErrorCode OVERTIME_REQUESTS_ALREADY_EXIST_FOR_THE_SAME_TIME_PERIOD = new ErrorCode(1_009_001_018, "已存在相同时间段的加班申请");
|
||||
ErrorCode THE_CURRENT_USERS_ATTENDANCE_GROUP_HAS_NOT_SET_OVERTIME_RULES = new ErrorCode(1_009_001_019, "当前用户所在考勤组未设置加班规则");
|
||||
|
||||
ErrorCode OA_REIMBURSEMENT_NOT_EXISTS = new ErrorCode(1_009_001_100, "报销申请不存在");
|
||||
ErrorCode OA_EVECTION_NOT_EXISTS = new ErrorCode(1_009_001_101, "出差申请不存在");
|
||||
|
@ -1,9 +1,11 @@
|
||||
package cn.iocoder.yudao.module.bpm.enums.task;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@ -48,6 +50,10 @@ public enum BpmProcessInstanceResultEnum {
|
||||
* 能被减签的状态
|
||||
*/
|
||||
public static final List<Integer> CAN_SUB_SIGN_STATUS_LIST = Arrays.asList(PROCESS.result, WAIT_BEFORE_TASK.result);
|
||||
/**
|
||||
* 处理中or通过 状态
|
||||
*/
|
||||
public static final List<Integer> PROCESSING_OR_PASSED = processingOrPassed();
|
||||
|
||||
/**
|
||||
* 结果
|
||||
@ -74,4 +80,22 @@ public enum BpmProcessInstanceResultEnum {
|
||||
SIGN_AFTER.getResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有类型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static List<Integer> getAllResult() {
|
||||
List<Integer> resultList = new ArrayList<>();
|
||||
Arrays.stream(BpmProcessInstanceResultEnum.class.getEnumConstants())
|
||||
.map(BpmProcessInstanceResultEnum::getResult)
|
||||
.forEach(resultList::add);
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public static List<Integer> processingOrPassed() {
|
||||
List<Integer> allResult = getAllResult();
|
||||
allResult.removeAll(Arrays.asList(REJECT.result,CANCEL.result));
|
||||
return allResult;
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,11 @@
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeaveCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeavePageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeaveRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.CalculateAndVerifyLeaveDTO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService;
|
||||
@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
@ -24,7 +26,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
|
||||
* OA 请假申请 Controller
|
||||
*
|
||||
* @author jason
|
||||
|
||||
*/
|
||||
@Tag(name = "管理后台 - OA 请假申请")
|
||||
@RestController
|
||||
@ -36,12 +37,17 @@ public class BpmOALeaveController {
|
||||
private BpmOALeaveService leaveService;
|
||||
|
||||
@PostMapping("/create")
|
||||
// @PreAuthorize("@ss.hasPermission('bpm:oa-leave:create')")
|
||||
@Operation(summary = "创建请求申请")
|
||||
@Operation(summary = "创建请假申请")
|
||||
public CommonResult<Long> createLeave(@Valid @RequestBody BpmOALeaveCreateReqVO createReqVO) {
|
||||
return success(leaveService.createLeave(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/calculateAndVerifyTheNumberOfLeaveDays")
|
||||
@Operation(summary = "计算请假时长")
|
||||
public CommonResult<BigDecimal> calculateAndVerifyTheNumberOfLeaveDays(@Valid @RequestBody CalculateAndVerifyLeaveDTO dto) {
|
||||
return success(leaveService.calculateAndVerifyTheNumberOfLeaveDays(getLoginUserId(), dto));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
// @PreAuthorize("@ss.hasPermission('bpm:oa-leave:query')")
|
||||
@Operation(summary = "获得请假申请")
|
||||
|
@ -1,10 +1,14 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime.BpmOAOvertimeCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime.BpmOAOvertimeItemVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime.BpmOAOvertimeRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAOvertimeConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAOvertimeItemService;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAOvertimeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -14,6 +18,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
@ -22,7 +27,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
|
||||
* OA 加班申请 Controller
|
||||
*
|
||||
* @author 符溶馨
|
||||
|
||||
*/
|
||||
@Tag(name = "管理后台 - OA 加班申请")
|
||||
@RestController
|
||||
@ -32,9 +36,11 @@ public class BpmOAOvertimeController {
|
||||
|
||||
@Resource
|
||||
private BpmOAOvertimeService overtimeService;
|
||||
@Resource
|
||||
private BpmOAOvertimeItemService overtimeItemService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建请求申请")
|
||||
@Operation(summary = "创建加班申请")
|
||||
public CommonResult<Long> createOvertime(@Valid @RequestBody BpmOAOvertimeCreateReqVO createReqVO) {
|
||||
|
||||
return success(overtimeService.createOvertime(getLoginUserId(), createReqVO));
|
||||
@ -44,19 +50,21 @@ public class BpmOAOvertimeController {
|
||||
@Operation(summary = "获得加班申请")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<BpmOAOvertimeRespVO> getOvertime(@RequestParam("id") Long id) {
|
||||
|
||||
BpmOAOvertimeDO overtime = overtimeService.getOvertime(id);
|
||||
|
||||
return success(BpmOAOvertimeConvert.INSTANCE.convert(overtime));
|
||||
List<BpmOAOvertimeItemDO> itemDOS = overtimeItemService.getByOvertimeId(id);
|
||||
List<BpmOAOvertimeItemVO> overtimeDateTimeVOS = BeanUtil.copyToList(itemDOS, BpmOAOvertimeItemVO.class);
|
||||
BpmOAOvertimeRespVO vo = BpmOAOvertimeConvert.INSTANCE.convert(overtime);
|
||||
return success(vo.setTotalTimeLength(overtime.getTimeLength()).setOvertimeDateTimeVOS(overtimeDateTimeVOS));
|
||||
}
|
||||
|
||||
@GetMapping("/getByProcessInstanceId")
|
||||
@Operation(summary = "获得加班申请")
|
||||
@Parameter(name = "processInstanceId", description = "流程实例编号", required = true, example = "1024")
|
||||
public CommonResult<BpmOAOvertimeRespVO> getByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) {
|
||||
|
||||
BpmOAOvertimeDO overtime = overtimeService.getByProcessInstanceId(processInstanceId);
|
||||
|
||||
return success(BpmOAOvertimeConvert.INSTANCE.convert(overtime));
|
||||
List<BpmOAOvertimeItemDO> itemDOS = overtimeItemService.getByOvertimeId(overtime.getId());
|
||||
List<BpmOAOvertimeItemVO> overtimeDateTimeVOS = BeanUtil.copyToList(itemDOS, BpmOAOvertimeItemVO.class);
|
||||
BpmOAOvertimeRespVO vo = BpmOAOvertimeConvert.INSTANCE.convert(overtime);
|
||||
return success(vo.setTotalTimeLength(overtime.getTimeLength()).setOvertimeDateTimeVOS(overtimeDateTimeVOS));
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ public class BpmOALeaveBaseVO {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "请假类型-参见 bpm_oa_leave_type 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "请假类型不能为空")
|
||||
private Integer type;
|
||||
@Schema(description = "假期设置id", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "假期设置id")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "原因不能为空")
|
||||
|
@ -1,20 +1,71 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "管理后台 - 请假申请创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BpmOALeaveCreateReqVO extends BpmOALeaveBaseVO {
|
||||
public class BpmOALeaveCreateReqVO {
|
||||
|
||||
@AssertTrue(message = "结束时间,需要在开始时间之后")
|
||||
public boolean isEndTimeValid() {
|
||||
return !getEndTime().isBefore(getStartTime());
|
||||
@Schema(description = "假期设置id", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "假期设置id")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "请假的开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate startTime;
|
||||
|
||||
@Schema(description = "请假的结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "结束时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate endTime;
|
||||
|
||||
@Schema(description = "请假时长 (单位根据请假最小单位来 按天or按半天 单位为天 按小时单位为小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private BigDecimal duration;
|
||||
|
||||
@Schema(description = "开始时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private String startTimeExtraFields;
|
||||
|
||||
@Schema(description = "结束时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private String endTimeExtraFields;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "请假最小单位 1按天 2按半天 3按小时")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "原因不能为空")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "流程实例编号")
|
||||
private String processInstanceId;
|
||||
|
||||
@Schema(description = "状态-参见 bpm_process_instance_result 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<UploadUserFile> fileItems;
|
||||
|
||||
|
||||
public LocalDateTime getStartTime() {
|
||||
return this.startTime.atStartOfDay();
|
||||
}
|
||||
|
||||
public LocalDateTime getEndTime() {
|
||||
return this.endTime.atStartOfDay();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
@ -20,8 +21,9 @@ public class BpmOALeavePageReqVO extends PageParam {
|
||||
@Schema(description = "状态-参见 bpm_process_instance_result 枚举", example = "1")
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "请假类型-参见 bpm_oa_type", example = "1")
|
||||
private Integer type;
|
||||
@Schema(description = "假期设置id", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "假期设置id")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "原因-模糊匹配", example = "阅读芋道源码")
|
||||
private String reason;
|
||||
|
@ -7,6 +7,7 @@ import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
@ -20,6 +21,21 @@ public class BpmOALeaveRespVO extends BpmOALeaveBaseVO {
|
||||
@Schema(description = "请假表单主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String leaveName;
|
||||
|
||||
@Schema(description = "请假时长(单位根据请假最小单位来 按天or按半天 单位为天 按小时单位为小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private BigDecimal duration;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "开始时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String startTimeExtraFields;
|
||||
|
||||
@Schema(description = "结束时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String endTimeExtraFields;
|
||||
|
||||
@Schema(description = "状态-参见 bpm_process_instance_result 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer result;
|
||||
|
||||
|
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Data
|
||||
public class CalculateAndVerifyLeaveDTO {
|
||||
|
||||
@Schema(description = "假期设置id", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "假期设置id")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "请假的开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate startTime;
|
||||
|
||||
@Schema(description = "请假的结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "结束时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate endTime;
|
||||
|
||||
@Schema(description = "开始时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private String startTimeExtraFields;
|
||||
|
||||
@Schema(description = "结束时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private String endTimeExtraFields;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
@NotNull(message = "请假最小单位 1按天 2按半天 3按小时")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "用户id (前端不用传)", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private Long userId;
|
||||
|
||||
public LocalDateTime getStartTime() {
|
||||
return this.startTime.atStartOfDay();
|
||||
}
|
||||
|
||||
public LocalDateTime getEndTime() {
|
||||
return this.endTime.atStartOfDay();
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
|
||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
@ -21,8 +24,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
||||
*/
|
||||
@Schema(description = "管理后台 - 加班申请创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode()
|
||||
@ToString(callSuper = true)
|
||||
public class BpmOAOvertimeCreateReqVO {
|
||||
|
||||
@Schema(description = "加班原因", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ -31,17 +32,19 @@ public class BpmOAOvertimeCreateReqVO {
|
||||
|
||||
@Schema(description = "加班的开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "加班的结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "结束时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "加班时长", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班时长不能为空")
|
||||
private BigDecimal timeLength;
|
||||
@Schema(description = "加班日期时间列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班日期时间列表")
|
||||
private List<BpmOAOvertimeItemVO> overtimeDateTimeVOS;
|
||||
|
||||
@Schema(description = "加班总时长", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班总时长不能为空")
|
||||
private BigDecimal totalTimeLength;
|
||||
|
||||
@Schema(description = "流程实例编号")
|
||||
private String processInstanceId;
|
||||
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 加班申请 创建 Request VO
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class BpmOAOvertimeItemVO {
|
||||
@Schema(description = "日期 yyyy-MM-dd")
|
||||
private String dateTimeStr;
|
||||
|
||||
@Schema(description = "加班时长", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班时长不能为空")
|
||||
private BigDecimal timeLength;
|
||||
}
|
||||
|
@ -38,9 +38,13 @@ public class BpmOAOvertimeRespVO extends BpmOABaseRespVO {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "加班时长", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班时长不能为空")
|
||||
private BigDecimal timeLength;
|
||||
@Schema(description = "加班日期时间列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班日期时间列表")
|
||||
private List<BpmOAOvertimeItemVO> overtimeDateTimeVOS;
|
||||
|
||||
@Schema(description = "加班总时长", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "加班总时长不能为空")
|
||||
private BigDecimal totalTimeLength;
|
||||
|
||||
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<UploadUserFile> fileItems;
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.convert.oa;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeaveCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeaveRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.CalculateAndVerifyLeaveDTO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@ -27,4 +28,5 @@ public interface BpmOALeaveConvert {
|
||||
|
||||
PageResult<BpmOALeaveRespVO> convertPage(PageResult<BpmOALeaveDO> page);
|
||||
|
||||
BpmOALeaveDO convertCalculateLeaveDTO(CalculateAndVerifyLeaveDTO dto);
|
||||
}
|
||||
|
@ -1,26 +1,26 @@
|
||||
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OA 请假申请 DO
|
||||
*
|
||||
* {@link #day} 请假天数,目前先简单做。一般是分成请假上午和下午,可以是 1 整天,可以是 0.5 半天
|
||||
*
|
||||
* @author jason
|
||||
|
||||
*/
|
||||
@TableName(value ="bpm_oa_leave", autoResultMap = true)
|
||||
@TableName(value = "bpm_oa_leave", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@ -36,18 +36,22 @@ public class BpmOALeaveDO extends BaseDO {
|
||||
private Long id;
|
||||
/**
|
||||
* 申请人的用户编号
|
||||
*
|
||||
* <p>
|
||||
* 关联 AdminUserDO 的 id 属性
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 请假类型
|
||||
* 假期设置id
|
||||
*/
|
||||
private String type;
|
||||
private Long holidaySettingId;
|
||||
/**
|
||||
* 原因
|
||||
*/
|
||||
private String reason;
|
||||
/**
|
||||
* 假期名称
|
||||
*/
|
||||
private String leaveName;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@ -56,13 +60,28 @@ public class BpmOALeaveDO extends BaseDO {
|
||||
* 结束时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
|
||||
/**
|
||||
* 请假天数
|
||||
* 请假时长(单位根据请假最小单位来 按天or按半天 单位为天 按小时单位为小时)
|
||||
*/
|
||||
private Long day;
|
||||
private BigDecimal duration;
|
||||
|
||||
/**
|
||||
* 开始时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm
|
||||
*/
|
||||
private String startTimeExtraFields;
|
||||
/**
|
||||
* 结束时间额外字段 根据请假最小单位来 1按天则为空 2按半天则1为上午 2为下午 3按小时则 格式为 HH:mm
|
||||
*/
|
||||
private String endTimeExtraFields;
|
||||
/**
|
||||
* 请假最小单位 1按天 2按半天 3按小时
|
||||
*/
|
||||
private Integer minUnit;
|
||||
|
||||
/**
|
||||
* 请假的结果
|
||||
*
|
||||
* <p>
|
||||
* 枚举 {@link BpmProcessInstanceResultEnum}
|
||||
* 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈
|
||||
*/
|
||||
@ -70,7 +89,7 @@ public class BpmOALeaveDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 对应的流程编号
|
||||
*
|
||||
* <p>
|
||||
* 关联 ProcessInstance 的 id 属性
|
||||
*/
|
||||
private String processInstanceId;
|
||||
@ -79,6 +98,6 @@ public class BpmOALeaveDO extends BaseDO {
|
||||
* 附件基本信息
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<UploadUserFile> fileItems ;
|
||||
private List<UploadUserFile> fileItems;
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,11 @@ public class BpmOAOvertimeDO extends BaseDO {
|
||||
*/
|
||||
private BigDecimal timeLength;
|
||||
|
||||
/**
|
||||
* 是否结算(0否 1是)
|
||||
*/
|
||||
private Integer settlementFlag;
|
||||
|
||||
/**
|
||||
* 出差的结果
|
||||
*
|
||||
|
@ -0,0 +1,64 @@
|
||||
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 加班申请子表 DO
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@TableName("bpm_oa_overtime_item")
|
||||
@KeySequence("bpm_oa_overtime_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BpmOAOvertimeItemDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 加班申请id
|
||||
*/
|
||||
private Long oaOvertimeId;
|
||||
/**
|
||||
* 申请人用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 日期 yyyy-MM-dd
|
||||
*/
|
||||
private String dateTimeStr;
|
||||
/**
|
||||
* 加班时长(小时)
|
||||
*/
|
||||
private BigDecimal timeLength;
|
||||
/**
|
||||
* 日期类型 类型 1工作日 2休息日 3节假日
|
||||
*/
|
||||
private Integer dateType;
|
||||
/**
|
||||
* 实际加班时长(根据计算方式和不同的日期类型)
|
||||
*/
|
||||
private BigDecimal actualTimeLength;
|
||||
/**
|
||||
* 实际加班时长单位
|
||||
*/
|
||||
private Integer unit;
|
||||
/**
|
||||
* 实际加班时长(分钟)
|
||||
*/
|
||||
private Long actualTimeLengthMinutes;
|
||||
|
||||
}
|
@ -24,7 +24,6 @@ public interface BpmOALeaveMapper extends BaseMapperX<BpmOALeaveDO> {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BpmOALeaveDO>()
|
||||
.eqIfPresent(BpmOALeaveDO::getUserId, userId)
|
||||
.eqIfPresent(BpmOALeaveDO::getResult, reqVO.getResult())
|
||||
.eqIfPresent(BpmOALeaveDO::getType, reqVO.getType())
|
||||
.likeIfPresent(BpmOALeaveDO::getReason, reqVO.getReason())
|
||||
.betweenIfPresent(BpmOALeaveDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(BpmOALeaveDO::getId));
|
||||
|
@ -0,0 +1,15 @@
|
||||
package cn.iocoder.yudao.module.bpm.dal.mysql.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 加班申请子表 Mapper
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmOAOvertimeItemMapper extends BaseMapperX<BpmOAOvertimeItemDO> {
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.PostApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.equipment.UsersExtApi;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.HolidayApi;
|
||||
import cn.iocoder.yudao.module.system.api.group.AttendanceGroupApi;
|
||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
|
||||
@ -20,13 +21,14 @@ import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
|
||||
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.supplier.SupplierApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.WorkOvertimeApi;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableFeignClients(clients = {FileApi.class, RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class, NotifyMessageSendApi.class,
|
||||
SubscribeMessageSendApi.class, SocialClientApi.class, UsersExtApi.class, AttendanceApi.class, BankApi.class, ConfigApi.class, PositionApi.class, SupplierApi.class, AssetsApi.class,
|
||||
AssetsTypeApi.class, AssetReceiveApi.class, AttendanceApi.class, AttendanceGroupApi.class
|
||||
AssetsTypeApi.class, AssetReceiveApi.class, AttendanceApi.class, AttendanceGroupApi.class,WorkOvertimeApi.class
|
||||
})
|
||||
public class RpcConfiguration {
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.bpm.handler;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.service.workovertime.WorkOvertimeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Author : AiKai
|
||||
* @Description : 利用Spring的发现机制,将实现了IChannelLoginService的类都put到channelLoginServiceMap里面。
|
||||
* 后面只需要根据channelType对应好 各个实现类的注解 如: @Component("sys") 就可以取出不同的业务实现类
|
||||
**/
|
||||
@Service
|
||||
public class WorkOvertimeHandler {
|
||||
private final Map<String, WorkOvertimeService> workServiceMap = new ConcurrentHashMap<>();
|
||||
|
||||
public WorkOvertimeHandler(Map<String, WorkOvertimeService> strategyMap) {
|
||||
this.workServiceMap.clear();
|
||||
strategyMap.forEach((k, v) -> this.workServiceMap.put(k, v));
|
||||
}
|
||||
|
||||
public WorkOvertimeService getResource(String channelType) {
|
||||
return workServiceMap.get(channelType);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.bpm.handler.enums;
|
||||
|
||||
public enum WorkOvertimeEnum {
|
||||
WEEKDAY(1, "weekDay"),
|
||||
REST_DAY(2, "restDay"),
|
||||
HOLIDAY(3, "holiday"),
|
||||
;
|
||||
private final Integer channelType;
|
||||
private final String serverName;
|
||||
|
||||
WorkOvertimeEnum(Integer channelType, String name) {
|
||||
this.channelType = channelType;
|
||||
this.serverName = name;
|
||||
}
|
||||
|
||||
public Integer getChannelType() {
|
||||
return channelType;
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
public static String getEnumServerName(Integer channelType) {
|
||||
for (WorkOvertimeEnum value : WorkOvertimeEnum.values()) {
|
||||
if (value.channelType.equals(channelType)) {
|
||||
return value.serverName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.bpm.job.workovertime;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAOvertimeMapper;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAOvertimeItemService;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAOvertimeService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class WorkOvertimeJob {
|
||||
|
||||
// TODO: 2024/11/04 - 每天凌晨2点执行
|
||||
|
||||
/**
|
||||
* 加班定时任务
|
||||
**/
|
||||
|
||||
@Resource
|
||||
private BpmOAOvertimeService overtimeService;
|
||||
@Resource
|
||||
private BpmOAOvertimeMapper overtimeMapper;
|
||||
@Resource
|
||||
private BpmOAOvertimeItemService overtimeItemService;
|
||||
|
||||
@XxlJob("workOvertimeJob")
|
||||
@TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
|
||||
public ReturnT<String> execute() throws Exception {
|
||||
log.info("开始 加班定时任务");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
List<BpmOAOvertimeDO> bpmOAOvertimeDOS = overtimeMapper.selectList(new LambdaQueryWrapper<BpmOAOvertimeDO>()
|
||||
.eq(BpmOAOvertimeDO::getSettlementFlag, 0)
|
||||
.eq(BpmOAOvertimeDO::getResult, BpmProcessInstanceResultEnum.APPROVE)
|
||||
.ge(BpmOAOvertimeDO::getEndTime, now));
|
||||
if (CollectionUtil.isNotEmpty(bpmOAOvertimeDOS)) {
|
||||
List<Long> ids = bpmOAOvertimeDOS.stream().map(BpmOAOvertimeDO::getId).collect(Collectors.toList());
|
||||
List<BpmOAOvertimeItemDO> items = overtimeItemService.getByOvertimeIds(ids);
|
||||
Map<Long, List<BpmOAOvertimeItemDO>> map = items.stream().collect(Collectors.groupingBy(BpmOAOvertimeItemDO::getOaOvertimeId));
|
||||
for (BpmOAOvertimeDO bpmOAOvertimeDO : bpmOAOvertimeDOS) {
|
||||
List<BpmOAOvertimeItemDO> bpmOAOvertimeItemDOS = map.get(bpmOAOvertimeDO.getId());
|
||||
overtimeService.handlingOvertime(bpmOAOvertimeDO, bpmOAOvertimeItemDOS, now);
|
||||
}
|
||||
}
|
||||
log.info("结束 加班定时任务");
|
||||
// 返回执行成功
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.string.DTO.IdCardDO;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
@ -7,7 +8,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.entry.BpmOAEntryCreateReqVO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAEntryConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAEntryMapper;
|
||||
@ -45,7 +45,7 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_ENTRY_NOT_
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BpmOAEntryServiceImpl implements BpmOAEntryService{
|
||||
public class BpmOAEntryServiceImpl implements BpmOAEntryService {
|
||||
|
||||
/**
|
||||
* OA 入职申请对应的流程定义 KEY
|
||||
@ -82,7 +82,7 @@ public class BpmOAEntryServiceImpl implements BpmOAEntryService{
|
||||
BpmOAEntryDO entry = BpmOAEntryConvert.INSTANCE.convert(createReqVO)
|
||||
.setUserId(getLoginUserId())
|
||||
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
||||
entryMapper.insert(entry) ;
|
||||
entryMapper.insert(entry);
|
||||
|
||||
// 获取入职部门信息
|
||||
DeptRespDTO dto = deptApi.getDept(entry.getEntryDeptId()).getCheckedData();
|
||||
|
@ -5,32 +5,38 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.BpmOALeaveRpcVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeaveCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeavePageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.CalculateAndVerifyLeaveDTO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoVO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 请假申请 Service 接口
|
||||
*
|
||||
* @author jason
|
||||
|
||||
*/
|
||||
public interface BpmOALeaveService {
|
||||
|
||||
/**
|
||||
* 创建请假申请
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userId 用户编号
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createLeave(Long userId, @Valid BpmOALeaveCreateReqVO createReqVO);
|
||||
|
||||
Map<String, AttendanceTimeRangeInfoVO> getAttendanceInfoByTimeRange(AttendanceTimeRangeInfoDTO attendanceTimeRangeInfoDTO);
|
||||
|
||||
/**
|
||||
* 更新请假申请的状态
|
||||
*
|
||||
* @param id 编号
|
||||
* @param id 编号
|
||||
* @param result 结果
|
||||
*/
|
||||
void updateLeaveResult(Long id, Integer result);
|
||||
@ -46,7 +52,7 @@ public interface BpmOALeaveService {
|
||||
/**
|
||||
* 获得请假申请分页
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userId 用户编号
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 请假申请分页
|
||||
*/
|
||||
@ -54,6 +60,7 @@ public interface BpmOALeaveService {
|
||||
|
||||
/**
|
||||
* 根据时间获取请假列表
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
@ -61,8 +68,18 @@ public interface BpmOALeaveService {
|
||||
|
||||
/**
|
||||
* 获得指定请假申请
|
||||
*
|
||||
* @param processInstanceId 流程实例编号
|
||||
* @return 出差申请
|
||||
*/
|
||||
BpmOALeaveDO getByProcessInstanceId(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 计算请假时长
|
||||
*
|
||||
* @param loginUserId
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
BigDecimal calculateAndVerifyTheNumberOfLeaveDays(Long loginUserId, CalculateAndVerifyLeaveDTO dto);
|
||||
}
|
||||
|
@ -4,15 +4,19 @@ import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.Constants;
|
||||
import cn.iocoder.yudao.framework.common.pojo.BpmOALeaveDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.BpmOALeaveRpcVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeaveCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.BpmOALeavePageReqVO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.leave.CalculateAndVerifyLeaveDTO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper;
|
||||
@ -20,20 +24,29 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.AttendanceApi;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceGroupShiftItemVO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoVO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.HolidayApi;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.dto.CreateUserHolidayDTO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.vo.HolidaySettingVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.FAILED_TO_APPLY_FOR_LEAVE;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_LEAVE_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* OA 请假申请 Service 实现类
|
||||
@ -58,49 +71,407 @@ public class BpmOALeaveServiceImpl extends BpmOABaseService implements BpmOALeav
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
@Resource
|
||||
private AttendanceApi attendanceApi;
|
||||
|
||||
@Resource
|
||||
private BpmHistoryProcessInstanceService historyProcessInstanceService;
|
||||
@Resource
|
||||
private HolidayApi holidayApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createLeave(Long userId, BpmOALeaveCreateReqVO createReqVO) {
|
||||
// 插入 OA 请假单
|
||||
long day = LocalDateTimeUtil.between(createReqVO.getStartTime(), createReqVO.getEndTime()).toDays();
|
||||
BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convert(createReqVO).setUserId(userId).setDay(day)
|
||||
BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convert(createReqVO)
|
||||
.setUserId(userId)
|
||||
.setFileItems(createReqVO.getFileItems())
|
||||
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
||||
|
||||
// 构建请假开始 or 结束时间
|
||||
LocalDateTime[] times = this.builderLeaveTime(leave);
|
||||
List<Integer> processingOrPassed = BpmProcessInstanceResultEnum.processingOrPassed();
|
||||
List<BpmOALeaveDO> bpmOALeaveDOS = leaveMapper.selectList(new LambdaQueryWrapper<BpmOALeaveDO>()
|
||||
.eq(BpmOALeaveDO::getUserId, userId)
|
||||
.le(BpmOALeaveDO::getStartTime, leave.getEndTime())
|
||||
.gt(BpmOALeaveDO::getEndTime, leave.getStartTime())
|
||||
.in(BpmOALeaveDO::getResult, processingOrPassed)
|
||||
);
|
||||
// -- 判断是否有重复时间
|
||||
if (CollectionUtil.isNotEmpty(bpmOALeaveDOS)) {
|
||||
for (BpmOALeaveDO bpmOALeaveDO : bpmOALeaveDOS) {
|
||||
LocalDateTime[] itemTimes = this.builderLeaveTime(bpmOALeaveDO);
|
||||
boolean intersects = LocalDateTimeUtils.intersects(times[0], times[1], itemTimes[0], itemTimes[1]);
|
||||
if (intersects) {
|
||||
throw exception(THERE_IS_ALREADY_A_RECORD_OF_REQUESTING_LEAVE_DURING_THIS_TIME_PERIOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
// -- 计算用户假期 -- 内含 判断假期是否充足
|
||||
BigDecimal duration = this.calculateAndVerifyTheNumberOfLeaveDays(leave);
|
||||
// 插入 OA 请假单
|
||||
leaveMapper.insert(leave);
|
||||
|
||||
// 发起 BPM 流程
|
||||
Map<String, Object> processInstanceVariables = new HashMap<>();
|
||||
processInstanceVariables.put("day", day);
|
||||
// processInstanceVariables.put("duration", leave.getDuration().toString());
|
||||
String processInstanceId = processInstanceApi.createProcessInstance(userId,
|
||||
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
|
||||
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))).getCheckedData();
|
||||
|
||||
// 将工作流的编号,更新到 OA 请假单中
|
||||
leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId));
|
||||
|
||||
// 判断是否为重新发起的流程
|
||||
if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) {
|
||||
|
||||
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
|
||||
}
|
||||
|
||||
List<UploadUserFile> fileItems = createReqVO.getFileItems();
|
||||
//这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id
|
||||
if (fileItems != null && !fileItems.isEmpty()) {
|
||||
uploadBpmFileProcessInstanceId(processInstanceId, fileItems);
|
||||
}
|
||||
|
||||
// 创建完流程后 - 减去对应用户的假期余额 - 记录请假原因
|
||||
String beginTimeStr = "";
|
||||
String endTimeStr = "";
|
||||
if (leave.getMinUnit() == 2) {
|
||||
beginTimeStr = "1".equals(leave.getStartTimeExtraFields()) ? "上午" : "下午";
|
||||
endTimeStr = "2".equals(leave.getStartTimeExtraFields()) ? "上午" : "下午";
|
||||
}
|
||||
String reason = "开始时间:" + leave.getStartTime().format(DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY)) + " " + beginTimeStr +
|
||||
" 结束时间:" + leave.getEndTime().format(DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY)) + " " + endTimeStr;
|
||||
holidayApi.createUserHoliday(new CreateUserHolidayDTO().setUserId(leave.getUserId()).setHolidaySettingId(leave.getHolidaySettingId())
|
||||
.setDirection(1).setHolidayBalance(duration).setReason(reason));
|
||||
return leave.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算校验用户假期余额是否充足
|
||||
*
|
||||
* @param leave
|
||||
*/
|
||||
private BigDecimal calculateAndVerifyTheNumberOfLeaveDays(BpmOALeaveDO leave) {
|
||||
//-- 判断用户假期额度是否充足 - 根据假期配置来计算出请假时长先
|
||||
CommonResult<HolidaySettingVO> holidaySettings = holidayApi.getHolidaySettings(leave.getUserId(), leave.getHolidaySettingId());
|
||||
if (!holidaySettings.isSuccess() || holidaySettings.getData() == null) {
|
||||
throw exception(GET_USER_HOLIDAY_EXCEPTION);
|
||||
}
|
||||
HolidaySettingVO vo = holidaySettings.getCheckedData();
|
||||
leave.setLeaveName(vo.getName());
|
||||
// 计算请假多久 - ok 怎么计算?
|
||||
// 先判断是什么类型的请假,然后计算请假时长
|
||||
// --- 草 - 这里还要根据用户的考勤组计算 - 计算是否是工作时间 妈的
|
||||
Integer minUnit = leave.getMinUnit();
|
||||
BigDecimal duration = BigDecimal.ZERO;
|
||||
// -- 先拿到请假的这几天 - 完了后去获取当前用户所在考勤组这几天是否需要工作 - 是不是工作时间
|
||||
if (vo.getCalculationMethod() == 0) {
|
||||
if (minUnit == 1) {
|
||||
// 按天
|
||||
// -- 如果是同一天的话 +1
|
||||
duration = new BigDecimal(String.valueOf(LocalDateTimeUtil.between(leave.getStartTime(), leave.getEndTime(), ChronoUnit.DAYS) + 1));
|
||||
} else if (minUnit == 2) {
|
||||
// -- 按半天
|
||||
duration = new BigDecimal(String.valueOf(LocalDateTimeUtil.between(leave.getStartTime(), leave.getEndTime(), ChronoUnit.DAYS) + 1));
|
||||
if (leave.getStartTimeExtraFields().equals(leave.getEndTimeExtraFields())) {
|
||||
duration = duration.subtract(new BigDecimal("0.5"));
|
||||
} else if (Integer.parseInt(leave.getStartTimeExtraFields()) > Integer.parseInt(leave.getEndTimeExtraFields())) {
|
||||
duration = duration.subtract(BigDecimal.ONE);
|
||||
}
|
||||
} else {
|
||||
// 按小时
|
||||
// -- 计算出相差的分钟
|
||||
long betweenMinutes = LocalDateTimeUtil.between(leave.getStartTime(), leave.getEndTime(), ChronoUnit.MINUTES);
|
||||
duration = this.hourRounding(vo.getRoundFlag(), vo.getRoundUnit(), vo.getRoundDirection(), betweenMinutes);
|
||||
}
|
||||
} else {
|
||||
//获取当前登录用户所在考勤组 以及每天的班次
|
||||
Map<String, AttendanceTimeRangeInfoVO> dataList = this.getAttendanceInfoByTimeRange(new AttendanceTimeRangeInfoDTO()
|
||||
.setUserId(leave.getUserId()).setStartTime(leave.getStartTime()).setEndTime(leave.getEndTime()));
|
||||
List<String> list = DateUtils.betweenDayList(leave.getStartTime(), leave.getEndTime());
|
||||
if (minUnit == 1) {
|
||||
for (String time : list) {
|
||||
AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO = dataList.get(time);
|
||||
if (attendanceTimeRangeInfoVO == null || attendanceTimeRangeInfoVO.getNeedAttendance().equals(0)
|
||||
|| CollectionUtil.isEmpty(attendanceTimeRangeInfoVO.getItems())) {
|
||||
continue;
|
||||
}
|
||||
duration = duration.add(BigDecimal.ONE);
|
||||
}
|
||||
} else if (minUnit == 2) {
|
||||
// -- 按半天
|
||||
// -- 假设每天都需要上班 那么直接看第一天的开始时间和最后一天的结束时间即可 - 那么 也有可能他其中也有不上班的 - 不上班的话 - 去一天
|
||||
BigDecimal withoutWorkDayNum = BigDecimal.ZERO;
|
||||
duration = new BigDecimal(String.valueOf(LocalDateTimeUtil.between(leave.getStartTime(), leave.getEndTime(), ChronoUnit.DAYS) + 1));
|
||||
if (leave.getStartTimeExtraFields().equals(leave.getEndTimeExtraFields())) {
|
||||
duration = duration.subtract(new BigDecimal("0.5"));
|
||||
} else if (Integer.parseInt(leave.getStartTimeExtraFields()) > Integer.parseInt(leave.getEndTimeExtraFields())) {
|
||||
duration = duration.subtract(BigDecimal.ONE);
|
||||
}
|
||||
for (String time : list) {
|
||||
AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO = dataList.get(time);
|
||||
if (attendanceTimeRangeInfoVO == null || attendanceTimeRangeInfoVO.getNeedAttendance().equals(0)
|
||||
|| CollectionUtil.isEmpty(attendanceTimeRangeInfoVO.getItems())) {
|
||||
LocalDateTime thisTime = LocalDateTimeUtil.parseDate(time, Constants.REPO_DATE_FORMAT).atStartOfDay();
|
||||
if (LocalDateTimeUtil.isSameDay(thisTime, leave.getStartTime())) {
|
||||
// -- 如果是开始时间
|
||||
if (Objects.equals(leave.getStartTimeExtraFields(), "1")) {
|
||||
withoutWorkDayNum = withoutWorkDayNum.add(BigDecimal.ONE);
|
||||
} else {
|
||||
withoutWorkDayNum = withoutWorkDayNum.add(new BigDecimal("0.5"));
|
||||
}
|
||||
} else if (LocalDateTimeUtil.isSameDay(thisTime, leave.getEndTime())) {
|
||||
// -- 如果是结束时间
|
||||
if (Objects.equals(leave.getStartTimeExtraFields(), "1")) {
|
||||
withoutWorkDayNum = withoutWorkDayNum.add(new BigDecimal("0.5"));
|
||||
} else {
|
||||
withoutWorkDayNum = withoutWorkDayNum.add(BigDecimal.ONE);
|
||||
}
|
||||
} else {
|
||||
withoutWorkDayNum = withoutWorkDayNum.add(BigDecimal.ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
duration = duration.subtract(withoutWorkDayNum);
|
||||
} else {
|
||||
long totalWorkMinutes = 0;
|
||||
for (String time : list) {
|
||||
AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO = dataList.get(time);
|
||||
if (attendanceTimeRangeInfoVO == null || attendanceTimeRangeInfoVO.getNeedAttendance().equals(0)
|
||||
|| CollectionUtil.isEmpty(attendanceTimeRangeInfoVO.getItems())) {
|
||||
continue;
|
||||
}
|
||||
// 获取当天时间 - 转为LocalDateTime
|
||||
LocalDateTime thisTime = LocalDateTimeUtil.parseDate(time, Constants.REPO_DATE_FORMAT).atStartOfDay();
|
||||
|
||||
// 升序从小到大
|
||||
List<AttendanceGroupShiftItemVO> items = attendanceTimeRangeInfoVO.getItems().stream()
|
||||
.sorted(Comparator.comparingInt(AttendanceGroupShiftItemVO::getLevel))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
AttendanceGroupShiftItemVO first = CollectionUtil.getFirst(items);
|
||||
AttendanceGroupShiftItemVO last = CollectionUtil.getLast(items);
|
||||
LocalDateTime beginTime = DateUtils.buildHHmmLocalDateTime(first.getBeginTime(), thisTime);
|
||||
|
||||
LocalDateTime lastTime = thisTime;
|
||||
if (Arrays.asList(1, 2).contains(last.getNextDayFlag())) {
|
||||
lastTime = lastTime.plusDays(1);
|
||||
}
|
||||
|
||||
LocalDateTime endTime = DateUtils.buildHHmmLocalDateTime(last.getEndTime(), lastTime);
|
||||
// -- 间隔的时间
|
||||
long intervalTime = 0L;
|
||||
int size = items.size();
|
||||
if (size > 1) {
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
// -- 第一天的话不可能所有时间都跨天 只可能是结束时间跨天
|
||||
LocalDateTime top = DateUtils.buildHHmmLocalDateTime(items.get(i).getBeginTime(), thisTime);
|
||||
LocalDateTime next = DateUtils.buildHHmmLocalDateTime(items.get(i + 1).getEndTime(), thisTime);
|
||||
// -- 只有这种情况需要设置下跨天
|
||||
if (items.get(i).getNextDayFlag() == 0 && items.get(i + 1).getNextDayFlag() == 1) {
|
||||
next = next.plusDays(1);
|
||||
}
|
||||
long between = LocalDateTimeUtil.between(top, next, ChronoUnit.MINUTES);
|
||||
intervalTime = intervalTime + between;
|
||||
}
|
||||
}
|
||||
|
||||
// -- 一天的时间
|
||||
long betweenMinutes = LocalDateTimeUtil.between(beginTime, endTime, ChronoUnit.MINUTES) - intervalTime;
|
||||
// -- 一天中休息的时间 (请假开始和结束时间特殊处理过)
|
||||
long allRestTime = 0L;
|
||||
|
||||
for (AttendanceGroupShiftItemVO item : items) {
|
||||
LocalDateTime workBeginTime = DateUtils.buildHHmmLocalDateTime(item.getBeginTime(), thisTime);
|
||||
LocalDateTime workEndTime = DateUtils.buildHHmmLocalDateTime(item.getEndTime(), thisTime);
|
||||
if (Arrays.asList(1, 2).contains(item.getNextDayFlag())) {
|
||||
workEndTime = workEndTime.plusDays(1);
|
||||
}
|
||||
boolean beginSameDayFlag = LocalDateTimeUtil.isSameDay(thisTime, leave.getStartTime());
|
||||
if (beginSameDayFlag) {
|
||||
// 如果请假开始时间 = 当前时间
|
||||
// 判断开始时间是否是上班时间
|
||||
boolean flag = LocalDateTimeUtil.isIn(leave.getStartTime(), workBeginTime, workEndTime);
|
||||
if (flag) {
|
||||
// 如果请假时间在当前时间段 - 再去判断 是否再休息时间段内 - 如果是再休息时间段内的话 拿休息结束时间当作请假开始时间
|
||||
if (item.getRestFlag() == 1) {
|
||||
// -- 这里分三个情况 - 1.在工作开始时间 到 休息开始时间内 2.在休息时间内 3.在休息结束时间到工作结束时间
|
||||
LocalDateTime restBeginTime = DateUtils.buildHHmmLocalDateTime(item.getRestBeginTime(), lastTime);
|
||||
LocalDateTime restEndTime = DateUtils.buildHHmmLocalDateTime(item.getRestEndTime(), lastTime);
|
||||
// -- 如果休息的结束时间小于休息的开始时间 - 说明跨天了
|
||||
if (restBeginTime.isAfter(restEndTime)) {
|
||||
restEndTime = restEndTime.plusDays(1);
|
||||
}
|
||||
long restTime = LocalDateTimeUtil.between(restBeginTime, restEndTime, ChronoUnit.MINUTES);
|
||||
if (LocalDateTimeUtil.isIn(leave.getStartTime(), workBeginTime, restBeginTime)) {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(workBeginTime, leave.getStartTime(), ChronoUnit.MINUTES) + restTime;
|
||||
|
||||
} else if (LocalDateTimeUtil.isIn(leave.getStartTime(), restBeginTime, restEndTime)) {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(workBeginTime, restBeginTime, ChronoUnit.MINUTES) + restTime;
|
||||
} else if (LocalDateTimeUtil.isIn(leave.getStartTime(), restEndTime, workEndTime)) {
|
||||
// -- 休息时间 = 工作开始时间 到 请假开始时间 - 期间的休息时间(因为总的已经减过了)
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(workBeginTime, leave.getStartTime(), ChronoUnit.MINUTES);
|
||||
}
|
||||
} else {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(workBeginTime, leave.getStartTime(), ChronoUnit.MINUTES);
|
||||
}
|
||||
} else {
|
||||
// -- 如果请假时间不在当前工作时间段内段话则把当前工作时间当做休息时间 -
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(workBeginTime, workEndTime, ChronoUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
|
||||
boolean endSameDayFlag = LocalDateTimeUtil.isSameDay(thisTime, leave.getEndTime());
|
||||
if (endSameDayFlag) {
|
||||
boolean flag = LocalDateTimeUtil.isIn(leave.getEndTime(), workBeginTime, workEndTime);
|
||||
if (flag) {
|
||||
// 如果请假时间在当前时间段 - 再去判断 是否再休息时间段内 - 如果是再休息时间段内的话 拿休息结束时间当作请假开始时间
|
||||
if (item.getRestFlag() == 1) {
|
||||
// -- 这里分三个情况 - 1.在工作开始时间 到 休息开始时间内 2.在休息时间内 3.在休息结束时间到工作结束时间
|
||||
LocalDateTime restBeginTime = DateUtils.buildHHmmLocalDateTime(item.getRestBeginTime(), lastTime);
|
||||
LocalDateTime restEndTime = DateUtils.buildHHmmLocalDateTime(item.getRestEndTime(), lastTime);
|
||||
// -- 如果休息的结束时间小于休息的开始时间 - 说明跨天了
|
||||
if (restBeginTime.isAfter(restEndTime)) {
|
||||
restEndTime = restEndTime.plusDays(1);
|
||||
}
|
||||
long restTime = LocalDateTimeUtil.between(restBeginTime, restEndTime, ChronoUnit.MINUTES);
|
||||
if (LocalDateTimeUtil.isIn(leave.getEndTime(), workBeginTime, restBeginTime)) {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(leave.getEndTime(), workEndTime, ChronoUnit.MINUTES);
|
||||
} else if (LocalDateTimeUtil.isIn(leave.getEndTime(), restBeginTime, restEndTime)) {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(restBeginTime, workEndTime, ChronoUnit.MINUTES);
|
||||
} else if (LocalDateTimeUtil.isIn(leave.getEndTime(), restEndTime, workEndTime)) {
|
||||
// -- 这里需要判断 请假开始时间和结束时间是不是同一天 - 如果是同一天的话 就会出现重复扣除休息时间的情况 - 所以要避免这个情况
|
||||
if (beginSameDayFlag) {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(leave.getEndTime(), workEndTime, ChronoUnit.MINUTES);
|
||||
} else {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(leave.getEndTime(), workEndTime, ChronoUnit.MINUTES) + restTime;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allRestTime = allRestTime + LocalDateTimeUtil.between(leave.getEndTime(), workEndTime, ChronoUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!beginSameDayFlag && !endSameDayFlag) {
|
||||
if (item.getRestFlag() == 1) {
|
||||
LocalDateTime restBeginTime = DateUtils.buildHHmmLocalDateTime(item.getRestBeginTime(), lastTime);
|
||||
LocalDateTime restEndTime = DateUtils.buildHHmmLocalDateTime(item.getRestEndTime(), lastTime);
|
||||
// -- 如果休息的结束时间小于休息的开始时间 - 说明跨天了
|
||||
if (restBeginTime.isAfter(restEndTime)) {
|
||||
restEndTime = restEndTime.plusDays(1);
|
||||
}
|
||||
long restTime = LocalDateTimeUtil.between(restBeginTime, restEndTime, ChronoUnit.MINUTES);
|
||||
// -- 休息时间 = 工作开始时间 到 请假开始时间 - 期间的休息时间(因为总的已经减过了)
|
||||
allRestTime = allRestTime + restTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
// -- 总的时间 减去休息时间
|
||||
betweenMinutes = betweenMinutes - allRestTime;
|
||||
totalWorkMinutes = totalWorkMinutes + betweenMinutes;
|
||||
}
|
||||
// 按小时
|
||||
duration = this.hourRounding(vo.getRoundFlag(), vo.getRoundUnit(), vo.getRoundDirection(), totalWorkMinutes);
|
||||
}
|
||||
}
|
||||
if (vo.getStatus() == 1 && vo.getHolidayBalance() != null && vo.getHolidayBalance().compareTo(duration) < 0) {
|
||||
throw exception(INSUFFICIENT_LEAVE_BALANCE);
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 小时计算取整
|
||||
*
|
||||
* @param roundFlag
|
||||
* @param roundUnit
|
||||
* @param roundDirection
|
||||
* @param totalWorkMinutes
|
||||
* @return
|
||||
*/
|
||||
private BigDecimal hourRounding(Integer roundFlag, Integer roundUnit, Integer roundDirection, long totalWorkMinutes) {
|
||||
BigDecimal roundedDuration;
|
||||
if (roundFlag == 0) {
|
||||
return BigDecimal.valueOf(totalWorkMinutes).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
|
||||
|
||||
} else {
|
||||
if (roundUnit == 0) {
|
||||
// 按半小时取整
|
||||
if (roundDirection == 0) {
|
||||
// 向下取整
|
||||
roundedDuration = BigDecimal.valueOf(Math.floor(totalWorkMinutes / 30.0) * 30).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
|
||||
} else {
|
||||
// 向上取整
|
||||
roundedDuration = BigDecimal.valueOf(Math.ceil(totalWorkMinutes / 30.0) * 30).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
} else {
|
||||
// 按一个小时取整
|
||||
if (roundDirection == 0) {
|
||||
// 向下取整
|
||||
roundedDuration = BigDecimal.valueOf(Math.floor(totalWorkMinutes / 60.0) * 60).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
|
||||
} else {
|
||||
// 向上取整
|
||||
roundedDuration = BigDecimal.valueOf(Math.ceil(totalWorkMinutes / 60.0) * 60).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roundedDuration;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 按时间范围获取出勤信息
|
||||
*
|
||||
* @param attendanceTimeRangeInfoDTO
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, AttendanceTimeRangeInfoVO> getAttendanceInfoByTimeRange(AttendanceTimeRangeInfoDTO attendanceTimeRangeInfoDTO) {
|
||||
CommonResult<Map<String, AttendanceTimeRangeInfoVO>> attendanceInfoByTimeRange = attendanceApi.getAttendanceInfoByTimeRange(attendanceTimeRangeInfoDTO);
|
||||
if (!attendanceInfoByTimeRange.isSuccess()) {
|
||||
throw exception(THE_USER_ATTENDANCE_INFORMATION_IS_ABNORMAL);
|
||||
}
|
||||
return attendanceInfoByTimeRange.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请假开始结束时间 -
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LocalDateTime[] builderLeaveTime(BpmOALeaveDO leave) {
|
||||
LocalDateTime startTime = leave.getStartTime();
|
||||
LocalDateTime endTime = leave.getEndTime();
|
||||
if (leave.getMinUnit() == 1) {
|
||||
startTime = LocalDateTimeUtil.beginOfDay(startTime);
|
||||
endTime = LocalDateTimeUtil.endOfDay(endTime);
|
||||
} else if (leave.getMinUnit() == 2) {
|
||||
if ("1".equals(leave.getStartTimeExtraFields())) {
|
||||
// -- 如果开始时间是1 - 则设为0点开始
|
||||
startTime = LocalDateTimeUtil.beginOfDay(startTime);
|
||||
} else {
|
||||
startTime = startTime.withHour(12).withMinute(0).withSecond(0);
|
||||
}
|
||||
if ("1".equals(leave.getEndTimeExtraFields())) {
|
||||
endTime = endTime.withHour(12).withMinute(0).withSecond(0);
|
||||
} else {
|
||||
endTime = LocalDateTimeUtil.endOfDay(endTime);
|
||||
}
|
||||
} else if (leave.getMinUnit() == 3) {
|
||||
String[] split = leave.getStartTimeExtraFields().split(":");
|
||||
startTime = startTime.withHour(Integer.parseInt(split[0])).withMinute(Integer.parseInt(split[1])).withSecond(0);
|
||||
split = leave.getEndTimeExtraFields().split(":");
|
||||
endTime = endTime.withHour(Integer.parseInt(split[0])).withMinute(Integer.parseInt(split[1])).withSecond(0);
|
||||
} else {
|
||||
throw exception(WRONG_TIME_FORMAT);
|
||||
}
|
||||
leave.setStartTime(startTime);
|
||||
leave.setEndTime(endTime);
|
||||
return new LocalDateTime[]{startTime, endTime};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateLeaveResult(Long id, Integer result) {
|
||||
BpmOALeaveDO bpmOALeaveDO = validateLeaveExists(id);
|
||||
BpmOALeaveDO leave = validateLeaveExists(id);
|
||||
leaveMapper.updateById(new BpmOALeaveDO().setId(id).setResult(result));
|
||||
// -- 如果是通过 - 则判断当前时间是否是请假开始时间前
|
||||
// -- 如果是的话 先插入到redis中 - (事前请假)
|
||||
@ -110,24 +481,27 @@ public class BpmOALeaveServiceImpl extends BpmOABaseService implements BpmOALeav
|
||||
if (result.equals(BpmProcessInstanceResultEnum.APPROVE.getResult())) {
|
||||
// 事后请假修改考勤 = 考勤的预设已经生成过了 - 并且已经在表里面存在了 - 所以要找到表中的数据 - 修改考勤状态
|
||||
CommonResult commonResult = attendanceApi.askingForLeaveAfterwardsToModifyAttendance(new AttendancePunchRecordDTO()
|
||||
.setUserId(bpmOALeaveDO.getUserId())
|
||||
.setStartTime(bpmOALeaveDO.getStartTime())
|
||||
.setEndTime(bpmOALeaveDO.getEndTime())
|
||||
.setUserId(leave.getUserId())
|
||||
.setStartTime(leave.getStartTime())
|
||||
.setEndTime(leave.getEndTime())
|
||||
.setLeaveId(id)
|
||||
.setLeaveType(bpmOALeaveDO.getType())
|
||||
.setLeaveName(leave.getLeaveName())
|
||||
);
|
||||
if (!commonResult.isSuccess()) {
|
||||
throw exception(FAILED_TO_APPLY_FOR_LEAVE);
|
||||
}
|
||||
if (now.isBefore(bpmOALeaveDO.getEndTime())) {
|
||||
if (now.isBefore(leave.getEndTime())) {
|
||||
// 事前请假 = 考勤预设可能还没有生成 - 因为可能请假好几天 - 所以这里处理就比较麻烦点 - 先看下考勤表里面有没有在这个区间的考勤 - 如果有的话先修改考勤状态 -
|
||||
// 然后将数据先存入redis - 在设置考勤预设的时候 就去redis 中查询是否有请假 - 有的话预设的时候就预设进去
|
||||
BpmOALeaveDTO dto = new BpmOALeaveDTO();
|
||||
BeanUtil.copyProperties(bpmOALeaveDO, dto);
|
||||
String key = "leave" + "_" + bpmOALeaveDO.getUserId().toString();
|
||||
BeanUtil.copyProperties(leave, dto);
|
||||
String key = "leave" + "_" + leave.getUserId().toString();
|
||||
stringRedisTemplate.opsForHash().put(key, id.toString(), JSONUtil.toJsonStr(dto));
|
||||
// -- 将请假put到redis的map中 -
|
||||
}
|
||||
} else if (Arrays.asList(BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()).contains(result)) {
|
||||
holidayApi.createUserHoliday(new CreateUserHolidayDTO().setUserId(leave.getUserId()).setHolidaySettingId(leave.getHolidaySettingId())
|
||||
.setDirection(0).setHolidayBalance(leave.getDuration()).setReason("请假审核不通过返回假期余额"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,4 +537,11 @@ public class BpmOALeaveServiceImpl extends BpmOABaseService implements BpmOALeav
|
||||
}
|
||||
return list.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal calculateAndVerifyTheNumberOfLeaveDays(Long loginUserId, CalculateAndVerifyLeaveDTO dto) {
|
||||
BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convertCalculateLeaveDTO(dto).setUserId(loginUserId);
|
||||
this.builderLeaveTime(leave);
|
||||
return this.calculateAndVerifyTheNumberOfLeaveDays(leave);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班申请子表 Service 接口
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
public interface BpmOAOvertimeItemService {
|
||||
|
||||
/**
|
||||
* 根据OA加班申请id获取加班申请子表
|
||||
*
|
||||
* @param overtimeId
|
||||
* @return
|
||||
*/
|
||||
List<BpmOAOvertimeItemDO> getByOvertimeId(Long overtimeId);
|
||||
|
||||
/**
|
||||
* 根据OA加班申请ids获取加班申请子表列表
|
||||
*
|
||||
* @param overtimeIds
|
||||
* @return
|
||||
*/
|
||||
List<BpmOAOvertimeItemDO> getByOvertimeIds(List<Long> overtimeIds);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAOvertimeItemMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班申请子表 Service 实现类
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BpmOAOvertimeItemServiceImpl implements BpmOAOvertimeItemService {
|
||||
|
||||
@Resource
|
||||
private BpmOAOvertimeItemMapper overtimeItemMapper;
|
||||
|
||||
@Override
|
||||
public List<BpmOAOvertimeItemDO> getByOvertimeId(Long overtimeId) {
|
||||
return overtimeItemMapper.selectList(new LambdaQueryWrapper<BpmOAOvertimeItemDO>()
|
||||
.eq(BpmOAOvertimeItemDO::getOaOvertimeId, overtimeId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BpmOAOvertimeItemDO> getByOvertimeIds(List<Long> overtimeIds) {
|
||||
if (CollectionUtil.isEmpty(overtimeIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return overtimeItemMapper.selectList(new LambdaQueryWrapper<BpmOAOvertimeItemDO>()
|
||||
.in(BpmOAOvertimeItemDO::getOaOvertimeId, overtimeIds));
|
||||
}
|
||||
}
|
@ -2,21 +2,24 @@ package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime.BpmOAOvertimeCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班申请 Service 接口
|
||||
*
|
||||
* @author 符溶馨
|
||||
|
||||
*/
|
||||
public interface BpmOAOvertimeService {
|
||||
|
||||
/**
|
||||
* 创建加班申请
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userId 用户编号
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
@ -25,10 +28,14 @@ public interface BpmOAOvertimeService {
|
||||
/**
|
||||
* 更新加班申请的状态
|
||||
*
|
||||
* @param id 编号
|
||||
* @param result 结果
|
||||
* @param processInstanceId 流程实例编号
|
||||
* @param id id
|
||||
* @param result 结果
|
||||
*/
|
||||
void updateOvertimeResult(Long id, Integer result);
|
||||
void updateOvertimeResult(String processInstanceId, Long id, Integer result);
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
void handlingOvertime(BpmOAOvertimeDO bpmOAOvertimeDO, List<BpmOAOvertimeItemDO> items, LocalDateTime now);
|
||||
|
||||
/**
|
||||
* 获得加班申请
|
||||
@ -40,6 +47,7 @@ public interface BpmOAOvertimeService {
|
||||
|
||||
/**
|
||||
* 获得指定的加班申请
|
||||
*
|
||||
* @param processInstanceId 流程实例编号
|
||||
* @return 加班申请
|
||||
*/
|
||||
|
@ -1,35 +1,65 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.BetweenFormatter;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.framework.common.Constants;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.overtime.BpmOAOvertimeCreateReqVO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAOvertimeConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAOvertimeItemMapper;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAOvertimeMapper;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||
import cn.iocoder.yudao.module.bpm.handler.WorkOvertimeHandler;
|
||||
import cn.iocoder.yudao.module.bpm.handler.enums.WorkOvertimeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import cn.iocoder.yudao.module.bpm.service.workovertime.WorkOvertimeService;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.AttendanceApi;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoVO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.HolidayApi;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.dto.OvertimeIncreasesHolidayDTO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.WorkOvertimeApi;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_OVERTIME_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* OA 加班申请 Service 实现类
|
||||
*
|
||||
* @author 符溶馨
|
||||
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAOvertimeService{
|
||||
public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAOvertimeService {
|
||||
|
||||
/**
|
||||
* OA 加班对应的流程定义 KEY
|
||||
@ -38,20 +68,92 @@ public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAO
|
||||
|
||||
@Resource
|
||||
private BpmOAOvertimeMapper overtimeMapper;
|
||||
|
||||
@Resource
|
||||
private BpmOAOvertimeItemMapper overtimeItemMapper;
|
||||
@Resource
|
||||
private BpmOAOvertimeItemService overtimeItemService;
|
||||
@Resource
|
||||
private BpmProcessInstanceApi processInstanceApi;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
@Resource
|
||||
private BpmHistoryProcessInstanceService historyProcessInstanceService;
|
||||
@Resource
|
||||
private BpmOALeaveService leaveService;
|
||||
@Resource
|
||||
private WorkOvertimeApi workOvertimeApi;
|
||||
@Resource
|
||||
private AttendanceApi attendanceApi;
|
||||
@Resource
|
||||
private WorkOvertimeHandler workOvertimeHandler;
|
||||
@Resource
|
||||
private HolidayApi holidayApi;
|
||||
|
||||
@Override
|
||||
public Long createOvertime(Long userId, BpmOAOvertimeCreateReqVO createReqVO) {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createOvertime(Long userId, BpmOAOvertimeCreateReqVO vo) {
|
||||
// 判断是否已存在相同时间段的加班申请
|
||||
List<String> dataTimes = DateUtils.betweenDayList(vo.getStartTime(), vo.getEndTime());
|
||||
List<Integer> processingOrPassed = BpmProcessInstanceResultEnum.processingOrPassed();
|
||||
// -- 减去一分钟的时间 - 由于前端可能是一天中的最开始时间 - 这里要处理下
|
||||
LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(vo.getStartTime());
|
||||
LocalDateTime endTime = LocalDateTimeUtil.endOfDay(vo.getEndTime().plusMinutes(-1));
|
||||
List<BpmOAOvertimeDO> overtimeDOS = overtimeMapper.selectList(new LambdaQueryWrapper<BpmOAOvertimeDO>()
|
||||
.eq(BpmOAOvertimeDO::getUserId, userId)
|
||||
.le(BpmOAOvertimeDO::getStartTime, endTime)
|
||||
.gt(BpmOAOvertimeDO::getEndTime, beginTime)
|
||||
.in(BpmOAOvertimeDO::getResult, processingOrPassed)
|
||||
);
|
||||
LocalDateTime[] times = new LocalDateTime[]{beginTime, endTime};
|
||||
if (CollectionUtil.isNotEmpty(overtimeDOS)) {
|
||||
for (BpmOAOvertimeDO overtimeDO : overtimeDOS) {
|
||||
LocalDateTime[] itemTimes = new LocalDateTime[]{overtimeDO.getStartTime(), overtimeDO.getEndTime()};
|
||||
boolean intersects = LocalDateTimeUtils.intersects(times[0], times[1], itemTimes[0], itemTimes[1]);
|
||||
if (intersects) {
|
||||
throw exception(OVERTIME_REQUESTS_ALREADY_EXIST_FOR_THE_SAME_TIME_PERIOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
CommonResult<WorkOvertimeRuleApiVO> resultData = workOvertimeApi.getOvertimeRulesByUserId(userId);
|
||||
// -- 获取用户考勤信息
|
||||
if (!resultData.isSuccess()) {
|
||||
throw exception(EXCEPTION_OCCURRED_WHILE_OBTAINING_OVERTIME_SETTINGS);
|
||||
}
|
||||
// -- 不在考勤组内不需要加班
|
||||
WorkOvertimeRuleApiVO workOvertimeRuleApiVO = resultData.getCheckedData();
|
||||
if (Constants.ZERO.equals(workOvertimeRuleApiVO.getIsGroup())) {
|
||||
throw exception(NO_NEED_TO_APPLY_FOR_OVERTIME_IF_NOT_IN_THE_ATTENDANCE_GROUP);
|
||||
}
|
||||
if (Constants.ZERO.equals(workOvertimeRuleApiVO.getIsOvertime())) {
|
||||
throw exception(THE_CURRENT_USERS_ATTENDANCE_GROUP_HAS_NOT_SET_OVERTIME_RULES);
|
||||
}
|
||||
List<WorkOvertimeRuleItemApiVO> workOvertimeRuleItems = workOvertimeRuleApiVO.getWorkOvertimeRuleItems();
|
||||
Map<Integer, WorkOvertimeRuleItemApiVO> map = workOvertimeRuleItems.stream().collect(Collectors.toMap(WorkOvertimeRuleItemApiVO::getType, Function.identity()));
|
||||
// 根据时间计算是工作日还是节假日还是休息日
|
||||
Map<String, AttendanceTimeRangeInfoVO> attendanceInfoByTimeRange = leaveService.getAttendanceInfoByTimeRange(
|
||||
new AttendanceTimeRangeInfoDTO().setUserId(userId).setStartTime(vo.getStartTime()).setEndTime(vo.getEndTime())
|
||||
);
|
||||
|
||||
//插入OA 转正申请
|
||||
BpmOAOvertimeDO overtime = BpmOAOvertimeConvert.INSTANCE.convert(createReqVO).setUserId(userId)
|
||||
for (String dataTime : dataTimes) {
|
||||
AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO = attendanceInfoByTimeRange.get(dataTime);
|
||||
WorkOvertimeRuleItemApiVO workOvertimeRuleItemApiVO = map.get(attendanceTimeRangeInfoVO.getDatType());
|
||||
if (workOvertimeRuleItemApiVO.getStatus() == 0) {
|
||||
String msg = "%s不允许加班";
|
||||
msg = String.format(msg, (dataTime + "号 " + (attendanceTimeRangeInfoVO.getDatType() == 1 ? "工作日" : attendanceTimeRangeInfoVO.getDatType() == 2 ? "休息日" : "节假日")));
|
||||
throw exception(new ErrorCode(1_009_001_017, msg));
|
||||
}
|
||||
}
|
||||
|
||||
//插入OA 加班申请
|
||||
BpmOAOvertimeDO overtime = BpmOAOvertimeConvert.INSTANCE.convert(vo).setUserId(userId)
|
||||
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
||||
overtimeMapper.insert(overtime) ;
|
||||
overtimeMapper.insert(overtime.setTimeLength(vo.getTotalTimeLength()));
|
||||
|
||||
// -- 记录一个item表
|
||||
List<BpmOAOvertimeItemDO> itemDOS = BeanUtil.copyToList(vo.getOvertimeDateTimeVOS(), BpmOAOvertimeItemDO.class);
|
||||
itemDOS.forEach(overtimeItemDO -> overtimeItemDO.setOaOvertimeId(overtime.getId()).setUserId(userId)
|
||||
.setDateType(attendanceInfoByTimeRange.get(overtimeItemDO.getDateTimeStr()).getDatType()));
|
||||
overtimeItemMapper.insertBatch(itemDOS);
|
||||
|
||||
// 发起 BPM 流程
|
||||
Map<String, Object> processInstanceVariables = new HashMap<>();
|
||||
@ -63,26 +165,111 @@ public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAO
|
||||
overtimeMapper.updateById(new BpmOAOvertimeDO().setId(overtime.getId()).setProcessInstanceId(processInstanceId));
|
||||
|
||||
// 判断是否为重新发起的流程
|
||||
if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) {
|
||||
|
||||
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
|
||||
if (vo.getProcessInstanceId() != null && vo.getResult() == 3) {
|
||||
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, vo.getProcessInstanceId());
|
||||
}
|
||||
|
||||
List<UploadUserFile> fileItems = createReqVO.getFileItems() ;
|
||||
List<UploadUserFile> fileItems = vo.getFileItems();
|
||||
//这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id
|
||||
if (fileItems != null && !fileItems.isEmpty()) {
|
||||
uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ;
|
||||
uploadBpmFileProcessInstanceId(processInstanceId, fileItems);
|
||||
}
|
||||
return overtime.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOvertimeResult(Long id, Integer result) {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateOvertimeResult(String processInstanceId, Long id, Integer result) {
|
||||
validateLeaveExists(id);
|
||||
BpmOAOvertimeDO bpmOAOvertimeDO = overtimeMapper.selectById(id);
|
||||
overtimeMapper.updateById(bpmOAOvertimeDO.setResult(result));
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
//获取加班子表
|
||||
List<BpmOAOvertimeItemDO> items = overtimeItemService.getByOvertimeId(id);
|
||||
// -- 审核通过
|
||||
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
|
||||
ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId);
|
||||
// -- 如果是最终节点 并且子表有数据
|
||||
if (instance.isEnded() && !items.isEmpty()) {
|
||||
this.handlingOvertime(bpmOAOvertimeDO, items, now);
|
||||
}
|
||||
}
|
||||
overtimeMapper.updateById(new BpmOAOvertimeDO().setId(id).setResult(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void handlingOvertime(BpmOAOvertimeDO bpmOAOvertimeDO, List<BpmOAOvertimeItemDO> items, LocalDateTime now) {
|
||||
// 判断是否事后 - 事前的不需要处理 - 等定时任务处理即可
|
||||
if (bpmOAOvertimeDO.getEndTime().isBefore(now)) {
|
||||
// -- 获取到当前用户所在考勤组的加班规则 -
|
||||
Long userId = bpmOAOvertimeDO.getUserId();
|
||||
CommonResult<WorkOvertimeRuleApiVO> resultData = workOvertimeApi.getOvertimeRulesByUserId(userId);
|
||||
if (!resultData.isSuccess()) {
|
||||
throw exception(EXCEPTION_OCCURRED_WHILE_OBTAINING_OVERTIME_SETTINGS);
|
||||
}
|
||||
// -- 不在考勤组内不需要加班
|
||||
WorkOvertimeRuleApiVO workOvertimeRuleApiVO = resultData.getCheckedData();
|
||||
if (Constants.ZERO.equals(workOvertimeRuleApiVO.getIsGroup())) {
|
||||
throw exception(NO_NEED_TO_APPLY_FOR_OVERTIME_IF_NOT_IN_THE_ATTENDANCE_GROUP);
|
||||
}
|
||||
if (Constants.ZERO.equals(workOvertimeRuleApiVO.getIsOvertime())) {
|
||||
throw exception(THE_CURRENT_USERS_ATTENDANCE_GROUP_HAS_NOT_SET_OVERTIME_RULES);
|
||||
}
|
||||
List<WorkOvertimeRuleItemApiVO> workOvertimeRuleItems = workOvertimeRuleApiVO.getWorkOvertimeRuleItems();
|
||||
Map<Integer, WorkOvertimeRuleItemApiVO> map = workOvertimeRuleItems.stream().collect(Collectors.toMap(WorkOvertimeRuleItemApiVO::getType, Function.identity()));
|
||||
// --- 用户加班时间期间的打卡记录
|
||||
Map<String, List<AttendancePunchRecordVO>> recordMap = new HashMap<>();
|
||||
//已经发生的 - 获取该用户最近几天的考勤记录 - 并且对比时间
|
||||
CommonResult<Map<String, List<AttendancePunchRecordVO>>> attendancePunchRecordByTimeRange = attendanceApi.getAttendancePunchRecordByTimeRange(
|
||||
new AttendancePunchRecordDTO().setUserId(bpmOAOvertimeDO.getUserId()).setStartTime(bpmOAOvertimeDO.getStartTime()).setEndTime(bpmOAOvertimeDO.getEndTime()));
|
||||
if (!attendancePunchRecordByTimeRange.isSuccess()) {
|
||||
throw exception(ABNORMAL_ACCESS_TO_ATTENDANCE_RECORDS);
|
||||
}
|
||||
recordMap = attendancePunchRecordByTimeRange.getCheckedData();
|
||||
List<BpmOAOvertimeItemDO> editItems = new ArrayList<>();
|
||||
Map<Long, BigDecimal> holidayMap = new HashMap<>();
|
||||
// - 这里不需要判断是否关闭加班 - 再申请的时候已经判断过了 - 这里只需要做计算加班时长的逻辑即可 !
|
||||
for (BpmOAOvertimeItemDO item : items) {
|
||||
WorkOvertimeRuleItemApiVO ruleItem = map.get(item.getDateType());
|
||||
WorkOvertimeService resource = workOvertimeHandler.getResource(WorkOvertimeEnum.getEnumServerName(ruleItem.getType()));
|
||||
List<AttendancePunchRecordVO> recordList = recordMap.get(item.getDateTimeStr());
|
||||
if (recordList == null) {
|
||||
recordList = new ArrayList<>();
|
||||
}
|
||||
recordList.sort(Comparator.comparing(AttendancePunchRecordVO::getShouldPunchTime));
|
||||
// -- 计算加班时长
|
||||
resource.getOvertimeHours(item, recordList, workOvertimeRuleApiVO, ruleItem);
|
||||
editItems.add(item);
|
||||
// -- 如果是记为调休 - 并且假期id不为空
|
||||
if (ruleItem.getTransformationType() == 1 && ruleItem.getHolidayId() != null) {
|
||||
// -- 计算调休
|
||||
if (item.getActualTimeLength().compareTo(BigDecimal.ZERO) > 0) {
|
||||
// -- 计算每个调休对象需要进行的调休时长 - 这里的单位是小时 - 还要获取假期的单位 来转换一下
|
||||
holidayMap.put(ruleItem.getHolidayId(), holidayMap.getOrDefault(ruleItem.getHolidayId(), BigDecimal.ZERO)
|
||||
.add(item.getActualTimeLength().multiply(ruleItem.getCompensatoryLeaveRatio())));
|
||||
}
|
||||
} else {
|
||||
// TODO: 2024/11/1 加班费不计算(后续有加班规则再计算)
|
||||
}
|
||||
}
|
||||
|
||||
//更新加班主表
|
||||
overtimeMapper.updateById(bpmOAOvertimeDO.setSettlementFlag(1));
|
||||
//更新加班子表
|
||||
overtimeItemMapper.updateBatch(editItems);
|
||||
//加班奖励假期
|
||||
for (Map.Entry<Long, BigDecimal> entry : holidayMap.entrySet()) {
|
||||
holidayApi.overtimeIncreasesHoliday(new OvertimeIncreasesHolidayDTO()
|
||||
.setUserId(userId)
|
||||
.setDirection(0)
|
||||
.setHolidayBalance(entry.getValue())
|
||||
.setHolidaySettingId(entry.getKey())
|
||||
.setUnit(workOvertimeRuleApiVO.getMoreRule().getUnit())
|
||||
.setConversion(workOvertimeRuleApiVO.getMoreRule().getConversion()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLeaveExists(Long id) {
|
||||
if (overtimeMapper.selectById(id) == null) {
|
||||
throw exception(OA_OVERTIME_NOT_EXISTS);
|
||||
|
@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
@ -26,6 +26,7 @@ public class BpmOAOvertimeResultListener extends BpmProcessInstanceResultEventLi
|
||||
|
||||
@Override
|
||||
protected void onEvent(BpmProcessInstanceResultEvent event) {
|
||||
overtimeService.updateOvertimeResult(Long.parseLong(event.getBusinessKey()), event.getResult());
|
||||
overtimeService.updateOvertimeResult(event.getId(), Long.parseLong(event.getBusinessKey()),
|
||||
event.getResult());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
/**
|
||||
* 加班节假日 Service 接口
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
public interface WorkOvertimeHolidayService {
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班 节假日
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Service("holiday")
|
||||
@Validated
|
||||
public class WorkOvertimeHolidayServiceImpl implements WorkOvertimeHolidayService, WorkOvertimeService {
|
||||
@Resource
|
||||
@Lazy
|
||||
private WorkOvertimePublicService workOvertimePublicService;
|
||||
|
||||
@Override
|
||||
public void getOvertimeHours(BpmOAOvertimeItemDO item, List<AttendancePunchRecordVO> recordList,
|
||||
WorkOvertimeRuleApiVO rule, WorkOvertimeRuleItemApiVO ruleItem) {
|
||||
// --- 计算方式 1按审批时长计算 2在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算 (这里是审批后的节点 只计算 1和2两种情况)
|
||||
// --------------------- 按审批时长计算 ---------------------
|
||||
if (ruleItem.getCalculationMode() == 1) {
|
||||
item.setActualTimeLength(item.getTimeLength());
|
||||
return;
|
||||
}
|
||||
// --------------------- 在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算 ---------------------
|
||||
BigDecimal overtimeHours = BigDecimal.ZERO;
|
||||
// -- 节假日 - 打了多久的卡就算多久 - 这里是计算加班时长 -
|
||||
AttendancePunchRecordVO first = CollUtil.getFirst(recordList);
|
||||
AttendancePunchRecordVO last = CollUtil.getLast(recordList);
|
||||
if (first.getPunchTime() == null || last.getPunchTime() == null) {
|
||||
item.setActualTimeLength(overtimeHours);
|
||||
return;
|
||||
}
|
||||
// -- 计算出加班多少分钟
|
||||
long minutes = LocalDateTimeUtil.between(first.getPunchTime(), last.getPunchTime(), ChronoUnit.MINUTES);
|
||||
// -- 计算取整 - 插入加班时间到item中
|
||||
workOvertimePublicService.calculateActualTimeLength(minutes, rule, item, ruleItem);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeDeductRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班公共服务 - Service 接口
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
public interface WorkOvertimePublicService {
|
||||
|
||||
/**
|
||||
* 计算加班时长 (这里按照分钟算)
|
||||
*
|
||||
* @param millis
|
||||
* @param deductRules
|
||||
* @return
|
||||
*/
|
||||
long calculateDeductedTime(long millis, List<WorkOvertimeDeductRuleApiVO> deductRules);
|
||||
|
||||
/**
|
||||
* 计算并插入实际加班
|
||||
*
|
||||
* @param millis
|
||||
* @param rule
|
||||
* @param item
|
||||
* @param ruleItem
|
||||
*/
|
||||
void calculateActualTimeLength(long millis, WorkOvertimeRuleApiVO rule, BpmOAOvertimeItemDO item, WorkOvertimeRuleItemApiVO ruleItem);
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeDeductRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班 节假日
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class WorkOvertimePublicServiceImpl implements WorkOvertimePublicService {
|
||||
|
||||
|
||||
@Override
|
||||
public long calculateDeductedTime(long millis, List<WorkOvertimeDeductRuleApiVO> deductRules) {
|
||||
deductRules.sort(Comparator.comparing(WorkOvertimeDeductRuleApiVO::getThreshold).reversed());
|
||||
for (WorkOvertimeDeductRuleApiVO rule : deductRules) {
|
||||
long deductNum = rule.getDeductNum() * 60;
|
||||
long threshold = rule.getThreshold() * 60;
|
||||
if (millis >= threshold) {
|
||||
millis = millis - deductNum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 确保扣除后的时长不为负数
|
||||
return millis < 0 ? 0L : millis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateActualTimeLength(long millis, WorkOvertimeRuleApiVO rule, BpmOAOvertimeItemDO item, WorkOvertimeRuleItemApiVO ruleItem) {
|
||||
BigDecimal overtimeHours = BigDecimal.ZERO;
|
||||
// -- 累计加班少于多少分钟,不计入加班
|
||||
if (millis < ruleItem.getOvertimeTotalHours()) {
|
||||
item.setActualTimeLength(overtimeHours);
|
||||
return;
|
||||
}
|
||||
// -- 先扣除休息时间 - 这里计算的是分钟
|
||||
if (ruleItem.getIsDeductBreakTime() == 1 && CollUtil.isNotEmpty(ruleItem.getDeductRules())) {
|
||||
List<WorkOvertimeDeductRuleApiVO> deductRules = ruleItem.getDeductRules();
|
||||
millis = this.calculateDeductedTime(millis, deductRules);
|
||||
}
|
||||
|
||||
if (rule.getMoreRule().getUnit() == 1) {
|
||||
// ------ 转为小时后取整
|
||||
overtimeHours = BigDecimal.valueOf(millis).divide(BigDecimal.valueOf(60.0), 2, RoundingMode.HALF_UP);
|
||||
} else {
|
||||
overtimeHours = BigDecimal.valueOf(millis).divide(BigDecimal.valueOf(60.0 * 24), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
if (rule.getMoreRule().getRoundingType() == 1) {
|
||||
//向下取整
|
||||
overtimeHours = calculateAdjustedOvertime(overtimeHours, rule.getMoreRule().getRoundingIncrementalValue());
|
||||
}
|
||||
item.setActualTimeLength(overtimeHours);
|
||||
item.setUnit(rule.getMoreRule().getUnit());
|
||||
item.setActualTimeLengthMinutes(millis);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(calculateAdjustedOvertime(BigDecimal.valueOf(3.0), BigDecimal.valueOf(1.5)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 向下取整
|
||||
*
|
||||
* @param time
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public static BigDecimal calculateAdjustedOvertime(BigDecimal time, BigDecimal n) {
|
||||
if (n.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
// 计算商
|
||||
BigDecimal quotient = time.divide(n, MathContext.DECIMAL128).setScale(0, RoundingMode.DOWN);
|
||||
// 商乘以 n,得到最终的加班时长
|
||||
return quotient.multiply(n);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
/**
|
||||
* 加班工作日 Service 接口
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
public interface WorkOvertimeRestDayService {
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班 休息日
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Service("restDay")
|
||||
@Validated
|
||||
public class WorkOvertimeRestDayServiceImpl implements WorkOvertimeRestDayService, WorkOvertimeService {
|
||||
@Resource
|
||||
private WorkOvertimePublicService workOvertimePublicService;
|
||||
|
||||
@Override
|
||||
public void getOvertimeHours(BpmOAOvertimeItemDO item, List<AttendancePunchRecordVO> recordList, WorkOvertimeRuleApiVO rule, WorkOvertimeRuleItemApiVO ruleItem) {
|
||||
// --- 计算方式 1按审批时长计算 2在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算 (这里是审批后的节点 只计算 1和2两种情况)
|
||||
// --------------------- 按审批时长计算 ---------------------
|
||||
if (ruleItem.getCalculationMode() == 1) {
|
||||
item.setActualTimeLength(item.getTimeLength());
|
||||
return;
|
||||
}
|
||||
// --------------------- 在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算 ---------------------
|
||||
BigDecimal overtimeHours = BigDecimal.ZERO;
|
||||
// -- 休息日 - 打了多久的卡就算多久 - 这里是计算加班时长 -
|
||||
AttendancePunchRecordVO first = CollUtil.getFirst(recordList);
|
||||
AttendancePunchRecordVO last = CollUtil.getLast(recordList);
|
||||
if (first == null || first.getPunchTime() == null || last == null || last.getPunchTime() == null) {
|
||||
item.setActualTimeLength(overtimeHours);
|
||||
return;
|
||||
}
|
||||
// -- 计算出加班多少分钟
|
||||
long minutes = LocalDateTimeUtil.between(first.getPunchTime(), last.getPunchTime(), ChronoUnit.MINUTES);
|
||||
// -- 计算取整 - 插入加班时间到item中
|
||||
workOvertimePublicService.calculateActualTimeLength(minutes, rule, item, ruleItem);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加班 - Service 接口
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
public interface WorkOvertimeService {
|
||||
|
||||
/**
|
||||
* 获取加班时长 计算方式 1按审批时长计算 2在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算 (这里是审批后的节点 只计算 1和2两种情况)
|
||||
*
|
||||
* @param item 加班记录
|
||||
* @param recordList 打卡记录
|
||||
* @param rule 加班规则
|
||||
* @param ruleItem 加班规则子表
|
||||
* @return
|
||||
*/
|
||||
void getOvertimeHours(BpmOAOvertimeItemDO item, List<AttendancePunchRecordVO> recordList, WorkOvertimeRuleApiVO rule, WorkOvertimeRuleItemApiVO ruleItem);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
/**
|
||||
* 加班工作日 Service 接口
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
public interface WorkOvertimeWeekDayService {
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.workovertime;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAOvertimeItemDO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeDeductRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleItemApiVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 加班 工作日
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Service("weekDay")
|
||||
@Validated
|
||||
public class WorkOvertimeWeekDayServiceImpl implements WorkOvertimeWeekDayService, WorkOvertimeService {
|
||||
|
||||
@Resource
|
||||
private WorkOvertimePublicService workOvertimePublicService;
|
||||
|
||||
@Override
|
||||
public void getOvertimeHours(BpmOAOvertimeItemDO item, List<AttendancePunchRecordVO> recordList, WorkOvertimeRuleApiVO rule, WorkOvertimeRuleItemApiVO ruleItem) {
|
||||
// --- 计算方式 1按审批时长计算 2在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算 (这里是审批后的节点 只计算 1和2两种情况)
|
||||
// --------------------- 按审批时长计算 ---------------------
|
||||
if (ruleItem.getCalculationMode() == 1) {
|
||||
item.setActualTimeLength(item.getTimeLength());
|
||||
return;
|
||||
}
|
||||
// --------------------- 在审批的时段内,按打卡时长计算 ---------------------
|
||||
BigDecimal overtimeHours = BigDecimal.ZERO;
|
||||
long totalMillis = 0L;
|
||||
//首先判断下
|
||||
if (Arrays.asList(1, 2).contains(ruleItem.getAllowOvertimeTimeType())) {
|
||||
// 合并 AttendancePunchRecordVO列表中 UpWorkOvertimeTime 的和
|
||||
Long upWorkOvertimeTime = recordList.stream().filter(a ->
|
||||
//获取正常打卡的上班卡
|
||||
a.getStatus().equals(0) && a.getWorkType().equals(0)
|
||||
// 计算班前多少分钟 小于n分钟 则不考虑
|
||||
&& a.getUpWorkOvertimeTime() > 0 && TimeUnit.MILLISECONDS.toMinutes(a.getUpWorkOvertimeTime()) > ruleItem.getBeforeWorkOvertime())
|
||||
.map(AttendancePunchRecordVO::getUpWorkOvertimeTime)
|
||||
// TODO: 2024/11/9 这行计算有问题
|
||||
.reduce(0L, Long::sum);
|
||||
// -- 转换为分钟
|
||||
long millis = TimeUnit.MILLISECONDS.toMinutes(upWorkOvertimeTime);
|
||||
totalMillis += millis;
|
||||
}
|
||||
|
||||
if (Arrays.asList(1, 3).contains(ruleItem.getAllowOvertimeTimeType())) {
|
||||
// 先将所有下班加班时长减去 下班加班起算时间
|
||||
recordList.forEach(a -> {
|
||||
long millis = TimeUnit.MINUTES.toMillis(ruleItem.getOvertimeStartingTime());
|
||||
if (millis > 0) {
|
||||
a.setDownWorkOvertimeTime(Math.max(a.getDownWorkOvertimeTime() - millis, 0));
|
||||
}
|
||||
});
|
||||
// 计算加班时长
|
||||
Long downWorkOvertimeTime = recordList.stream().filter(a ->
|
||||
//获取正常打卡的下班卡
|
||||
a.getStatus().equals(0) && a.getWorkType().equals(1)
|
||||
//计算班后多少分钟 小于n分钟 则不考虑
|
||||
&& a.getDownWorkOvertimeTime() > 0 && TimeUnit.MILLISECONDS.toMinutes(a.getDownWorkOvertimeTime()) >= ruleItem.getAfterWorkOvertime()
|
||||
).map(AttendancePunchRecordVO::getDownWorkOvertimeTime)
|
||||
.reduce(0L, Long::sum);
|
||||
// 下班n分钟后开始算加班 -
|
||||
long millis = TimeUnit.MILLISECONDS.toMinutes(downWorkOvertimeTime);
|
||||
totalMillis += millis;
|
||||
}
|
||||
// -- 计算取整 - 插入加班时间到item中
|
||||
workOvertimePublicService.calculateActualTimeLength(totalMillis, rule, item, ruleItem);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 合并 AttendancePunchRecordVO列表中 UpWorkOvertimeTime 的和
|
||||
List<AttendancePunchRecordVO> recordList = new ArrayList<>();
|
||||
List<Long> collect = recordList.stream().filter(a ->
|
||||
//获取正常打卡的上班卡
|
||||
TimeUnit.MILLISECONDS.toMinutes(23114096L) > 30)
|
||||
.map(AttendancePunchRecordVO::getUpWorkOvertimeTime).collect(Collectors.toList());
|
||||
System.out.println(collect );
|
||||
System.out.println(collect );
|
||||
|
||||
LocalDateTime localDateTime = LocalDateTime.of(2024, 6, 25, 17, 30, 0);
|
||||
LocalDateTime plus = localDateTime.plus(1931472, ChronoUnit.MILLIS);
|
||||
long between = LocalDateTimeUtil.between(localDateTime, plus, ChronoUnit.MINUTES);
|
||||
System.out.println(plus);
|
||||
System.out.println(between);
|
||||
// 将1931472毫秒转换为分钟
|
||||
long millis = TimeUnit.MINUTES.toMillis(1);
|
||||
System.out.println(millis);
|
||||
// List<AttendancePunchRecordVO> recordList = Arrays.asList(
|
||||
// new AttendancePunchRecordVO().setStatus(0).setWorkType(1).setUpWorkOvertimeTime(20L),
|
||||
// new AttendancePunchRecordVO().setStatus(0).setWorkType(1).setUpWorkOvertimeTime(10L)
|
||||
// );
|
||||
// Long upWorkOvertimeTime = recordList.stream().filter(a -> a.getStatus().equals(0) && a.getWorkType().equals(1)).map(AttendancePunchRecordVO::getUpWorkOvertimeTime)
|
||||
// .reduce(0L, Long::sum);
|
||||
// System.out.println(upWorkOvertimeTime);
|
||||
|
||||
}
|
||||
}
|
@ -56,16 +56,23 @@ spring:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 1 # 数据库索引
|
||||
# password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
xxl:
|
||||
job:
|
||||
enabled: false # 是否开启调度中心,默认为 true 开启
|
||||
enabled: true # 是否开启调度中心,默认为 true 开启
|
||||
admin:
|
||||
addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址
|
||||
executor:
|
||||
appname: ${spring.application.name} # 执行器 AppName
|
||||
ip: # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
|
||||
port: 6669 # ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
|
||||
logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
|
||||
#accessToken: default_token
|
||||
logretentiondays: 30 # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
|
@ -41,43 +41,41 @@ spring:
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例
|
||||
url: jdbc:mysql://47.97.8.94:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: root
|
||||
# username: sa
|
||||
# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W
|
||||
slave: # 模拟从库,可根据自己需要修改
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例
|
||||
url: jdbc:mysql://47.97.8.94:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: root
|
||||
# username: sa
|
||||
# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
host: 47.97.8.94 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 0 # 数据库索引
|
||||
# password: 123456 # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
xxl:
|
||||
job:
|
||||
enabled: false # 是否开启调度中心,默认为 true 开启
|
||||
admin:
|
||||
addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址
|
||||
executor:
|
||||
appname: ${spring.application.name} # 执行器 AppName
|
||||
ip: # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
|
||||
port: 6669 # ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
|
||||
logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
|
||||
#accessToken: default_token
|
||||
logretentiondays: 30 # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
|
@ -73,11 +73,19 @@ spring:
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
xxl:
|
||||
job:
|
||||
enabled: false # 是否开启调度中心,默认为 true 开启
|
||||
enabled: true # 是否开启调度中心,默认为 true 开启
|
||||
admin:
|
||||
addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址
|
||||
executor:
|
||||
appname: ${spring.application.name} # 执行器 AppName
|
||||
ip: # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
|
||||
port: 6669 # ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
|
||||
logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
|
||||
#accessToken: default_token
|
||||
logretentiondays: 30 # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
|
@ -3,7 +3,7 @@ spring:
|
||||
name: bpm-server
|
||||
|
||||
profiles:
|
||||
active: dev #local
|
||||
active: local #local
|
||||
# active: prod
|
||||
|
||||
server:
|
||||
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAOvertimeItemMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
</mapper>
|
@ -56,7 +56,7 @@ spring:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 1 # 数据库索引
|
||||
# password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
|
@ -45,33 +45,23 @@ spring:
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例
|
||||
url: jdbc:mysql://47.97.8.94:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: root
|
||||
# username: sa
|
||||
# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W
|
||||
slave: # 模拟从库,可根据自己需要修改
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例
|
||||
url: jdbc:mysql://47.97.8.94:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: root
|
||||
# username: sa
|
||||
# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
host: 47.97.8.94 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 0 # 数据库索引
|
||||
# password: 123456 # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
|
@ -3,7 +3,7 @@ spring:
|
||||
name: infra-server
|
||||
|
||||
profiles:
|
||||
active: dev #local
|
||||
active: local #local
|
||||
# active: prod
|
||||
|
||||
server:
|
||||
|
@ -1,17 +1,16 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 自提门店分页 Request VO")
|
||||
|
@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.system.api.attendance;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoVO;
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -11,6 +14,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@Tag(name = "RPC 服务 - 考勤")
|
||||
@ -19,7 +23,7 @@ public interface AttendanceApi {
|
||||
String PREFIX = ApiConstants.PREFIX + "/attendance";
|
||||
|
||||
@PostMapping(PREFIX + "/askingForLeaveAfterwardsToModifyAttendance")
|
||||
@Operation(summary = "获取考勤记录")
|
||||
@Operation(summary = "事后请假修改考勤")
|
||||
CommonResult askingForLeaveAfterwardsToModifyAttendance(@RequestBody AttendancePunchRecordDTO attendancePunchRecordDTO);
|
||||
|
||||
@GetMapping(PREFIX + "getReplacementCardNum")
|
||||
@ -29,4 +33,14 @@ public interface AttendanceApi {
|
||||
@PostMapping("/replacementCard")
|
||||
@Operation(summary = "批量补卡")
|
||||
CommonResult<Boolean> replacementCard(@RequestBody List<Long> punchRecordIds);
|
||||
|
||||
|
||||
@PostMapping(PREFIX + "/getAttendanceInfoByTimeRange")
|
||||
@Operation(summary = "按时间范围获取考勤设置信息")
|
||||
CommonResult<Map<String, AttendanceTimeRangeInfoVO>> getAttendanceInfoByTimeRange(@RequestBody AttendanceTimeRangeInfoDTO attendanceTimeRangeInfoDTO);
|
||||
|
||||
|
||||
@PostMapping(PREFIX + "/getAttendancePunchRecordByTimeRange")
|
||||
@Operation(summary = "按时间范围获取打卡记录")
|
||||
CommonResult<Map<String, List<AttendancePunchRecordVO>>> getAttendancePunchRecordByTimeRange(@RequestBody AttendancePunchRecordDTO attendancePunchRecordDTO);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class AttendancePunchRecordDTO {
|
||||
*/
|
||||
private Long leaveId;
|
||||
/**
|
||||
* 请假类型
|
||||
* 请假名称
|
||||
*/
|
||||
private String leaveType;
|
||||
private String leaveName;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package cn.iocoder.yudao.module.system.api.attendance.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
/**
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Data
|
||||
public class AttendanceTimeRangeInfoDTO {
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@Schema(description = "开始时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@Schema(description = "结束时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
/**
|
||||
* 时间列表yyyy-MM-dd格式
|
||||
*/
|
||||
private List<String> times;
|
||||
|
||||
/**
|
||||
* 节假日自动排休 0否 1是
|
||||
*/
|
||||
private Integer autoHolidaysFlag;
|
||||
|
||||
/**
|
||||
* 考勤组id
|
||||
*/
|
||||
private Long groupId;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.system.api.attendance.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Data
|
||||
public class AttendanceGroupShiftItemVO {
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "957")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "班次id", example = "22909")
|
||||
private Long kqAttendanceGroupShiftId;
|
||||
|
||||
@Schema(description = "级别 从1到~ 排序用")
|
||||
private Integer level;
|
||||
|
||||
@Schema(description = "开始打卡时间")
|
||||
private String beginTime;
|
||||
|
||||
@Schema(description = "结束打卡时间")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "是否次日(开始时间 大于 结束时间)跨天 0否 1跨天 2结束时间跨天")
|
||||
private Integer nextDayFlag;
|
||||
|
||||
@Schema(description = "是否开启中间时间段休息 0否 1是")
|
||||
private Integer restFlag;
|
||||
|
||||
@Schema(description = "休息开始时间 HH:mm")
|
||||
private String restBeginTime;
|
||||
|
||||
@Schema(description = "休息结束时间 HH:mm")
|
||||
private String restEndTime;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.attendance.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@ -122,9 +123,14 @@ public class AttendancePunchRecordVO {
|
||||
private Long leaveEarlyTime;
|
||||
|
||||
/**
|
||||
* 加班时长时间戳
|
||||
* 下班加班时长时间戳
|
||||
*/
|
||||
private Long workOvertimeTime;
|
||||
private Long downWorkOvertimeTime;
|
||||
|
||||
/**
|
||||
* 上班加班时长时间戳
|
||||
*/
|
||||
private Long upWorkOvertimeTime;
|
||||
|
||||
/**
|
||||
* 是否已提醒 0否 1是
|
||||
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.api.attendance.vo;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户打卡记录 DO
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Data
|
||||
public class AttendanceTimeRangeInfoVO {
|
||||
/**
|
||||
* 是否需要考勤
|
||||
*/
|
||||
@Schema(description = "是否需要考勤 0否 1是")
|
||||
private Integer needAttendance = 0;
|
||||
|
||||
@Schema(description = "是否在考勤组内 0否 1是")
|
||||
private Integer inGroup = 1;
|
||||
/**
|
||||
* 日期类型
|
||||
*/
|
||||
@Schema(description = "日期类型 1工作日 2休息日 3节假日")
|
||||
private Integer datType = 1;
|
||||
/**
|
||||
* 当日班次信息
|
||||
*/
|
||||
@Schema(description = "班次子表信息")
|
||||
private List<AttendanceGroupShiftItemVO> items = ListUtil.empty();
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.system.api.attendance.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户打卡记录 DO
|
||||
*
|
||||
* @author 艾楷
|
||||
*/
|
||||
@Data
|
||||
public class AttendanceVO {
|
||||
@Schema(description = "是否需要考勤组id")
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "是否需要考勤 0否 1是")
|
||||
private Integer needAttendance = 0;
|
||||
|
||||
|
||||
@Schema(description = "考勤时间范围信息")
|
||||
private AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO;
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.api.holiday;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.dto.CreateUserHolidayDTO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.dto.OvertimeIncreasesHolidayDTO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.vo.HolidaySettingVO;
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@Tag(name = "RPC 服务 - 假期")
|
||||
public interface HolidayApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/holiday";
|
||||
|
||||
|
||||
@PostMapping(PREFIX + "/getHolidaySettings")
|
||||
@Operation(summary = "获取假期设置")
|
||||
CommonResult<HolidaySettingVO> getHolidaySettings(@RequestParam("userId") Long userId,
|
||||
@RequestParam("holidaySettingId") Long holidaySettingId);
|
||||
|
||||
|
||||
@PostMapping(PREFIX + "/createUserHoliday")
|
||||
@Operation(summary = "创建用户请假")
|
||||
CommonResult createUserHoliday(@RequestBody CreateUserHolidayDTO dto);
|
||||
|
||||
@PostMapping(PREFIX + "/overtimeIncreasesHoliday")
|
||||
@Operation(summary = "加班增加假期")
|
||||
CommonResult overtimeIncreasesHoliday(@RequestBody OvertimeIncreasesHolidayDTO dto);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.system.api.holiday.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class CreateUserHolidayDTO {
|
||||
|
||||
@Schema(description = "用户id", example = "18256")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "假期设置id", example = "25199")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "操作方向 0新增 1减去")
|
||||
private Integer direction;
|
||||
|
||||
@Schema(description = "假期余额(这里的单位根据假期设置的来 没有固定单位)")
|
||||
private BigDecimal holidayBalance;
|
||||
|
||||
@Schema(description = "原由")
|
||||
private String reason;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.system.api.holiday.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class OvertimeIncreasesHolidayDTO {
|
||||
|
||||
@Schema(description = "用户id", example = "18256")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "假期设置id", example = "25199")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "操作方向 0新增 1减去")
|
||||
private Integer direction;
|
||||
|
||||
@Schema(description = "假期余额(这里的单位根据假期设置的来 没有固定单位)")
|
||||
private BigDecimal holidayBalance;
|
||||
|
||||
@Schema(description = "原由")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "时长单位 1小时 2天")
|
||||
private Integer unit;
|
||||
|
||||
@Schema(description = "日折算时长 n小时 = 一天 ")
|
||||
private BigDecimal conversion;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package cn.iocoder.yudao.module.system.api.holiday.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class HolidaySettingVO {
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24863")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期规则名称", example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "应用范围 0全公司 1指定(记录在kq_holiday_setting_range 表中)", example = "赵六")
|
||||
private Integer applicationScope;
|
||||
|
||||
@Schema(description = "新员工请假类型 1入职即可请假 2转正后才可请假", example = "2")
|
||||
private Integer newEmployeeLeaveType;
|
||||
|
||||
@Schema(description = "是否带薪 0否 1是")
|
||||
private Integer salaryFlag;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "请假取整 0否 1是")
|
||||
private Integer roundFlag;
|
||||
|
||||
@Schema(description = "取整方向 0向下 1向上 (需要取整才有意义)")
|
||||
private Integer roundDirection;
|
||||
|
||||
@Schema(description = "取整单位 0按半小时 1按小时 (需要取整才有意义)")
|
||||
private Integer roundUnit;
|
||||
|
||||
@Schema(description = "请假计算方式 0按自然日计算(休息日也会记录请假) 1按工作日计算(请假时段中不包含员工的休息日)")
|
||||
private Integer calculationMethod;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "当前用户该假期余额余额")
|
||||
private BigDecimal holidayBalance;
|
||||
|
||||
@Schema(description = "假期设置状态 0关闭 1开启")
|
||||
private Integer status;
|
||||
}
|
@ -82,14 +82,14 @@ public interface AdminUserApi {
|
||||
@Parameter(name = "userId", description = "用户id", example = "1024", required = true)
|
||||
@Parameter(name = "fieldworkFlag", description = "是否可外勤打卡 | 0否 1是", example = "1", required = true)
|
||||
void updateFieldworkType(@RequestParam("userId") Long userId,
|
||||
@RequestParam("fieldworkFlag") Integer fieldworkFlag);
|
||||
@RequestParam("fieldworkFlag") Integer fieldworkFlag);
|
||||
|
||||
@PostMapping(PREFIX + "/updateUserStaffing")
|
||||
@Operation(summary = "修改用户信息")
|
||||
@Parameter(name = "userId", description = "用户id", example = "1024", required = true)
|
||||
@Parameter(name = "userStaffing", description = "用户编制", example = "1", required = true)
|
||||
void updateUserStaffing(@RequestParam("userId") Long userId,
|
||||
@RequestParam("userStaffing") Integer userStaffing);
|
||||
@RequestParam("userStaffing") Integer userStaffing);
|
||||
|
||||
@GetMapping(PREFIX + "/getUserIdsByUserNature")
|
||||
@Operation(summary = "获取所有用户性质为外勤的用户")
|
||||
@ -101,4 +101,7 @@ public interface AdminUserApi {
|
||||
@Parameter(name = "factoryId", description = "工厂id", example = "1024", required = false)
|
||||
CommonResult<List<AdminUserRpcVO>> getFactoryUsers(@RequestParam(name = "factoryId", required = false) Long factoryId);
|
||||
|
||||
@PostMapping(PREFIX + "/updateUserEntryDate")
|
||||
@Operation(summary = "更新用户入职信息")
|
||||
CommonResult updateUserEntryDate(@RequestBody UserSaveRespDTO userSaveRespDTO);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
@ -51,6 +52,10 @@ public class UserSaveRespDTO {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate birthdayDay;
|
||||
|
||||
@Schema(description = "入职日期", example = "03-23")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDateTime entryDate;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoVO;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@Tag(name = "RPC 服务 - 加班")
|
||||
public interface WorkOvertimeApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/workOvertimeApi";
|
||||
|
||||
|
||||
@GetMapping(PREFIX + "/getOvertimeRulesByUserId")
|
||||
@Operation(summary = "获取加班规则")
|
||||
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||
CommonResult<WorkOvertimeRuleApiVO> getOvertimeRulesByUserId(@RequestParam("userId") Long userId);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class WorkOvertimeDeductRuleApiVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "26316")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "加班规则id", example = "7404")
|
||||
private Long ruleId;
|
||||
|
||||
@Schema(description = "加班规则子表id", example = "7404")
|
||||
private Long ruleItemId;
|
||||
|
||||
@Schema(description = "每天加班满n小时 临界值")
|
||||
private Integer threshold;
|
||||
|
||||
@Schema(description = "扣除的数量")
|
||||
private Integer deductNum;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class WorkOvertimeMoreRuleApiVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "13083")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "加班规则id", example = "20044")
|
||||
private Long ruleId;
|
||||
|
||||
@Schema(description = "加班时长单位 1小时 2天")
|
||||
private Integer unit;
|
||||
|
||||
@Schema(description = "是否需要取整 0不取整 1向下取整", example = "2")
|
||||
private Integer roundingType;
|
||||
|
||||
@Schema(description = "取整递增值")
|
||||
private BigDecimal roundingIncrementalValue;
|
||||
|
||||
@Schema(description = "日折算时长 n小时 = 一天 ")
|
||||
private BigDecimal conversion;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更多规则拓展列表")
|
||||
private List<WorkOvertimeMoreRuleExtApiVO> moreRuleExtList;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class WorkOvertimeMoreRuleExtApiVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "9017")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "加班更多规则id", example = "8676")
|
||||
private Long moreRuleId;
|
||||
|
||||
@Schema(description = "类型 1风险预警 2最大加班时间", example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "日期类型 1每天 2每周 3每月", example = "1")
|
||||
private Integer dayType;
|
||||
|
||||
@Schema(description = "小时阀值累计超过n小时")
|
||||
private Integer threshold;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class WorkOvertimeRuleApiVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32262")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "规则名称", example = "张三")
|
||||
private String ruleName;
|
||||
|
||||
@Schema(description = "引用范围考勤组ids")
|
||||
private String attendanceGroupIds;
|
||||
|
||||
@Schema(description = "负责人", example = "3784")
|
||||
private Long leaderUserId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "加班规则子表")
|
||||
private List<WorkOvertimeRuleItemApiVO> workOvertimeRuleItems;
|
||||
|
||||
@Schema(description = "更多规则")
|
||||
private WorkOvertimeMoreRuleApiVO moreRule;
|
||||
|
||||
@Schema(description = "是否在考勤组内 0否 1是")
|
||||
private Integer isGroup = 1;
|
||||
|
||||
@Schema(description = "是否有加班规则 0否 1是")
|
||||
private Integer isOvertime = 1;
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class WorkOvertimeRuleItemApiVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "6361")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "加班规则id", example = "30012")
|
||||
private Long ruleId;
|
||||
|
||||
@Schema(description = "类型 1工作日 2休息日 3节假日", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "状态 0不允许加班 1允许加班", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "可加班时间类型(只有类型为工作日有意义) 1允许班前和班后加班 2仅允许班前加班 3仅允许班后加班", example = "1")
|
||||
private Integer allowOvertimeTimeType;
|
||||
|
||||
@Schema(description = "计算方式 1按审批时长计算 2在审批的时段内,按打卡时长计算 3无需审批,按打卡时长计算")
|
||||
private Integer calculationMode;
|
||||
|
||||
@Schema(description = "加班起算时间 下班n分钟后开始算加班")
|
||||
private Integer overtimeStartingTime;
|
||||
|
||||
@Schema(description = "班前加班少于多少分钟,不计入加班")
|
||||
private Integer beforeWorkOvertime;
|
||||
|
||||
@Schema(description = "班后加班少于多少分钟,不计入加班")
|
||||
private Integer afterWorkOvertime;
|
||||
|
||||
@Schema(description = "累计加班少于多少分钟,不计入加班")
|
||||
private Integer overtimeTotalHours;
|
||||
|
||||
@Schema(description = "是否扣除休息时间 0否 1是")
|
||||
private Integer isDeductBreakTime;
|
||||
|
||||
@Schema(description = "加班时长计为调休或加班费 0否 1是")
|
||||
private Integer isTransformation;
|
||||
|
||||
@Schema(description = "转换类型 1计为调休 2计为加班费", example = "1")
|
||||
private Integer transformationType;
|
||||
|
||||
@Schema(description = "调休转换比例")
|
||||
private BigDecimal compensatoryLeaveRatio;
|
||||
|
||||
@Schema(description = "假期id", example = "24104")
|
||||
private Long holidayId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "扣除规则列表")
|
||||
private List<WorkOvertimeDeductRuleApiVO> deductRules;
|
||||
}
|
@ -206,7 +206,7 @@
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -1,14 +1,25 @@
|
||||
package cn.iocoder.yudao.module.system.api.attendance;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO;
|
||||
import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.punchrecord.AttendancePunchRecordDO;
|
||||
import cn.iocoder.yudao.module.system.service.attendance.AttendanceService;
|
||||
import cn.iocoder.yudao.module.system.service.attendance.AttendanceService;
|
||||
import cn.iocoder.yudao.module.system.service.attendance.punchrecord.AttendancePunchRecordService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@ -21,7 +32,8 @@ public class AttendanceApiImpl implements AttendanceApi {
|
||||
|
||||
@Resource
|
||||
private AttendancePunchRecordService attendancePunchRecordService;
|
||||
|
||||
@Resource
|
||||
private AttendanceService attendanceService;
|
||||
|
||||
@Override
|
||||
public CommonResult askingForLeaveAfterwardsToModifyAttendance(AttendancePunchRecordDTO attendancePunchRecordDTO) {
|
||||
@ -39,4 +51,21 @@ public class AttendanceApiImpl implements AttendanceApi {
|
||||
attendanceService.replacementCardBatch(punchRecordIds);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CommonResult<Map<String, AttendanceTimeRangeInfoVO>> getAttendanceInfoByTimeRange(AttendanceTimeRangeInfoDTO attendanceTimeRangeInfoDTO) {
|
||||
return CommonResult.success(attendanceService.getAttendanceInfoByTimeRange(attendanceTimeRangeInfoDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Map<String, List<AttendancePunchRecordVO>>> getAttendancePunchRecordByTimeRange(AttendancePunchRecordDTO dto) {
|
||||
List<String> dateList = DateUtils.betweenDayList(dto.getStartTime(), dto.getEndTime());
|
||||
List<AttendancePunchRecordDO> list = attendancePunchRecordService.list(new LambdaQueryWrapper<AttendancePunchRecordDO>()
|
||||
.eq(AttendancePunchRecordDO::getUserId, dto.getUserId())
|
||||
.in(AttendancePunchRecordDO::getDayTime, dateList));
|
||||
List<AttendancePunchRecordVO> vos = BeanUtil.copyToList(list, AttendancePunchRecordVO.class);
|
||||
Map<String, List<AttendancePunchRecordVO>> map = vos.stream().collect(Collectors.groupingBy(AttendancePunchRecordVO::getDayTime));
|
||||
return CommonResult.success(map);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.system.api.holiday;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.dto.CreateUserHolidayDTO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.dto.OvertimeIncreasesHolidayDTO;
|
||||
import cn.iocoder.yudao.module.system.api.holiday.vo.HolidaySettingVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysetting.HolidaySettingDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidayuser.HolidayUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.holiday.holidayuser.HolidayUserMapper;
|
||||
import cn.iocoder.yudao.module.system.service.holiday.holidaysetting.HolidaySettingService;
|
||||
import cn.iocoder.yudao.module.system.service.holiday.holidayuserrecord.HolidayUserRecordService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
public class HolidayApiImpl implements HolidayApi {
|
||||
|
||||
@Resource
|
||||
private HolidaySettingService holidaySettingService;
|
||||
@Resource
|
||||
private HolidayUserMapper holidayUserMapper;
|
||||
@Resource
|
||||
private HolidayUserRecordService holidayUserRecordService;
|
||||
|
||||
|
||||
@Override
|
||||
public CommonResult<HolidaySettingVO> getHolidaySettings(Long userId, Long holidaySettingId) {
|
||||
HolidaySettingVO vo = new HolidaySettingVO();
|
||||
HolidaySettingDO holidaySetting = holidaySettingService.getHolidaySetting(holidaySettingId);
|
||||
HolidayUserDO holidayUserDO = holidayUserMapper.selectOne(new LambdaQueryWrapper<HolidayUserDO>().eq(HolidayUserDO::getHolidaySettingId, holidaySettingId).eq(HolidayUserDO::getUserId, userId));
|
||||
BeanUtil.copyProperties(holidaySetting, vo);
|
||||
vo.setHolidayBalance(holidayUserDO == null ? null : holidayUserDO.getHolidayBalance());
|
||||
vo.setStatus(holidaySetting.getHolidayBalanceSettingDO().getStatus());
|
||||
return CommonResult.success(vo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult createUserHoliday(CreateUserHolidayDTO dto) {
|
||||
holidayUserRecordService.createUserHoliday(dto);
|
||||
return CommonResult.success("ok");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult overtimeIncreasesHoliday(OvertimeIncreasesHolidayDTO dto) {
|
||||
holidayUserRecordService.overtimeIncreasesHoliday(dto);
|
||||
return CommonResult.success("ok");
|
||||
}
|
||||
|
||||
}
|
@ -115,4 +115,10 @@ public class AdminUserApiImpl implements AdminUserApi {
|
||||
return success(BeanUtils.toBean(factoryUsers, AdminUserRpcVO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult updateUserEntryDate(UserSaveRespDTO dto) {
|
||||
userService.updateUserEntryDate(dto.getId(), dto.getEntryDate());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.system.api.workovertime;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.Constants;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.api.workovertime.vo.WorkOvertimeRuleApiVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.workovertime.WorkOvertimeRuleDO;
|
||||
import cn.iocoder.yudao.module.system.service.attendance.group.AttendanceGroupService;
|
||||
import cn.iocoder.yudao.module.system.service.workovertime.WorkOvertimeRuleAttendanceGroupService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@Validated
|
||||
public class WorkOvertimeApiImpl implements WorkOvertimeApi {
|
||||
|
||||
@Resource
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
@Resource
|
||||
private WorkOvertimeRuleAttendanceGroupService workOvertimeRuleAttendanceGroupService;
|
||||
|
||||
@Override
|
||||
public CommonResult<WorkOvertimeRuleApiVO> getOvertimeRulesByUserId(Long userId) {
|
||||
WorkOvertimeRuleApiVO vo = new WorkOvertimeRuleApiVO();
|
||||
//先获取当前用户所在考勤组 - 再根据考勤组 查询对应的加班规则
|
||||
AttendanceGroupDO attendanceGroupDO = attendanceGroupService.getByUserId(userId);
|
||||
if (attendanceGroupDO == null) {
|
||||
return CommonResult.success(vo.setIsGroup(Constants.ZERO));
|
||||
}
|
||||
WorkOvertimeRuleDO workOvertimeRuleDO = workOvertimeRuleAttendanceGroupService.getRuleByAttendanceGroupId(attendanceGroupDO.getId());
|
||||
if (workOvertimeRuleDO == null) {
|
||||
return CommonResult.success(vo.setIsOvertime(Constants.ZERO));
|
||||
}
|
||||
BeanUtil.copyProperties(workOvertimeRuleDO, vo);
|
||||
return CommonResult.success(vo);
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ -28,6 +29,8 @@ public class AttendancePunchPageVO {
|
||||
private Integer punchType = 4;
|
||||
@Schema(description = "当天考勤列表")
|
||||
private List<AttendanceOnTheDayDTO> attendanceOnTheDayDTOS;
|
||||
@Schema(description = "是否加班 0否 1是")
|
||||
private Integer workOvertimeFlag = 0;
|
||||
|
||||
/**
|
||||
* redisKey
|
||||
@ -71,4 +74,16 @@ public class AttendancePunchPageVO {
|
||||
* 当前用户
|
||||
*/
|
||||
private AdminUserDO user;
|
||||
|
||||
/**
|
||||
* 处理加班打卡 不计算是否迟到早退
|
||||
* @param punchType
|
||||
*/
|
||||
public void setPunchType(Integer punchType) {
|
||||
if (this.getFieldworkFlag() == 0) {
|
||||
this.punchType = punchType;
|
||||
} else {
|
||||
this.punchType = Arrays.asList(0, 2).contains(punchType) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,13 @@ public class AttendanceGroupController {
|
||||
return success(BeanUtils.toBean(pageResult, AttendanceGroupRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/getAllFilterWorkOvertimeRule")
|
||||
@Operation(summary = "获得所有考勤组过滤已绑定过加班规则的")
|
||||
public CommonResult<List<AttendanceGroupRespVO>> getAllFilterWorkOvertimeRule(@RequestParam(required = false) Long workOvertimeRuleId) {
|
||||
List<AttendanceGroupDO> pageResult = groupService.getAllFilterWorkOvertimeRule(workOvertimeRuleId);
|
||||
return success(BeanUtils.toBean(pageResult, AttendanceGroupRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出考勤组 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('attendance:group:export')")
|
||||
|
@ -25,6 +25,9 @@ public class AttendanceGroupPageReqVO extends PageParam {
|
||||
@Schema(description = "群组名称", example = "李四")
|
||||
private String groupName;
|
||||
|
||||
@Schema(description = "考勤人员名称", example = "李四")
|
||||
private String userNickname;
|
||||
|
||||
@Schema(description = "考勤类型 1固定班制 2排班制", example = "1")
|
||||
private Integer type;
|
||||
|
||||
|
@ -33,6 +33,18 @@ public class AttendanceGroupShiftItemRespVO {
|
||||
@ExcelProperty("结束打卡时间")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "是否开启中间时间段休息 0否 1是")
|
||||
@ExcelProperty("是否开启中间时间段休息 0否 1是")
|
||||
private Integer restFlag;
|
||||
|
||||
@Schema(description = "休息开始时间 HH:mm")
|
||||
@ExcelProperty("休息开始时间 HH:mm")
|
||||
private String restBeginTime;
|
||||
|
||||
@Schema(description = "休息结束时间 HH:mm")
|
||||
@ExcelProperty("休息结束时间 HH:mm")
|
||||
private String restEndTime;
|
||||
|
||||
@Schema(description = "是否必须 0否 1是 (如果不是必须系统会自动打卡)")
|
||||
@ExcelProperty("是否必须 0否 1是 (如果不是必须系统会自动打卡)")
|
||||
private Integer mustFlag;
|
||||
@ -61,4 +73,4 @@ public class AttendanceGroupShiftItemRespVO {
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,18 @@ public class AttendanceGroupShiftItemSaveReqVO {
|
||||
@Schema(description = "结束打卡时间")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "是否开启中间时间段休息 0否 1是")
|
||||
@ExcelProperty("是否开启中间时间段休息 0否 1是")
|
||||
private Integer restFlag;
|
||||
|
||||
@Schema(description = "休息开始时间 HH:mm")
|
||||
@ExcelProperty("休息开始时间 HH:mm")
|
||||
private String restBeginTime;
|
||||
|
||||
@Schema(description = "休息结束时间 HH:mm")
|
||||
@ExcelProperty("休息结束时间 HH:mm")
|
||||
private String restEndTime;
|
||||
|
||||
@Schema(description = "是否必须 0否 1是 (如果不是必须系统会自动打卡)")
|
||||
private Integer mustFlag;
|
||||
|
||||
@ -44,4 +56,4 @@ public class AttendanceGroupShiftItemSaveReqVO {
|
||||
@Schema(description = "下班后打卡时间(分钟) 默认 120分钟")
|
||||
private Integer afterPunchTimeDownWork;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo.HolidayBalanceSettingPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo.HolidayBalanceSettingRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo.HolidayBalanceSettingSaveReqVO;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaybalancesetting.HolidayBalanceSettingDO;
|
||||
import cn.iocoder.yudao.module.system.service.holiday.holidaybalancesetting.HolidayBalanceSettingService;
|
||||
|
||||
@Tag(name = "管理后台 - 假期余额设置")
|
||||
@RestController
|
||||
@RequestMapping("/system/holiday-balance-setting")
|
||||
@Validated
|
||||
public class HolidayBalanceSettingController {
|
||||
|
||||
@Resource
|
||||
private HolidayBalanceSettingService holidayBalanceSettingService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建假期余额设置")
|
||||
public CommonResult<Long> createHolidayBalanceSetting(@Valid @RequestBody HolidayBalanceSettingSaveReqVO createReqVO) {
|
||||
return success(holidayBalanceSettingService.createHolidayBalanceSetting(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新假期余额设置")
|
||||
public CommonResult<Boolean> updateHolidayBalanceSetting(@Valid @RequestBody HolidayBalanceSettingSaveReqVO updateReqVO) {
|
||||
holidayBalanceSettingService.updateHolidayBalanceSetting(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除假期余额设置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
public CommonResult<Boolean> deleteHolidayBalanceSetting(@RequestParam("id") Long id) {
|
||||
holidayBalanceSettingService.deleteHolidayBalanceSetting(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得假期余额设置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<HolidayBalanceSettingRespVO> getHolidayBalanceSetting(@RequestParam("id") Long id) {
|
||||
HolidayBalanceSettingDO holidayBalanceSetting = holidayBalanceSettingService.getHolidayBalanceSetting(id);
|
||||
return success(BeanUtils.toBean(holidayBalanceSetting, HolidayBalanceSettingRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得假期余额设置分页")
|
||||
public CommonResult<PageResult<HolidayBalanceSettingRespVO>> getHolidayBalanceSettingPage(@Valid HolidayBalanceSettingPageReqVO pageReqVO) {
|
||||
PageResult<HolidayBalanceSettingDO> pageResult = holidayBalanceSettingService.getHolidayBalanceSettingPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, HolidayBalanceSettingRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出假期余额设置 Excel")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportHolidayBalanceSettingExcel(@Valid HolidayBalanceSettingPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<HolidayBalanceSettingDO> list = holidayBalanceSettingService.getHolidayBalanceSettingPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "假期余额设置.xls", "数据", HolidayBalanceSettingRespVO.class,
|
||||
BeanUtils.toBean(list, HolidayBalanceSettingRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 假期余额设置分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class HolidayBalanceSettingPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "假期设置id", example = "31488")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "状态 0关闭 1开启", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发放方式 1每月自动发放 2每年自动发放 3手动发放 4加班时长自动计入余额", example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "发放日期 当发放方式为每月自动发放时 该值代表的是几号 当发放方式为每年自动发放时 该值代表 1每年员工入职日 2每年1月1日", example = "1")
|
||||
private Integer issueTimeType;
|
||||
|
||||
@Schema(description = "发放日期(设置好后 插入发放日期 - 发放完成后插入下一次发放日期) 如果是 null 的话代表手动发放和加班自动计算或者每年员工入职日")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] issueTime;
|
||||
|
||||
@Schema(description = "额度规则 1固定规则 2按工龄 (0代表自动发放或者加班自动计算)")
|
||||
private Integer quotaRule;
|
||||
|
||||
@Schema(description = "固定额度 (单位天)")
|
||||
private Integer quota;
|
||||
|
||||
@Schema(description = "是否按实际工作时长发放 0否 1是(例如:每年1月1日发放6天假期,入职时间是6月1日的员工则按照半年发放3天假期,当余额出现小数时按四舍五入取整)")
|
||||
private Integer actualWorkFlag;
|
||||
|
||||
@Schema(description = "有效期类型 1自发放日起1个月 2自发放日起1周年 3按入职日期起12个月 4自然年1月1日-12月31日 5每年固定时间作废 6永久有效 7每月固定时间作废 8每季末作废")
|
||||
private Integer validityPeriod;
|
||||
|
||||
@Schema(description = "每年固定时间作废格式 MM-dd 例如 09-10 每年9月10号作废", example = "12794")
|
||||
private String fixedEveryYearInvalid;
|
||||
|
||||
@Schema(description = "每月固定时间作废 格式 1 or 4 or 7 or 10")
|
||||
private Integer fixedEveryMonthInvalid;
|
||||
|
||||
@Schema(description = "是否允许延长有效期 0否 1是")
|
||||
private Integer extensionAllowedFlag;
|
||||
|
||||
@Schema(description = "有效期过后延长时间(天)")
|
||||
private Integer extendNum;
|
||||
|
||||
@Schema(description = "是否开启假期提醒 0否 1是")
|
||||
private Integer expirationReminderFlag;
|
||||
|
||||
@Schema(description = "提醒时间(天) 假期过期前多少天提醒")
|
||||
private Integer reminderTimeNum;
|
||||
|
||||
@Schema(description = "提醒范围 1员工 2部门主管 3全部通知")
|
||||
private Integer reminderRange;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayworkingage.vo.HolidayWorkingAgeRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayworkingage.vo.HolidayWorkingAgeSaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 假期余额设置 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class HolidayBalanceSettingRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29911")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期设置id", example = "31488")
|
||||
@ExcelProperty("假期设置id")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "状态 0关闭 1开启", example = "1")
|
||||
@ExcelProperty("状态 0关闭 1开启")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发放方式 1每月自动发放 2每年自动发放 3手动发放 4加班时长自动计入余额", example = "2")
|
||||
@ExcelProperty("发放方式 1每月自动发放 2每年自动发放 3手动发放 4加班时长自动计入余额")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "发放日期 当发放方式为每月自动发放时 该值代表的是几号 当发放方式为每年自动发放时 该值代表 1每年员工入职日 2每年1月1日", example = "1")
|
||||
@ExcelProperty("发放日期 当发放方式为每月自动发放时 该值代表的是几号 当发放方式为每年自动发放时 该值代表 1每年员工入职日 2每年1月1日")
|
||||
private Integer issueTimeType;
|
||||
|
||||
@Schema(description = "发放日期(设置好后 插入发放日期 - 发放完成后插入下一次发放日期) 如果是 null 的话代表手动发放和加班自动计算或者每年员工入职日")
|
||||
@ExcelProperty("发放日期(设置好后 插入发放日期 - 发放完成后插入下一次发放日期) 如果是 null 的话代表手动发放和加班自动计算或者每年员工入职日")
|
||||
private LocalDateTime issueTime;
|
||||
|
||||
@Schema(description = "额度规则 1固定规则 2按工龄 (0代表自动发放或者加班自动计算)")
|
||||
@ExcelProperty("额度规则 1固定规则 2按工龄 (0代表自动发放或者加班自动计算)")
|
||||
private Integer quotaRule;
|
||||
|
||||
@Schema(description = "固定额度 (单位天)")
|
||||
@ExcelProperty("固定额度 (单位天)")
|
||||
private Integer quota;
|
||||
|
||||
@Schema(description = "是否按实际工作时长发放 0否 1是(例如:每年1月1日发放6天假期,入职时间是6月1日的员工则按照半年发放3天假期,当余额出现小数时按四舍五入取整)")
|
||||
@ExcelProperty("是否按实际工作时长发放 0否 1是(例如:每年1月1日发放6天假期,入职时间是6月1日的员工则按照半年发放3天假期,当余额出现小数时按四舍五入取整)")
|
||||
private Integer actualWorkFlag;
|
||||
|
||||
@Schema(description = "有效期类型 1自发放日起1个月 2自发放日起1周年 3按入职日期起12个月 4自然年1月1日-12月31日 5每年固定时间作废 6永久有效 7每月固定时间作废 8每季末作废")
|
||||
@ExcelProperty("有效期类型 1自发放日起1个月 2自发放日起1周年 3按入职日期起12个月 4自然年1月1日-12月31日 5每年固定时间作废 6永久有效 7每月固定时间作废 8每季末作废")
|
||||
private Integer validityPeriod;
|
||||
|
||||
@Schema(description = "每年固定时间作废格式 MM-dd 例如 09-10 每年9月10号作废", example = "12794")
|
||||
@ExcelProperty("每年固定时间作废格式 MM-dd 例如 09-10 每年9月10号作废")
|
||||
private String fixedEveryYearInvalid;
|
||||
|
||||
@Schema(description = "每月固定时间作废 格式 1 or 4 or 7 or 10")
|
||||
@ExcelProperty("每月固定时间作废 格式 1 or 4 or 7 or 10")
|
||||
private Integer fixedEveryMonthInvalid;
|
||||
|
||||
@Schema(description = "是否允许延长有效期 0否 1是")
|
||||
@ExcelProperty("是否允许延长有效期 0否 1是")
|
||||
private Integer extensionAllowedFlag;
|
||||
|
||||
@Schema(description = "有效期过后延长时间(天)")
|
||||
@ExcelProperty("有效期过后延长时间(天)")
|
||||
private Integer extendNum;
|
||||
|
||||
@Schema(description = "是否开启假期提醒 0否 1是")
|
||||
@ExcelProperty("是否开启假期提醒 0否 1是")
|
||||
private Integer expirationReminderFlag;
|
||||
|
||||
@Schema(description = "提醒时间(天) 假期过期前多少天提醒")
|
||||
@ExcelProperty("提醒时间(天) 假期过期前多少天提醒")
|
||||
private Integer reminderTimeNum;
|
||||
|
||||
@Schema(description = "提醒范围 1员工 2部门主管 3全部通知")
|
||||
@ExcelProperty("提醒范围 1员工 2部门主管 3全部通知")
|
||||
private Integer reminderRange;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "假期额度工龄配置 (如果有的话就传)")
|
||||
private List<HolidayWorkingAgeRespVO> holidayWorkingAgeRespVOS;
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayworkingage.vo.HolidayWorkingAgeSaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 假期余额设置新增/修改 Request VO")
|
||||
@Data
|
||||
public class HolidayBalanceSettingSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", example = "29911")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期设置id", example = "31488")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "状态 0关闭 1开启", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发放方式 1每月自动发放 2每年自动发放 3手动发放 4加班时长自动计入余额", example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "发放日期 当发放方式为每月自动发放时 该值代表的是几号 当发放方式为每年自动发放时 该值代表 1每年员工入职日 2每年1月1日", example = "1")
|
||||
private Integer issueTimeType;
|
||||
|
||||
@Schema(description = "发放日期(设置好后 插入发放日期 - 发放完成后插入下一次发放日期) 如果是 null 的话代表手动发放和加班自动计算或者每年员工入职日")
|
||||
private LocalDateTime issueTime;
|
||||
|
||||
@Schema(description = "额度规则 1固定规则 2按工龄 (0代表自动发放或者加班自动计算)")
|
||||
private Integer quotaRule;
|
||||
|
||||
@Schema(description = "固定额度 (单位天)")
|
||||
private Integer quota;
|
||||
|
||||
@Schema(description = "是否按实际工作时长发放 0否 1是(例如:每年1月1日发放6天假期,入职时间是6月1日的员工则按照半年发放3天假期,当余额出现小数时按四舍五入取整)")
|
||||
private Integer actualWorkFlag;
|
||||
|
||||
@Schema(description = "有效期类型 1自发放日起1个月 2自发放日起1周年 3按入职日期起12个月 4自然年1月1日-12月31日 5每年固定时间作废 6永久有效 7每月固定时间作废 8每季末作废")
|
||||
private Integer validityPeriod;
|
||||
|
||||
@Schema(description = "每年固定时间作废格式 MM-dd 例如 09-10 每年9月10号作废", example = "12794")
|
||||
private String fixedEveryYearInvalid;
|
||||
|
||||
@Schema(description = "每月固定时间作废 格式 1 or 4 or 7 or 10")
|
||||
private Integer fixedEveryMonthInvalid;
|
||||
|
||||
@Schema(description = "是否允许延长有效期 0否 1是")
|
||||
private Integer extensionAllowedFlag;
|
||||
|
||||
@Schema(description = "有效期过后延长时间(天)")
|
||||
private Integer extendNum;
|
||||
|
||||
@Schema(description = "是否开启假期提醒 0否 1是")
|
||||
private Integer expirationReminderFlag;
|
||||
|
||||
@Schema(description = "提醒时间(天) 假期过期前多少天提醒")
|
||||
private Integer reminderTimeNum;
|
||||
|
||||
@Schema(description = "提醒范围 1员工 2部门主管 3全部通知")
|
||||
private Integer reminderRange;
|
||||
|
||||
@Schema(description = "假期额度工龄配置 (如果有的话就传)")
|
||||
private List<HolidayWorkingAgeSaveReqVO> holidayWorkingAgeSaveReqVOS;
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
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.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.HolidaySettingPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.HolidaySettingRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.HolidaySettingSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysetting.HolidaySettingDO;
|
||||
import cn.iocoder.yudao.module.system.service.holiday.holidaysetting.HolidaySettingService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 假期设置")
|
||||
@RestController
|
||||
@RequestMapping("/system/holiday-setting")
|
||||
@Validated
|
||||
public class HolidaySettingController {
|
||||
|
||||
@Resource
|
||||
private HolidaySettingService holidaySettingService;
|
||||
|
||||
@PostMapping("/createOrEdit")
|
||||
@Operation(summary = "创建修改假期设置")
|
||||
public CommonResult<Long> createOrEdit(@Valid @RequestBody HolidaySettingSaveReqVO createReqVO) {
|
||||
return success(holidaySettingService.createOrEdit(createReqVO));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除假期设置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
public CommonResult<Boolean> deleteHolidaySetting(@RequestParam("id") Long id) {
|
||||
holidaySettingService.deleteHolidaySetting(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得假期设置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<HolidaySettingRespVO> getHolidaySetting(@RequestParam("id") Long id) {
|
||||
HolidaySettingRespVO vo = holidaySettingService.getHolidaySettingRespVO(id);
|
||||
return success(vo);
|
||||
}
|
||||
|
||||
@GetMapping("/getLimitBalanceHolidayList")
|
||||
@Operation(summary = "获取限制余额的假期列表")
|
||||
public CommonResult<List<HolidaySettingDO>> getLimitBalanceHolidayList() {
|
||||
List<HolidaySettingDO> vos = holidaySettingService.getLimitBalanceHolidayList();
|
||||
return success(vos);
|
||||
}
|
||||
|
||||
@GetMapping("/getAllHolidaySetting")
|
||||
@Operation(summary = "获取所有假期设置")
|
||||
public CommonResult<List<HolidaySettingRespVO>> getAllHolidaySetting(@RequestParam Long userId) {
|
||||
List<HolidaySettingRespVO> vos = holidaySettingService.getAllHolidaySetting(userId);
|
||||
return success(vos);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得假期设置分页")
|
||||
public CommonResult<PageResult<HolidaySettingRespVO>> getHolidaySettingPage(@Valid HolidaySettingPageReqVO pageReqVO) {
|
||||
PageResult<HolidaySettingDO> pageResult = holidaySettingService.getHolidaySettingPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, HolidaySettingRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出假期设置 Excel")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportHolidaySettingExcel(@Valid HolidaySettingPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<HolidaySettingDO> list = holidaySettingService.getHolidaySettingPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "假期设置.xls", "数据", HolidaySettingRespVO.class,
|
||||
BeanUtils.toBean(list, HolidaySettingRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.dto;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.DetermineHolidayBalanceSettingSwitchVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.PersonnelChangesVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaybalancesetting.HolidayBalanceSettingDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysetting.HolidaySettingDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysettingrange.HolidaySettingRangeDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidayworkingage.HolidayWorkingAgeDO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class RecalculateAssignedDTO {
|
||||
@Schema(description = "假期设置")
|
||||
private HolidaySettingDO holidaySetting;
|
||||
@Schema(description = "假期余额设置")
|
||||
private HolidayBalanceSettingDO holidayBalanceSetting;
|
||||
@Schema(description = "假期额度工龄配置")
|
||||
private List<HolidayWorkingAgeDO> holidayWorkingAges;
|
||||
@Schema(description = "人员范围")
|
||||
private PersonnelChangesVO personnelChangesVO;
|
||||
@Schema(description = "变动")
|
||||
private DetermineHolidayBalanceSettingSwitchVO determineHolidayBalanceSettingSwitchVO;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class DetermineHolidayBalanceSettingSwitchVO {
|
||||
|
||||
@Schema(description = "开关是否变动 true 是 false 否")
|
||||
private boolean changeFlag;
|
||||
|
||||
@Schema(description = "开关是否开启 true 是 false 否")
|
||||
private boolean switchFlag;
|
||||
|
||||
@Schema(description = "发放方式调整 true 是 false 否")
|
||||
private boolean adjustTypeFlag;
|
||||
|
||||
@Schema(description = "发放日期调整 true 是 false 否")
|
||||
private boolean dateAdjustFlag;
|
||||
|
||||
@Schema(description = "额度规则调整 true 是 false 否")
|
||||
private boolean quotaRuleFlag;
|
||||
|
||||
@Schema(description = "额度调整 true 是 false 否")
|
||||
private boolean quotaFlag;
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class HolidaySettingEditVO {
|
||||
@Schema(description = "是否可以直接通过 0否 1是", example = "赵六")
|
||||
private Integer passFlag = 1;
|
||||
|
||||
@Schema(description = "提示", example = "赵六")
|
||||
private String msg;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 假期设置分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class HolidaySettingPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "假期规则名称", example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "应用范围 0全公司 1指定(记录在kq_holiday_setting_range 表中)", example = "赵六")
|
||||
private Integer applicationScope;
|
||||
|
||||
@Schema(description = "新员工请假类型 1入职即可请假 2转正后才可请假", example = "2")
|
||||
private Integer newEmployeeLeaveType;
|
||||
|
||||
@Schema(description = "是否带薪 0否 1是")
|
||||
private Integer salaryFlag;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "请假取整 0否 1是")
|
||||
private Integer roundFlag;
|
||||
|
||||
@Schema(description = "取整方向 0向下 1向上 (需要取整才有意义)")
|
||||
private Integer roundDirection;
|
||||
|
||||
@Schema(description = "取整单位 0按半小时 1按小时 (需要取整才有意义)")
|
||||
private Integer roundUnit;
|
||||
|
||||
@Schema(description = "请假计算方式 0按自然日计算(休息日也会记录请假) 1按工作日计算(请假时段中不包含员工的休息日)")
|
||||
private Integer calculationMethod;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo.HolidayBalanceSettingRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangeRespVO;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 假期设置 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class HolidaySettingRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24863")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期规则名称", example = "赵六")
|
||||
@ExcelProperty("假期规则名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "应用范围 0全公司 1指定(记录在kq_holiday_setting_range 表中)", example = "赵六")
|
||||
@ExcelProperty("应用范围 0全公司 1指定(记录在kq_holiday_setting_range 表中)")
|
||||
private Integer applicationScope;
|
||||
|
||||
@Schema(description = "新员工请假类型 1入职即可请假 2转正后才可请假", example = "2")
|
||||
@ExcelProperty("新员工请假类型 1入职即可请假 2转正后才可请假")
|
||||
private Integer newEmployeeLeaveType;
|
||||
|
||||
@Schema(description = "是否带薪 0否 1是")
|
||||
@ExcelProperty("是否带薪 0否 1是")
|
||||
private Integer salaryFlag;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时")
|
||||
@ExcelProperty("请假最小单位 1按天 2按半天 3按小时")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "请假取整 0否 1是")
|
||||
@ExcelProperty("请假取整 0否 1是")
|
||||
private Integer roundFlag;
|
||||
|
||||
@Schema(description = "取整方向 0向下 1向上 (需要取整才有意义)")
|
||||
@ExcelProperty("取整方向 0向下 1向上 (需要取整才有意义)")
|
||||
private Integer roundDirection;
|
||||
|
||||
@Schema(description = "取整单位 0按半小时 1按小时 (需要取整才有意义)")
|
||||
@ExcelProperty("取整单位 0按半小时 1按小时 (需要取整才有意义)")
|
||||
private Integer roundUnit;
|
||||
|
||||
@Schema(description = "请假计算方式 0按自然日计算(休息日也会记录请假) 1按工作日计算(请假时段中不包含员工的休息日)")
|
||||
@ExcelProperty("请假计算方式 0按自然日计算(休息日也会记录请假) 1按工作日计算(请假时段中不包含员工的休息日)")
|
||||
private Integer calculationMethod;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "假期规则人员范围")
|
||||
private List<HolidaySettingRangeRespVO> holidaySettingRangeRespVOS;
|
||||
|
||||
@Schema(description = "假期余额设置")
|
||||
private HolidayBalanceSettingRespVO holidayBalanceSettingRespVO;
|
||||
|
||||
@Schema(description = "余额规则 发放方式 1每月自动发放 2每年自动发放 3手动发放 4加班时长自动计入余额 null 表示不限制余额")
|
||||
private Integer balanceRule;
|
||||
|
||||
@Schema(description = "假期余额余额")
|
||||
private BigDecimal holidayBalance;;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaybalancesetting.vo.HolidayBalanceSettingSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangeSaveReqVO;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 假期设置新增/修改 Request VO")
|
||||
@Data
|
||||
public class HolidaySettingSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", example = "24863")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期规则名称", example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "应用范围 0全公司 1指定(记录在kq_holiday_setting_range 表中)", example = "赵六")
|
||||
private Integer applicationScope;
|
||||
|
||||
@Schema(description = "新员工请假类型 1入职即可请假 2转正后才可请假", example = "2")
|
||||
private Integer newEmployeeLeaveType;
|
||||
|
||||
@Schema(description = "是否带薪 0否 1是")
|
||||
private Integer salaryFlag;
|
||||
|
||||
@Schema(description = "请假最小单位 1按天 2按半天 3按小时")
|
||||
private Integer minUnit;
|
||||
|
||||
@Schema(description = "请假取整 0否 1是")
|
||||
private Integer roundFlag;
|
||||
|
||||
@Schema(description = "取整方向 0向下 1向上 (需要取整才有意义)")
|
||||
private Integer roundDirection;
|
||||
|
||||
@Schema(description = "取整单位 0按半小时 1按小时 (需要取整才有意义)")
|
||||
private Integer roundUnit;
|
||||
|
||||
@Schema(description = "请假计算方式 0按自然日计算(休息日也会记录请假) 1按工作日计算(请假时段中不包含员工的休息日)")
|
||||
private Integer calculationMethod;
|
||||
|
||||
@Schema(description = "假期规则人员范围")
|
||||
private List<HolidaySettingRangeSaveReqVO> holidaySettingRangeSaveReqVOS;
|
||||
|
||||
@Schema(description = "假期余额设置")
|
||||
private HolidayBalanceSettingSaveReqVO holidayBalanceSettingSaveReqVO;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysettingrange.HolidaySettingRangeDO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PersonnelChangesVO {
|
||||
@Schema(description = "原所有人员")
|
||||
private List<HolidaySettingRangeDO> oldAllList;
|
||||
|
||||
@Schema(description = "需要新增的人员范围")
|
||||
private List<HolidaySettingRangeDO> saveList;
|
||||
|
||||
@Schema(description = "需要删除的人员范围")
|
||||
private List<HolidaySettingRangeDO> delList;
|
||||
|
||||
@Schema(description = "现有的人员范围")
|
||||
private List<HolidaySettingRangeDO> newAllList;
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
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.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangeRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo.HolidaySettingRangeSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidaysettingrange.HolidaySettingRangeDO;
|
||||
import cn.iocoder.yudao.module.system.service.holiday.holidaysettingrange.HolidaySettingRangeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 假期规则人员范围")
|
||||
@RestController
|
||||
@RequestMapping("/system/holiday-setting-range")
|
||||
@Validated
|
||||
public class HolidaySettingRangeController {
|
||||
|
||||
@Resource
|
||||
private HolidaySettingRangeService holidaySettingRangeService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建假期规则人员范围")
|
||||
public CommonResult<Long> createHolidaySettingRange(@Valid @RequestBody HolidaySettingRangeSaveReqVO createReqVO) {
|
||||
return success(holidaySettingRangeService.createHolidaySettingRange(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新假期规则人员范围")
|
||||
public CommonResult<Boolean> updateHolidaySettingRange(@Valid @RequestBody HolidaySettingRangeSaveReqVO updateReqVO) {
|
||||
holidaySettingRangeService.updateHolidaySettingRange(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除假期规则人员范围")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
public CommonResult<Boolean> deleteHolidaySettingRange(@RequestParam("id") Long id) {
|
||||
holidaySettingRangeService.deleteHolidaySettingRange(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得假期规则人员范围")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<HolidaySettingRangeRespVO> getHolidaySettingRange(@RequestParam("id") Long id) {
|
||||
HolidaySettingRangeDO holidaySettingRange = holidaySettingRangeService.getHolidaySettingRange(id);
|
||||
return success(BeanUtils.toBean(holidaySettingRange, HolidaySettingRangeRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得假期规则人员范围分页")
|
||||
public CommonResult<PageResult<HolidaySettingRangeRespVO>> getHolidaySettingRangePage(@Valid HolidaySettingRangePageReqVO pageReqVO) {
|
||||
PageResult<HolidaySettingRangeDO> pageResult = holidaySettingRangeService.getHolidaySettingRangePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, HolidaySettingRangeRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出假期规则人员范围 Excel")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportHolidaySettingRangeExcel(@Valid HolidaySettingRangePageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<HolidaySettingRangeDO> list = holidaySettingRangeService.getHolidaySettingRangePage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "假期规则人员范围.xls", "数据", HolidaySettingRangeRespVO.class,
|
||||
BeanUtils.toBean(list, HolidaySettingRangeRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 假期规则人员范围分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class HolidaySettingRangePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "假期设置id", example = "27475")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "目标类型 1考勤组 2部门 3个人", example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "根据目标类型对应的id", example = "3161")
|
||||
private Long objectId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 假期规则人员范围 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class HolidaySettingRangeRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12790")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期设置id", example = "27475")
|
||||
@ExcelProperty("假期设置id")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "目标类型 1考勤组 2部门 3个人", example = "2")
|
||||
@ExcelProperty("目标类型 1考勤组 2部门 3个人")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "根据目标类型对应的id", example = "3161")
|
||||
@ExcelProperty("根据目标类型对应的id")
|
||||
private Long objectId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysettingrange.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.util.*;
|
||||
|
||||
@Schema(description = "管理后台 - 假期规则人员范围新增/修改 Request VO")
|
||||
@Data
|
||||
public class HolidaySettingRangeSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", example = "12790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "假期设置id", example = "27475")
|
||||
private Long holidaySettingId;
|
||||
|
||||
@Schema(description = "目标类型 1考勤组 2部门 3个人", example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "根据目标类型对应的id", example = "3161")
|
||||
private Long objectId;
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuser;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
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.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuser.vo.HolidayUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuser.vo.HolidayUserRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuser.vo.HolidayUserSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuser.vo.HolidayUserVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.holiday.holidayuser.HolidayUserDO;
|
||||
import cn.iocoder.yudao.module.system.service.holiday.holidayuser.HolidayUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 员工假期")
|
||||
@RestController
|
||||
@RequestMapping("/system/holiday-user")
|
||||
@Validated
|
||||
public class HolidayUserController {
|
||||
|
||||
@Resource
|
||||
private HolidayUserService holidayUserService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建员工假期")
|
||||
@PreAuthorize("@ss.hasPermission('system:holiday-user:create')")
|
||||
public CommonResult<Long> createHolidayUser(@Valid @RequestBody HolidayUserSaveReqVO createReqVO) {
|
||||
return success(holidayUserService.createHolidayUser(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新员工假期")
|
||||
@PreAuthorize("@ss.hasPermission('system:holiday-user:update')")
|
||||
public CommonResult<Boolean> updateHolidayUser(@Valid @RequestBody HolidayUserSaveReqVO updateReqVO) {
|
||||
holidayUserService.updateHolidayUser(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除员工假期")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('system:holiday-user:delete')")
|
||||
public CommonResult<Boolean> deleteHolidayUser(@RequestParam("id") Long id) {
|
||||
holidayUserService.deleteHolidayUser(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/getHolidayUserDynamic")
|
||||
@Operation(summary = "获得员工假期动态列表")
|
||||
public CommonResult<HolidayUserVO> getHolidayUserDynamic(@Valid UserPageReqVO userPageReqVO) {
|
||||
HolidayUserVO holidayUser = holidayUserService.getHolidayUserDynamic(userPageReqVO);
|
||||
return success(holidayUser);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得员工假期")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:holiday-user:query')")
|
||||
public CommonResult<HolidayUserRespVO> getHolidayUser(@RequestParam("id") Long id) {
|
||||
HolidayUserDO holidayUser = holidayUserService.getHolidayUser(id);
|
||||
return success(BeanUtils.toBean(holidayUser, HolidayUserRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得员工假期分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:holiday-user:query')")
|
||||
public CommonResult<PageResult<HolidayUserRespVO>> getHolidayUserPage(@Valid HolidayUserPageReqVO pageReqVO) {
|
||||
PageResult<HolidayUserDO> pageResult = holidayUserService.getHolidayUserPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, HolidayUserRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出员工假期 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:holiday-user:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportHolidayUserExcel(@Valid HolidayUserPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<HolidayUserDO> list = holidayUserService.getHolidayUserPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "员工假期.xls", "数据", HolidayUserRespVO.class,
|
||||
BeanUtils.toBean(list, HolidayUserRespVO.class));
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user