Introduction
In Odoo, models define how data is structured and stored in the database. Every piece of business data you work with, from sales orders to invoices to journal entries, lives in a model.
Understanding Odoo models is essential for both developers and functional consultants. Models are the foundation of the Odoo data architecture. They define Odoo fields, relationships, and business logic.
This article focuses on one of the most important models in Odoo Accounting: account.move.line. Whether you are building custom reports, integrating external systems, or configuring reconciliation workflows, you will work with this model.
What is the account.move.line Model
The account.move.line model represents individual journal entry lines in Odoo. Each line is one debit or credit in a journal entry. Together, the lines of a journal entry must balance: total debits must equal total credits.
This model in Odoo is used by the Accounting module. It is the child of account.move, which represents the journal entry itself (invoices, bills, bank statements, journal entries). Every journal entry has one or more lines.
The model is defined in the account module. Other modules extend it through Odoo model inheritance. Sale adds invoice line details. Purchase adds bill line details. Account analytic adds analytic distribution. Each module adds what it needs without duplicating the core structure.
Key Fields in the Model
Here are the most important Odoo fields in the account.move.line model. Understanding these will help you work effectively with journal entries and accounting data.
1. name
Type: Char. This field stores the label or description of the line. It is required and typically displayed in journal entry views and reports. For invoice lines, it often comes from the product name or a custom description.
2. move_id
Type: Many2one (account.move). Links the line to its parent journal entry. Every line belongs to exactly one move. This is the main relationship in the model.
3. account_id
Type: Many2one (account.account). The account this line is posted to. Required. Must be a non-view, non-closed account. Used for chart of accounts reporting and grouping.
4. debit
Type: Float. The debit amount. Default is 0.0. For each line, either debit or credit is set, not both. Debits increase asset and expense accounts.
5. credit
Type: Float. The credit amount. Default is 0.0. Credits increase liability, equity, and revenue accounts. The sum of all debits must equal the sum of all credits in a move.
6. balance
Type: Float. A computed field: debit minus credit. Represents the net effect of the line. Positive for debits, negative for credits. Used in reports and reconciliation.
7. partner_id
Type: Many2one (res.partner). The customer, vendor, or other party linked to this line. Used for receivable and payable tracking, aging reports, and reconciliation.
8. date
Type: Date. The effective date of the line. Usually inherited from the parent move. Used for period closing, reporting, and aging.
9. date_maturity
Type: Date. The due date for payment. Relevant for receivables and payables. Used for aging reports and payment scheduling.
10. currency_id
Type: Many2one (res.currency). The currency of the line. Can differ from the company currency for multi-currency entries.
11. amount_currency
Type: Float. The amount in the line currency. Used when the journal entry is in a foreign currency. Together with currency_id, enables multi-currency accounting.
12. quantity
Type: Float. Optional quantity. Used for product-based lines (invoices, bills). Enables quantity-based reporting and unit price calculations.
13. product_id
Type: Many2one (product.product). The product linked to this line. Populated when the line comes from a sale order, purchase order, or invoice line.
14. product_uom_id
Type: Many2one (uom.uom). The unit of measure for the quantity. Used with product_id for proper quantity display and conversion.
15. price_unit
Type: Float. The unit price. Used with quantity to compute amounts on invoice and bill lines.
16. tax_ids
Type: Many2many (account.tax). Taxes applied to this line. Odoo creates additional lines for tax amounts when posting. Used for VAT and other tax calculations.
17. tax_line_id
Type: Many2one (account.tax). For tax lines, this references the tax that generated the line. Distinguishes tax lines from regular account lines.
18. analytic_account_id
Type: Many2one (account.analytic.account). The analytic account for cost and revenue tracking. Used when analytic accounting is enabled.
19. analytic_distribution
Type: Json or Text. Stores analytic distribution across multiple analytic accounts. Replaces analytic_account_id in newer Odoo versions when using analytic plans.
20. ref
Type: Char. Usually related from the parent move. External reference or memo. Displayed on reports and used for reconciliation matching.
21. narration
Type: Text. Usually related from the parent move. Internal note or memo. Not printed on customer-facing documents by default.
22. journal_id
Type: Many2one (account.journal). The journal of the parent move. Used for filtering and reporting by journal.
23. company_id
Type: Many2one (res.company). The company. In multi-company setups, each line belongs to one company. Affects record visibility and consolidation.
24. reconciled
Type: Boolean. Indicates whether the line has been fully reconciled. Used to filter unreconciled items in reconciliation views.
25. full_reconcile_id
Type: Many2one (account.full.reconcile). Links all lines that were reconciled together. Enables tracing of reconciliation groups.
26. payment_id
Type: Many2one (account.payment). For payment lines, links to the payment record. Used when reconciling invoices with payments.
27. statement_id
Type: Many2one (account.bank.statement). For bank statement lines, links to the statement. Used in bank reconciliation.
28. statement_line_id
Type: Many2one (account.bank.statement.line). Links to the specific bank statement line. Used when matching moves to bank transactions.
29. display_type
Type: Selection. Can be 'line_section' or 'line_note' for section headers and notes in the journal entry. These lines have no debit or credit and are for display only.
30. create_date
Type: Datetime. Stores when the record was created. Automatically managed by Odoo. Useful for auditing.
31. write_date
Type: Datetime. Stores when the record was last modified. Automatically managed. Helps track changes over time.
How This Model Is Used in Business Workflows
1. Customer Invoicing
When you confirm an invoice, Odoo creates account.move.line records. Revenue lines go to income accounts. Receivable lines go to the customer receivable account. Tax lines are created for each tax. The partner_id links to the customer for aging and reconciliation.
2. Vendor Bills
Bills create lines for expenses, input VAT, and payables. Each line has an account_id, debit or credit, and partner_id. The structure mirrors customer invoices but with different account types.
3. Bank Reconciliation
Bank statement lines are matched to move lines via statement_line_id. When you reconcile, Odoo links the lines through full_reconcile_id. The reconciled field is set to True.
4. Manual Journal Entries
Users create journal entries with multiple lines. Each line has an account, debit or credit, and optional partner. Odoo enforces that debits equal credits before posting.
5. Analytic and Cost Reporting
When analytic accounting is enabled, lines carry analytic_account_id or analytic_distribution. Reports group by analytic account to show cost and revenue by project, department, or other dimension.
How Developers Extend This Model
Developers extend account.move.line using several patterns. Odoo model inheritance is the main mechanism.
Model Inheritance
Use _inherit = 'account.move.line' to extend the model. Add new Odoo fields, override methods, or add constraints. The inherit model in Odoo keeps your changes in a separate module for easy upgrades.
Adding Fields
Define new Odoo fields in your inherited model. Use the right field type: Char, Many2one, Boolean, Integer, Text, Selection. Consider company-dependent fields for multi-company. Be careful with computed fields and their dependencies.
Python Extensions
Override create, write, or unlink to add logic. Use super() to call the original. Avoid breaking the debit-equals-credit invariant. The API model in Odoo exposes these methods for external integrations.
Odoo Studio
Odoo Studio lets you add fields to account.move.line without code. Good for quick customizations like extra labels or tags. For complex logic or reconciliation rules, custom modules are more maintainable.
Best Practices
- Never create or modify move lines directly without going through the move. Use the move's API (e.g. line_ids) so Odoo can maintain consistency and run all checks.
- When building reports, filter by move_id.state = 'posted' to exclude drafts and cancelled entries.
- Use account_id with the right account type (receivable, payable, etc.) for proper aging and reconciliation behavior.
- When integrating via API, create the move first, then add lines. Ensure debits equal credits before posting.
- For custom fields, use the
x_prefix or a module prefix to avoid conflicts with future Odoo versions.
Common Mistakes
- Setting both debit and credit on the same line. Each line should have either debit or credit, not both.
- Creating unbalanced moves. The sum of debits must equal the sum of credits. Odoo validates this on post.
- Modifying posted lines without using the proper reversal or adjustment workflow. Posted entries should be adjusted via new moves, not direct edits.
- Forgetting to set partner_id on receivable and payable lines. This breaks aging reports and reconciliation.
- Overriding core methods without calling super(). This can break reconciliation, locking, or other modules.
Conclusion
The account.move.line model is central to Odoo Accounting. It stores every debit and credit in journal entries, invoices, and bills. Understanding its fields and how modules extend it will help you configure, customize, and integrate Odoo effectively.
Whether you are a functional consultant mapping accounting workflows or a developer building custom reports and integrations, a solid grasp of account.move.line will save time and prevent errors.
Need Help With Your Odoo Implementation?
Dasolo helps companies implement, customize, and optimize Odoo. We specialize in API integrations and Odoo development. Our team has deep experience with the Odoo data architecture and models like account.move.line.
If you need help with your Odoo implementation, custom modules, or integrations, we are here to help. Book a demo to discuss your project.