HR and Payroll is the Odoo module that touches every employee — and where compliance failure has the most direct legal consequences. In Bangladesh, the Labor Act 2006 (amended 2018) sets mandatory minimums for leave, Provident Fund, and Gratuity that every employer must meet. Odoo can be configured to enforce all of them — but it does not arrive pre-configured for Bangladesh.
This guide covers the complete setup sequence: employee records, leave types, salary structures, PF rules, Gratuity provisioning, income tax deduction, and payroll processing. I've drawn on live deployments in RMG factories (400+ employees), SME trading companies, and Dhaka-based service businesses.
A payroll error affects real people. Test every salary rule against actual employee data before go-live.
Bangladesh labor law baseline
Before configuring anything in Odoo, confirm the legal baseline your payroll must meet. Under the Bangladesh Labor Act 2006 (as amended), the mandatory minimum obligations are:
| Obligation | Legal minimum | Who it applies to |
|---|---|---|
| Earned Leave | 1 day per 18 working days (approx. 10–11 days/year for factory workers; varies for staff) | All workers after 12 months of service |
| Sick Leave | 14 days per year with full pay | All employees |
| Casual Leave | 10 days per year with full pay | All employees |
| Maternity Leave | 16 weeks (8 pre + 8 post delivery) with full pay | Female employees with ≥6 months service |
| Festival Leave | 11 days per year (Eid ul-Fitr, Eid ul-Adha, and national holidays) | All employees |
| Provident Fund | 5% employee contribution + 5% employer contribution of basic salary (where PF scheme exists) | Employees covered by company PF scheme |
| Gratuity | 30 days' wages per year of service (workers); 1 month basic per year (staff) | Employees with ≥1 year of service on termination |
BGMEA/BKMEA member factories are additionally governed by the Minimum Wage Board gazette notification, which sets minimum wages by grade for RMG workers. If your factory is a BGMEA member, your Odoo salary structure must enforce these minimums. Underpaying by grade is a compliance failure — not just a payroll error. The practical setup: pull the current Minimum Wage Board gazette for your sector, create one Job Position per gazetted grade, record the gazetted floor wage on each, and review every contract's basic wage against its grade floor before confirming it. Treat any contract below the floor as a blocker, not a warning.
Employee master setup
Each employee record in Odoo (Employees → New) must capture these Bangladesh-specific fields:
| Field / Tab | What to configure |
|---|---|
| Job Position / Grade | Link to a Job Position that determines salary band and PF eligibility. Create grades that match your company's grading structure (Grade A, B, C or Officer, Senior Officer, Manager). |
| Date of Joining | Critical for Gratuity calculation and leave entitlement accrual. Odoo calculates years of service from this date. |
| NID / Passport | Store National ID number in the "Private Information" tab. Required for bank transfers, PF registration, and income tax filing. |
| Bank Account | Add under Private Information → Save → Salary tab → Bank Account. This is the account Odoo uses for direct payroll payment. Required if you batch-pay salaries via bank transfer. |
| TIN (Tax ID) | Employee TIN for income tax computation and Form-16 equivalent. Store in the Private Information tab under "Tax ID". |
| Contract | Every employee must have an active contract (Employees → Employee → Contracts tab → New). The contract sets the salary structure, wage, and PF/Gratuity eligibility. Payroll will not run for an employee without a confirmed contract. |
Leave types & allocation
Odoo's Leave module (Time Off) manages requests, approvals, and balance tracking. Configure these leave types for Bangladesh:
Earned Leave (Annual)
Accrual type: "Based on worked time" — 1 day per 18 working days. Configure as carried-forward leave. Unused balance must be encashed or carried to next year.
Sick Leave
Allocation type: Fixed (14 days at start of each leave year). Sick leave cannot be carried forward. Paid at full basic salary.
Casual Leave
Allocation type: Fixed (10 days at start of leave year). Cannot be accumulated or encashed. Used for short-notice personal emergencies.
Maternity Leave
Create as a separate leave type with "No allocation" (applied on request). Fully paid. Requires medical certificate. Cannot be denied to eligible employees.
Festival / Public Holiday
Configure as Public Holidays in the Work Schedule (not leave allocations). These are non-working days on the company calendar — they don't consume leave balance.
Without Pay Leave
Create as a separate leave type with "No allocation" — the leave is unpaid and triggers a salary deduction on the payslip. Odoo calculates the deduction automatically if the "Leave Deduction" option is enabled on the salary structure.
Set the leave approval workflow on each leave type: one-step (direct manager) or two-step (manager then HR). For large manufacturing operations with 400+ employees, I recommend a two-step approval for Earned Leave and Maternity Leave; single-step for Casual and Sick.
Salary structure
The salary structure defines every earning and deduction line on the payslip. In Bangladesh, the typical staff salary structure looks like this:
In Odoo, each line is a salary rule within the salary structure. Go to Payroll → Configuration → Salary Structures → New. Add rules for each earning and deduction. Rules are ordered — Basic Salary must exist before HRA can reference it (since HRA = 50% × Basic).
Provident Fund (PF) setup
PF in Odoo is two salary rules: one employee deduction, one employer contribution.
| Rule | Code | Type | Computation | Account |
|---|---|---|---|---|
| Employee PF | EMP_PF | Deduction (negative) | -5% × Basic Salary | PF Payable (2XXX) |
| Employer PF | COM_PF | Not on payslip — company cost | 5% × Basic Salary | PF Payable (2XXX) |
Both amounts accumulate in the PF Payable account. At month-end, the total PF Payable balance is remitted to the employee's PF trust or fund. The journal entry: Debit PF Payable → Credit Bank. After remittance, the PF Payable account balances to zero.
In most Bangladesh companies, PF applies only after a probation period (typically 3–6 months). In Odoo, handle this by creating two contract templates: one "Probation" template with a salary structure that has no PF rules, and one "Confirmed" template that includes PF. When an employee passes probation, update their contract to the Confirmed template.
Gratuity provision
Gratuity in Bangladesh is a terminal benefit — paid only when the employee leaves after completing at least one year of service. In Odoo, track Gratuity as a monthly provision (accrual), not a payslip deduction.
The monthly accrual entry:
- Debit: Gratuity Expense (P&L)
- Credit: Gratuity Provision (Balance Sheet liability)
Accrual amount = (Last Basic Salary ÷ 12) × years of service. For most companies, this is approximated as 1/12 of annual basic salary per month. The Gratuity Provision account on the balance sheet grows each month. When an employee leaves after qualifying for Gratuity, the actual payment is settled against the provision: Debit Gratuity Provision → Credit Bank.
Odoo does not have a native Gratuity provision module for Bangladesh. Implement this as either (a) a manual monthly journal entry, or (b) a salary rule marked as "Does not appear on payslip" with the appropriate account mapping — the rule calculates the provision per employee and posts the accrual automatically during payroll processing.
Income tax on salary
Income tax deduction at source (TDS on salary) must be applied monthly from the salary of every employee who earns above the tax-free threshold. For the 2025–26 tax year, the threshold is BDT 3,50,000 annual income (BDT 29,167/month gross).
Configure TDS as a salary rule:
- Rule code:
INCOME_TAX - Type: Deduction (negative, appears on payslip)
- Computation: Python code that applies the Bangladesh progressive tax slabs to the employee's annual projected income, divides by 12, and returns the monthly TDS amount
- Account: TDS on Salary Payable (2XXX)
The progressive tax slabs for Bangladesh FY2025–26 are:
| Annual Income (BDT) | Tax Rate |
|---|---|
| Up to 3,50,000 | Nil |
| 3,50,001 – 4,50,000 | 5% |
| 4,50,001 – 7,50,000 | 10% |
| 7,50,001 – 11,50,000 | 15% |
| 11,50,001 – 16,50,000 | 20% |
| Above 16,50,000 | 25% |
Implement this as a Python-based salary rule in Odoo. The rule annualises the employee's current month gross salary, applies the slab calculation, and returns 1/12 of the annual tax liability. At year-end, reconcile the total TDS deducted against the employee's actual tax return to handle any over- or under-deduction.
Salary TDS must be remitted to the NBR via treasury challan by the 15th of the following month. This is tracked separately from VAT compliance — see my guide on NBR VAT compliance in Odoo for the broader NBR filing structure. Salary TDS remittance uses Treasury Form-Challan, not the Mushak forms.
Running payroll in Odoo
Once salary structures, PF rules, and leave deductions are configured, the monthly payroll process in Odoo is:
- Close attendance / leave — ensure all leave requests for the month are approved or rejected. Any approved Unpaid Leave affects the salary deduction calculation.
- Create payslip batch — Payroll → Payslip Batches → New. Set the period (e.g., May 2026). Click "Generate Payslips" — Odoo creates one draft payslip per active employee with a confirmed contract.
- Review payslips — open any payslip and verify the computed values. Pay particular attention to employees who had salary changes, promotions, or joined mid-month (partial month calculation).
- Validate the batch — once satisfied, Confirm the batch. Odoo posts the journal entries: Salary Expense (P&L) → Salaries Payable (BS), Employee PF deduction, Employer PF contribution, TDS deduction, and Gratuity accrual.
- Pay salaries — generate the salary payment in Accounting → Vendor Bills or use Batch Payments. Debit Salaries Payable → Credit Bank. For companies paying via mobile banking (bKash, Nagad), export the payment file from Odoo and upload to the mobile banking portal.
- Remit statutory deductions — by the 15th of the following month: PF to PF fund, TDS to NBR treasury challan.
For change management during payroll go-live — convincing finance teams and employees to trust the new system — see my field notes on change management in ERP deployments. Payroll is the module that generates the most resistance: everyone checks their payslip.
Payroll configuration for Bangladesh compliance is one of the more technically involved parts of an Odoo implementation. For a sense of where it sits in the overall project budget, try the Odoo cost estimator. If you're setting up for the first time or migrating from a legacy payroll system, reach out for a configuration review →
Frequently asked questions
How do I configure Provident Fund in Odoo for Bangladesh?
PF is configured as two salary rules: Employee PF (–5% of Basic, posted to PF Payable) and Employer PF (+5% of Basic, also to PF Payable, but not shown on the employee's payslip — it's a company cost). Both accumulate in the PF Payable account monthly. Remit the combined balance to the PF fund by the 15th of the following month. Exclude employees in probation by using a separate contract template without PF rules.
How is Gratuity calculated and provisioned in Odoo?
Under Bangladesh Labor Law, Gratuity = 1 month's basic salary × years of service (for staff), paid on termination after 1+ year of service. In Odoo, provision it monthly via a journal entry: Debit Gratuity Expense (P&L) → Credit Gratuity Provision (Balance Sheet). Accrual = 1/12 of annual entitlement. On the employee's last day, settle the Gratuity Provision balance: Debit Provision → Credit Bank.
What leave types are legally required in Bangladesh?
Under the Bangladesh Labor Act: Earned Leave (10–11 days/year, accrual-based), Sick Leave (14 days/year, fixed allocation), Casual Leave (10 days/year, fixed allocation), Maternity Leave (16 weeks for eligible female employees). Public holidays (11 national days) are configured as non-working days on the Work Schedule — they do not consume leave allocation.
Can Odoo handle income tax (TDS) on salary for Bangladesh?
Yes, with a custom Python-based salary rule that implements the NBR's progressive income tax slabs. The rule annualises the monthly gross, applies the current-year tax table, divides by 12, and posts the monthly TDS to an Income Tax Payable account. This must be recalculated if an employee's salary changes mid-year (Odoo handles the recalculation automatically on the next payslip run).