# -*- coding: utf-8 -*- from odoo import models, fields, api, _ from odoo.exceptions import UserError class AccountPaymentRegister(models.TransientModel): _inherit = 'account.payment.register' def _create_payments(self): # Intercept centralized payments if self.journal_id.is_centralized: return self._create_centralized_payments() return super(AccountPaymentRegister, self)._create_payments() def _create_centralized_payments(self): """ Custom logic to create inter-company clearing moves when paying via a centralized journal. """ journal = self.journal_id if not journal.parent_company_id or not journal.parent_journal_id: raise UserError(_("The selected journal is marked as centralized but is missing parent company/journal configuration.")) if not journal.branch_intercompany_account_id or not journal.parent_intercompany_account_id: raise UserError(_("Inter-company (RK) accounts must be configured on the centralized journal.")) branch_company = self.company_id parent_company = journal.parent_company_id payments = self.env['account.payment'] # We process batches. In centralized mode, we usually expect 1 batch if coming from a single bill. # But we handle multiple if needed. for batch_result in self.batches: lines = batch_result['lines'] amount = abs(sum(lines.mapped('amount_residual'))) if self.currency_id != branch_company.currency_id: amount = abs(sum(lines.mapped('amount_residual_currency'))) # 1. Create Clearing Move in Branch Company # Debit: Payable Account (clears the vendor bill) # Credit: Inter-company (RK) Account (Liability to Parent) # Currency logic: Odoo 19 requires debit/credit in company currency # and amount_currency in foreign currency. amount_company_curr = abs(sum(lines.mapped('amount_residual'))) amount_currency = 0.0 currency_id = False if self.currency_id != branch_company.currency_id: amount_currency = sum(lines.mapped('amount_residual_currency')) currency_id = self.currency_id.id clearing_move_vals = { 'move_type': 'entry', 'company_id': branch_company.id, 'journal_id': journal.id, 'date': self.payment_date, 'ref': _("Centralized Payment for %s") % (", ".join(lines.move_id.mapped('name'))), 'line_ids': [ (0, 0, { 'name': _("Clearing: %s") % (", ".join(lines.move_id.mapped('name'))), 'partner_id': self.partner_id.id, 'account_id': lines[0].account_id.id, # The payable account 'debit': amount_company_curr if self.payment_type == 'outbound' else 0.0, 'credit': amount_company_curr if self.payment_type == 'inbound' else 0.0, 'currency_id': currency_id, 'amount_currency': amount_currency if self.payment_type == 'outbound' else -amount_currency, }), (0, 0, { 'name': _("Due to Parent (%s)") % parent_company.name, 'partner_id': False, 'account_id': journal.branch_intercompany_account_id.id, 'debit': amount_company_curr if self.payment_type == 'inbound' else 0.0, 'credit': amount_company_curr if self.payment_type == 'outbound' else 0.0, 'currency_id': currency_id, 'amount_currency': -amount_currency if self.payment_type == 'outbound' else amount_currency, }), ], } branch_move = self.env['account.move'].create(clearing_move_vals) branch_move.action_post() # Reconcile Branch Move with the Bill Lines clearing_lines = branch_move.line_ids.filtered(lambda l: l.account_id == lines[0].account_id) (lines + clearing_lines).reconcile() # 2. Create actual Payment in Parent Company # We use account.payment to ensure it shows up in bank reconciliation in the parent payment_vals = { 'company_id': parent_company.id, 'journal_id': journal.parent_journal_id.id, 'payment_type': self.payment_type, 'partner_type': self.partner_type, 'partner_id': self.partner_id.id, 'amount': abs(amount_currency) if currency_id else amount_company_curr, 'currency_id': self.currency_id.id, 'date': self.payment_date, 'memo': _("Centralized Pay for %s (%s)") % (branch_company.name, ", ".join(lines.move_id.mapped('name'))), 'destination_account_id': journal.parent_intercompany_account_id.id, } # Create payment in parent company context parent_payment = self.env['account.payment'].with_company(parent_company).sudo().create(payment_vals) parent_payment.action_post() payments |= parent_payment return payments