|
|
@@ -0,0 +1,220 @@
|
|
|
+package com.ylx.attendanceconfig.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.ylx.attendanceconfig.domain.AttendanceDeductionRule;
|
|
|
+import com.ylx.attendanceconfig.domain.AttendanceRule;
|
|
|
+import com.ylx.attendanceconfig.domain.dto.AttendanceDeductionRuleDTO;
|
|
|
+import com.ylx.attendanceconfig.domain.dto.AttendanceRuleAddDTO;
|
|
|
+import com.ylx.attendanceconfig.domain.vo.AttendanceDeductionRuleVO;
|
|
|
+import com.ylx.attendanceconfig.domain.vo.AttendanceRuleDetailVO;
|
|
|
+import com.ylx.attendanceconfig.mapper.AttendanceDeductionRuleMapper;
|
|
|
+import com.ylx.attendanceconfig.mapper.AttendanceRuleMapper;
|
|
|
+import com.ylx.attendanceconfig.service.AttendanceConfigService;
|
|
|
+import com.ylx.common.exception.ServiceException;
|
|
|
+import com.ylx.common.utils.SecurityUtils;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class AttendanceConfigServiceImpl implements AttendanceConfigService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private AttendanceRuleMapper attendanceRuleMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private AttendanceDeductionRuleMapper attendanceDeductionRuleMapper;
|
|
|
+
|
|
|
+ private static final int NOT_DELETE = 0;
|
|
|
+ private static final int DELETE = 1;
|
|
|
+ private static final int ENABLED = 1;
|
|
|
+ private static final int DISABLED = 0;
|
|
|
+ private static final int EARLY_LEAVE_DEDUCTION = 1;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void addAttendanceRule(AttendanceRuleAddDTO dto) {
|
|
|
+ checkRuleParam(dto);
|
|
|
+
|
|
|
+ AttendanceRule rule = new AttendanceRule();
|
|
|
+ rule.setRuleName(StrUtil.blankToDefault(StrUtil.trim(dto.getRuleName()), "默认考勤规则"));
|
|
|
+ rule.setMerchantId(StrUtil.trim(dto.getMerchantId()));
|
|
|
+ rule.setBasicWorkHours(dto.getBasicWorkHours());
|
|
|
+ rule.setWorkDurationRuleEnabled(dto.getWorkDurationRuleEnabled());
|
|
|
+ rule.setStatus(ObjectUtil.defaultIfNull(dto.getStatus(), ENABLED));
|
|
|
+ rule.setIsDelete(NOT_DELETE);
|
|
|
+ rule.setCreateBy(SecurityUtils.getUsername());
|
|
|
+ rule.setUpdateBy(SecurityUtils.getUsername());
|
|
|
+
|
|
|
+ int insertRuleResult = attendanceRuleMapper.insert(rule);
|
|
|
+ if (insertRuleResult <= 0 || ObjectUtil.isNull(rule.getId())) {
|
|
|
+ throw new ServiceException("新增考勤规则失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dto.getWorkDurationRuleEnabled() == ENABLED) {
|
|
|
+ List<AttendanceDeductionRuleDTO> sortedRules = sortDeductionRules(dto.getDeductionRules());
|
|
|
+ for (int i = 0; i < sortedRules.size(); i++) {
|
|
|
+ AttendanceDeductionRuleDTO deductionDto = sortedRules.get(i);
|
|
|
+ AttendanceDeductionRule deductionRule = new AttendanceDeductionRule();
|
|
|
+ deductionRule.setRuleId(rule.getId());
|
|
|
+ deductionRule.setRuleType(ObjectUtil.defaultIfNull(deductionDto.getRuleType(), EARLY_LEAVE_DEDUCTION));
|
|
|
+ deductionRule.setStartMinutes(deductionDto.getStartMinutes());
|
|
|
+ deductionRule.setEndMinutes(deductionDto.getEndMinutes());
|
|
|
+ deductionRule.setDeductAmount(deductionDto.getDeductAmount());
|
|
|
+ deductionRule.setSortOrder(i + 1);
|
|
|
+ deductionRule.setIsDelete(NOT_DELETE);
|
|
|
+ deductionRule.setCreateBy(SecurityUtils.getUsername());
|
|
|
+ deductionRule.setUpdateBy(SecurityUtils.getUsername());
|
|
|
+
|
|
|
+ int insertDeductionResult = attendanceDeductionRuleMapper.insert(deductionRule);
|
|
|
+ if (insertDeductionResult <= 0) {
|
|
|
+ throw new ServiceException("新增考勤扣款区间失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<AttendanceRuleDetailVO> listAttendanceRules() {
|
|
|
+ List<AttendanceRule> ruleList = attendanceRuleMapper.selectList(new LambdaQueryWrapper<AttendanceRule>()
|
|
|
+ .orderByDesc(AttendanceRule::getCreateTime));
|
|
|
+ return ruleList.stream()
|
|
|
+ .map(this::toDetailVO)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void deleteAttendanceRule(Long id) {
|
|
|
+ if (ObjectUtil.isNull(id) || id <= 0) {
|
|
|
+ throw new ServiceException("考勤规则ID不正确");
|
|
|
+ }
|
|
|
+ AttendanceRule rule = attendanceRuleMapper.selectOne(new LambdaQueryWrapper<AttendanceRule>()
|
|
|
+ .eq(AttendanceRule::getId, id)
|
|
|
+ .eq(AttendanceRule::getIsDelete, NOT_DELETE));
|
|
|
+ if (ObjectUtil.isNull(rule)) {
|
|
|
+ throw new ServiceException("考勤规则不存在或已删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ String username = SecurityUtils.getUsername();
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ int updateRuleResult = attendanceRuleMapper.update(null, new LambdaUpdateWrapper<AttendanceRule>()
|
|
|
+ .eq(AttendanceRule::getId, id)
|
|
|
+ .eq(AttendanceRule::getIsDelete, NOT_DELETE)
|
|
|
+ .set(AttendanceRule::getIsDelete, DELETE)
|
|
|
+ .set(AttendanceRule::getUpdateBy, username)
|
|
|
+ .set(AttendanceRule::getUpdateTime, now));
|
|
|
+ if (updateRuleResult <= 0) {
|
|
|
+ throw new ServiceException("删除考勤规则失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ attendanceDeductionRuleMapper.update(null, new LambdaUpdateWrapper<AttendanceDeductionRule>()
|
|
|
+ .eq(AttendanceDeductionRule::getRuleId, id)
|
|
|
+ .eq(AttendanceDeductionRule::getIsDelete, NOT_DELETE)
|
|
|
+ .set(AttendanceDeductionRule::getIsDelete, DELETE)
|
|
|
+ .set(AttendanceDeductionRule::getUpdateBy, username)
|
|
|
+ .set(AttendanceDeductionRule::getUpdateTime, now));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void deleteDeductionRule(Long id) {
|
|
|
+ if (ObjectUtil.isNull(id) || id <= 0) {
|
|
|
+ throw new ServiceException("扣款区间ID不正确");
|
|
|
+ }
|
|
|
+ AttendanceDeductionRule deductionRule = attendanceDeductionRuleMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<AttendanceDeductionRule>()
|
|
|
+ .eq(AttendanceDeductionRule::getId, id));
|
|
|
+ if (ObjectUtil.isNull(deductionRule)) {
|
|
|
+ throw new ServiceException("扣款区间不存在或已删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ int updateResult = attendanceDeductionRuleMapper.deleteById(id);
|
|
|
+ if (updateResult <= 0) {
|
|
|
+ throw new ServiceException("删除扣款区间失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkRuleParam(AttendanceRuleAddDTO dto) {
|
|
|
+ if (ObjectUtil.isNull(dto)) {
|
|
|
+ throw new ServiceException("考勤规则参数不能为空");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNull(dto.getBasicWorkHours()) || dto.getBasicWorkHours().compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ throw new ServiceException("基本工作时长必须大于0");
|
|
|
+ }
|
|
|
+ if (dto.getWorkDurationRuleEnabled() != ENABLED && dto.getWorkDurationRuleEnabled() != DISABLED) {
|
|
|
+ throw new ServiceException("工作时长规则值不正确");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNotNull(dto.getStatus()) && dto.getStatus() != ENABLED && dto.getStatus() != DISABLED) {
|
|
|
+ throw new ServiceException("考勤规则状态值不正确");
|
|
|
+ }
|
|
|
+ if (dto.getWorkDurationRuleEnabled() == ENABLED) {
|
|
|
+ checkDeductionRules(dto.getDeductionRules());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkDeductionRules(List<AttendanceDeductionRuleDTO> deductionRules) {
|
|
|
+ if (CollectionUtil.isEmpty(deductionRules)) {
|
|
|
+ throw new ServiceException("启用工作时长规则时,扣款区间不能为空");
|
|
|
+ }
|
|
|
+ List<AttendanceDeductionRuleDTO> sortedRules = sortDeductionRules(deductionRules);
|
|
|
+ int expectedStartMinutes = 1;
|
|
|
+ for (AttendanceDeductionRuleDTO deductionRule : sortedRules) {
|
|
|
+ if (ObjectUtil.defaultIfNull(deductionRule.getRuleType(), EARLY_LEAVE_DEDUCTION) != EARLY_LEAVE_DEDUCTION) {
|
|
|
+ throw new ServiceException("扣款规则类型不正确");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNull(deductionRule.getStartMinutes()) || deductionRule.getStartMinutes() <= 0) {
|
|
|
+ throw new ServiceException("开始分钟数必须大于0");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNull(deductionRule.getEndMinutes()) || deductionRule.getEndMinutes() < deductionRule.getStartMinutes()) {
|
|
|
+ throw new ServiceException("结束分钟数不能小于开始分钟数");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNull(deductionRule.getDeductAmount()) || deductionRule.getDeductAmount().compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ throw new ServiceException("扣款金额不能小于0");
|
|
|
+ }
|
|
|
+ if (deductionRule.getStartMinutes() != expectedStartMinutes) {
|
|
|
+ throw new ServiceException("扣款区间必须从1分钟开始且连续");
|
|
|
+ }
|
|
|
+ expectedStartMinutes = deductionRule.getEndMinutes() + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<AttendanceDeductionRuleDTO> sortDeductionRules(List<AttendanceDeductionRuleDTO> deductionRules) {
|
|
|
+ return deductionRules.stream()
|
|
|
+ .sorted(Comparator.comparing(AttendanceDeductionRuleDTO::getStartMinutes))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ private AttendanceRuleDetailVO toDetailVO(AttendanceRule rule) {
|
|
|
+ AttendanceRuleDetailVO vo = new AttendanceRuleDetailVO();
|
|
|
+ BeanUtil.copyProperties(rule, vo);
|
|
|
+ vo.setDeductionRules(getDeductionRuleVOList(rule.getId()));
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<AttendanceDeductionRuleVO> getDeductionRuleVOList(Long ruleId) {
|
|
|
+ List<AttendanceDeductionRule> deductionRules = attendanceDeductionRuleMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<AttendanceDeductionRule>()
|
|
|
+ .eq(AttendanceDeductionRule::getRuleId, ruleId)
|
|
|
+ .orderByAsc(AttendanceDeductionRule::getSortOrder)
|
|
|
+ .orderByAsc(AttendanceDeductionRule::getStartMinutes));
|
|
|
+ return deductionRules.stream().map(entity -> {
|
|
|
+ AttendanceDeductionRuleVO vo = new AttendanceDeductionRuleVO();
|
|
|
+ BeanUtil.copyProperties(entity, vo);
|
|
|
+ return vo;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+}
|