Home / Blog / Tutorials / Audit Your Odoo
TutorialsLATAM

Audit Your Odoo: 50 Checks for SMBs in LATAM

A 50-check list across 10 categories that the CFO and tech lead work through in 4 hours.
The output: a clear call to rescue the system, bring in an external auditor, or migrate to a clean Odoo 18.

Sergei Filatov
Sergei FilatovFounder · data-metrics.pro · May 27, 2026
◷ 12 min read

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 SUNATSATDIANARCAor 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.

i
One-minute summary. 50 checks across 10 categories: configuration, fiscal localization, custom code, data quality, performance, integrations, cron jobs, backups, security, and operations. Typical run: 4 hours of tech lead time plus 1 hour of CFO time. In 70% of installs, the self-audit catches 3–5 critical defects the implementation partner chose not to mention. Applies to Odoo 15–18 with at least 6 months in production.

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)

  1. 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.
  2. Edition: Community or Enterprise. The full accounting module in Community exists only through third-party OCA modules.
  3. Developer mode is enabled for users at the right technical level — no more, no less.
  4. Active user count reconciled against the license. Going over the limit invites an audit from Odoo SA.
  5. 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.

  1. The relevant l10n_xx module is installed (l10n_pel10n_mxl10n_col10n_arl10n_cl).
  2. The l10n_xx version matches the Odoo major version. OCA l10n-peru patches typically lag the core upgrade by 2–4 weeks.
  3. Electronic-signature certificates are installed and don't expire within the next 90 days.
  4. Peru: l10n_pe_edi configured for CPE. Is the GRE (electronic delivery note) closed correctly?
  5. Peru: SIRE integration (RVIE + RCE) is live. If it isn't, that's a deferred fine.
  6. Mexico: Carta Porte 3.1 and Pagos 2.0 complements installed.
  7. Colombia: electronic payroll integrated. Is there a RADIAN connector for invoice factoring?
  8. Argentina / Chile: webhooks to ARCA (formerly AFIP) and SII are active. Validation rejections are logged where someone can actually find them.
!
SUNAT can fine you per missing CPE — the 2026 UIT sits at roughly S/ 5,350 and serves as the base for multi-UIT penalties. DIAN hits differently for missing electronic payroll: loss of deductibility can cost an SMB USD 4,000 to USD 15,000 a year. Never assume "invoices are going out" means "localization is correctly configured."

#3. Custom code (5 checks)

  1. How many lines of custom code in addons/custom/. More than 5,000 — either you're an ERP builder, or you have a problem.
  2. Custom modules have unit tests. At least one.
  3. Every custom module ships with a README that explains why, not what.
  4. How many custom modules duplicate native functionality (Sale, Inventory, MRP). That's code that breaks on every upgrade.
  5. Who signed the last commit on each custom module. Is that person still at the company?

#4. Data quality (6 checks)

  1. How many duplicates in res.partner by vat (GROUP BY vat HAVING COUNT(*) > 1).
  2. How many products in product.template with no active BoM — critical for manufacturing SMBs.
  3. How many accounting lines without a counterparty (account.move.line WHERE partner_id IS NULL). Each one breaks the by-customer report.
  4. Phantom SKUs: products with no movement in the last 12 months.
  5. Total Odoo stock reconciles with the physical inventory (±2%).
  6. Last year's accounting periods are closed, or left open for after-the-fact corrections.

#5. Performance (4 checks)

  1. Top-10 slow queries in pg_stat_statements. Any over 5 seconds.
  2. Postgres database size: up to 20 GB is normal, 20–50 GB requires regular vacuum and cleanup, more than 50 GB demands real archival.
  3. POS response time during peak hours: under 1 second.
  4. How often per day WorkerLostMemoryErroror 504 Gateway Timeout shows up in the logs.

#6. Integrations (5 checks)

  1. You have an inventory of active integrations — Shopify, MercadoLibre, banking webhooks, ContPaq, Siigo.
  2. Every integration has retry with exponential backoff.
  3. Where failed payloads are stored. If nowhere, you have silent data loss.
  4. Someone monitors integration errors — Sentry, Datadog, or at minimum a manual cron script with a Slack notification.
  5. Disaster recovery for the most recent integration was tested in the last 90 days.

#7. Cron jobs (4 checks)

  1. How many active records in ir.cron.
  2. How many have nextcall more than 7 days in the past (zombies).
  3. Which cron job is the heaviest by average execution time.
  4. Whether any cron runs every minute. Is there a business reason?

#8. Backups and recovery (4 checks)

  1. Daily backup of database and filestore runs automatically and is verified.
  2. The backup lives in a separate geographic region — S3/GCS in another region, not the same data center.
  3. A restore was tested in the last 90 days. RTO measured in seconds, minutes, or hours.
  4. Retention policy is documented. Sensible default: 7 daily4 weekly12 monthly.

#9. Security and access (5 checks)

  1. All admin accounts have 2FA enabled.
  2. No shared admin account that IT hands around over WhatsApp. With that, the audit trail is useless and the bus factor is 1.
  3. Filestore access is protected at the OS level (only the odoo user).
  4. Rate limiting is active on portal and website routes to slow down brute force.
  5. Audit log is enabled for the unlink action (record deletion).

#10. Operations and learning (4 checks)

  1. 5 key users have been interviewed: what workarounds do they use outside Odoo — shadow Excel, WhatsApp groups for order status.
  2. Every process has a documented owner: a specific person, not "the department."
  3. An incident log exists for the last 90 days with root-cause analysis, not "it broke, we fixed it."
  4. 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

ConditionAppliesWhy
On-prem or self-hosted Odoo, > 6 months in productionYesPathologies accumulate over time; on fresh installs half the checks return false-green
Team has a tech lead who can run psql and read logsYesThis is a technical document, not a managerial summary
4 focused hours in a single sessionYesStretched across 2 weeks, the first and last checks already describe different realities
Odoo Online (SaaS without shell)PartialHalf the checks on DB, cron, and logs don't apply; you need a 25-check alternative flow
Mexico with heavily customized CFDINoComplement details need expert review, not a universal checklist
Argentina with legacy XML and no ARCA webhooksNoRequires targeted validations, not 50 universal ones
The only "tech lead" is the accountant, no SQL or sysadmin backgroundNoThe 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 checks14 red11 yellow25 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:

  1. l10n_pe_edi had 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.
  2. 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.
  3. 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.

i
Download the full template. PDF with all 50 checks, ready-to-run 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.