My own company keeps its books in Odoo 19 Community: the Ecuadorian side under the SRI's rules and the Colombian side under the DIAN's, on a single multi-company installation. What I install for a client is this same thing.
Three views, from the whole to the part: the map of the layers, the journey of a document until the tax authority clears it, and which of all that already existed and what I had to port or write.
One database, two companies with their own chart of accounts and currency, and three layers of software on top. No number on this page is an estimate: each one comes from the repository or from the log of a test run.
1Odoo 19 Community installation serving both companies
32OCA modules pinned by version in the image
16localisation modules installed here that I ported to 19 or wrote
580green tests across the eleven modules of the Ecuadorian localisation
99tests of Colombian withholding, its bridge and its certificates
Both test figures come from continuous integration, not from a run by hand: every push spins up a throwaway database, installs the whole recipe and only goes green when the log says zero failures and zero errors.
02
The map
Odoo 19 Community in the middle and three layers around it: what the core ships, what the OCA adds and what I put in. Ecuador and Colombia are not two systems: they are two branches of the same one, on a single multi-company database.
Who talks to the installation, and what each one asks of it.The three layers, and the two branches that come out of them.Module by module, under its technical name.
The zoom moves on its own; hover to stop it and pick a level. Every box says what it is, which module covers it and what it is for: without that discipline a map needs someone to explain it.
03
The journey of a document
The same thing in lanes: who performs each step and which layer it comes from. The label at the foot of each box says whether the step is handled by the Odoo core, an OCA module, one I ported to 19 or one I wrote.
Ecuador, with the SRI
From the moment the invoice is confirmed to the moment the customer gets a cleared document.
The XML is built with its 49-digit access key, signed with the company's certificate and filed with the SRI. What the customer receives is the cleared XML and the RIDE, its printed representation.
Colombia, with the DIAN
The same trip on the other side of the border, under a different rule and a different format.
The document travels as UBL 2.1 signed with XAdES, issued as in-house software: there is no technology provider in between. The DIAN receives it in the testing or the production environment, and the answer feeds the printed form the customer reads.
And withholding, where the in-house work sits
In Colombia the buyer withholds from the seller, and that is where the localisation had gaps.
The counterparty is described once, in the fields of its tax registration. From there come the fiscal position that matches its condition, the concept with its minimum threshold in tax units, and the local trade tax rate of its municipality, looked up by its official code. In the electronic document each withholding travels under its own tribute, and at the end of the period the counterparty gets its certificate.04
What already existed, and what I added
“Doing the localisation” often just means installing it. Here the account is split: top to bottom, what came ready and what had to be made.
The label in the margin says where each piece comes from. The bottom two rows are the ones that did not exist on version 19 when they were needed.
Odoo 19 Community
Accounting, the tax engine and both charts of accounts. l10n_ec ships the Ecuadorian chart with the SRI code already set on every tax; l10n_co ships the 378-account Colombian chart with its 65 taxes, identification types and withholding rates.
The OCA, already published on 19
32 accounting modules pinned by version in the image: reconciliation, bank statement import, financial reports, templated statements, year-end closing and assets. From Colombia, the DIAN master data, electronic invoicing as in-house software and self-withholding on sales.
Six modules ported to 19
Four of Ecuadorian electronic invoicing, which the OCA had left on the 17.0 branch, and two of Colombian withholding, which stopped at 18.0. Each port lives in its own workshop repository, with its history, its tests and the OCA quality checks green.
Ten written from scratch
In Ecuador: the delivery waybill, the transactional annex, a go-live wizard and inbound processing of the documents suppliers issue. In Colombia: the bridge between withholding and electronic invoicing, the financial statements by chart-of-accounts group, the draft of the VAT and withholding returns (forms 300 and 350) and the annual information return. Plus my own two modules, the one that scopes every expense and the one that issues withholding certificates.
No third-party piece comes in through another door: OCA modules arrive as PyPI wheels pinned by version and hash, and my own workshops by full commit. Moving up a version means changing the commit, reading the diff and deploying.
05
Both sides, on the production database
Both localisations are installed on the company's production Odoo, the same one that keeps its books. This is not a demo environment.
Ecuador, installed in production
The Ecuadorian localisation is installed on the company's production Odoo, with the company's signing certificate loaded and the SRI configuration written as a repeatable script: regime, accounting obligation, branch and issuing point, journals, payment methods and numbering.
Colombia, installed in production
Withholding at source, the bridge to electronic invoicing and the certificates have been on the production database since September 2026, with this tax year's unit value and six fiscal positions that apply themselves from what the counterparty's tax registration declares. Since October they have been joined by the financial statements, the draft of forms 300 and 350 and the annual information return.
No tax setting is entered by guesswork. Every rate, every concept and every minimum threshold comes from its rule, with the decree or resolution noted beside it; whatever cannot be cited is asked at the source before it goes in.
06
And in your company
What runs here is what I install: the same modules pinned by commit, the same configuration written as repeatable scripts, and the same test battery before anything touches your database.