Skip to content
faceela

Moving From Zoho or Tally to Odoo: What Actually Has to Move

· 13 min read · Faceela

The sentence arrives in almost every first meeting, and it is always said the same way, as though it were the easy part:

"We have five years in Tally. We want all of it in Odoo."

It sounds like a request for a file transfer. It is not. It is four separate requests wearing one coat, and the person asking has usually never had to separate them, because the old system never made them separate. That is the whole problem, and it is also the opportunity.

We have moved a general trading company off Zoho Books and Zoho CRM onto Odoo in 2023, a real estate business off Zoho in 2024, and other companies off other systems for reasons everybody in this market already recognises. The pattern does not vary much. The migration that is quoted is a data exercise. The migration that actually happens is a decision exercise, and the data is the easy half.

This is what that means in practice, and what it should cost you in argument before it costs you in money.

"Migrate" is three jobs, not one

Break the sentence apart before anybody opens a spreadsheet, because the three pieces have almost nothing in common except the word.

Master records are the things that persist: customers, suppliers, items, the chart of accounts, tax codes, employees, price lists. They must move, because without them the new system cannot transact at all. They are also the only part of the migration where the old data is genuinely reusable — and even then it arrives with fewer columns than Odoo needs, which is the next section.

Opening balances are your financial position at one instant: the trial balance, receivables and payables by counterparty and age, stock by item and location, fixed assets and their accumulated depreciation, VAT position, bank balances, retention where you are a contractor. These do not come out of the old system as a migration. They come out as a report at a fixed moment, and they are then loaded as a journal that somebody signs.

History is everything else: every invoice, receipt, delivery note and journal entry that ever happened. This is the part everyone asks for by default and almost nobody needs in the form they are asking for.

The prices are not close. Masters are usually a matter of days and mostly of cleaning. Opening balances are a matter of agreement, and the effort is in the arguing, not the loading. History, loaded properly into a live ERP with all its accounting consequences intact, can cost more than everything else in the project put together — and it buys you something you can usually get another way for almost nothing.

Your old system was answering fewer questions

Here is the part that surprises people, and it is the reason a migration cannot be a transfer.

An accounting package and an ERP do not hold the same information about the same object. They hold what each one needed in order to do its job. Zoho Books needed enough about a customer to invoice them and chase them. TallyPrime needed enough about a stock item to value it and put it on a voucher. Odoo needs enough about both to run the operation that produces the invoice in the first place.

So the export arrives, and it is missing columns — not because the export is bad, but because the columns were never there.

A partner is one record, not three. In Odoo, a company you both buy from and sell to is a single partner with both roles, and it can carry a hierarchy: the company, its branches, the individuals inside it, the delivery address that is different from the invoice address. Old systems very often carry the same organisation as two unrelated records with two spellings, and they are almost never linked. Deciding which spelling is real, and which contact belongs under which company, is a judgement call made by a person who knows the customer — not a merge rule.

A unit of measure becomes arithmetic. In an accounting package, "CTN" is usually text that prints on an invoice. In Odoo it is a conversion the system performs: you buy in cartons, you stock in pieces, you sell in either, and the ratio between them is now load-bearing. Every item where the ratio is wrong, or where two people meant different things by "box", produces a stock error the day you go live.

Stock acquires a place. "We have 400 units" is a complete answer in a package that only values inventory. In Odoo it is an incomplete answer, because the system wants to know where — which warehouse, which location, what is in quality control, what is reserved against an order, what is in transit. Companies that ran a single implicit store now have to name their locations, and naming them is an operations decision, not a data one.

Inventory starts posting itself. This is the change that catches finance teams hardest. Many accounting packages are run periodically: stock is valued at period end and a journal is passed. Odoo, configured the way most implementations configure it, values inventory automatically, so a goods receipt posts to the ledger the moment the storekeeper confirms it. The costing method — standard, FIFO or average — stops being a note in a spreadsheet and becomes a setting that generates entries every day. Choose it before the load, because changing it afterwards on live valued stock is not a settings change, it is a project.

Tax moves to the line. A tax code that sat on the document now sits on each line, which is correct and which is also the moment a company discovers that some of its invoices were mixed and nobody had noticed.

Payment terms stop being a sentence. "60 days" written in a notes field becomes a structured term that drives due dates, ageing and dunning. Every customer whose real terms differ from their recorded terms will surface in the first ageing report after go-live, and it is much better to surface them during the migration.

A new dimension appears, and it is the valuable one. Analytic accounts — projects, contracts, cost centres, vehicles, sites — are usually the reason the company is moving in the first place. They have no equivalent in the old data at all. Nothing to migrate, everything to design.

That is the honest shape of it. A meaningful share of the migration is not moving data. It is filling in columns that never existed, and each empty column is a question somebody in your business has to answer once, properly, for the first time.

If you have not yet settled whether the move is right at all, that argument is when you have outgrown your accounting software, and the product comparison is Odoo against Zoho and Tally.

The history question, answered properly

Now the expensive one.

Ask why you want the history, and the answers are always one of four. Each has a cheap answer and an expensive answer, and the expensive answer is the same for all four: load it into Odoo.

"For comparison — I want last year next to this year." You want reporting, not transactions. A summarised trial balance by month, or revenue by customer by month, loaded as opening journals or held in a reporting layer, gives you the comparison for a small fraction of the cost of loading the documents that produced it.

"For the auditor." Your auditor wants records, not your ERP. Which brings us to the obligation everybody in the UAE now carries.

"To chase what I am owed." This is a genuine need and it is already covered: open receivables come across as part of the opening balances, invoice by invoice, with dates and ages, because you cannot chase a lump sum. What you do not need is the paid ones.

"Because we paid for that data." This is the real answer more often than the other three, and it is not a stupid one — it is just a sunk cost. The data is not lost. It is in the old system, and the old system can be kept.

The pattern that works, and that we use, is a boundary rather than a volume:

What you wantWhere it should liveRoughly what it costs
Open receivables and payables, by documentOdoo, in the opening balancesIncluded in any competent migration
Stock on hand, by item and locationOdoo, from a physical countThe count, not the load
Current-year comparativesOdoo, as summarised monthly journalsDays
Prior-year comparativesA reporting layer, or a manual comparativeDays
Closed documents, older than the boundaryThe old system, retained read-onlyThe licence, or nothing
Statutory retention for seven yearsThe old system, or a certified exportNothing
Serial and batch history where a recall must reach itOdoo, deliberately, as a defined scopeA real line in the budget

That last row is the exception that proves the rule. If you are in food, pharmaceuticals, medical devices or anything where a recall has to reach a specific batch, historical traceability is not nostalgia — it is a control, and it belongs in the operational system. Price it, scope it, and load it on purpose. Everything above it in that table is a habit rather than a requirement.

The instant, and the signature

Opening balances are not a data problem. They are an accountability problem wearing data's clothes.

Two disciplines carry most of the weight, and neither is technical.

The first is that every balance is taken at a stated instant, and the instant is the same for all of them. A trial balance extracted on Friday morning that includes a posting made on Friday afternoon is not a balance; it is a number with a timestamp that does not match the number next to it. The most common migration defect we see is not bad data. It is good data taken at three different moments.

The second is that every opening balance is signed by the person who owns that ledger. Not agreed in a meeting. Signed, on a document that states what the figure is and when it was taken. Eleven months later, when somebody asks why the opening balance on a customer account was what it was, that signature is the answer, and its absence is a three-day forensic exercise nobody has budgeted.

Opening stock is the one that hurts. It comes from a count, not from a report, because the count is your last chance to discover that the gap between the shelf and the ledger is nine per cent rather than the one per cent everybody assumed — and because the operations team will use the new system only if they believe the number in it. The reasons that gap exists in the first place are why your stock figure is wrong, and they do not fix themselves by changing software.

The mechanics of the weekend on which all this actually happens — the freeze, the sequence, the go decision, the rollback that must exist — are a separate discipline entirely, and they are set out in the cutover weekend.

The parallel run, and the honest version of it

Somebody will propose running both systems for a month. It sounds prudent. It usually is not, and it is worth knowing why before you commit to it.

A true parallel run means every transaction is entered twice, in two systems, by the same people, and the two are reconciled. It doubles the workload of your busiest staff during the month they can least afford it. In practice it collapses in the second week: the new system falls behind because the old one is faster for people who know it, and you end up with a partial second set of books that agrees with nothing. Now you have three positions instead of two, and the reconciliation you commissioned to reduce risk has become the risk.

What works instead is narrower and cheaper, and it is what you almost certainly meant:

Run the old system read-only alongside the new one for as long as you like. It answers questions, it holds the history, it satisfies retention, and it costs nothing but a licence. What it must not do is accept a new transaction, because the moment it does you have two live sets of books.

Where you genuinely need assurance, parallel one process rather than the whole company — payroll is the usual candidate, because it is monthly, self-contained, and wrong in a way people notice immediately. Run one cycle in both, reconcile to the fils, then stop.

And reconcile forward rather than sideways. For the first fortnight, produce a daily pack that reconciles what was entered against what came out. A systematic error found on day three is a hundred records. The same error found in week five is four thousand, and by then people have built workarounds around it.

Who signs, and why it decides the timeline

Every migration has exactly one bottleneck, and it is never the loading.

Somebody has to decide that this customer record is the real one and that one is a duplicate. Somebody has to decide which of the three spellings of a supplier is the entity you actually owe money to. Somebody has to decide the unit conversion for four hundred items, the location structure, the costing method, the analytic dimension, and which of two opening balances is right when the sub-ledger and the general ledger disagree.

These decisions cannot be made by your partner, and a partner who offers to make them is selling you a problem dressed as a service. They can only be made by people who know your business, and those people have day jobs.

So the practical question at the start of a migration is not "how long will the data take?" It is: who are the four or five named people who will answer these questions, how many hours a week do they genuinely have, and what happens to their normal work while they do it? A project with a clean plan and no named data owners will slip, and it will slip in the least visible way — decisions deferred one at a time until the cutover date arrives with a list of open questions attached.

Name them at the start. Put the hours in writing. It is the single highest-return thing you can do before the project begins, and it costs nothing.

What this actually costs

Migration is one line in a budget that has five, and it is the line most often quoted before anybody has looked at the data. A fixed migration fee agreed before somebody has profiled your customer, item and balance records is not a price. It is an assumption with a number attached, and when the assumption fails, the conversation is about a variation order rather than about your data.

The honest sequence is: profile first, then price. A few days spent counting the records, measuring the duplicates, checking whether the item master has units at all, and finding out how many of your open invoices are actually open, converts the largest unknown in the project into a scope. It is cheap, and it is the only thing that makes the rest of the quote mean anything.

For a first planning number against your own user count and complexity, the ERP cost estimator gives a band with its assumptions disclosed. What separates a band from a budget is exactly the profiling described above.

And keep the two categories apart in your head while you read the quote. Configuration is what the system was built to let you change; customisation is code somebody now owns forever. A migration that requires custom code to represent your old data is usually a migration that has not yet asked whether the old shape was worth preserving — a distinction with a long commercial tail, set out in configuration against customisation.

Where this leaves you

The company that migrates well is not the one with the cleanest export. It is the one that separated the three jobs, drew a boundary under history instead of loading it by reflex, named the people who would answer the questions, and signed its opening balances at a single stated instant.

The company that migrates badly usually did one thing: it treated the migration as the technical tail end of a software purchase, discovered in the last fortnight that nobody had decided what a carton was, and went live on numbers its own operations team did not believe.

Nothing in that second outcome was caused by Odoo, or by Zoho, or by Tally. It was caused by asking a data question when the real question was a business one.

If you are leaving an accounting package and want the masters profiled, the history boundary drawn and the opening balances scoped by people who have done it before, that is a defined piece of work and it is where our Odoo implementation starts — with your data, before the quote, not after it.

Source note

The record retention requirement cited above is from the Federal Tax Authority's public statement of 28 August 2025, which states that Taxable Persons and Exempt Persons must retain relevant records for at least seven years following the end of the tax period to which they relate. Obligations change; confirm the current position with the FTA or your tax adviser before designing a retention approach.

Next step

Is this happening in your company?

If the article described your situation, the useful next move is a diagnosis rather than another article. Tell us the one thing that is not working.

Monday to Friday, 9:00 AM – 6:00 PM (GST)

Prefer we call you?

Leave your WhatsApp number and we will reach out.

We reply on WhatsApp first. Include your country code.

No newsletter, no reselling your number. We use it to reply to you — see our privacy policy.

WhatsApp us