Payroll (HR Payroll)#

In payroll, hours + expenses + contracted pay are combined into payslips (hr.payslip). They then flow to Netvisor for payment.

Monthly rhythm#

Typical month:

DayTask
1–31Installers log hours via the PWA, foreman approves weekly
30–31Office closes the month, verifies all approvals are done
1st of next monthPayslip creation from previous month’s data
1.–5.Payslip review, corrections
5.–10.Sending to Netvisor for payment
14./15.Pay date (via Netvisor)

Creating a payslip#

HR → Payroll → Payslips → Create.

Typical fields:

  • Employee — who
  • Period — e.g. 1 May 2026 – 31 May 2026
  • Contract — only selectable once an employment contract exists

Then → Compute Sheet calculates lines from the employee’s contract + period’s hours + expenses.

Contract types (hr.contract)#

Generally at ELT:

  • Monthly salary — office staff and foreman
  • Hourly wage — for some installers, especially part-time
  • Commission-based — sales side (where applicable)

The contract must be active at the start of the payroll period. Expiring contracts (e.g. fixed-term ending) must be watched.

Hours flow to payslips#

If an installer is hourly-paid, their FSM task hours flow into the payslip automatically if:

  • The hour is approved (state = Approved).
  • The hour is within the payroll period.
  • The hour is billable=False (if billable=True → invoicing only, not payroll).

For monthly-salary employees, hours don’t directly affect pay but appear on the payslip as reference info.

Expenses on payslips#

Approved HR Expenses rows (mileage, per diems, materials) flow into payslips as net payments (untaxed). The installer gets these as a single payment alongside the salary.

Tax and employer contribution handling#

Finland-specific:

  • Withholding tax is set from the employee’s tax card and the contract.
  • TyEL / pension is ELT’s obligation at the percentage set by the insurer.
  • Sickness insurance contribution and unemployment insurance at percentages from the government tables.

These are calculated automatically from the contract + the in-force tax rules, which are updated yearly via Odoo’s HR Payroll Localization module.

Sending to Netvisor#

Per payslip (manual):

  1. Open the Payslip.
  2. Action → Send to Netvisor.
  3. Netvisor accepts, returns a key.

All at once (with auto flag or cron on):

  • Cron Send payslips to Netvisor, monthly 1st day at 08:00 — off by default.
  • The auto_send_payroll=True flag triggers in action_payslip_done.

Recommendation: manual until you’ve verified XML builds correctly and Netvisor shows payslips as they look in Odoo. Only then switch to automation.

Troubleshooting#

Hours don’t flow to the payslip
- **Approvals**: Is every row `state=Approved`? Submitted doesn't flow. - **Contract**: Is `hr.contract` active on the day of the hour? - **Billable flag**: If billable=True, the row goes to customer invoicing, not payroll. Check this is correct per employee.
Payslip state stuck in ‘Draft’
Compute Sheet may have failed. Open chatter — errors logged there. Common: - Missing work schedule on the contract - Empty `wage` field - Tax card details missing
Netvisor sending returns an error
- Is the **business ID** in Netvisor settings in the right `1234567-8` form? - Do **all employees have a personal ID** in the Odoo employee form? Netvisor requires it. - Is the **payroll period numbering unique**? Sometimes a duplicate on the Netvisor side prevents resending. [Netvisor integration](../netvisor/) troubleshooting has more.