Selaa lähdekoodia

年假计算+上一年年假清空

jzh 1 vuosi sitten
vanhempi
commit
0ab0781632

+ 17 - 0
zjugis-framework/zjugis-common/src/main/java/com/zjugis/framework/common/util/date/DateUtils.java

@@ -179,4 +179,21 @@ public class DateUtils {
         return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now());
     }
 
+
+    /**
+     * 获取当前日期的1月1日
+     */
+    public static LocalDateTime getFirstDayOfYear() {
+        return LocalDateTime.now().withDayOfYear(1);
+    }
+
+
+    /**
+     * 计算两个日期之间相差的年份
+     */
+    public static Integer getYears(LocalDateTime from, LocalDateTime to) {
+        Period period = Period.between(from.toLocalDate(), to.toLocalDate());
+        return period.getYears();
+    }
+
 }

+ 1 - 1
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/controller/admin/staff/StaffRecordsController.java

@@ -52,7 +52,7 @@ public class StaffRecordsController {
     @GetMapping("/detail")
     @Operation(summary = "我的档案")
     public CommonResult<RecordsRespVO> getStuffDetail(@Valid @NotNull(message = "用户id不能为空") String userId) {
-        return success(RecordsConvert.INSTANCE.convertDetail(recordsService.getRecordDetail(userId)));
+        return success(recordsService.getRecordDetail(userId));
     }
 
 

+ 14 - 0
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/controller/admin/staff/vo/records/RecordsBaseVO.java

@@ -205,4 +205,18 @@ public class RecordsBaseVO {
     private String yhzh;
 
     private String hz;
+
+    /**
+     * 初始司领
+     */
+    private Integer cssl;
+
+    /**
+     * 年假
+     */
+    private Integer nj;
+    /**
+     * 司领
+     */
+    private Integer sl;
 }

+ 11 - 1
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/dal/dataobject/staff/StaffRecordSDO.java

@@ -225,7 +225,7 @@ public class StaffRecordSDO extends BaseDO {
     private String nldj;
 
     /**
-     * 是否已调档
+     * 是否已调档 1是 2否
      */
     private Integer sfytd;
 
@@ -330,4 +330,14 @@ public class StaffRecordSDO extends BaseDO {
     private String yhzh;
 
     private String hz;
+
+    /**
+     * 初始司领
+     */
+    private Integer cssl;
+
+    /**
+     * 年假
+     */
+    private Integer nj;
 }

+ 154 - 0
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/job/leave/YearLeaveJob.java

@@ -0,0 +1,154 @@
+package com.zjugis.module.adm.job.leave;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.zjugis.framework.common.util.date.DateUtils;
+import com.zjugis.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.zjugis.module.adm.dal.dataobject.attendance.AttendanceRecordDO;
+import com.zjugis.module.adm.dal.dataobject.staff.StaffRecordSDO;
+import com.zjugis.module.adm.dal.mysql.staff.RecordsMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * 年假计算
+ *
+ * @author jzh
+ * @since 2024/2/22 16:07
+ */
+@Component
+@Slf4j
+public class YearLeaveJob {
+    @Resource
+    private RecordsMapper recordsMapper;
+
+
+    /**
+     * 年假计算
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @XxlJob("annualLeaveJob")
+    public void annualLeaveJob() throws InterruptedException {
+
+        //查询未删除员工
+        List<StaffRecordSDO> staffs = recordsMapper.selectList(new LambdaQueryWrapperX<StaffRecordSDO>().eq(StaffRecordSDO::getDeleted, "0"));
+        List<StaffRecordSDO> res = new ArrayList<>();
+        for (StaffRecordSDO staff : staffs) {
+            int leave = statisticAnnualLeave(staff);
+            //剩余年假
+            int leftLeave = staff.getNj() == null ? 0 : staff.getNj();
+            staff.setNj(leave + leftLeave);
+            res.add(staff);
+        }
+
+        log.info("年假计算完毕 开始入库");
+        if (CollectionUtil.isNotEmpty(res)) {
+            recordsMapper.updateBatch(res);
+        }
+        log.info("年假入库完毕 年假计算程序运行结束");
+    }
+
+
+    /**
+     * 一、年假逻辑:
+     * ①国家政策
+     * ≥ 1年 & < 10年:5天
+     * ≥10年 & < 20年:10天
+     * ≥20年:15天
+     * ②逻辑
+     * 入职有个初始年假天数。
+     * 每年1月1日23:50,计算每个人的新一年的年假天数
+     * ③每年3月1日  0:00,上一年度剩余年假清0,>新一年年假则=新一年年假,否则不管了
+     * 二,工龄
+     * 每入职满5年,公司奖励年假1天
+     * 司龄以1月1日算
+     */
+    private int statisticAnnualLeave(StaffRecordSDO staff) {
+        LocalDateTime now = DateUtils.getFirstDayOfYear(); //今年
+        LocalDateTime workTime = staff.getCjgzsj() == null ? now : staff.getCjgzsj(); // 参加工作时间
+        LocalDateTime enterTime = staff.getRgssj() == null ? now : staff.getRgssj();//入公司时间
+
+        //计算法定年假
+        int lowLeave = getLowAnnual(workTime, now);
+        //计算公司年假
+        int workLeave = getWorkAnnual(enterTime, now);
+        //初始年假 用于离职之后回来的员工
+        int initLeave = (staff.getCssl() == null ? 0 : staff.getCssl()) / 5;
+
+        //总年假
+        return lowLeave + workLeave + initLeave;
+    }
+
+
+    /**
+     * 计算公司年假
+     *
+     * @param enterTime 进公司时间
+     * @param now       现在
+     */
+    private int getWorkAnnual(LocalDateTime enterTime, LocalDateTime now) {
+        int year = DateUtils.getYears(enterTime, now);
+        return year / 5;
+    }
+
+    /**
+     * 计算法定年假
+     * <p>
+     * ①国家政策
+     * ≥ 1年 & < 10年:5天
+     * ≥10年 & < 20年:10天
+     * ≥20年:15天
+     *
+     * @param workTime 工作时间
+     * @param now      现在
+     */
+    private int getLowAnnual(LocalDateTime workTime, LocalDateTime now) {
+        int year = DateUtils.getYears(workTime, now);
+        if (1 <= year && 10 > year) {
+            return 5;
+        } else if (10 <= year && 20 > year) {
+            return 10;
+        } else if (20 <= year) {
+            return 15;
+        }
+        return 0;
+    }
+
+
+    /**
+     * 上一年年假清零
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @XxlJob("annualLeaveClearJob")
+    public void annualLeaveClearJob() throws InterruptedException {
+        //查询未删除员工
+        List<StaffRecordSDO> staffs = recordsMapper.selectList(new LambdaQueryWrapperX<StaffRecordSDO>().eq(StaffRecordSDO::getDeleted, "0"));
+        List<StaffRecordSDO> res = new ArrayList<>();
+        for (StaffRecordSDO staff : staffs) {
+            int year = statisticAnnualLeave(staff);
+            int left = staff.getNj() == null ? 0 : staff.getNj();
+
+            if (year < left) {
+                staff.setNj(year);
+                res.add(staff);
+            }
+            res.add(staff);
+
+        }
+
+        log.info("年假计算完毕 开始入库");
+        if (CollectionUtil.isNotEmpty(res)) {
+            recordsMapper.updateBatch(res);
+        }
+        log.info("年假入库完毕 年假计算程序运行结束");
+
+    }
+}

+ 1 - 1
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/service/staff/RecordsService.java

@@ -22,7 +22,7 @@ public interface RecordsService {
     /**
      * 员工档案详情
      */
-    StaffRecordSDO getRecordDetail(String userId);
+    RecordsRespVO getRecordDetail(String userId);
 
     /**
      * 员工档案更新

+ 13 - 2
zjugis-module-adm/zjugis-module-adm-biz/src/main/java/com/zjugis/module/adm/service/staff/RecordsServiceImpl.java

@@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 
 /**
  * @Author 陈俊
@@ -33,8 +34,18 @@ public class RecordsServiceImpl implements RecordsService {
     }
 
     @Override
-    public StaffRecordSDO getRecordDetail(String userId) {
-        return recordsMapper.selectStaffDetail(userId);
+    public RecordsRespVO getRecordDetail(String userId) {
+        //计算年假  这里计算根据入职时间到现在的年份
+        StaffRecordSDO staffRecordSDO = recordsMapper.selectStaffDetail(userId);
+        RecordsRespVO vo = RecordsConvert.INSTANCE.convertDetail(staffRecordSDO);
+        LocalDateTime now = LocalDateTime.now();
+        if (vo.getRgssj() != null) {
+            LocalDateTime enterTime = staffRecordSDO.getRgssj();
+            int companyYear = Math.toIntExact(ChronoUnit.YEARS.between(enterTime, now));
+            int initYear = vo.getCssl() == null ? 0 : vo.getCssl();
+            vo.setSl(companyYear + initYear);
+        }
+        return vo;
     }
 
     @Override

+ 119 - 0
zjugis-module-adm/zjugis-module-adm-biz/src/test/java/com/zjugis/module/adm/jnatest/AnnualLeaveTest.java

@@ -0,0 +1,119 @@
+package com.zjugis.module.adm.jnatest;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.zjugis.framework.common.util.date.DateUtils;
+import com.zjugis.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.zjugis.framework.test.core.ut.BaseDbUnitTest;
+import com.zjugis.module.adm.AdmServerApplication;
+import com.zjugis.module.adm.dal.dataobject.staff.StaffRecordSDO;
+import com.zjugis.module.adm.dal.mysql.staff.RecordsMapper;
+import com.zjugis.module.adm.service.attendance.AttendanceSheetServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author jzh
+ * @since 2024/2/23 13:35
+ */
+@Slf4j
+@SpringBootTest(classes = AdmServerApplication.class)
+public class AnnualLeaveTest {
+
+    @Resource
+    private RecordsMapper recordsMapper;
+
+
+    /**
+     * 年假计算
+     */
+    @Test
+    public void annualLeaveJob() throws InterruptedException {
+
+        //查询未删除员工
+        List<StaffRecordSDO> staffs = recordsMapper.selectList(new LambdaQueryWrapperX<StaffRecordSDO>().eq(StaffRecordSDO::getDeleted, "0"));
+        List<StaffRecordSDO> res = new ArrayList<>();
+        for (StaffRecordSDO staff : staffs) {
+            int annual = statisticAnnualLeave(staff);
+            //剩余年假
+            int leftAnnual = staff.getNj() == null ? 0 : staff.getNj();
+            staff.setNj(annual + leftAnnual);
+            res.add(staff);
+        }
+
+        log.info("年假计算完毕 开始入库");
+        if (CollectionUtil.isNotEmpty(res)) {
+            recordsMapper.updateBatch(res);
+        }
+        log.info("年假入库完毕 年假计算程序运行结束");
+    }
+
+    /**
+     * 上一年年假清零
+     */
+    @Test
+    public void annualLeaveClearJob() throws InterruptedException {
+        //查询未删除员工
+        List<StaffRecordSDO> staffs = recordsMapper.selectList(new LambdaQueryWrapperX<StaffRecordSDO>().eq(StaffRecordSDO::getDeleted, "0").eq(StaffRecordSDO::getNickname, "蒋政豪"));
+        List<StaffRecordSDO> res = new ArrayList<>();
+        for (StaffRecordSDO staff : staffs) {
+            int year = statisticAnnualLeave(staff);
+
+            if (year < staff.getNj()) {
+                staff.setNj(year);
+                res.add(staff);
+            }
+            res.add(staff);
+
+        }
+
+        log.info("上一年年假清零完毕 开始入库");
+        if (CollectionUtil.isNotEmpty(res)) {
+            recordsMapper.updateBatch(res);
+        }
+        log.info("年假清零数据入库完毕 年假计算程序运行结束");
+
+    }
+
+    private int statisticAnnualLeave(StaffRecordSDO staff) {
+        LocalDateTime now = DateUtils.getFirstDayOfYear(); //今年
+        LocalDateTime workTime = staff.getCjgzsj() == null ? now : staff.getCjgzsj(); // 参加工作时间
+        LocalDateTime enterTime = staff.getRgssj() == null ? now : staff.getRgssj();//入公司时间
+
+        //计算法定年假
+        int lowAnnual = getLowAnnual(workTime, now);
+        //计算公司年假
+        int workAnnual = getWorkAnnual(enterTime, now);
+        //初始年假 用于离职之后回来的员工
+        int initAnnual = (staff.getCssl() == null ? 0 : staff.getCssl()) / 5;
+
+        return lowAnnual + workAnnual + initAnnual;
+    }
+
+
+    private int getWorkAnnual(LocalDateTime enterTime, LocalDateTime now) {
+        int year = DateUtils.getYears(enterTime, now);
+        return year / 5;
+    }
+
+    private int getLowAnnual(LocalDateTime workTime, LocalDateTime now) {
+        int year = DateUtils.getYears(workTime, now);
+        if (1 <= year && 10 > year) {
+            return 5;
+        } else if (10 <= year && 20 > year) {
+            return 10;
+        } else if (20 <= year) {
+            return 15;
+        }
+        return 0;
+    }
+}