[Frappe HR v16] Biweekly Payroll with 30-day commercial month — payment_days issues

Setup summary:

  • Frappe HR / ERPNext v16 (latest)

  • Payroll frequency: Biweekly (two payrolls per month: 1–15 and 16–end of month)

  • Company rule: 30-day commercial month — each fortnight must equal exactly 15 days.

  • Salary structure earnings:

    • Salario Mensual (B): 40% of base salary

    • Bono Alimentación (BA): Fixed $40/month allowance

    • Complemento de Alimentación (CA): Remaining 60% minus the $40 fixed bonus

The problem: Our company follows a 30-day commercial month rule. Regardless of whether the month has 28, 30, or 31 days, each full fortnight must pay exactly 50% of the monthly salary (15 days).

Current formulas use payment_days as the base:

  • Salario Mensual: (base * 0.4 / 30) * payment_days

  • Bono Alimentación: (40 / 30) * payment_days

  • Complemento Alimentación: ((base * 0.6 - 40) / 30) * payment_days

This calculation fails in two scenarios because payment_days reflects real calendar days:

  1. February (2nd fortnight, 16–28): payment_days = 13. The employee gets paid 13/30 instead of 15/30.

  2. 31-day months (2nd fortnight, 16–31): payment_days = 16. The employee is overpaid by 1 day.

Specific Scenarios to handle:

  • Mid-month joiners: If an employee starts on the 20th, they should be paid for 11 days (from 20th to 30th) based on the 30-day rule, regardless of the actual calendar days.

  • Proportional Deductions: When an employee has an absence, the reduction must apply proportionally to all 3 components. My current formulas handle this via payment_days, but the base is incorrect due to the calendar issue mentioned above.

What I’ve tried:

  • Setting formulas with payment_days — breaks on short/long months.

  • Looking for a “Fixed Days” or “Commercial Month” setting in HR/Payroll Settings — couldn’t find a native toggle in v16.

  • Using complex condition fields in salary components — hard to maintain and audit.

Questions:

  1. Is there a native way in Frappe HR v16 to force total_working_days = 15 for biweekly periods regardless of the calendar?

  2. Is a Server Script on before_save of the Salary Slip the recommended approach to normalize payment_days to 15 (or calculate proportional days for new hires) before components are processed? Will this work correctly with bulk Payroll Entry?

  3. Alternatively, would it be cleaner to set fixed amounts per fortnight (e.g., base * 0.4 / 2) and handle absences/late entries via a separate Deduction component using (base / 30) * absent_days?

Any guidance from the community or anyone who has solved Latin American “Commercial Month” payroll in Frappe HR would be greatly appreciated.

Versions:

  • Frappe: v16

  • Frappe HR: v16

  • ERPNext: v16