The CRM behind NationwideLegal, on Odoo 18
NationwideLegal in the United States runs its commercial operation on a CRM that Polargate built on Odoo 18 Enterprise and still directs technically: one custom module, five new models, permissions rebuilt around how the team actually sells, and a verification pass against production after every deploy.

- 99
- automated tests written for the module, from zero at the start
- 313 ms
- to read the new fields across 400 real production records
The problem
The CRM had to fit a sales team, not an org chart. Odoo ships one broad administrator role and very little between it and a plain user, so the salesperson who needed to see the whole pipeline also ended up able to change anything, and anyone who needed to add a colleague needed administrator rights to do it. Activities made it worse, because the calendar showed everybody's work to everybody. On top of that, transactional email was failing, the data entry screens looked nothing like the tool the team had come from, and nobody had checked whether a future upgrade could be undone without losing data.
What we built
One custom module on Odoo 18 Enterprise, depending on nothing beyond Community modules: five new models, each with its complete access rights file and no gaps, plus extensions of the native opportunity, contact, activity and stage models. The access model was rebuilt as four separate per-user controls instead of one monolithic role. A custom group creates users with a barrier inside the model itself, so it can never create or touch an administrator. The calendar was solved outside record rules, because record rules do not govern reading on that model. Mail was fixed in the authentication layer, not in the ERP. And the delivery chain carries its own rules: the test suite runs on every development and staging build, promotion to production is triggered by a person, and every deploy ends with read-only checks against the live system.
The outcome
Fifteen deliverables were completed in five weeks and consolidated into a handover document. The module went from no tests of its own to 99 green, with the negative cases verified too. Salespeople see their own calendar and the administrator sees all of it. Users can be created without handing out administrator rights, verified in the browser with an account that holds nothing but that permission. Transactional mail sends. Migrations are reversible because the rollback was rehearsed, with 132 rows and 56 relations across 200 records recovered intact. Merge to live in production takes ten to fifteen minutes, and every deploy ends with the same checks: on the last one, the new fields read across 400 real records in 313 ms.
Stack
- Odoo
The context
The client is NationwideLegal in the United States. Its commercial operation runs on a CRM: opportunities, the firms they belong to, the contacts inside each firm and the addresses behind them. Polargate built that CRM on Odoo 18 Enterprise and has held its technical direction since.
Everything custom lives in a single module. It depends on nothing beyond Community modules, so no third party addon sits in the critical path. The module adds five new models, each with its complete access rights file and no gaps, and extends the native models for opportunities, contacts, activities and stages.
The delivery chain is deliberately boring: a private repository, a managed Odoo project, and NationwideLegal production pointing at the same environment. The platform runs the test suite on every development and staging build. Promotion to production is never automatic, a person triggers it by hand. From merge to the live version in production takes ten to fifteen minutes.
Permissions built around how the team actually sells
The access model was rebuilt around how the sales team really works, with four separate per-user controls instead of one monolithic role. A user can be granted one and not the others, which is what a sales floor needs and what a single role cannot express.
The calendar
Sales users see their own activities. The administrator sees and manages all of them. Getting there was not a record rule. In Odoo, reading activities is not governed by record rules, because that model carries its own native search and access check, so it had to be solved another way. The first version leaned on a context flag and leaked. When NationwideLegal reported it, we fixed it live and retested with the affected user account.
Creating users without being an administrator
Odoo has no intermediate role that can create users without being an administrator. We verified that in a local environment: the only native group with the permission escalates itself to administrator in a single write. So we built our own group, with its own access control list and a barrier inside the model. It cannot leave anyone holding administrator groups, it cannot modify a user who already is one, and it cannot write another user password. Verified in the browser with an account that holds nothing but that permission.
Data entry that matches the tool the team came from
Company, address and contact go in on a single page, the way it worked in the tool the team used before. Duplicate detection runs on an indexed normalised name that ignores punctuation and legal suffixes, warns, and offers to attach the record to the one that already exists instead of creating a second. The suffix list needed pruning: some of the words in it were collapsing two genuinely different firms into one.
Transactional email
Mail was failing, and the fault was not in the ERP. It was in the authentication layer. With SMTP authentication enabled and the right account configured, the error was gone.
Upgrades that can be undone
We did not take the risk classification of a migration on trust, we rehearsed it in a container, reproducibly. The finding: when a field is removed from the model, the platform does not drop the table or the columns, it leaves them orphaned with the data still inside. Seeded rows survived the upgrade and the rollback returned both the code and the access to the data, 132 rows and 56 relations across 200 records. The migration is reversible, and it is reversible because it was tested, not because the documentation says so.
Verification against production, after every deploy
There is a written recipe and it runs after every deploy. Read the live version of the module. Check the view against the combined definition, not the inherited one. Confirm the new fields exist. Time reading them over real records: 400 opportunities came back in 313 ms, which is the check that no loop and no heavy query slipped in. Download the assets bundle and validate it, because a broken bundle is invisible until a user opens the page. The discipline is hard and simple: in production you look, you do not touch.
Audits work the same way. The first phase is not reading code, it is running the scenario against a real environment impersonating the affected user, recording the state before and after every write. Validating a permission with an administrator account proves nothing, because the bypass exempts it. A test that only asserts the text of an attribute proves nothing either. One of these audits ran across 41 agents and 2.3 million tokens, with two independent skeptics challenging every finding before it was accepted.
Continued technology direction
Fifteen deliverables were completed in five weeks and consolidated into a handover document. The module went from no tests of its own to 99 green, with the negative cases verified too, because a permission test that passes when it should fail is worse than no test at all.
The engagement runs on one rule that keeps it healthy: scope and priority are agreed before an item goes on the list, not after, and the weekly reference document is issued by Polargate.
Questions about this project
Can Odoo be customised without losing the ability to roll back?
Can salespeople get different permissions in Odoo without being administrators?
Related work
Global Dynamic Security GroupBrand and bilingual site for Global Dynamic Security Group
Brand identity, a 15-page identity manual and a bilingual Spanish and English corporate site for Global Dynamic Security Group (GDS), a security services group in the Dominican Republic, delivered as one fixed-price project.
2026Read the case
GlobaliaThe corporate web platform of Globalia
Globalia, the Spanish travel group, had its people data in Microsoft 365 and its public website somewhere else. Polargate built one web platform on a single repository: an employee directory synced from Microsoft 365, a digital business card with Apple Wallet and Google Wallet passes, and the group's public site, made readable by AI crawlers without rebuilding it. Pedro Ciordia works at Globalia, so this is related-party revenue, not a client won on the open market.
2026Read the case
B2B services company, EuropeHardening a corporate website that a DNS filter was blocking
A customer's corporate DNS filter was rejecting our client's domain, and that stopped the client operating as one of that customer's suppliers. The site was not compromised and not blacklisted. It was simply unhardened. Polargate diagnosed it in a week, migrated the CMS to hosting the client controls, and hardened it there, because the CMS admin panel was the only access available.
2026Read the case
Start the engine
Tell us what you are building in a few short questions. A senior engineer answers in writing within 48 business hours, with a first take on scope, timeline and price.