← All articles

Blog

How to Localize Odoo for Indonesian Tax: PPN, PPh, and e-Faktur

A practical walkthrough of localizing Odoo for Indonesian tax — PPN 12%, PPh withholding, e-Faktur integration, and the gotchas that catch most teams.

5 min read
  • bottom

Out of the box, Odoo’s Indonesian localization is acceptable but not finished. It gives you a starting chart of accounts and a few default tax codes, and then leaves you to deal with PPN at the new 12% rate, the maze of PPh withholding types, and the entirely separate question of how invoices get into e-Faktur. Most teams discover the gaps three days before their first month-end.

This is the practical version of what actually has to be configured, what costs money, and what’s free.

What the l10n_id module actually gives you

When you install l10n_id (the Indonesia localization), you get a basic chart of accounts following the Indonesian standard structure, PPN 11%/12% tax codes, PPh 21/23/4(2)/26 tax codes as templates, and Indonesian fiscal position definitions. That’s the floor.

What it does not give you: a working e-Faktur integration, correct withholding behavior on vendor bills, NPWP validation on partners, automatic NSFP (Nomor Seri Faktur Pajak) sequencing, or the .xml export format that e-Faktur Desktop actually wants. All of those are gaps you fill yourself or with paid add-ons.

PPN 12% — straightforward, with one trap

PPN 12% is the easiest piece. Configure the tax in Accounting → Configuration → Taxes, set the rate, point it at the correct payable and receivable accounts, and apply fiscal positions if you sell across categories. If you started Odoo before April 2022 you may still have 10% defaults lying around — go check, because old products sometimes inherit old tax codes.

The trap is around partial-VAT goods and the recent rules where certain categories use a different effective base. Odoo handles this with tax computations on a subset of the amount; you have to model it as a tax with a “based on” filter rather than a simple percentage. If your accountant says “the effective rate is 1.1%” or “12% of 11/12 of the price”, that is the signal that you need a non-trivial tax setup, not a single number.

PPh withholding — where most setups break

PPh on vendor invoices is the part that catches the most teams. The local module gives you the tax codes, but doesn’t wire them into a sane workflow. The two failure modes we see all the time:

The first is treating PPh as a normal tax — applying it on the invoice line and ending up with the wrong cash payment, because PPh is a deduction from what you pay the vendor, not an addition. The second is doing it manually in Excel, then re-keying numbers into Odoo, which works until the volume hits about thirty vendor invoices a month.

The right pattern: configure each PPh type (21 for individuals, 23 for services to corporations, 4(2) for specific final taxes, 26 for non-residents) as a separate withholding tax that posts to a “PPh payable” account. Set the calculation to be on the DPP (the tax base, not the gross), and link it to the journal entry so the bukti potong report can be generated cleanly at month-end. Then build a simple report — even just a saved filter on journal items — that gives you the data your accountant needs for the SPT Masa filing.

e-Faktur — Odoo does not talk to it directly

This is the part where expectations diverge most from reality. e-Faktur is a separate desktop application provided by DJP (Direktorat Jenderal Pajak). It expects either manual entry or a specific .csv import format. Odoo does not, out of the box, push invoices into e-Faktur.

There are three workable patterns. The cheapest is manual: your tax team exports a list from Odoo and re-keys it into e-Faktur. This works for under maybe forty B2B invoices a month and is what most small UKM do. The second pattern is a CSV export — write or buy a small Odoo report that produces the exact .csv shape e-Faktur Desktop imports, including the NPWP, NSFP slot, and DPP fields. We’ve built this for clients in about 2–4 development days. The third pattern is full API integration via one of the licensed PJAP (Penyedia Jasa Aplikasi Perpajakan) providers — Pajakku, OnlinePajak, Klikpajak — which gives you direct posting from Odoo. Expect Rp 25–60 juta in setup plus a monthly fee, justified if you do more than around two hundred faktur a month.

NPWP and partner data hygiene

Before any of the above works, your partner records have to be clean. Every customer and vendor that takes a faktur needs a valid 15- or 16-digit NPWP stored on the contact. Without this, e-Faktur will reject the line. We strongly recommend adding a validator to the partner form (a few lines of Python in a custom module) that refuses to save an invalid NPWP, and a one-time data cleanup pass before go-live. The cost is small. The cost of not doing it is months of bad invoices and rejected faktur.

What it actually costs to do properly

For a single-entity SME doing PPN, PPh, and CSV-based e-Faktur, expect roughly Rp 35–75 juta in implementation work on top of your base Odoo project. This covers the chart of accounts cleanup, withholding tax configuration, NPWP validation, a custom e-Faktur CSV export, the bukti potong report, and training your finance team. Multi-entity setups (a PT plus a CV, or operations across Jakarta and Bali with separate NSFP ranges) add another Rp 20–40 juta.

What to ask any vendor before signing: show me a sample CSV export you’ve built for e-Faktur, show me a real vendor bill with PPh 23 posted correctly, and tell me how the bukti potong report works at month-end. If they wave their hands at any of these, keep shopping.

If you’d like a candid look at where your current Odoo setup stands on Indonesian tax — and what the gap is to “month-end is boring again” — we offer a free one-hour review with one of our localization leads. Bring your chart of accounts and a sample vendor bill; we’ll point at the cracks.