
Migrating data and opening balances to Odoo for Egyptian companies
How do customer, vendor and stock balances move into Odoo without breaking the tie-out to the old system? Import in order, post invoice by invoice, then lock the period.
Executive summary
- Per Odoo's official documentation, version 19.0: the general import tool works on any business object as a CSV or XLSX file, links records through an External ID column, and requires the referenced record to be imported before the record that refers to it.
- The Get started guide in the Accounting documentation sets out the move from other software: master data first, then the opening entries — the trial balance as one imported entry that must itself balance, open invoices and bills, the inventory and bank balances.
- Receivables and payables must not be counted twice: in the opening trial balance their accounts are replaced by clearing accounts, and each open invoice or bill is imported on its own, for the amount still due, against the clearing account.
- Stock quantities are imported through the Physical Inventory page once product costs are set; the value is carried by the opening trial balance, equal to cost times quantity.
- Fixed assets: the documentation describes creating them one by one or from an asset model, and no import of existing assets or of their accumulated depreciation.
- Once the clearing accounts are at zero and the balances tie to the old trial balance, the prior period is locked by setting Lock Everything under Accounting ‣ Accounting ‣ Lock Dates.
Master data order and the import tool
Odoo's import tool is generic: from any list view, the Action icon, then Import records, with a ready template whose columns already map to Odoo's fields (a documented example is Import Template for Customers) or a file mapped manually, then Test, then Import.
The External ID column is what links files together: a unique identifier per record, best prefixed with its source's name ("company_1", not "1"), through which relations are imported (a column such as Related Company/External ID) and the same record is updated on re-import instead of being duplicated; an ID that is altered or removed may add a duplicate. The rule that governs the order is explicit: "the records of the related object need to be imported first". The transition guide applies it to accounting: the chart of accounts is created before any other record, and product categories before products. An account with an equivalent in the localisation's standard chart is renamed and recoded, not deleted, because some standard accounts are defaults on products, product categories, contacts and in the Accounting settings; the others are created or imported with at minimum a Code, an Account Name and a Type (the code is optional in Odoo 20, released in September 2026). Egyptian taxes, by contrast, arrive configured with the localisation package l10n_eg, Egypt's "default fiscal localization package" in the documentation's words, so the practical step is checking them against the old system's tax codes, not importing them afresh.
Opening balances
The documentation offers three moments to switch: the end of the fiscal year, the easiest because it minimises the data to transfer; the end of a tax period; or the middle of one, which it does not recommend because that period's tax filing must then combine data from both systems.
The old trial balance goes into the journal-entry import template from Accounting ‣ Accounting ‣ Journal Entries: one entry, with its reference, date and journal on the first line only, and each account on its own line with a debit or a credit, never 0.00 or a negative figure. The trial balance must itself balance; it is imported as a draft, reviewed and posted. Each bank, cash and credit-card journal gets an opening statement whose Starting Balance is set to the account's actual balance before the first transaction; Odoo 20's release notes add that any journal entry affecting a bank account must now originate from a bank transaction.
Customer and vendor balances: invoice by invoice
If the trial balance carries the receivables account and the open invoices are created as well, the receivable doubles, as the documentation's own example shows, and the same applies to payables. The answer is clearing accounts: in the trial-balance file, Accounts Receivable is replaced by AR Clearing and Accounts Payable by AP Clearing.
The open invoices, with credit notes and refunds, are then imported one by one with Odoo's templates, from their menus under Accounting ‣ Customers and Accounting ‣ Vendors. Each carries the partner, named exactly as the contact; its number, which must not already exist in the database; its date, in the same year as the number; a due date or payment terms, not both; and a single line for the amount still due, posted to the clearing account. The documentation recommends that single line rather than the original invoice lines, so that tax accounts are not affected twice. A foreign-currency invoice needs a historical exchange rate for its date before import. The imported drafts are then confirmed (Actions ‣ Confirm Entries).
The test is set in advance: open invoices less credit notes must equal the receivables on the opening trial balance, and vendor bills less refunds the payables, so that both clearing accounts come to zero after import.
Stock: quantities and value
The documentation states that the opening inventory follows the same steps whatever the accounting standard or valuation method; the method and its accounts are set beforehand under Accounting ‣ Configuration ‣ Settings, in the Inventory Valuation section. Product costs go in first. The count is then prepared in the inventory-adjustments import template from Inventory ‣ Operations ‣ Physical Inventory — product, Counted quantity, and location and lot or serial number where they apply — imported, applied with Apply All with an Inventory Reason such as "Opening inventory" and a Counting Date, and confirmed with Update Quantities.
The value is carried by the opening trial balance: its inventory accounts must equal the sum, across products, of cost times quantity. The Inventory Valuation report (under Accounting ‣ Review) shows, as Stock Variation, any difference between the posted inventory value and the valuation held in the Inventory app.
Fixed assets
An asset is recorded on an account of type Fixed Assets or Non-current Assets, and the asset documentation describes creating it from Accounting ‣ Accounting ‣ Assets ‣ Create, from a purchase journal item, or faster from an asset model (Assets Models) where the same kind of asset recurs; in Odoo 20, according to its release notes, depreciation models replace asset models. Neither that page nor the transition guide describes importing existing assets or their accumulated depreciation. In practice, each asset's cost, depreciation to the cut-over date and remaining life are taken from the old register, and the depreciation board is checked against it before the asset is confirmed, because the opening trial balance already carries that accumulated depreciation.
Reconciliation and locking the period
Before any lock is set, the migrated balances are reconciled to the old system's trial balance and sub-ledgers, account by account — through the Trial Balance, General Ledger, Aged Receivable/Payable and Partner Ledger reports — and the reconciliation is recorded in a signed memo kept with the migration file. The transition guide's final step is to check that every clearing account is balanced and change its Account Type to Off-Balance Sheet. The prior period is then locked by setting Lock Everything under Accounting ‣ Accounting ‣ Lock Dates: a posted entry dated on or before it can no longer be modified, and any new entry dated within it is posted on the day after the lock date; the other lock dates and the exceptions are a separate subject. The obligation to keep the old system's records continues, for the period set by article 38 of the Unified Tax Procedures Law No. 206 of 2020, detailed in Mandatory and electronic books in Egypt.
What this requires
- Clean and de-duplicate customer, vendor and product data before export from the old system, not after import.
- Set up the chart of accounts first, renaming and recoding standard accounts rather than deleting them, then the other master data, with one External ID kept for each record throughout the project.
- Switch at the end of a fiscal year or of a tax period, not in the middle of a tax period.
- Replace receivables and payables in the opening trial balance with clearing accounts, and import each open invoice for the amount still due against them.
- Set product costs before importing the count, and make the inventory accounts on the trial balance equal cost times quantity.
- Take each asset's cost, accumulated depreciation and remaining life from the old register before entering it.
- Obtain a signed reconciliation, with the clearing accounts at zero, before setting Lock Everything.
The firm's ERP Consulting Department plans the migration, carries out the data import and reconciles the balances before the lock is approved.
Mahmoud Nassef — Chartered Accountant (Egyptian Register), Founder Partner
Member, Egyptian Society of Accountants & Auditors
Member, Egyptian Tax Society
Member, Egyptian Society for Public Finance and Taxation
Partner profile · Book a consultation
Disclaimer: This bulletin is prepared for general information on the legislation in force at the date of its publication. It does not constitute a professional opinion or tax or legal advice on any particular matter, and it should not be relied upon in place of advice based on an examination of the circumstances of each case. Nassef & Partners International accepts no responsibility for any action taken, or refrained from, in reliance on its contents. The positions stated remain subject to subsequent legislation and decisions.
