加班定时任务 - 修改开发环境配置
This commit is contained in:
parent
5639596118
commit
8aa1ce4a1e
@ -28,7 +28,7 @@ public interface ErrorCodeConstants {
|
||||
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 NO_OVERTIME_ALLOWED = new ErrorCode(1_009_001_016, "不允许加班");
|
||||
ErrorCode ABNORMAL_ACCESS_TO_ATTENDANCE_RECORDS = new ErrorCode(1_009_001_016, "获取考勤记录异常");
|
||||
ErrorCode OA_REIMBURSEMENT_NOT_EXISTS = new ErrorCode(1_009_001_100, "报销申请不存在");
|
||||
ErrorCode OA_EVECTION_NOT_EXISTS = new ErrorCode(1_009_001_101, "出差申请不存在");
|
||||
ErrorCode OA_SEAL_NOT_EXISTS = new ErrorCode(1_009_001_102, "用章申请不存在");
|
||||
|
@ -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>
|
||||
|
@ -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,6 +36,8 @@ public class BpmOAOvertimeController {
|
||||
|
||||
@Resource
|
||||
private BpmOAOvertimeService overtimeService;
|
||||
@Resource
|
||||
private BpmOAOvertimeItemService overtimeItemService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建请求申请")
|
||||
@ -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.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.setOvertimeDateTimeVOS(overtimeDateTimeVOS));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -62,6 +62,11 @@ public class BpmOAOvertimeDO extends BaseDO {
|
||||
*/
|
||||
private BigDecimal timeLength;
|
||||
|
||||
/**
|
||||
* 是否结算(0否 1是)
|
||||
*/
|
||||
private Integer settlementFlag;
|
||||
|
||||
/**
|
||||
* 出差的结果
|
||||
*
|
||||
|
@ -1,13 +1,12 @@
|
||||
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
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
|
||||
@ -46,7 +45,7 @@ public class BpmOAOvertimeItemDO extends BaseDO {
|
||||
*/
|
||||
private BigDecimal timeLength;
|
||||
/**
|
||||
* 日期类型 类型 0工作日 1休息日 2节假日
|
||||
* 日期类型 类型 1工作日 2休息日 3节假日
|
||||
*/
|
||||
private Integer dateType;
|
||||
/**
|
||||
@ -54,8 +53,12 @@ public class BpmOAOvertimeItemDO extends BaseDO {
|
||||
*/
|
||||
private BigDecimal actualTimeLength;
|
||||
/**
|
||||
* 是否结算(0否 1是)
|
||||
* 实际加班时长单位
|
||||
*/
|
||||
private Integer settlementFlag;
|
||||
private Integer unit;
|
||||
/**
|
||||
* 实际加班时长(分钟)
|
||||
*/
|
||||
private Long actualTimeLengthMinutes;
|
||||
|
||||
}
|
||||
|
@ -20,13 +20,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, HolidayApi.class,
|
||||
AssetsTypeApi.class, AssetReceiveApi.class
|
||||
AssetsTypeApi.class, AssetReceiveApi.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;
|
||||
}
|
||||
|
||||
}
|
@ -18,4 +18,12 @@ public interface BpmOAOvertimeItemService {
|
||||
* @return
|
||||
*/
|
||||
List<BpmOAOvertimeItemDO> getByOvertimeId(Long overtimeId);
|
||||
|
||||
/**
|
||||
* 根据OA加班申请ids获取加班申请子表列表
|
||||
*
|
||||
* @param overtimeIds
|
||||
* @return
|
||||
*/
|
||||
List<BpmOAOvertimeItemDO> getByOvertimeIds(List<Long> overtimeIds);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
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;
|
||||
@ -7,6 +8,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -26,4 +28,13 @@ public class BpmOAOvertimeItemServiceImpl implements BpmOAOvertimeItemService {
|
||||
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,8 +2,12 @@ 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 接口
|
||||
@ -30,6 +34,9 @@ public interface BpmOAOvertimeService {
|
||||
*/
|
||||
void updateOvertimeResult(String processInstanceId, Long id, Integer result);
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
void handlingOvertime(BpmOAOvertimeDO bpmOAOvertimeDO, List<BpmOAOvertimeItemDO> items, LocalDateTime now);
|
||||
|
||||
/**
|
||||
* 获得加班申请
|
||||
*
|
||||
|
@ -16,13 +16,18 @@ 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;
|
||||
@ -32,10 +37,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -74,6 +78,10 @@ public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAO
|
||||
private WorkOvertimeApi workOvertimeApi;
|
||||
@Resource
|
||||
private AttendanceApi attendanceApi;
|
||||
@Resource
|
||||
private WorkOvertimeHandler workOvertimeHandler;
|
||||
@Resource
|
||||
private HolidayApi holidayApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -96,7 +104,7 @@ public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAO
|
||||
WorkOvertimeRuleItemApiVO workOvertimeRuleItemApiVO = map.get(attendanceTimeRangeInfoVO.getDatType());
|
||||
if (workOvertimeRuleItemApiVO.getStatus() == 0) {
|
||||
String msg = "%s不允许加班";
|
||||
msg = String.format(msg, (dataTime + "号 " + (attendanceTimeRangeInfoVO.getDatType() == 0 ? "工作日" : attendanceTimeRangeInfoVO.getDatType() == 1 ? "休息日" : "节假日")));
|
||||
msg = String.format(msg, (dataTime + "号 " + (attendanceTimeRangeInfoVO.getDatType() == 1 ? "工作日" : attendanceTimeRangeInfoVO.getDatType() == 2 ? "休息日" : "节假日")));
|
||||
throw exception(new ErrorCode(1_009_001_016, msg));
|
||||
}
|
||||
}
|
||||
@ -139,7 +147,7 @@ public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAO
|
||||
return overtime.getId();
|
||||
}
|
||||
|
||||
// TODO: 2024/10/29 加班申请通过 并且加班时间已过的 - 再去获取他的子表 -
|
||||
// TODO: 2024/10/29 加班申请通过 并且加班时间已过的
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -157,43 +165,70 @@ public class BpmOAOvertimeServiceImpl extends BpmOABaseService implements BpmOAO
|
||||
if (instance.isEnded() && !items.isEmpty()) {
|
||||
this.handlingOvertime(bpmOAOvertimeDO, items, now);
|
||||
}
|
||||
} else if (BpmProcessInstanceResultEnum.REJECT.getResult().equals(result)
|
||||
|| BpmProcessInstanceResultEnum.CANCEL.getResult().equals(result)
|
||||
|| BpmProcessInstanceResultEnum.BACK.getResult().equals(result)) {
|
||||
// -- 审核拒绝 - 已取消 - 驳回
|
||||
|
||||
}
|
||||
overtimeMapper.updateById(new BpmOAOvertimeDO().setId(id).setResult(result));
|
||||
}
|
||||
|
||||
private void handlingOvertime(BpmOAOvertimeDO bpmOAOvertimeDO, List<BpmOAOvertimeItemDO> items, LocalDateTime 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();
|
||||
List<WorkOvertimeRuleItemApiVO> workOvertimeRuleItems = workOvertimeRuleApiVO.getWorkOvertimeRuleItems();
|
||||
Map<Integer, WorkOvertimeRuleItemApiVO> map = workOvertimeRuleItems.stream().collect(Collectors.toMap(WorkOvertimeRuleItemApiVO::getType, Function.identity()));
|
||||
for (BpmOAOvertimeItemDO item : items) {
|
||||
// - 这里不需要判断是否关闭加班 - 再申请的时候已经判断过了 - 这里只需要做计算加班时长的逻辑即可
|
||||
WorkOvertimeRuleItemApiVO workOvertimeRuleItemApiVO = map.get(item.getDateType());
|
||||
if (workOvertimeRuleItemApiVO.getCalculationMode() == 1) {
|
||||
item.setActualTimeLength(item.getTimeLength());
|
||||
item.setSettlementFlag(1);
|
||||
@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();
|
||||
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());
|
||||
recordList.sort(Comparator.comparing(AttendancePunchRecordVO::getShouldPunchTime));
|
||||
// -- 计算加班时长
|
||||
resource.getOvertimeHours(item, recordList, workOvertimeRuleApiVO, ruleItem);
|
||||
editItems.add(item);
|
||||
|
||||
} else if (workOvertimeRuleItemApiVO.getCalculationMode() == 2) {
|
||||
// -- 这里要区分申请加班的时间是已经发生了的还是未来要做的事情 / -- 如果是已经发生了的那么直接取考勤记录计算加班时长 - 如果是未来将要发生的 那么先存到一个地方 - 后面处罚打卡的时候再判断下是不是加班的
|
||||
if (bpmOAOvertimeDO.getEndTime().isBefore(now)) {
|
||||
//已经发生的 - 获取该用户最近几天的考勤记录 - 并且对比时间
|
||||
CommonResult<Map<String, List<AttendancePunchRecordVO>>> attendancePunchRecordByTimeRange = attendanceApi.getAttendancePunchRecordByTimeRange(
|
||||
new AttendancePunchRecordDTO().setUserId(item.getUserId()).setStartTime(bpmOAOvertimeDO.getStartTime()).setEndTime(bpmOAOvertimeDO.getEndTime()));
|
||||
if (ruleItem.getTransformationType() == 1) {
|
||||
// -- 计算调休
|
||||
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 加班费不计算(后续有加班规则再计算)
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
//更新加班主表
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,52 @@
|
||||
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.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.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,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,102 @@
|
||||
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.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 加班 工作日
|
||||
*
|
||||
* @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(1)
|
||||
// 计算班前多少分钟 小于n分钟 则不考虑
|
||||
&& a.getUpWorkOvertimeTime() > 0 && TimeUnit.MILLISECONDS.toMinutes(a.getUpWorkOvertimeTime()) > ruleItem.getBeforeWorkOvertime())
|
||||
.map(AttendancePunchRecordVO::getUpWorkOvertimeTime)
|
||||
.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) {
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
@ -39,33 +39,40 @@ spring:
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
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:
|
||||
|
@ -39,24 +39,24 @@ spring:
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
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,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是
|
||||
|
@ -24,8 +24,8 @@ public class AttendanceTimeRangeInfoVO {
|
||||
/**
|
||||
* 日期类型
|
||||
*/
|
||||
@Schema(description = "日期类型 0工作日 1休息日 2节假日")
|
||||
private Integer datType = 0;
|
||||
@Schema(description = "日期类型 1工作日 2休息日 3节假日")
|
||||
private Integer datType = 1;
|
||||
/**
|
||||
* 当日班次信息
|
||||
*/
|
||||
|
@ -2,6 +2,7 @@ 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;
|
||||
@ -27,4 +28,8 @@ public interface HolidayApi {
|
||||
@PostMapping(PREFIX + "/createUserHoliday")
|
||||
@Operation(summary = "创建用户请假")
|
||||
CommonResult createUserHoliday(@RequestBody CreateUserHolidayDTO dto);
|
||||
|
||||
@PostMapping(PREFIX + "/overtimeIncreasesHoliday")
|
||||
@Operation(summary = "加班增加假期")
|
||||
CommonResult overtimeIncreasesHoliday(@RequestBody OvertimeIncreasesHolidayDTO dto);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class CreateUserHolidayDTO {
|
||||
|
@ -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 Integer conversion;
|
||||
}
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.system.api.attendance.vo.AttendanceTimeRangeInfoV
|
||||
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;
|
||||
@ -24,5 +25,6 @@ public interface WorkOvertimeApi {
|
||||
|
||||
@GetMapping(PREFIX + "/getOvertimeRulesByUserId")
|
||||
@Operation(summary = "获取加班规则")
|
||||
CommonResult<WorkOvertimeRuleApiVO> getOvertimeRulesByUserId(@RequestParam Long userId);
|
||||
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||
CommonResult<WorkOvertimeRuleApiVO> getOvertimeRulesByUserId(@RequestParam("userId") Long userId);
|
||||
}
|
||||
|
@ -3,7 +3,10 @@ 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 {
|
||||
|
@ -25,7 +25,7 @@ public class WorkOvertimeMoreRuleApiVO {
|
||||
@Schema(description = "取整递增值")
|
||||
private BigDecimal roundingIncrementalValue;
|
||||
|
||||
@Schema(description = "日折算时长 n分钟 = 一天 ")
|
||||
@Schema(description = "日折算时长 n小时 = 一天 ")
|
||||
private Integer conversion;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -3,6 +3,7 @@ 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;
|
||||
@ -44,4 +45,10 @@ public class HolidayApiImpl implements HolidayApi {
|
||||
return CommonResult.success("ok");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult overtimeIncreasesHoliday(OvertimeIncreasesHolidayDTO dto) {
|
||||
holidayUserRecordService.overtimeIncreasesHoliday(dto);
|
||||
return CommonResult.success("ok");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -78,8 +78,11 @@ public class AttendancePunchRecordSaveReqVO {
|
||||
@Schema(description = "早退时长时间戳")
|
||||
private Long leaveEarlyTime;
|
||||
|
||||
@Schema(description = "加班时长时间戳")
|
||||
private Long workOvertimeTime;
|
||||
@Schema(description = "下班加班时长时间戳")
|
||||
private Long downWorkOvertimeTime;
|
||||
|
||||
@Schema(description = "上班加班时长时间戳")
|
||||
private Long upWorkOvertimeTime;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -28,11 +28,11 @@ public class WorkOvertimeMoreRulePageReqVO extends PageParam {
|
||||
@Schema(description = "取整递增值")
|
||||
private BigDecimal roundingIncrementalValue;
|
||||
|
||||
@Schema(description = "日折算时长 n分钟 = 一天 ")
|
||||
@Schema(description = "日折算时长 n小时 = 一天 ")
|
||||
private Integer conversion;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ public class WorkOvertimeMoreRuleRespVO {
|
||||
@ExcelProperty("取整递增值")
|
||||
private BigDecimal roundingIncrementalValue;
|
||||
|
||||
@Schema(description = "日折算时长 n分钟 = 一天 ")
|
||||
@ExcelProperty("日折算时长 n分钟 = 一天 ")
|
||||
@Schema(description = "日折算时长 n小时 = 一天 ")
|
||||
@ExcelProperty("日折算时长 n小时 = 一天 ")
|
||||
private Integer conversion;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -26,7 +26,7 @@ public class WorkOvertimeMoreRuleSaveReqVO {
|
||||
@Schema(description = "取整递增值")
|
||||
private BigDecimal roundingIncrementalValue;
|
||||
|
||||
@Schema(description = "日折算时长 n分钟 = 一天 ")
|
||||
@Schema(description = "日折算时长 n小时 = 一天 ")
|
||||
private Integer conversion;
|
||||
|
||||
@Schema(description = "更多规则拓展列表")
|
||||
|
@ -136,9 +136,14 @@ public class AttendancePunchRecordDO extends BaseDO {
|
||||
private Long leaveEarlyTime;
|
||||
|
||||
/**
|
||||
* 加班时长时间戳
|
||||
* 下班加班时长时间戳
|
||||
*/
|
||||
private Long workOvertimeTime;
|
||||
private Long downWorkOvertimeTime;
|
||||
|
||||
/**
|
||||
* 上班加班时长时间戳
|
||||
*/
|
||||
private Long upWorkOvertimeTime;
|
||||
|
||||
/**
|
||||
* 是否已提醒 0否 1是
|
||||
|
@ -47,7 +47,7 @@ public class WorkOvertimeMoreRuleDO extends BaseDO {
|
||||
*/
|
||||
private BigDecimal roundingIncrementalValue;
|
||||
/**
|
||||
* 日折算时长 n分钟 = 一天
|
||||
* 日折算时长 n小时 = 一天
|
||||
*/
|
||||
private Integer conversion;
|
||||
|
||||
|
@ -223,7 +223,8 @@ public class AttendanceServiceImpl implements AttendanceService {
|
||||
//取绝对值 如果status是负数则变为正数
|
||||
.setLateTime(Constants.ONE.equals(status) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
|
||||
.setLeaveEarlyTime(Constants.TWO.equals(status) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
|
||||
.setWorkOvertimeTime(Constants.ZERO.equals(status) && Constants.ONE.equals(pageVO.getPunchType()) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
|
||||
.setDownWorkOvertimeTime(Constants.ZERO.equals(status) && Constants.ONE.equals(pageVO.getPunchType()) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
|
||||
.setUpWorkOvertimeTime(Constants.ZERO.equals(status) && Constants.ZERO.equals(pageVO.getPunchType()) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
|
||||
.setRemark(dto.getRemark())
|
||||
.setImage(dto.getImage())
|
||||
.setPunchAddress(dto.getPunchAddress());
|
||||
|
@ -292,7 +292,7 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
|
||||
LocalDateTime localDateTime = LocalDateTimeUtil.parseDate(time, Constants.REPO_DATE_FORMAT).atStartOfDay();
|
||||
Boolean holiday = attendanceService.isHoliday(localDateTime);
|
||||
// -- 如果是节假日的话先插入下是节假日 - 不管上不上班
|
||||
attendanceTimeRangeInfoVO.setDatType(holiday ? Constants.TWO : Constants.ZERO);
|
||||
attendanceTimeRangeInfoVO.setDatType(holiday ? Constants.THREE : Constants.ONE);
|
||||
Boolean isHolidayFlag = Constants.TRUE.equals(dto.getAutoHolidaysFlag()) ?
|
||||
holiday : null;
|
||||
// -- 当前是节假日 并且是放假
|
||||
@ -305,7 +305,7 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
|
||||
AttendanceFixedDO attendanceFixedDO = this.getByGroupIdAndWeek(dto.getGroupId(), week);
|
||||
// -- 当前没有班次 - 不需要考勤
|
||||
if (attendanceFixedDO == null || attendanceFixedDO.getAttendanceGroupShiftId() == null) {
|
||||
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.ONE));
|
||||
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.TWO));
|
||||
continue;
|
||||
}
|
||||
List<AttendanceGroupShiftItemDO> attendanceGroupShiftItemDOList = attendanceGroupShiftItemService.getGroupShiftItemListByShiftId(attendanceFixedDO.getAttendanceGroupShiftId());
|
||||
|
@ -322,7 +322,7 @@ public class AttendanceSchedulingServiceImpl implements AttendanceSchedulingServ
|
||||
LocalDateTime localDateTime = LocalDateTimeUtil.parseDate(time, Constants.REPO_DATE_FORMAT).atStartOfDay();
|
||||
Boolean holiday = attendanceService.isHoliday(localDateTime);
|
||||
// -- 如果是节假日的话先插入下是节假日 - 不管上不上班
|
||||
attendanceTimeRangeInfoVO.setDatType(holiday ? Constants.TWO : Constants.ZERO);
|
||||
attendanceTimeRangeInfoVO.setDatType(holiday ? Constants.THREE : Constants.ONE);
|
||||
Boolean isHolidayFlag = Constants.TRUE.equals(dto.getAutoHolidaysFlag()) ?
|
||||
holiday : null;
|
||||
// -- 当前是节假日 并且是放假
|
||||
@ -333,7 +333,7 @@ public class AttendanceSchedulingServiceImpl implements AttendanceSchedulingServ
|
||||
AttendanceSchedulingDO attendanceSchedulingDO = this.getSchedulingByIndexDay(dto.getGroupId(), beginTimeDay);
|
||||
// -- 当前没有班次 - 不需要考勤
|
||||
if (attendanceSchedulingDO == null || Constants.ONE.equals(attendanceSchedulingDO.getRestFlag()) || attendanceSchedulingDO.getAttendanceGroupShiftId() == null) {
|
||||
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.ONE));
|
||||
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.TWO));
|
||||
continue;
|
||||
}
|
||||
List<AttendanceGroupShiftItemDO> attendanceGroupShiftItemDOList = attendanceGroupShiftItemService.getGroupShiftItemListByShiftId(attendanceSchedulingDO.getAttendanceGroupShiftId());
|
||||
|
@ -32,6 +32,7 @@ public interface DeptService {
|
||||
|
||||
/**
|
||||
* 更新工厂部门
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateFactoryDept(DeptSaveReqVO updateReqVO);
|
||||
@ -87,7 +88,7 @@ public interface DeptService {
|
||||
List<DeptDO> getChildDeptList(Long id);
|
||||
|
||||
/**
|
||||
* 获得指定部门的所有子部门
|
||||
* 获得指定部门的所有子部门 (包含自己)
|
||||
*
|
||||
* @param id 部门编号
|
||||
* @return 子部门列表
|
||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.holiday.holidayuserrecord;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
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.controller.admin.holiday.holidaysetting.dto.RecalculateAssignedDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuserrecord.vo.HolidayUserRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuserrecord.vo.HolidayUserRecordSaveReqVO;
|
||||
@ -139,4 +140,11 @@ public interface HolidayUserRecordService {
|
||||
* @param list
|
||||
*/
|
||||
void editReminder(List<HolidayUserRecordDO> list);
|
||||
|
||||
/**
|
||||
* 加班增加余额
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
void overtimeIncreasesHoliday(OvertimeIncreasesHolidayDTO dto);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
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.controller.admin.holiday.holidaysetting.dto.RecalculateAssignedDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidaysetting.vo.DetermineHolidayBalanceSettingSwitchVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.holiday.holidayuserrecord.vo.HolidayUserRecordPageReqVO;
|
||||
@ -33,6 +34,7 @@ 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.Month;
|
||||
import java.time.Period;
|
||||
@ -104,6 +106,7 @@ public class HolidayUserRecordServiceImpl implements HolidayUserRecordService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<HolidayUserRecordDO> addHolidayUserRecord(Long userId, Long holidaySettingId, BigDecimal addAmount) {
|
||||
List<HolidayUserRecordDO> editList = new ArrayList<>();
|
||||
// -- 扣除用户记录中的余额 - (获取没有过期的余额列表 - 并且余额 > 0 - 按照过期时间升序 从最快过期的开始扣)
|
||||
@ -664,4 +667,61 @@ public class HolidayUserRecordServiceImpl implements HolidayUserRecordService {
|
||||
list.forEach(a -> a.setExpirationReminderFlag(1));
|
||||
holidayUserRecordMapper.updateBatch(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void overtimeIncreasesHoliday(OvertimeIncreasesHolidayDTO dto) {
|
||||
Long userId = dto.getUserId();
|
||||
List<HolidayUserDO> holidayUserDOS = holidayUserMapper.selectList(new LambdaQueryWrapper<HolidayUserDO>().eq(HolidayUserDO::getUserId, userId)
|
||||
.eq(HolidayUserDO::getHolidaySettingId, dto.getHolidaySettingId()));
|
||||
// 过滤掉不适用的
|
||||
if (CollectionUtils.isEmpty(holidayUserDOS)){
|
||||
return;
|
||||
}
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Map<Long, BigDecimal> userQuotaMap = new HashMap<>();
|
||||
List<Long> userIds = Collections.singletonList(userId);
|
||||
HolidaySettingDO holidaySetting = holidaySettingService.getHolidaySetting(dto.getHolidaySettingId());
|
||||
|
||||
Integer minUnit = holidaySetting.getMinUnit();
|
||||
// -- 加班时间单位转换假期时间单位 - ?
|
||||
BigDecimal holidayBalance = this.overtimeUnitToHolidayUnitConversion(dto, minUnit);
|
||||
|
||||
HolidayBalanceSettingDO holidayBalanceSettingDO = holidaySetting.getHolidayBalanceSettingDO();
|
||||
userQuotaMap.put(userId, holidayBalance);
|
||||
// -- 获取用户的假期表
|
||||
Map<Long, HolidayUserDO> holidayUserDOMap = this.getHolidayUserMap(userIds, holidaySetting, holidayBalanceSettingDO);
|
||||
List<HolidayUserRecordDO> newHolidayUserRecordDOList = new ArrayList<>();
|
||||
List<HolidayUserDO> newHolidayUserDOList = new ArrayList<>();
|
||||
String remark = "加班" + (dto.getDirection() == 0 ? "增加" : "减去");
|
||||
this.calculateUserHolidays(userQuotaMap, userId, holidayUserDOMap, holidaySetting, holidayBalanceSettingDO, newHolidayUserRecordDOList, newHolidayUserDOList, now, remark, dto.getDirection(), dto.getReason());
|
||||
if (CollUtil.isNotEmpty(newHolidayUserRecordDOList)) {
|
||||
holidayUserRecordMapper.insertBatch(newHolidayUserRecordDOList);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(newHolidayUserDOList)) {
|
||||
holidayUserMapper.insertOrUpdateBatch(newHolidayUserDOList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加班单位转换为 假期单位 计算时长
|
||||
*
|
||||
* @param dto
|
||||
* @param minUnit 请假最小单位 1按天 2按半天 3按小时
|
||||
* @return
|
||||
*/
|
||||
private BigDecimal overtimeUnitToHolidayUnitConversion(OvertimeIncreasesHolidayDTO dto, Integer minUnit) {
|
||||
BigDecimal holidayBalance = dto.getHolidayBalance();
|
||||
if (dto.getUnit() == 1) {
|
||||
if (minUnit == 1 || minUnit == 2) {
|
||||
// 转换为天 -
|
||||
holidayBalance = dto.getHolidayBalance().divide(BigDecimal.valueOf(dto.getConversion()), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
} else {
|
||||
// -- 转换为小时
|
||||
if (minUnit == 3) {
|
||||
holidayBalance = dto.getHolidayBalance().multiply(BigDecimal.valueOf(dto.getConversion()));
|
||||
}
|
||||
}
|
||||
return holidayBalance;
|
||||
}
|
||||
}
|
||||
|
@ -687,7 +687,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
public List<AdminUserDO> getUserListByStatus(Integer userType, Long deptId, Integer status) {
|
||||
List<Long> deptIds = new ArrayList<>();
|
||||
if (deptId != null) {
|
||||
deptIds = convertList(deptService.getChildDeptList(deptId), DeptDO::getId);
|
||||
deptIds = convertList(deptService.getChildDept(deptId), DeptDO::getId);
|
||||
}
|
||||
return userMapper.selectListByStatus(userType, deptIds, status);
|
||||
}
|
||||
|
@ -143,8 +143,8 @@ public class WorkOvertimeRuleServiceImpl implements WorkOvertimeRuleService {
|
||||
List<Long> attendanceGroupIds = StrUtil.isEmpty(createReqVO.getAttendanceGroupIds()) ?
|
||||
Collections.emptyList() :
|
||||
Arrays.stream(createReqVO.getAttendanceGroupIds().split(",")).map(Long::valueOf).collect(Collectors.toList());
|
||||
List<List<Long>> attendanceGroupIdLists = CollectionUtils.diffList(attendanceGroupIds, oldAttendanceGroupIds, ObjectUtil::equal);
|
||||
workOvertimeRuleAttendanceGroupService.insertDeleteBatch(ruleId,attendanceGroupIdLists);
|
||||
List<List<Long>> attendanceGroupIdLists = CollectionUtils.diffList(oldAttendanceGroupIds, attendanceGroupIds, ObjectUtil::equal);
|
||||
workOvertimeRuleAttendanceGroupService.insertDeleteBatch(ruleId, attendanceGroupIdLists);
|
||||
// ------------------------------------------- 处理 加班规则考勤组关联 结束 -------------------------------------------
|
||||
|
||||
// ------------------------------------------- 处理 加班规则子表 开始 -------------------------------------------
|
||||
@ -217,6 +217,7 @@ public class WorkOvertimeRuleServiceImpl implements WorkOvertimeRuleService {
|
||||
WorkOvertimeRuleDO workOvertimeRuleDO = workOvertimeRuleMapper.selectById(id);
|
||||
List<Long> workOvertimeRuleAttendanceGroupDOS = workOvertimeRuleAttendanceGroupService.getListByRuleId(id)
|
||||
.stream().map(WorkOvertimeRuleAttendanceGroupDO::getAttendanceGroupId).collect(Collectors.toList());
|
||||
|
||||
String attendanceGroupIds = StrUtil.join(",", workOvertimeRuleAttendanceGroupDOS);
|
||||
workOvertimeRuleDO.setAttendanceGroupIds(attendanceGroupIds);
|
||||
List<WorkOvertimeDeductRuleDO> deductRules = workOvertimeDeductRuleService.getListByRuleId(id);
|
||||
|
@ -39,24 +39,24 @@ spring:
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&allowMultiQueries=true # MySQL Connector/J 8.X 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&allowMultiQueries=true # MySQL Connector/J 8.X 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 1 # 数据库索引
|
||||
# password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
|
@ -41,33 +41,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: 123456
|
||||
# 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: 123456
|
||||
# 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: system-server
|
||||
|
||||
profiles:
|
||||
active: dev #local
|
||||
active: local #local
|
||||
# active: prod
|
||||
|
||||
server:
|
||||
|
@ -39,24 +39,24 @@ spring:
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 1 # 数据库索引
|
||||
# password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
|
@ -39,24 +39,24 @@ spring:
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro-dev
|
||||
url: jdbc:mysql://rm-bp1yloyj508qld78jno.mysql.rds.aliyuncs.com: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 连接的示例
|
||||
name: ruoyi-vue-pro
|
||||
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: Znalyrds2024
|
||||
password: yhtkj@2024!
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 1 # 数据库索引
|
||||
# password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
|
@ -41,33 +41,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.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.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 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
host: 47.97.8.94 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 0 # 数据库索引
|
||||
# password: 123456 # 密码,建议生产环境开启
|
||||
password: yhtkj@2024! # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
@ -142,4 +132,4 @@ resource:
|
||||
#视频能力
|
||||
video:
|
||||
previewUrls: /artemis/api/video/v2/cameras/previewURLs
|
||||
replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs
|
||||
replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs
|
||||
|
@ -3,7 +3,7 @@ spring:
|
||||
name: smartfactory-server
|
||||
|
||||
profiles:
|
||||
active: dev
|
||||
active: local
|
||||
|
||||
server:
|
||||
port: 48090
|
||||
|
Loading…
Reference in New Issue
Block a user