Skip to main content

Payroll Processing

Payroll is run per BU, per period. ONe-HR has two separate computation engines — one for Non-Executives and one for Executives — because the formulas diverge meaningfully: executives do not receive overtime or holiday-premium pay, but still have allowances, leave processing, and mandatory deductions.

Audience

Payroll officers, compensation specialists, MSD administrators.

Screenshots in this section

Payroll screenshots have every money column blurred — basic pay, allowances, contributions, deductions, net pay. The structure of the form and the workflow is what we document, not the specific figures.

Data model

ModelPurpose
hr.payroll.masterOne record per payroll batch (one per BU per period).
hr.payroll.transactionsOne record per employee per batch — the employee's payslip.
hr.payroll.attendanceTime-card data attached to the batch.
hr.employee.loan.deductionPer-payroll loan deduction records linking back to the loan ledger.
hr.payroll.supplementalManual additions or adjustments on a specific transaction.
hr.employee.other.benefits.transactionOB amounts paid in this payroll.

Running payroll

HR ▸ Tasks ▸ Compute Payroll (Non-Executives) or Compute Payroll (Executives).

Each wizard creates a new hr.payroll.master record with:

FieldExample
NameNE-2026-APR (Non-Exec) / EX-2026-APR (Exec)
ExecutivesBoolean — drives the employee filter
Month of / Year ofPeriod components
From / To datesPeriod boundaries

Employee selection

Each wizard selects active employees for the logged-in BU matching the executive flag:

employees = env['hr.employee'].search([
('company_id', '=', company.id),
('active', '=', True),
('executive', '=', executives_flag),
('include_in_payroll', '=', True),
])

Employees with include_in_payroll=False are skipped — that's how an HR admin excludes a specific employee without archiving them.

Per-employee flow

For each selected employee, the wizard:

  1. Creates an hr.payroll.transactions row.
  2. Pulls attendance/time-card data for the period (hr.payroll.attendance).
  3. Walks the time card day-by-day, accumulating: basic pay, OT hours (various types), absences, late/undertime, leave days, LWOP days.
  4. Computes each pay component using the formulas below.
  5. Processes government contributions (SSS/PhilHealth/HDMF) with a balance guard — skip if the contribution would push net pay negative.
  6. Processes active loans — deduct min(deductions_per_payroll, remaining_balance) per loan, with the same balance guard.
  7. Sums everything into gross pay, total deductions, and net pay.

Basic pay components

Daily basic pay

  • Source: employee.daily_rate
  • Applied for every non-absent day, for both Non-Executives and daily-paid Executives.

Monthly basic pay

  • Source: employee.semi_monthly_rate (half of monthly — the semi-monthly payout)
  • Applied for pay_type='monthly' employees.

Leave processing

For each day in the period, the wizard looks up approved leave transactions covering that day. For each match:

leave_qty = 0.5 if half_day else 1.0
if balance > 0:
balance -= leave_qty # paid leave — deduct from balance
leave_pay += leave_qty * daily_rate
else:
lwop_day += leave_qty # no balance — Leave Without Pay
lwop_ded += leave_qty * daily_rate

Key rules:

  • Half-days count as 0.5.
  • Balance-zero days become LWOP automatically — daily rate is deducted.
  • Balance reduction happens during the payroll run; the is_payroll_locked flag on the leave transaction then prevents further edits.

Overtime (Non-Executives only)

Executives do not receive OT, RD-OT, holiday-premium, or night-differential pay. For Non-Executives, the multipliers are:

Pay typeFormulaApplies when
Regular OThourly_rate × 1.25 × hoursExtra hours beyond the scheduled day
Rest Day OTFirst 8h: hourly_rate × 1.3 × hours. Beyond 8h: hourly_rate × 1.69 × (hours - 8)OT on a non-work day
National Holidayhourly_rate × 2.0 × hoursWork on a regular holiday
Special HolidayFirst 8h: hourly_rate × 1.3. Beyond 8h: hourly_rate × 1.69Work on a special non-working holiday
Night Differentialhourly_rate × 1.0 × hours (additional)Hours within the 22:00–06:00 window
Night Diff OThourly_rate × 0.10 × hours (additional)ND hours that are also OT

All numeric multipliers are hardcoded in the wizard — changing them requires a code update.

Lunch break interaction

OT that overlaps the lunch break has 1 hour deducted from the OT hours (see Overtime & OB). The deducted-or-not decision is recorded on hr.filed.overtime.lunch_break_deducted at approval time, before payroll runs.

Allowances (both Exec and Non-Exec)

Flat amounts added per payroll — Meal, Transportation, Miscellaneous, plus COLA (daily_cola × working days in period). Active Other Benefits are also added, each recorded as one hr.employee.other.benefits.transaction row for trail.

Deductions

DeductionFormula
Latelate_hours × hourly_rate
Undertimeundertime_hours × hourly_rate
Absentabsent_days × daily_rate
LWOPlwop_day × daily_rate

Government contributions

Applied with a balance guard — the deduction is only taken if (net_pay - deduction) > 0, otherwise skipped (the employer's matching contribution is still recorded; the unpaid employee share becomes an HR-manual catchup).

SSS

Bracket-lookup from sss.table using employee.tm_monthly:

sss_ee = empshare / 2 # semi-monthly
sss_er = emprshare / 2

PhilHealth

From the employee's Compensation tab (ded_phic_ee, ded_phic_er) — no bracket lookup at payroll time. Already the semi-monthly amounts.

HDMF

From the employee's Compensation tab (ded_hdmf_ee, ded_hdmf_er), divided by 2 at payroll time for the semi-monthly split. Defaults to 100 each per semi-monthly period.

Loans

Active loans (active=True, remaining_balance > 0, date_start <= period_end) are deducted:

deducted_amount = min(loan.deductions_per_payroll, loan.remaining_balance)

One hr.employee.loan.deduction row is created per loan per payroll, and loan.remaining_balance is decremented.

Withholding Tax

Computed from the employee's tax_code + tm_{period} against the WHT table (see Compliance Tables — WHT).

Supplemental entries

A payroll transaction can have one or more hr.payroll.supplemental rows. Each row is a named positive or negative adjustment applied on top of the computed pay. Use cases:

  • Retroactive rate adjustment.
  • One-time bonus / incentive.
  • Reimbursement for expenses not covered by OB.
  • Correction for a prior-period error.

Supplementals are manually added after the compute wizard completes — they don't reset on recompute.

Payroll review

The payroll master form shows a stat button for the count of transactions. Each transaction can be opened individually, showing the full breakdown (basic pay, OT lines, allowances, deductions, contributions, net pay).

Re-running the wizard for the same period replaces the existing transactions (after confirmation) — useful when attendance or rates were corrected after the first run.

Posting

Once reviewed, payroll is posted — this flips is_payroll_locked=True on every leave transaction and loan deduction that contributed to the batch, preventing retroactive edits. After posting:

  • Leave transactions in the period can no longer be edited (only viewed).
  • Loan remaining_balance is locked in.
  • Supplementals can still be added but are flagged as post-posting adjustments.

This is the hard boundary between "working draft" and "committed payroll" — anything past this needs a supplemental in the next period, not an edit here.