This was back in 2022: we raised the Odoo version in use at MI7 Japan Inc. (now Genelec Japan Inc.) — "MI7" below — from V10 to V15. Quartile has done upgrade work for several customers, but there is still almost nothing written up publicly about it in Japan. So, what was hard about it. It is rather a catalogue of pitfalls and may not make for enjoyable reading, but we have tried to include things useful to Odoo service providers and user companies alike, so do have a look.
About MI7
MI7 is a distributor responsible for bringing overseas makers into the Japanese market and growing that market for them: manufacturers of high-tech electronic musical instruments and professional audio hardware, and makers of software for writing scores and editing music. They do more than import and sell — they work on several fronts as each case requires, from setting marketing strategy to establishing joint-venture local subsidiaries.
To contribute to the media industry as a pioneer in this domain, they have built machinery that uses IT to reconcile stock, handle orders and purchasing, and reconcile billing in real time, putting them in a position to offer high value-added services. Odoo is the platform behind it.
- Odoo apps in use: Sales, e-Commerce, Purchase, Inventory, Manufacturing, Invoicing
- Users: around 20
Project background
MI7 originally implemented Odoo under a different Odoo service provider and went live in autumn 2018. Circumstances including unilateral changes to the terms of service led them to switch partners, and they have used Quartile's services since summer 2020.
From around autumn 2020, MI7's wish to widen the scope of their Odoo use in order to reform their own services was taking concrete shape. Meanwhile V10 had dropped out of Odoo's support in autumn 2019, so a move to a newer version was overdue for maintainability and security. The need for an upgrade was rising from both the attacking and the defending side, so to speak.
Looking at the existing Odoo environment, the fact that "an enormous amount of customisation has been done" was the obstacle to upgrading. When Quartile took over support for MI7, there were more than 54,000 lines of customisation counting only what is meaningful — excluding comments, blank lines and translations — or more than 27,000 lines excluding the theme. We had been building up our understanding of that customisation little by little while answering individual maintenance requests, but at the point the upgrade project started we were nowhere near understanding the whole of it.
How the work went
Put very roughly, if you make the database structure and the custom modules work on the new version, you can run Odoo on the new version.
That is what "upgrading" means in the narrow sense. What was unusual this time was the enormous body of customisation we did not fully understand. We knew the quality of the custom code we had inherited was not good, so our view was that it should be tidied up first. In other words, before starting on the database and custom modules, we should "take stock of the requirements and improve the existing customisation modules".
So the broad sequence was as follows.
1. Take stock of the requirements and improve the existing custom modules
2. Make the custom modules work on the new version
3. Make the database work on the new version
1. Take stock of the requirements and improve the existing customisation modules
We were, we admit, somewhat optimistic about this at the outset (lesson learned), and once we opened it up the work proved close to endless.
- What we assumed: about half the existing custom code would need reworking
- What happened: about nine tenths of it did
We sorted the existing custom code into one of the following.
a) Implementations that are unnecessary
b) Implementations whose intent is unclear
c) Implementations that are needed but hard to maintain
d) Implementations that are needed and of acceptable quality
We had a sense that a) to c) might be about half of it; unpicking what was actually there, almost all of it fell into those categories.
"a) Implementations that are unnecessary" were mostly cases where something Odoo's standard functionality should have handled had been dealt with by writing a feature instead. For each of those we agreed the point with the customer and then dropped the feature, moving them to operating with the standard functionality.
There were a great many "b) Implementations whose intent is unclear" too — enough that agreeing every one individually with the customer would have taken more time than there was. To some extent we judged them unnecessary ourselves and dropped them (which makes that part "a) unnecessary"), and where doing so looked risky we asked the customer about the history, reconsidered from scratch what the implementation ought to be, and then reworked it.
Most of the remainder was "c) Implementations that are needed but hard to maintain". To give a few examples:
- modules were carved up by business area, as in "xxx_sale", rather than by purpose, with features serving all sorts of purposes thrown in together
- because of that, there were several places where the dependencies between modules had broken down (mutual dependencies)
- overriding standard methods was used heavily in place of extending them
- the same method was copy-pasted into various places
and clearing all of it took a considerable amount of time — more than 500 hours. Not again, please.
The result was that custom code of more than 27,000 lines, excluding the website theme, was compressed to about 18,000. Based on Odoo's rate for taking on maintenance of custom code (USD 18 per 100 lines per month), that amounts to a reduction in maintenance cost of more than JPY 220,000 a month (at USD 1 = JPY 140).
2. Making the custom modules work on the new version
Making the custom modules work on the new version is Quartile's work. Paying Odoo to do it is not entirely off the table, but it was not a realistic option here: the volume was simply too large, and we knew from the start that its contents needed substantial review. Odoo's service scope does not include requirements definition.
3. Making the database work on the new version
Making the database work on the new version is supported by Odoo's own dedicated scripts if you are on Odoo Enterprise. On Community, the work is done with the OpenUpgrade scripts maintained at OCA. MI7 are on Enterprise, so the former applied.
Results
Roughly speaking, the results were these.
- performance improved overall (it moves briskly now)
- it handles better and people get more done
- cleaning up the custom code brought maintenance costs down
- the customer understands Odoo's features more deeply
- the ground is prepared for taking on new areas
Performance improved overall (it moves briskly now)
Performance improved on both the front end (the shop) and the back end. That the shop's page load speed — which bears directly on the customer's experience — improved markedly was a significant result.
It handles better and people get more done
Odoo has made all sorts of UI improvements across its versions. On the back end: import and export, menu search, updating a field across multiple records at once. On the front end, the range of snippets has filled out and become more expressive, so a website can be made to look tidy without much effort and without depending on a third-party theme.
Cleaning up the custom code brought maintenance costs down
As described above, the volume of custom code was cut sharply, and the environment now builds under our continuous integration tooling. Dealing with a problem when one arises is far easier than it was, and the chance of trouble when applying a change is much reduced.
The customer understands Odoo's features more deeply
There were many places where the basis or background of the custom modules we inherited was unclear, so we ended up redoing requirements definition almost as if it were a fresh Odoo implementation. Explaining the concepts and constraints of Odoo's standard functionality, what OCA modules do and how we approach customisation, in detail, along the way, has left the customer's understanding of Odoo far ahead of where it was — as they told us themselves. Where before they would not have known what to do about a problem, they now have a feel for roughly where to look.
When Quartile explain a feature or how we dealt with a problem, we make a point of covering the actual data, how to check it, and the background to the decisions. So a customer who takes an interest in Odoo picks up the know-how and can handle a fair amount themselves. This was not a result we had explicitly hoped for, so hearing it recognised was very welcome.
The ground is prepared for taking on new areas
Before this migration, the inherited custom modules had changed Odoo's standard behaviour or added constraints to it, to the point that the environment would not build or pass tests under continuous integration. Adding scope or writing new customisation from there was risky, and they were stuck.
Tidying the code base has made them light on their feet and widened the possibilities for using Odoo in new areas. Concrete discussions are already under way about running helpdesk, subscription and marketing features.
What we would do differently
To be entirely open about it, the largest failing was that our initial estimate was too soft: the work took more effort than expected and there was a substantial delay.
The difficulty of estimating comes down to two things.
- we did not have an accurate picture of the specification or quality of the custom modules we inherited
- it was an upgrade across a relatively large number of versions, 10.0 to 15.0
The second can be approached by dealing with problems as the work proceeds, but on the first we should have arranged things differently.
Day to day we work with Odoo itself, OCA modules and custom modules we wrote ourselves, and for those the quality is broadly assured or we know what is in them. Features developed by a third party who does not share our quality standards are an entirely different matter. It may not have changed the effort the work actually took, but our initial estimate was too low, the schedule had to be adjusted several times, and we caused the customer inconvenience.
Looking ahead
The question of "how to move an existing Odoo environment to a new version smoothly" should become much more widely recognised as Odoo spreads in Japan. Thinking again about what can be done to get ahead of it, we arrive at the following. Quartile already do these things, but they are points that both users and providers will want to be aware of in order to keep lifecycle costs down.
1. Avoid customisation as far as possible
Precisely because Odoo is easy to extend by customising it, excessive customisation happens if you are not careful. When a customer's requirement comes up, the important thing is not to head that way lightly because "we can handle it with customisation", but to ask whether the process can be fitted to the standard functionality, and to decide on customisation only where there is a clear reason it cannot be avoided rather than a vague one.
Customers often do not think as far as the later maintenance cost or the cost of handling an upgrade — which is exactly why we as providers should have a firm grip on it.
2. Use only OCA third-party modules
Odoo is often praised for the sheer number of third-party modules available (more than 40,000 in the Odoo app store as of May 2023), but most of them do not follow any proper quality standard. In our experience, a non-OCA third-party module will generally run once installed, but look at the code and it is a mess. An OCA module is fundamentally sound in design and meets a defined set of quality management standards.
3. Hold your own custom modules to OCA's quality standard
Quartile's policy is to develop modules at OCA for anything general (and we shape requirements definition so that requirements come out general where they can). Where a requirement cannot be made general, we develop for the customer — using the same coding style checks and continuous integration as OCA, which is what assures the module's quality.
There is one large benefit to this: working with OCA becomes smooth. When adding a feature for a customer quickly we sometimes work away from OCA for a while, and if we later want to add that module to OCA, raising a pull request against the OCA repository is easy.
In summary
Upgrading a customised environment is difficult in any ERP system, and Odoo is no exception: it demands patient trial and error and repeated verification. It is common at implementation time to give no thought to maintainability or the cost of upgrading, and to make the wrong call as a result.
The remedy is thoroughly unglamorous: lean towards using Odoo's standard functionality wherever possible, and hold the line against casual customisation. It is precisely because Odoo is so extensible that this needs watching. The more half-baked the consultant, the more readily they reach for customisation.
And where a custom module does go in, do it under machinery and a process that assures quality. It is safer to assume that skimping on this never comes out all right in the end. It will always cost more. Users would do well to learn about this side too — and if you can, contact several providers and ask what practices they follow.
In the customer's words
The upgrade improved performance overall, and the system handles better and lets us get more done. Cleaning up the custom code improved maintainability, and understanding how Odoo works more deeply has widened the range of problems we can solve ourselves. We learned first-hand that customisation should be avoided wherever possible.
Photo by Karsten Würth on Unsplash
[Odoo Version Upgrade Case Study] MI7 Japan Inc. (V10→V15)