1自动生成年假

1.1基本业务场景

假期类型为定额类且规则是自动生成的需要定时任务自动生成假期,根据基准值和生成条件来确定年假生成的额度。
image-20250714170445623

image-20250714170504252

image-20250714170518878

基准值:福利工龄日期、社会工龄日期
!!#ff0000 生成条件!!:福利工龄日期满N个月、社会工龄日期满N个月

是否预支年假:是、否。即是生成已工作年份年假和未来为工作时间的年假(预支,员工刚入职生成今年一年的年假)
基准值单位:月、自然年
例如:基准值以月为单位:
基准值单位选择为“月”,非预支类型年假,若起始日期为2022年10月1日,则2023年10月1日基准值满12个月
示例:若年假计算规则:以“福利工龄”为基准值+“福利工龄”为基础条件+“自然年”为计算周期+取整方式为“向下取整”+额度单位为“天”+基准值单位为“月”: 小王于2015年7月12日首次参加工作,于2022年2月10日加入公司,公司规定:福利工龄满12个月(2023年2月10日)后给予年假,年假阶梯是福利工龄12个月60个月给予5天,60个月120个月给予7天。 小王于2022年5月10日,入职满12个月,此时生成年假。 计算规则为:(20221231-20220211)/3657=6.19,向下取整为6天。
基准值以自然年为单位:
基准值单位选择为“自然年”,非预支类型年假,若起始日期为2022年10月1日,2023年1月1日开始则为第二个自然年。
示例:若年假计算规则:以“福利工龄”为基准值+“福利工龄”为基础条件+“自然年”为计算周期+取整方式为“向下取整”+额度单位为“天”+基准值单位为“自然年”: 小王于2018年7月12日首次参加工作,于2022年2月10日加入公司,公司规定:福利工龄满12个月(2023年2月10日)后给予年假,年假阶梯是社会工龄第1-5自然年给予5天, 小王于2023年2月10日,入职满12个月,此时生成年假。 计算规则为:(20221231-20220210)/365
5=4.42,向下取整为4天。

1.2业务实现逻辑梳理

整体逻辑流程图

image-20250714170735668

以自然年为计算周期逻辑

名词解释:

  • 基准:基准值日期(社会工龄日期 or 福利工龄日期)

  • M:以基准值日期为准,生成条件满M个月

  • T:当前时间

  • 司内(红点):入职日期

  • 司内年底(黑点):入职当年的自然年底

  • 司内2年底(黑点):入职第二年的自然年底

1.不预支年假,即满足年假生成条件,生成上年应休年假
image-20250714170540813
2.预支年假
image-20250714170551746
3.不预支年假,即满足年假生成条件
image-20250714170603847
4.预支年假
image-20250714170616417

代码逻辑:通过比较当前时间在哪个时间段、是否预支年假,传入不同的额度开始计算日期参数,再根据是否存在跨额度的情况计算出最终的应休年假。

1.3特殊场景-年假跨额度生成处理方式

1 员工当前年年假生成数刚好在两个阶段中是,需要对两个阶段进行合并计算出最终的年假
年假跨阶段7天/10天; 计算公式:(153/365)*7+(173/365)*10
image-20250714170640952

1.4测试用例

根据以下测试用例可以和上面的流程图相结合,便于理解年假生成逻辑。

不预支年假:

image-20250714171231119

预支年假:

高管类个性化规则:

image-20250714171407722

2初始化有效打卡记录

一般来讲,考勤计算需要先拿到每个员工每天每个班次的有效打卡记录,以这个记录为基准来计算考勤。

image-20250715172749571

3考勤计算全流程

考勤计算分为数据准备、数据验证、组装数据、数据拆分计算这四个步骤,其中涉及的表及业务逻辑如下图。

考勤计算的定时任务也和初始化有效打卡记录的整体逻辑一致,都是根据员工的pdc时间筛选出需要计算考勤的员工和考勤日期,按照日期给每个员工计算考勤。

image-20250715172047166

考勤计算涉及的相关表:

image-20250717151034055

3.1数据准备

image-20250715171507019

3.2数据验证

image-20250715171624480

3.3组装数据

此处获取班次信息(标记0点)的作用是,跨天班次可能会存在休息时间跨天的情况,也可能跨天时是排班的情况,需要将0点前后的考勤状态拆分。

例如:跨天班次B(19:00-5:00),休息时间为23:00–1:00,3:00–4:00

拆分0点后,班次结果为: [2025-07-16 19:00,2025-07-16 23:00]【排班】

​ [2025-07-16 23:00,2025-07-16 0:00] 【休息】

​ [2025-07-17 0:00,2025-07-17 1:00] 【休息】

​ [2025-07-17 1:00,2025-07-17 3:00] 【排班】

​ [2025-07-17 3:00,2025-07-17 4:00] 【休息】

​ [2025-07-17 4:00,2025-07-17 5:00] 【排班】

后续的考勤拆分是以这个拆分了0点后的班次作为循环条件,与打卡、请假、销假、出差等数据进行比较。image-20250715171644104

3.4数据拆分计算

考勤核算流程图

image-20250715171705033

考勤核算规则

image-20250715172024559

image-20250715172037235

考勤状态

休息请假出差正常出勤早到迟到早退延迟下班旷工排班弹性排班

三、数据处理(考勤计算前)
1、数据准备:所有数据需分段存储至GtdAttendanceResult对象中,并标识出该段目前的考勤状态
例:班次为9:00-18:00,休息时间为12:00-14:00
分段存储后:9:00-12:00(排班),12:00-14:00(休息),14:00-18:00(排班)

考勤计算

1、初次比较
1.1、以班次作为基础数据,打卡、请假、销假、出差等数据作为比较数据

image-20250715172448644

1.2、根据考勤核算规则优先级,将比较数据逐一与基础数据进行比对,不重合时间段保留当前考勤状态,重合时间段按照优先级比对出两段考勤状态
1.3、为了提升比对效率,若当前比较数据比对完毕,则终止循环,进入下一次比较数据的循环
image-20250715172416478

2、二次比较
2.1、二次比较确定考勤异常最终状态,例:初次比较得出迟到、早退,需要与系统配置的时长进行比对,确定是否为旷工

3、弹性班次注意事项
3.1、需先计算员工应下班时间(根据上班打卡时间和上班总时长计算)
3.2、班次时间需这样拆分 -> 最早到岗时间,最晚到岗时间 ; 最晚到岗时间,实际下班时间 ; 实际下班时间,最晚下班时间

4、多段班注意事项
4.1、多段班需要逐段班次进行比较

五、考勤结果、明细存储
1、保存考勤明细存在转换天数精度丢失问题
现采用减法计算:1 - 请假天数 - 实际出勤天数(包含出差天数) = 旷工天数
特殊处理:若考勤结果无旷工时间段,且减法后旷工天数 > 0 ,则将旷工天数补入实际出勤天数

4考勤处理流程

考勤一般都是与OA流程挂钩的,员工的请假、加班、出差、销假等操作在OA系统发起,对接到UHR系统,对接后考勤处理流程如下。

image-20250715173137044

4.1拆分请假/出差数据

员工提交整段请假记录时,后台需要按照员工班次进行拆分,存储到数据库时请假结果按天存储,销假是也要删除对应拆分结果。

而且对于员工排班发生变更前的请假/出差记录,计算考勤前需要重新拆分。

具体拆分逻辑如下:

image-20250715173311178

5考勤日历

5.1相关表设计

其中 gtd_emp_calendar 因数据量过大,不再使用。

gtd_work_calendar_details工作日历明细表,精确到天,每天绑定一个班次。

sys_organization为组织表,emp_org_allocation为员工的组织分配表(员工有异动时添加一条数据)。

image-20250716142327119

  • gtd_holiday_manage:节假日管理实体,包含节假日名称、代码、开始日期、结束日期、法定节假日、调休日期等信息。
  • gtd_work_calendar_details:工作日历明细表,记录每个工作日历的具体日期安排,包括班次、日期类型等。
  • gtd_holiday_calendar_history:工作日历和节假日关联历史表,用于记录工作日历应用节假日前的原始数据,便于后续恢复或修改。

5.2相关业务逻辑

工作日历按周期顺延

image-20250716193716828

节假日应用工作日历

节假日管理信息配置中,支持编辑法定节假日日期、关联调休日期、法定节假日(非3倍计薪)

image-20250717102302183

一个节假日支持应用到多个工作日历上

image-20250717103717525

节假日应用到多个工作日历的业务流程图如下:

image-20250717111533223

整个节假日历史关联表的业务逻辑可以总结为:

  1. 历史记录管理 :

    • 保存原始工作日历数据( holidayId 为 null )
    • 保存节假日应用后的工作日历数据( holidayId 为节假日ID)
    • 当修改节假日设置时,先恢复原始数据,再应用新设置
  2. 节假日应用 :

    • 将节假日期间的工作日设置为休息日( classId 为 null )
    • 根据节假日类型设置不同的 holidayType (法定节假日或普通节假日)
  3. 调休处理 :

    • 将调休日设置为工作日( holidayType 为普通日期)
    • 为调休日分配合适的班次(通过查找最近的班次)
  4. 数据一致性 :

    • 通过事务保证工作日历明细和历史记录的一致性
    • 通过批量操作提高性能

获取员工班次步骤

员工班次有两种来源:
①.直接导入员工班次到员工班次明细表;
②.通过部门绑定工作日历或直接给员工绑定工作日历;
两者都存在时①优先级高于②

image-20250716143401092

员工工作日历变更

组织绑定工作日历

image-20250716162159584

入职/异动刷新员工考勤日历逻辑

组织与日历绑定关系

  • 组织1 (2024-01-01 日历A),(2024-01-25 日历B)
    组织1组 (2024-01-30 日历C),(2024-05-02 日历D)
  • 组织2 (2024-01-01 日历E)
    组织2组
  • 组织3 (2024-01-01 日历F)
    组织3组

员工异动流程

在2024-01-01号入职组织2组
在2024-01-20号从组织2组异动至组织1组
在2024-05-01号从组织1组异动至组织3组

组织2组:[2024-01-01,2024-01-20]
组织1组:[2024-01-20,2024-05-01] 异动时间段
组织3组:[2024-05-01,9999-12-31]
异动时间段需生成的考勤日历:20号,25号,30号共三条

获取组织1组及上级所有考勤日历

倒序排序(2024-05-02,2024-01-30,2024-01-25,2024-01-01)

如此以下遍历员工所在的各个组织比较…

image-20250716151015869

6生成员工补卡余额

每个月会给员工生成补卡余额,定时任务会每天更新该员工的补卡余额。

image-20250716164814345

7加班审核

image-20250716175428067