Skip to content

feat(earned_leaves): support earned leave accrual after configurable service or eligibility days - #5013

Open
md-umair-21 wants to merge 4 commits into
frappe:developfrom
md-umair-21:earned-leave
Open

feat(earned_leaves): support earned leave accrual after configurable service or eligibility days#5013
md-umair-21 wants to merge 4 commits into
frappe:developfrom
md-umair-21:earned-leave

Conversation

@md-umair-21

@md-umair-21 md-umair-21 commented Jul 28, 2026

Copy link
Copy Markdown

Problem
Some companies require earned leave accrual to begin only after an employee completes a minimum service period.
Although earned leave already supports periodic accrual, there was no server-side mechanism to delay accrual until the required service period was completed.

The existing applicable_after setting only prevents employees from applying for leave. It does not delay earned leave accrual.
This could result in earned leave accruing before the intended service period

Solution:-
This PR introduces earned leave eligibility based on the employee's Date of Joining.
Earned leave accrual begins only after the employee completes the configured number of calendar days of service.

Changes Applied:-

  1. Added a New Earned Leave Eligibility Field on Leave Type
  • Added earned_leave_eligibility_days to Leave Type.
  • This field is shown only for earned leave types.
  • It stores the number of calendar days an employee must complete before earned leave can start accruing.

Why:

  • Existing earned leave settings handled frequency and rounding, but there was no field to define when accrual should actually begin.
  • This keeps the rule specific to earned leave instead of making it a generic leave rule.
  1. Added Server-Side Eligibility Date Calculation

Introduced logic to calculate the accrual eligibility date using:

date_of_joining + earned_leave_eligibility_days

The effective accrual start date is calculated as:

max(effective_from, date_of_joining + eligibility_days)

Why:

Accrual must not begin before both:

  • The leave policy period is active
  • The employee has completed the required service period
  1. Updated Earned Leave Accrual Logic to Respect Eligibility
  • Earned leave allocation now starts only from the computed accrual start date.
  • No earned leave is accrued before eligibility.
  • Backdated leave allocation excludes periods before the employee becomes eligible.
  • The first eligible period is prorated if eligibility begins in the middle of a month.
  • Normal periodic accrual continues unchanged after eligibility begins.

Why:

  • This ensures the service-period rule is enforced consistently during both normal and backdated allocation flows.
  1. Updated Earned Leave Schedule Generation
  • Earned leave schedule rows are not generated before eligibility.
  • Schedule generation begins only from the first eligible accrual period.
  • Future schedule rows continue using the configured accrual frequency.

Why:

  • Schedule rows should reflect actual accrual eligibility, not only the leave period dates.
  1. Fixed Catch-Up Allocation Row Consistency
  • Preserved the full catch-up allocation row created during leave policy assignment.
  • Prevented the first catch-up row from being overwritten by only the prorated amount of the first eligible period.

Why:

  • Without this, the allocated total could be correct while the first schedule row showed a lower amount, causing a mismatch between the schedule and the actual allocation.
  1. Kept Application Restriction Aligned by Default
  • When earned_leave_eligibility_days is set, applicable_after is raised to at least the same value.

Why:

  • This keeps accrual eligibility and application eligibility aligned by default.
  • It avoids situations where leave accrues only after a service period but can still be applied for earlier due to looser application settings.
  1. Added Regression Test Coverage

Added tests for:

  • No accrual before eligibility
  • Prorated first eligible period
  • Unchanged full monthly accrual after eligibility
  • Backdated assignment respecting eligibility
  • Catch-up schedule row matching the allocated total
  • Alternate eligibility values such as 120 days

Why:

  • These cases cover both the new eligibility rule and the schedule consistency fix.

Use Case

A company policy may require earned leave to begin only after an employee completes a defined service period, such as 365 calendar days from the Date of Joining.

In this case:

  • Leave should not accrue before the eligibility date.
  • The first eligible month may be prorated if eligibility begins during the month.
  • Full periodic accrual should continue from the following eligible periods.

Example Scenario

Date of Joining: 2025-06-15

Eligibility Days: 365

Leave Period: 2026-01-01 to 2026-12-31

Leave Control Panel Based On: Leave Period

Annual Allocation: 30

Frequency: Monthly

Allocate On Day: First Day

Assignment Created On: 2026-07-28

Expected Result

  • Eligibility date: 2026-06-15
  • June prorated accrual: 1.33
  • July full accrual: 2.5
  • Total allocated on 2026-07-28: 3.83
  • First catch-up schedule row remains 3.83

Feature Flow

  1. Create an earned Leave Type.
  2. Configure earned_leave_eligibility_days.
  3. Assign the leave policy to an employee.
  4. The system calculates the eligibility date using the employee's Date of Joining.
  5. No earned leave is accrued before the eligibility date.
  6. If eligibility begins during an accrual period, the first eligible period is prorated.
  7. Full periodic accrual continues after the first eligible period.
  8. Backdated assignments exclude all ineligible periods.
  9. Earned leave schedule rows are generated only from the eligibility date.
  10. Catch-up schedule rows remain consistent with the actual allocated total.

Test Scenarios

  1. No accrual is created before the eligibility date.
  2. The first eligible month is prorated correctly.
  3. Full monthly accrual remains unchanged after eligibility.
  4. Backdated leave policy assignment respects the eligibility date.
  5. The catch-up schedule row matches the allocated total.
  6. Alternate eligibility values, such as 120 days, behave consistently.
image image image

no-docs

Comment thread hrms/hr/doctype/leave_type/leave_type.py
@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (4): Last reviewed commit: "fix(earned_leaves): block eligibility ch..." | Re-trigger Greptile

Comment thread hrms/hr/doctype/leave_type/leave_type.py Outdated
Comment thread hrms/hr/doctype/leave_type/leave_type.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant