diff --git a/account_operating_unit/__init__.py b/account_operating_unit/__init__.py index e3c4fddcdc..1fc45468f5 100644 --- a/account_operating_unit/__init__.py +++ b/account_operating_unit/__init__.py @@ -2,4 +2,3 @@ from . import models from . import report -from . import wizards diff --git a/account_operating_unit/models/account_move.py b/account_operating_unit/models/account_move.py index 12557c6a68..b83a6467be 100644 --- a/account_operating_unit/models/account_move.py +++ b/account_operating_unit/models/account_move.py @@ -94,7 +94,9 @@ def _check_ou_balance(self, move): def _post(self, soft=True): ml_obj = self.env["account.move.line"] for move in self: - if not move.company_id.ou_is_self_balanced: + if not move.company_id.ou_is_self_balanced or self.env.context.get( + "inter_ou_balance_entry", False + ): continue # If all move lines point to the same operating unit, there's no diff --git a/account_operating_unit/models/account_move_line.py b/account_operating_unit/models/account_move_line.py index 5d36deeded..f04242f8ab 100644 --- a/account_operating_unit/models/account_move_line.py +++ b/account_operating_unit/models/account_move_line.py @@ -54,3 +54,62 @@ def _check_move_operating_unit(self): " same." ) ) + + def _check_ou_balance(self, lines): + # Look for the balance of each OU + ou_balance = {} + for line in lines: + if line.operating_unit_id.id not in ou_balance: + ou_balance[line.operating_unit_id.id] = 0.0 + ou_balance[line.operating_unit_id.id] += line.credit - line.debit + return ou_balance + + def reconcile(self): + # if one OU pays the invoices of different OU + # a regularization entry must be created (this + # was a feature in version <= 12) + if self and not self[0].company_id.ou_is_self_balanced: + return super().reconcile() + bank_journal = self.mapped("move_id.journal_id").filtered( + lambda l: l.type in ("bank", "cash") + ) + if not bank_journal: + return super().reconcile() + bank_journal = bank_journal[0] + # If all move lines point to the same operating unit, there's no + # need to create a balancing move line + if len(self.mapped("operating_unit_id")) <= 1: + return super().reconcile() + # Create balancing entries for un-balanced OU's. + move_vals = self._prepare_inter_ou_balancing_move(bank_journal) + move = self.env["account.move"].create(move_vals) + ou_balances = self._check_ou_balance(self) + amls = [] + for ou_id in list(ou_balances.keys()): + # If the OU is already balanced, then do not continue + if move.company_id.currency_id.is_zero(ou_balances[ou_id]): + continue + # Create a balancing move line in the operating unit + # clearing account + line_data = move._prepare_inter_ou_balancing_move_line( + move, ou_id, ou_balances + ) + if line_data: + amls.append( + self.with_context(check_move_validity=False).create(line_data) + ) + if amls: + move.with_context(check_move_validity=True).write( + {"line_ids": [(4, aml.id) for aml in amls]} + ) + move.with_context(inter_ou_balance_entry=True).action_post() + return super().reconcile() + + def _prepare_inter_ou_balancing_move(self, journal): + move_vals = { + "journal_id": journal.id, + "date": max(self.mapped("date")), + "ref": "Inter OU Balancing", + "company_id": journal.company_id.id, + } + return move_vals diff --git a/account_operating_unit/tests/test_payment_operating_unit.py b/account_operating_unit/tests/test_payment_operating_unit.py index 75aeb2d60e..5fc7b6ea93 100644 --- a/account_operating_unit/tests/test_payment_operating_unit.py +++ b/account_operating_unit/tests/test_payment_operating_unit.py @@ -68,10 +68,19 @@ def test_payment_from_two_invoices(self): register_payments.action_create_payments() payments = self.payment_model.search([], order="id desc", limit=2) + inter_ou_moves = self.move_model.search( + [("ref", "=", "Inter OU Balancing")], order="id desc", limit=2 + ) + self.assertEqual( + sum(inter_ou_moves[0].mapped("line_ids.debit")), invoices[0].amount_total + ) + self.assertEqual( + sum(inter_ou_moves[1].mapped("line_ids.debit")), invoices[1].amount_total + ) for payment in payments: # Validate that inter OU balance move lines are created - self.assertEqual(len(payment.move_id.line_ids), 4) - self.assertEqual(payment.amount, invoices[0].amount_total) + self.assertEqual(len(payment.move_id.line_ids), 2) + self.assertAlmostEqual(payment.amount, invoices[0].amount_total) self.assertEqual(payment.state, "posted") for invoice in invoices: self.assertEqual(invoice.payment_state, "paid") diff --git a/account_operating_unit/wizards/__init__.py b/account_operating_unit/wizards/__init__.py deleted file mode 100644 index 77e487c8c7..0000000000 --- a/account_operating_unit/wizards/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). - -from . import account_payment_register diff --git a/account_operating_unit/wizards/account_payment_register.py b/account_operating_unit/wizards/account_payment_register.py deleted file mode 100644 index 91318b6d71..0000000000 --- a/account_operating_unit/wizards/account_payment_register.py +++ /dev/null @@ -1,46 +0,0 @@ -# © 2020 Jarsa Sistemas, SA de CV -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). - -from odoo import _, models -from odoo.exceptions import UserError - - -class AccountPaymentRegister(models.TransientModel): - _inherit = "account.payment.register" - - def _get_reconciled_moves(self, payment): - return payment.reconciled_bill_ids + payment.reconciled_invoice_ids - - def _create_payments(self): - payments = super()._create_payments() - if self.group_payment and len(payments) > 1: - return payments - for payment in payments: - to_reconcile = self.env["account.move.line"] - reconciled_moves = self._get_reconciled_moves(payment) - if len(reconciled_moves.operating_unit_id) > 1: - raise UserError( - _( - "The OU in the Bills/Invoices to register payment must be the same." - ) - ) - if reconciled_moves.operating_unit_id != payment.operating_unit_id: - destination_account = payment.destination_account_id - line = payment.move_id.line_ids.filtered( - lambda l: l.account_id == destination_account - ) - line.write( - { - "operating_unit_id": reconciled_moves.operating_unit_id.id, - } - ) - # reconcile with case self balanced only - if payment.move_id.company_id.ou_is_self_balanced: - to_reconcile |= line - to_reconcile |= reconciled_moves.line_ids.filtered( - lambda l: l.account_id == destination_account - ) - payment.action_draft() - payment.action_post() - to_reconcile.filtered(lambda r: not r.reconciled).reconcile() - return payments