Odoo 11无法创建不平衡日记账分录求助:V8可用代码V11失效
Hey there! Let's dig into why your journal entry code stopped working when moving from Odoo 8 to Odoo 11, and how to fix it.
The Root Cause
Odoo 11 introduced stricter validation for journal entries. In older versions like Odoo 8, you could create an empty move first, then add debit/credit lines one by one. But in Odoo 11+, the system checks for balance during each step—so creating a move with no lines, or adding just one line (leaving the entry unbalanced temporarily) triggers the "Cannot Create Unbalanced Journal Entry" error.
Solution 1: Create Move + Lines in One Go (Recommended)
The cleanest approach is to define all your journal lines upfront and pass them directly when creating the account.move using Odoo's one2many field syntax (0, 0, {values}). This way, the system validates the full balanced entry immediately.
Here's the revised code:
def create_journal_entry(self): move_pool = self.env['account.move'] name = "Advance payment: %s" % (self.employee_id.name) debit_account_id = self.debit_id.id credit_account_id = self.payment_method.id # Prepare both debit and credit lines in one2many format move_lines = [ # Debit line (0, 0, { 'name': name, 'partner_id': self.employee_id.address_home_id.id if self.employee_id.address_home_id else False, 'account_id': debit_account_id, 'debit': self.need_amount, 'credit': 0.0 }), # Credit line (0, 0, { 'name': name, 'partner_id': self.employee_id.address_home_id.id if self.employee_id.address_home_id else False, 'account_id': credit_account_id, 'debit': 0.0, 'credit': self.need_amount }) ] # Create the move with all lines included move_data = { 'journal_id': self.payment_method.id, 'ref': name, 'company_id': self.company_id.id, 'line_ids': move_lines } move_id = move_pool.create(move_data) return move_id
Solution 2: Create Draft Move First, Add Lines, Then Validate
If you need to keep the line creation separate (for example, if you have conditional logic for lines), you can create the move in draft state first, add lines, then post it once it's balanced:
def create_journal_entry(self): move_pool = self.env['account.move'] move_line_pool = self.env['account.move.line'] name = "Advance payment: %s" % (self.employee_id.name) debit_account_id = self.debit_id.id credit_account_id = self.payment_method.id # Create move in draft state (avoids immediate balance checks) move_data = { 'journal_id': self.payment_method.id, 'ref': name, 'company_id': self.company_id.id, 'state': 'draft' # Explicitly set to draft (default may already be draft, but safe to specify) } move_id = move_pool.create(move_data) # Add debit line debit_line = { 'move_id': move_id.id, 'name': name, 'partner_id': self.employee_id.address_home_id.id if self.employee_id.address_home_id else False, 'account_id': debit_account_id, 'debit': self.need_amount, 'credit': 0.0 } move_line_pool.create(debit_line) # Add credit line credit_line = { 'move_id': move_id.id, 'name': name, 'partner_id': self.employee_id.address_home_id.id if self.employee_id.address_home_id else False, 'account_id': credit_account_id, 'debit': 0.0, 'credit': self.need_amount } move_line_pool.create(credit_line) # Validate the move to set it to posted state move_id.post() return move_id
Key Notes
- Double-check that
self.payment_methodis indeed a record ofaccount.journal(since you're using its ID forjournal_id—your original code worked in Odoo 8, so this is likely correct, but worth confirming). - The first solution is more efficient and aligns with Odoo's modern best practices, so it's the preferred approach.
内容的提问来源于stack exchange,提问作者Mahmoud Elsaka




