Who can delete invoices in your Odoo?
TechnoVision Engineering
Publication date pending · 8 min read
An auditor asks it, or a finance director asks it after an invoice goes missing. It sounds like a five-minute question with a definite answer. It has a definite answer. Producing it is the problem.
Why the obvious methods fail
There are three things people try first, and each one is wrong in a different way.
| Method | Why it gives the wrong answer |
|---|---|
| Read the user form | It shows the boxes that were ticked, not the transitive closure of what those groups imply |
| Check who has the Accounting Manager group | Delete on account.move may be granted by several groups, and access is a union — Accounting Manager is one of the answers, not the answer |
| Look at ir.model.access for account.move | Correct as far as it goes, and it tells you which groups, not which people — and it silently ignores every account that bypasses access control |
The four things a real answer includes
A correct answer to "who can delete invoices" has to account for all of these, and an answer missing any one of them is not a partial answer, it is a wrong one.
- Every group that grants unlink on account.move — not the first one you find, because access is a union and there is no deny.
- Every user who holds any of those groups, through the full transitive closure of group inheritance rather than the ticked boxes.
- Any record rules that narrow which invoices those users can touch — and whether those rules are global (narrowing) or group rules (which OR together and can widen).
- Every account that bypasses access control entirely: the superuser, and anyone with Settings access.
The bypass accounts are usually the answer
The version that matters more
The same machinery answers a question that comes up far more often and gets asked far more casually: what could the person who left last month still do, if their account is still active?
And its mirror image, which is the one that actually creates risk: make the new joiner like the person they are replacing, minus the finance parts. Copying a user copies the ticked boxes. It does not tell you what the closure of those boxes grants, so "minus the finance parts" is done by eye, and it is usually done wrong.
Answering it in practice
For one model and a small database you can do it with SQL and an afternoon. The problems start when the answer needs to be current: any group change invalidates it, and nobody re-runs an afternoon of SQL after a routine permission change.
That is the gap Access X-Ray fills. It resolves the four layers on demand and shows the answer with the path that produced it — by user, by model, or as a side-by-side comparison of two accounts. The comparison view is the one people use most, because "make her like him, minus finance" turns out to be the question everybody actually has.
What good looks like
You should be able to answer, in under a minute and without writing SQL: who can delete this, who can export this, what can this account reach, and how do these two accounts differ. If any of those takes longer than a minute, the answer is not being checked — and a permission nobody checks is a permission nobody controls.