diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc index d6c2f9a..fee86a4 100644 Binary files a/__pycache__/__init__.cpython-312.pyc and b/__pycache__/__init__.cpython-312.pyc differ diff --git a/data/__pycache__/__init__.cpython-312.pyc b/data/__pycache__/__init__.cpython-312.pyc index 54aa997..2814bfc 100644 Binary files a/data/__pycache__/__init__.cpython-312.pyc and b/data/__pycache__/__init__.cpython-312.pyc differ diff --git a/doc/__pycache__/__init__.cpython-312.pyc b/doc/__pycache__/__init__.cpython-312.pyc index 15b342d..990f4b8 100644 Binary files a/doc/__pycache__/__init__.cpython-312.pyc and b/doc/__pycache__/__init__.cpython-312.pyc differ diff --git a/models/__init__.py b/models/__init__.py index 18ebd68..7ae7e6d 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- from . import account_batch_payment from . import account_payment -from . import account_payment_register \ No newline at end of file +from . import account_payment_register +from . import account_payment_debug diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc index 5c881a1..c2b51c6 100644 Binary files a/models/__pycache__/__init__.cpython-312.pyc and b/models/__pycache__/__init__.cpython-312.pyc differ diff --git a/models/__pycache__/account_batch_payment.cpython-312.pyc b/models/__pycache__/account_batch_payment.cpython-312.pyc index 0e3842f..4963f81 100644 Binary files a/models/__pycache__/account_batch_payment.cpython-312.pyc and b/models/__pycache__/account_batch_payment.cpython-312.pyc differ diff --git a/models/__pycache__/account_payment.cpython-312.pyc b/models/__pycache__/account_payment.cpython-312.pyc index 2a5f2c0..e0107a2 100644 Binary files a/models/__pycache__/account_payment.cpython-312.pyc and b/models/__pycache__/account_payment.cpython-312.pyc differ diff --git a/models/account_batch_payment.py b/models/account_batch_payment.py index 88992eb..9266563 100644 --- a/models/account_batch_payment.py +++ b/models/account_batch_payment.py @@ -9,6 +9,23 @@ _logger = logging.getLogger(__name__) class AccountBatchPayment(models.Model): _inherit = "account.batch.payment" + # Override payment_ids to remove strict company check, allowing cross-company payments to be added + payment_ids = fields.One2many( + 'account.payment', + 'batch_payment_id', + string="Payments", + required=True, + check_company=False + ) + + company_id = fields.Many2one( + 'res.company', + string='Company', + related='journal_id.company_id', + store=True, + readonly=True + ) + # Add a field to store direct payment lines direct_payment_line_ids = fields.One2many( 'account.batch.payment.line', @@ -83,12 +100,21 @@ class AccountBatchPayment(models.Model): 'currency_id': line.currency_id.id, 'date': line.date, 'journal_id': self.journal_id.id, + 'company_id': line.company_id.id, 'payment_method_line_id': payment_method_line.id, 'ref': line.memo, 'expense_account_id': line.expense_account_id.id, } - payment = self.env['account.payment'].create(payment_vals) + # Create the payment with the branch's company context, bypassing security limits momentarily + payment = self.env['account.payment'].sudo().with_context( + allowed_company_ids=[line.company_id.id, self.company_id.id, self.env.company.id], + default_company_id=line.company_id.id, + ).create(payment_vals) + + # Since some compute methods might try to overwrite company_id based on journal, force it again + payment.write({'company_id': line.company_id.id}) + payment.action_post() # Link the payment to the line @@ -109,6 +135,25 @@ class AccountBatchPayment(models.Model): # If validation fails, log the error but don't prevent payment creation _logger.warning(f"Failed to automatically validate batch payment {self.id}: {str(e)}") + @api.constrains('batch_type', 'journal_id', 'payment_ids') + def _check_payments_constrains(self): + """Override standard constraint to allow cross-company / cross-journal payments.""" + for record in self: + all_types = set(record.payment_ids.mapped('payment_type')) + if all_types and record.batch_type not in all_types: + raise ValidationError(_("The batch must have the same type as the payments it contains.")) + all_payment_methods = record.payment_ids.payment_method_id + if len(all_payment_methods) > 1: + raise ValidationError(_("All payments in the batch must share the same payment method.")) + if all_payment_methods and record.payment_method_id not in all_payment_methods: + raise ValidationError(_("The batch must have the same payment method as the payments it contains.")) + payment_null = record.payment_ids.filtered(lambda p: p.amount == 0) + if payment_null: + raise ValidationError(_('You cannot add payments with zero amount in a Batch Payment.')) + non_posted = record.payment_ids.filtered(lambda p: p.state != 'posted') + if non_posted: + raise ValidationError(_('You cannot add payments that are not posted.')) + class AccountBatchPaymentLine(models.Model): _name = "account.batch.payment.line" @@ -120,9 +165,15 @@ class AccountBatchPaymentLine(models.Model): required=True, ondelete='cascade' ) + company_id = fields.Many2one( + 'res.company', + string='Company', + default=lambda self: self.env.company + ) partner_id = fields.Many2one( 'res.partner', - string='Partner' + string='Partner', + check_company=True # Removed required=True to avoid constraint issues ) amount = fields.Monetary( @@ -138,6 +189,7 @@ class AccountBatchPaymentLine(models.Model): expense_account_id = fields.Many2one( 'account.account', string='Expense Account', + check_company=True, domain="[('account_type', 'not in', ('asset_receivable', 'liability_payable'))]" ) memo = fields.Char(string='Memo') diff --git a/models/account_payment_debug.py b/models/account_payment_debug.py new file mode 100644 index 0000000..1b014aa --- /dev/null +++ b/models/account_payment_debug.py @@ -0,0 +1,22 @@ +import logging +from odoo import models, api + +_logger = logging.getLogger(__name__) + +class AccountPayment(models.Model): + _inherit = "account.payment" + + @api.model + def search(self, args, offset=0, limit=None, order=None, count=False): + try: + with open('/tmp/odoo_payment_search.log', 'a') as f: + f.write(f"\\n{'='*40}\\n") + f.write(f"ACCOUNT PAYMENT SEARCH CALLED\\n") + f.write(f"Args: {args}\\n") + f.write(f"Context: {self.env.context}\\n") + f.write(f"{'='*40}\\n") + except Exception as e: + _logger.error(f"Failed to log to /tmp: {e}") + + return super(AccountPayment, self).search(args, offset, limit, order, count) + diff --git a/views/account_batch_payment_views.xml b/views/account_batch_payment_views.xml index 03b5cfd..6d7ee3b 100644 --- a/views/account_batch_payment_views.xml +++ b/views/account_batch_payment_views.xml @@ -9,6 +9,7 @@ + @@ -23,6 +24,15 @@