Home / Blog / Tutorials / Odoo audit · 50-point checklist
TutorialsLATAM

Odoo audit: 50-point checklist for LATAM SMBs

Ten blocks, fifty points, explicit severity.
Decide in an afternoon whether your Odoo is healthy, carries 3-7 must-fix defects, or is past saving.

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

One-minute summary

If your Odoo has been in production more than a year and never went through an independent review, the statistic is stable: it carries 3 to 7 must-fix defects under the hood. The partner that installed it would rather not mention them, because each one is the next billable project.

This article is a map. 50 points organized into 10 blocks, from stack version to disaster recovery plan. It applies in any LATAM country with the local regulator swap: SUNAT in Peru, SAT in Mexico, DIAN in Colombia, ARCA (formerly AFIP) in Argentina, SII in Chile, SRI in Ecuador, DGI in Uruguay, SET in Paraguay. The checklist is the same. The l10n_* items change by country.

  • 70% of LATAM SMBs that implemented Odoo through a partner live with 3 to 7 must-fix defects.
  • Audit ≠ sales diagnostic. It is forensics: reading Postgres, custom code, cron jobs, integrations, and l10n_* hooks.
  • In 2026, SUNAT, SAT, DIAN, ARCA, and SII tightened validations — one l10n error voids deductibility across the chain.
  • The checklist covers 10 blocks: stack, localization, custom code, data, performance, cron, integrations, security, backups, team.
  • An external audit costs USD 1,500 to 5,000. The annual cost of skipping it typically runs USD 30,000 to 80,000 in fines, lost deductibility, and rework.
  • In roughly 7% of cases the outcome is «do not save it, migrate». That counts as a result too: it saves six months of budget.
!
What an audit is not. If your partner offers a «free review» with a quote attached, that is a sales diagnostic, not an audit. The difference: a real audit ships a PDF with reproducible SQL queries, severity per item, and the exact date for each finding. It does not include an hour estimate to fix things. That comes later, and anyone can do that part.

Why 2026 is the year of Odoo audits in LATAM

Every regulator in the region tightened fiscal discipline at the same time. Odoo, as a multi-country ERP, ended up at the center of the impact — not because of bad architecture, but because 80% of LATAM rollouts went fast through Gold or Silver partners billing by the hour, with no incentive to close the project out.

Peru (SUNAT). SIRE — Sistema Integrado de Registros Electrónicos — is mandatory for every general-regime taxpayer. Purchase and sales books generate automatically from the e-invoice; manual PLE is no longer accepted. A mismatch between SIRE and invoice falls under Código Tributario article 175.1: floor of 50% UIT (S/. 2,675 with UIT 2026 = S/. 5,350), ceiling of 0.6% of annual revenue. The GRE — Guía de Remisión Electrónica — is mandatory for goods movement even when the SMB invoices under S/. 300,000.

Mexico (SAT). CFDI 4.0 and Carta Porte 3.1 are validated in real time through a PAC. The regulator reconciles CFDI against DIOT and contabilidad electrónica. Penalties for inconsistency, per CFF articles 83 and 84, reach MXN 134,840 per defective document. A Carta Porte with an incorrect recipient RFC voids the buyer's deductibility.

Colombia (DIAN). Electronic payroll has been mandatory for every employer since 2024in 2026 DIAN cross-checks payroll against PILA — a mismatch voids salary deductibility on income tax. The electronic-equivalent document applies to every small supplier since July 2024, and validations were tightened.

Argentina (ARCA). AFIP became Agencia de Recaudación y Control Aduanero in October 2024. Monotributo and Régimen General are unified inside the ARCA portal, and the Factura Electrónica with QR (RG 5616/2024) is mandatory across the board. Older Odoo configurations using wsfev1 and wsfex webservices still work, but the endpoints moved — dozens of SMBs found out the hard way in Q1 2026.

Chile (SII). DTE — Documento Tributario Electrónico — has been around for years; the Boleta Electrónica with QR has been mandatory since 20222026 added Factura de Compra validations for withholding-agent regime. l10n_cl on versions 16 and 17 without backport patches gets XML rejection.

Odoo version. Odoo 18 is the current stable release (October 2024). OCA and Odoo S.A. support the previous three versions. If you are still on Odoo 15 in 2026, you are outside the support corridor: l10n patches for the new regulator rules ship in master first and rarely get backported.

The checklist · 50 points across 10 blocks

Each item has a severity: 🔴 must-fix, 🟡 should, 🟢 nice-to-have. Rule of thumb: an audit that reports fewer than three 🔴 items on a LATAM SMB more than a year old probably looked at the surface. If it reports more than ten, schedule the remediation roadmap across 3 to 6 months, not 3 to 6 weeks.

#1. Stack and version (5 items)

  1. 🔴 Odoo version is N or N-1. Anything ≤ 15 in 2026 is out of support. Upgrade path starts at USD 8,000 for an SMB with a 5-20 GB database.
  2. 🟡 Postgres ≥ 14. Postgres 12 hit EOL in November 2024. No more security patches.
  3. 🟡 Python 3.10+ for Odoo 17 and 18. Zero tolerance for 2.7 or 3.6.
  4. 🟡 Reverse proxy with TLS 1.3. nginx or traefik. Apache 2.2 is a 12-year-old release and still turns up in production.
  5. 🟢 Containerization or real monitoring. Docker Compose, k8s, or a systemd unit with journald. nohup ./odoo-bin & on a stray EC2 shows up more often than you would expect.

#2. Localization l10n_* (8 items)

  1. 🔴 l10n_pel10n_mx_edil10n_col10n_ar_edil10n_cl_edi installed and active per company. The module is often installed but not activated on the specific company record.
  2. 🔴 PSE / PAC / signing certificates valid. Two-year validity in Colombia, three in Chile, two for the SUNAT digital cert in Peru.
  3. 🔴 Regulator endpoints set to production, not sandbox. Live installs pointing at demo URLs do happen.
  4. 🔴 Tax catalogs (account.tax) current. IGV PE 18%, IVA CO 19%, IVA AR 21%, IVA MX 16%, IVA CL 19% — configuration must match the 2026 resolutions.
  5. 🟡 SUNAT/SAT/DIAN/ARCA hooks unpatched by hand. If the consultant edited account_edi inside addons/ instead of an override module, every upgrade breaks the integration.
  6. 🟡 GRE / Carta Porte / Remisión configured. Not every SMB knows GRE in Peru applies to intra-company moves.
  7. 🟡 Books (PLE in PE, DIOT in MX, IIBB jurisdicción in AR) generated automatically. If PLE gets exported to Excel and then hand-edited, that is a red flag.
  8. 🟢 OCA l10n_* extensions for country-specific documents (credit vs debit notes, aggregated invoice, withholdings).

#3. Custom code (5 items)

  1. 🔴 Inventory of custom modules. How many modules live in custom/60% of SMBs carry more than 8.
  2. 🔴 Custom code has at least smoke-test coverage. If tests/ is empty, every deploy is a coin toss.
  3. 🟡 Modules that duplicate native functionality, flagged for removal. A custom sale_extension adding 3 fields is fine. A full custom CRM replacing the native one should be rewritten.
  4. 🟡 __manifest__.py with correct depends and version. A module that has shipped version: '1.0' for 4 years means versioning is not happening.
  5. 🟢 Git history with readable commit messages. Minimum bar so git blame stays useful.

#4. Data quality (6 items)

  1. 🔴 Duplicates in res.partner by RUC / RFC / NIT / CUIT. Typically 8 to 15% of records.
  2. 🔴 Production products with no bom_id or stale BoM. If MRP is active and the BoM has not been reviewed in a year, costing is lying.
  3. 🟡 Journal entries with no counterpart. Control query: SELECT COUNT(*) FROM account_move WHERE state='posted' AND id NOT IN (SELECT move_id FROM account_move_line); — must return 0.
  4. 🟡 product.product with no default_code above 10%: stock identification limps.
  5. 🟡 Negative stock on physical goods — workflow bypass.
  6. 🟢 notedescription fields free of business logic. «Do not ship before the 15th» buried inside an order note is a process pretending to be a comment.

#5. Performance (5 items)

  1. 🔴 Top-20 slow queries analyzed via pg_stat_statements. If the extension is off, turn it on and collect at least 7 days of data.
  2. 🟡 Indexes on FK columns. Odoo does not always auto-create indexes on m2o fields; on large tables (stock_moveaccount_move_line) it matters.
  3. 🟡 Workers and cron workers sized for the infra. Formula: workers = (CPU × 2) + 1cron_workers = max(2, CPU / 2).
  4. 🟡 limit_memory_hard and limit_time_real configured. Odoo defaults are sometimes too tight, sometimes too loose.
  5. 🟢 Redis for sessions or dedicated cache above 50 concurrent users.

#6. Cron jobs (4 items)

  1. 🔴 Every active cron has an owner and a description. Query: SELECT name, interval_number, interval_type, lastcall FROM ir_cron WHERE active=true; — every row must be explainable.
  2. 🟡 Crons untriggered for more than 90 days, marked for removal.
  3. 🟡 No crons running below 10 minutes without business justification. Polling every minute across 20 crons30% CPU with no useful work.
  4. 🟢 Cron error logging to an external system (Sentry, Datadog, or at minimum a rotated log file).

#7. Integrations (5 items)

  1. 🔴 Webhooks with retry (3+ attempts) and a dead-letter queue. Without retry, Shopify → Odoo drops orders during traffic spikes.
  2. 🔴 API endpoint registry. Not code: a table listing who calls what, authentication, owner, and SLA.
  3. 🟡 Idempotency. A re-fired webhook with the same ID must not create a duplicate order.
  4. 🟡 API keys and OAuth tokens in encrypted secrets, not in ir.config_parameter plain text.
  5. 🟢 Integration latency monitoring. If ContPaq, Siigo, MercadoLibre, or Tiendanube slows down, the monitor tells you, not the user.

#8. Security (6 items)

  1. 🔴 No shared admin account. One user per employee, role-based permissions.
  2. 🔴 2FA on for admin and finance roles.
  3. 🔴 Filestore not publicly reachable. Direct /web/content/... URLs must require auth.
  4. 🟡 Rate-limit on /web/login and API endpoints. Native Odoo has none — configure at the nginx layer.
  5. 🟡 Audit log on critical models (res.usersaccount.tax, posted account.movevia mail.tracking or OCA auditlog.
  6. 🟢 Quarterly permission review.

#9. Backups and DR (4 items)

  1. 🔴 Postgres + filestore backup, daily, off-site. If the backup sits on the same server, it is not a backup.
  2. 🔴 RTO tested. Not «we have backups», but «yesterday we restored the database in 2.5 hours».
  3. 🟡 Retention policy documented. 7 / 30 / 365 days — each company decides deliberately.
  4. 🟢 Disaster recovery plan on one page. Who calls whom, in what order, what is the first step.

#10. Team and processes (2 items)

  1. 🔴 Bus factor > 1. If only one person can deploy or knows the custom code, it is not a risk, it is inevitability.
  2. 🟡 Documentation for the top-10 processes. Not every button — describe «how we close the month» in 1 to 2 pages.

Five mistakes every SMB repeats

Findings vary by company, but a hard core of five mistakes shows up in one out of every two audits. I list them with concrete consequence — without the consequence, everything is «important»; with the consequence, priority falls out naturally.

Mistake 1. Custom modules on top of account_edi without the override pattern. The consultant edits the XML template inside addons/l10n_pe_edi/ directly. On the next git pull or upgrade, changes vanish and the invoice ships with the default structure. Consequence: 6 months of silent rejections and a SUNAT fine at the quarterly check worth tens of thousands of soles. The cure is the «my module inherits and overrides» pattern, the way Odoo intended.

Mistake 2. pg_stat_statements turned off. SMB with a 40 GB database and 80 concurrent users. POS lags on Saturdays. Nobody knows why. Turn the extension on, and within 3 days the picture is clear: a custom report runs a full table scan on account_move_line (12M rows) every 15 minutes. The fix is one index. The cost before diagnosis: 8 hours of team time every Saturday, for 6 months.

Mistake 3. Cron jobs inherited from consultants long gone. 17 active tasks in ir_cron11 point to code in custom/ modules that were deleted or deactivated. Each logs an error every 5 minutes. Logs balloon to 8 GB per day, disk fills, Odoo crashes. Deactivating them: 30 minutes. Nobody did it because «what if it mattered».

Mistake 4. PSE / PAC certificate expired, no one warned. In Colombia the DIAN certificate expired on a Saturday. By Monday morning, finance had not noticed. 9:00 Monday: every invoice rejected, e-commerce stops emitting. Per DIAN resolution, a 5-business-day registration failure starts at 1 SMMLV (~COP 1,420,000 in 2026) plus the loss of B2B clients. Cure: a certificate calendar in Google Calendar and expiration monitoring.

Mistake 5. Backups in /opt/backups/ on the same machine. SMB with 3-year-old Odoo, 30 GB Postgres. Container crashes, disk corrupts, sysadmin restores — backups were on the same volume. They recover from a 14-month-old backup on the bookkeeper's laptop. Hole: a year of transactions. Off-site via S3 or rsync.net costs USD 40 per month.

«The partner installed the ERP. We paid hourly for 18 months. When we asked for the audit, the first finding was that the partner had been the source of 9 of the 14 must-fix items.»
i
Who pays for the audit. The conflict of interest is obvious: if the same partner that built the system audits it, the report runs short. The cure is not finding another equally commercial partner, but hiring someone who has no reason to win the remediation project. A fixed-fee external audit removes the incentive. If your current partner then runs the remediation, great — but someone else took the picture.

Anonymous case: retailer in Colombia, 6 stores, Odoo 16 → audit → stability

Anonymized early-2026 case: apparel retail chain, 6 physical stores in Bogotá and Medellín, Shopify e-commerce, Odoo 16 community with a custom integration module to Shopify and to DIAN via PSE «X». Pre-audit symptoms:

  • 11% of invoices rejected by DIAN with reason «inconsistencia en NIT del adquirente».
  • Month-end close at 11 business days (their target: under 5).
  • POS freezing at payment during peak hours.
  • A single freelance dev «knows everything»; the rest are afraid to touch it.

What surfaced in 6 business days of audit:

  • 14% duplicates in res.partner by NIT, including clients with NIT 222222222222 «generic customer» — that was the real source of the DIAN rejections.
  • The custom Shopify webhook had no retry; they were losing ~2% of orders during peaks.
  • 9 cron jobs were leftovers from a prior PSE integration; 3 were still calling a dead endpoint.
  • account.tax for IVA on excluded goods (books, essential products) had been misconfigured since 2023.

What got fixed across 6 weeks of remediation:

AreaActionResult at 8 weeks
DataDeduplicate res.partner with OCA partner_deduplicateDIAN rejection: 11% → 0.6%
IntegrationsWebhook retry + DLQ via OCA queue_jobOrder loss: ~2% → 0%
CronDeactivate 9 orphan crons, audit log onLogs: 8 GB/day → 200 MB/day
TaxesRefresh account.tax per DIAN 2026Month-end close: 11 days → 4 days
TeamPair the freelance dev with two juniorsBus factor: 1 → 3

Total cost, audit + remediation: USD 7,200 (USD 1,800 auditUSD 5,400 across 6 weeks at USD 900/week). Estimated annual avoided cost: USD 38,000 across DIAN fines, e-commerce losses, and team rework.

Download the checklist · what comes next

The full 50-point checklist, with SQL queries to self-check 30 of them, a report template, and a simple ROI calculator (avoided cost vs cost of audit) ships by email. Leave your address and the PDF lands. This is not a newsletter with «useful articles» every week. One file and a single follow-up after 14 days.

After the PDF, you have three real paths: fix with your current partner (with concrete requirements drawn from the report), fix with another partner or a freelance, or migrate to another platform. All three are valid. The choice depends on the score and the remaining budget. To walk through the report once it ships, the audit service page has the form; below are related resources for each decision.

Frequently asked questions

How long does an audit take?

5 to 10 business days, as long as Postgres read-only access and filestore are provided on day 1. Without access, it stretches.

Does the audit interrupt operations?

No. Everything that gets read is read-only. Postgres bandwidth peaks at 5% of normal load.

I work with a Gold partner — do I still need an independent audit?

If the partner bills hourly and keeps selling the «next phase», yes. If they are on a fixed-scope contract with phased payments and written SLAs, probably not.

Can I run the audit myself using this checklist?

Yes — 60% of the points come down to SQL and grep. The other 40% require reading custom code and business context. An internal audit by your own dev takes 40 to 60 hours; an external one takes the same 40 to 60, minus the bias.

What if the conclusion is that the Odoo cannot be saved?

In roughly 7% of cases the result is migration or re-implementation. You get a migration roadmap (Odoo Enterprise vs SAP Business One vs Microsoft Dynamics 365 BC vs Defontana), cost estimate, and cut-over plan. Cheaper than patching forever.

Does the audit cover Odoo Enterprise and Community?

Both. Enterprise adds a few commercial modules (Studio, Documents, Helpdesk Pro), but architecturally the audit is identical.

What about Odoo SaaS (odoo.com hosted)?

On SaaS there is no Postgres access and no custom code. The audit narrows to UI, configuration, and XML-RPC exports. Reduced format, around USD 800.

What does the auditor ask for on day 1?

A read-only Postgres user, filestore access, the list of custom/ modules with their Git remotes, sandbox PAC/PSE credentials, the latest ir.cron report, and a 30-minute conversation with whoever runs the month-end close. Without those five inputs, the first two days are spent asking for them.