# -*- coding: utf-8 -*- from odoo import models, fields, api, _ class AccountBatchPayment(models.Model): _inherit = "account.batch.payment" def generate_payments_from_lines(self): """Override to transfer deduction fields to generated payments""" self.ensure_one() payment_ids = [] # First, try to use the journal's available payment methods available_payment_methods = self.journal_id._get_available_payment_method_lines(self.batch_type) # Fix: Check payment_method_id.code, not just code payment_method_line = available_payment_methods.filtered(lambda x: x.payment_method_id.code == 'direct_batch') if not payment_method_line: # If no direct batch payment method found, prefer 'manual' method for bank journals if available_payment_methods: # Try to find 'manual' payment method (most common for bank transfers) manual_method = available_payment_methods.filtered(lambda x: x.payment_method_id.code == 'manual') payment_method_line = manual_method[:1] if manual_method else available_payment_methods[0] else: # Fallback: try to find or create a direct batch payment method line payment_method_line = self.env['account.payment.method.line'].search([ ('payment_method_id.code', '=', 'direct_batch'), ('journal_id', '=', self.journal_id.id) ], limit=1) if not payment_method_line: # Try to create the payment method line if it doesn't exist payment_method = self.env['account.payment.method'].search([ ('code', '=', 'direct_batch'), ('payment_type', '=', self.batch_type) ], limit=1) if payment_method: # Check if a payment method line already exists for this journal and method existing_pml = self.env['account.payment.method.line'].search([ ('payment_method_id', '=', payment_method.id), ('journal_id', '=', self.journal_id.id) ], limit=1) if not existing_pml: payment_method_line = self.env['account.payment.method.line'].create({ 'name': payment_method.name, 'payment_method_id': payment_method.id, 'journal_id': self.journal_id, }) else: payment_method_line = existing_pml else: from odoo.exceptions import ValidationError raise ValidationError(_("No payment method found for this journal.")) # Check that all lines have a partner for line in self.direct_payment_line_ids: if not line.partner_id: from odoo.exceptions import ValidationError raise ValidationError(_("All payment lines must have a partner selected.")) for line in self.direct_payment_line_ids: # Determine payment type and partner type based on batch type payment_type = self.batch_type partner_type = 'customer' if self.batch_type == 'inbound' else 'supplier' # Create the payment payment_vals = { 'payment_type': payment_type, 'partner_type': partner_type, 'partner_id': line.partner_id.id, 'amount': line.amount, 'currency_id': line.currency_id.id, 'date': line.date, 'journal_id': self.journal_id.id, 'payment_method_line_id': payment_method_line.id, 'ref': line.memo, 'expense_account_id': line.expense_account_id.id if line.expense_account_id else False, } payment = self.env['account.payment'].create(payment_vals) # Transfer deduction lines from batch payment line to payment if line.deduction_line_ids: for deduction in line.deduction_line_ids: self.env['payment.deduction.line'].create({ 'payment_id': payment.id, 'amount_substract': deduction.amount_substract, 'substract_account_id': deduction.substract_account_id.id, 'name': deduction.name, 'sequence': deduction.sequence, }) payment.action_post() # Link the payment to the line line.payment_id = payment.id payment_ids.append(payment.id) # Add the generated payments to the batch if payment_ids: self.write({ 'payment_ids': [(4, payment_id) for payment_id in payment_ids] }) # Automatically validate the batch payment after generating payments if self.state == 'draft': try: self.validate_batch() except Exception as e: # If validation fails, log the error but don't prevent payment creation import logging _logger = logging.getLogger(__name__) _logger.warning(f"Failed to automatically validate batch payment {self.id}: {str(e)}") class AccountBatchPaymentLine(models.Model): _inherit = "account.batch.payment.line" deduction_line_ids = fields.One2many( 'payment.deduction.line', 'batch_payment_line_id', string='Deductions', help='Payment deductions (e.g., withholding tax, fees)', ) amount_substract = fields.Monetary( string='Total Deductions', currency_field='currency_id', compute='_compute_amount_substract', store=True, help='Total amount to be deducted from the payment', ) @api.depends('deduction_line_ids.amount_substract') def _compute_amount_substract(self): for line in self: line.amount_substract = sum(line.deduction_line_ids.mapped('amount_substract'))