Why 4 hours — not 4 weeks
If your Odoo has been "almost ready" for six months, you don't have a waiting problem. You have a diagnosis problem. This template gives you the minimum-sufficient list of 50 checks that the CFO and tech lead of a Peru, Mexico, Colombia, Argentina, or Chile SMB can run through in 4 hours and get an honest answer: rescue the system, optimize it, or burn it down and migrate to a clean Odoo 18.
A forensic external audit runs 30–60 person-hours and costs USD 1,500 to USD 5,000 per install. Doing that every quarter for every SMB ERP is too expensive. The self-audit solves a different problem: every three months, give the team a signal whether it's worth calling in an external expert at all.
Across a sample of 60+ Odoo installs in LATAM (Peru, Mexico, Chile, Colombia, Argentina from 2018 to 2026), 78% of systems were recoverable — but only when problems were caught before month-end close started slipping by 14 days or invoices began bouncing in batches at SUNAT, SAT, DIAN, ARCA, or SII.
The self-audit is early warning. The external consultant's PDF is surgery. Don't confuse the two, and don't expect one to substitute for the other.
The 10 categories of the self-audit
The 50 checks split into 10 categories of 4 to 6 items each. Every item gets a verdict: yes / no / partial. The more nos in a single category, the higher the priority of a focused audit in that area. Reserve the detailed external audit for cases where the reddest category is fiscal or custom code.
#1. Configuration and version (5 checks)
- Odoo version: 16.0, 17.0, or 18.0 LTS. If you're still on 13–15, you're running a deprecated stack with no security patches.
- Edition: Community or Enterprise. The full accounting module in Community exists only through third-party OCA modules.
- Developer mode is enabled for users at the right technical level — no more, no less.
- Active user count reconciled against the license. Going over the limit invites an audit from Odoo SA.
- A process document exists that references concrete Odoo modules, not "everything works somehow."
#2. Fiscal localization (8 checks)
The most explosive category. Most fines originate here.
- The relevant
l10n_xxmodule is installed (l10n_pe,l10n_mx,l10n_co,l10n_ar,l10n_cl). - The
l10n_xxversion matches the Odoo major version. OCA l10n-peru patches typically lag the core upgrade by 2–4 weeks. - Electronic-signature certificates are installed and don't expire within the next 90 days.
- Peru:
l10n_pe_ediconfigured for CPE. Is the GRE (electronic delivery note) closed correctly? - Peru: SIRE integration (RVIE + RCE) is live. If it isn't, that's a deferred fine.
- Mexico: Carta Porte 3.1 and Pagos 2.0 complements installed.
- Colombia: electronic payroll integrated. Is there a RADIAN connector for invoice factoring?
- Argentina / Chile: webhooks to ARCA (formerly AFIP) and SII are active. Validation rejections are logged where someone can actually find them.
#3. Custom code (5 checks)
- How many lines of custom code in
addons/custom/. More than 5,000 — either you're an ERP builder, or you have a problem. - Custom modules have unit tests. At least one.
- Every custom module ships with a README that explains why, not what.
- How many custom modules duplicate native functionality (Sale, Inventory, MRP). That's code that breaks on every upgrade.
- Who signed the last commit on each custom module. Is that person still at the company?
#4. Data quality (6 checks)
- How many duplicates in
res.partnerbyvat(GROUP BY vat HAVING COUNT(*) > 1). - How many products in
product.templatewith no active BoM — critical for manufacturing SMBs. - How many accounting lines without a counterparty (
account.move.line WHERE partner_id IS NULL). Each one breaks the by-customer report. - Phantom SKUs: products with no movement in the last 12 months.
- Total Odoo stock reconciles with the physical inventory (±2%).
- Last year's accounting periods are closed, or left open for after-the-fact corrections.
#5. Performance (4 checks)
- Top-10 slow queries in
pg_stat_statements. Any over 5 seconds. - Postgres database size: up to 20 GB is normal, 20–50 GB requires regular vacuum and cleanup, more than 50 GB demands real archival.
- POS response time during peak hours: under 1 second.
- How often per day
WorkerLost,MemoryError, or 504 Gateway Timeout shows up in the logs.
#6. Integrations (5 checks)
- You have an inventory of active integrations — Shopify, MercadoLibre, banking webhooks, ContPaq, Siigo.
- Every integration has retry with exponential backoff.
- Where failed payloads are stored. If nowhere, you have silent data loss.
- Someone monitors integration errors — Sentry, Datadog, or at minimum a manual cron script with a Slack notification.
- Disaster recovery for the most recent integration was tested in the last 90 days.
#7. Cron jobs (4 checks)
- How many active records in
ir.cron. - How many have
nextcallmore than 7 days in the past (zombies). - Which cron job is the heaviest by average execution time.
- Whether any cron runs every minute. Is there a business reason?
#8. Backups and recovery (4 checks)
- Daily backup of database and filestore runs automatically and is verified.
- The backup lives in a separate geographic region — S3/GCS in another region, not the same data center.
- A restore was tested in the last 90 days. RTO measured in seconds, minutes, or hours.
- Retention policy is documented. Sensible default: 7 daily + 4 weekly + 12 monthly.
#9. Security and access (5 checks)
- All admin accounts have 2FA enabled.
- No shared admin account that IT hands around over WhatsApp. With that, the audit trail is useless and the bus factor is 1.
- Filestore access is protected at the OS level (only the
odoouser). - Rate limiting is active on portal and website routes to slow down brute force.
- Audit log is enabled for the
unlinkaction (record deletion).
#10. Operations and learning (4 checks)
- 5 key users have been interviewed: what workarounds do they use outside Odoo — shadow Excel, WhatsApp groups for order status.
- Every process has a documented owner: a specific person, not "the department."
- An incident log exists for the last 90 days with root-cause analysis, not "it broke, we fixed it."
- Upgrade plan to the next LTS (Odoo 19) is decided: approved, deferred to 2027, or not even discussed.
When this self-audit applies — and when it doesn't
| Condition | Applies | Why |
|---|---|---|
| On-prem or self-hosted Odoo, > 6 months in production | Yes | Pathologies accumulate over time; on fresh installs half the checks return false-green |
Team has a tech lead who can run psql and read logs | Yes | This is a technical document, not a managerial summary |
| 4 focused hours in a single session | Yes | Stretched across 2 weeks, the first and last checks already describe different realities |
| Odoo Online (SaaS without shell) | Partial | Half the checks on DB, cron, and logs don't apply; you need a 25-check alternative flow |
| Mexico with heavily customized CFDI | No | Complement details need expert review, not a universal checklist |
| Argentina with legacy XML and no ARCA webhooks | No | Requires targeted validations, not 50 universal ones |
| The only "tech lead" is the accountant, no SQL or sysadmin background | No | The self-audit will produce more noise than signal; call an external directly |
Common mistakes when running the audit
Mistake 1. Filling it in "by feel." The team paints checks green without verifying. With no psql and no log reading, this stops being an audit and becomes self-deception.
Mistake 2. Ignoring the yellows. Partial is not OK. It means "take a separate hour and resolve it" — in 3 months, that yellow becomes red.
Mistake 3. The same person who implemented the system runs the audit. Direct conflict of interest: they won't flag their own defects. At minimum, bring in a second pair of eyes — another dev, the accountant, or the COO.
Mistake 4. Blind trust in the fiscal localization. "Invoices are going out" does not mean "the localization is correctly configured." SUNAT, SAT, and DIAN can accept an XML with a warning that materializes as a fine during the annual review.
Mistake 5. Running it once. The ERP is a living system. Run it once, and in 90 days half the answers are stale. Minimum cadence: quarterly. Before any major upgrade: mandatory.
Anonymous case: retail chain in Lima
Retail chain, 9 stores, Odoo 16 Enterprise with 18 months in production. The CFO initiated the self-audit — 4 hours with the tech lead and the senior accountant.
Result distribution across 50 checks: 14 red, 11 yellow, 25 green.
"We thought the problem was performance. It turned out performance was a symptom — the real problem was fiscal localization and backups we'd never restored."
Top-3 findings:
l10n_pe_edihad received no patches since install day. Roughly 8% of CPEs went out with the wrong series format — SUNAT accepted them with a warning. On the annual review, that would have turned into rejection and a multi-UIT fine.- 6 out of 11 cron jobs were refreshing a cache no active code consumed. CPU sat at 30% constant, and nobody could explain where it came from.
- Backups were running, but a restore had never been tested in 18 months. On a staging restore, it became clear the filestore wasn't being copied — the company had no real backup of 1.2 TB of invoices and product photos.
After 6 weeks of repair (3 devs × 6 weeks at partial load + 2 accounting weeks of re-issuance): month-end close dropped from 9 days to 3, server load fell −35%, and backups moved to S3 in another region with a tested restore (RTO 90 minutes).
ROI: USD 4,800 in spend. Recovery: an estimated USD 18,000+ per year from shorter month-end close and elimination of CPE fine risk at SUNAT.
Your next step: rescue, audit, or migrate
After the self-audit, you have three paths.
Path 1. Rescue and optimize. Fewer than 10 reds, concentrated in categories 4 (data), 5 (performance), and 8 (backups). The system is salvageable by the internal team in 6–10 weeks. See the methodology in Odoo project rescue.
Path 2. Detailed external audit. More than 10 reds, or the reds sit in categories 2 (fiscal localization) and 3 (custom code). Bring in an external consultant for a 5–10-day forensic review. Scope details in Odoo audit.
Path 3. Migration or replacement. Roughly 7% of cases in our sample: the system carries so much technical debt that starting fresh on Odoo 18 or 19 is cheaper. Make that call on data, not emotion. Review the migration decision framework before closing the debate.
psql queries, email templates to coordinate the review with the team, and a Notion board to track progress. Email-gated, no spam. Once every two weeks — Pulso Odoo LATAM newsletter: download Audit Your Odoo.Frequently asked questions
How long does it really take to work through all 50 checks?
4 focused hours from the tech lead plus 1 hour from the CFO. If you finish faster, someone is painting things green by guesswork; if it takes much longer, you have too much documentation and not enough working ERP.
25 checks done deeply beats 50 done superficially — if you only have 2 hours, start with categories 2 (fiscal) and 8 (backups).
Can I use this for a single country only?
Yes. Categories 1 and 3–10 are universal across LATAM. Only category 2 (fiscal localization) is country-specific — take the checks for your jurisdiction (PE, MX, CO, AR, CL, PY, EC, UY) and drop the rest.
What do I do if I end up with more than 10 red items?
Don't fix them all at once. Prioritize in this order: fiscal localization first (regulator-fine risk), then backups (data-loss risk), then performance and data quality. A full rescue cycle typically runs 8–12 weeks.
Does this replace a formal external audit?
No. An external audit delivers 30–60 expert hours plus a 30–60-page PDF with priorities and USD estimates. The self-audit is early warning — it tells you whether paying for the external audit is worth it.
Does it work on Odoo Online (SaaS)?
Partially, about 60% of the checks. Categories on DB, cron, performance, and backups depend on shell access that Odoo Online doesn't expose. For Online, you need a 25-check alternative flow.
What if my implementation partner pushes back — says "it's not needed"?
That's a red flag in itself. A partner aligned with the client's long-term success would propose this check. Resistance signals hidden problems.
How often should I rerun the audit?
Quarterly at a minimum. Before any major upgrade: mandatory. After a relevant incident: ad-hoc within 7 days.
Doesn't Odoo have a standard report that covers half of this already?
No. Some of the data is in Apps → Settings (version, edition, user count), but fiscal localization, cron zombies, and data quality require direct SQL. Odoo's UI deliberately hides those technical details.
