From ce8ad842a28f611dd633009ca3fa8941521e2d2f Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Mon, 15 Jun 2015 11:57:11 +0200 Subject: [PATCH] [FIX] account: fix payment on multiple invoices --- addons/account/account_invoice.py | 6 +- addons/account/account_move.py | 19 +++--- addons/account/account_payment.py | 61 +++++++------------ addons/account/views/account_payment_view.xml | 2 +- 4 files changed, 38 insertions(+), 50 deletions(-) diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 8b769016a90..f4b855b4aad 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -520,10 +520,12 @@ class AccountInvoice(models.Model): tax_grouped[key]['amount'] += val['amount'] return tax_grouped - @api.one + @api.multi def register_payment(self, payment_line, writeoff_acc_id=False, writeoff_journal_id=False): """ Reconcile payable/receivable lines from the invoice with payment_line """ - line_to_reconcile = self.move_id.line_ids.filtered(lambda r: not r.reconciled and r.account_id.internal_type in ('payable', 'receivable')) + line_to_reconcile = self.env['account.move.line'] + for inv in self: + line_to_reconcile += inv.move_id.line_ids.filtered(lambda r: not r.reconciled and r.account_id.internal_type in ('payable', 'receivable')) return (line_to_reconcile + payment_line).reconcile(writeoff_acc_id, writeoff_journal_id) @api.v7 diff --git a/addons/account/account_move.py b/addons/account/account_move.py index 61a8bffd3cd..acb682e88bf 100644 --- a/addons/account/account_move.py +++ b/addons/account/account_move.py @@ -695,14 +695,17 @@ class AccountMoveLine(models.Model): def _get_pair_to_reconcile(self): #field is either 'amount_residual' or 'amount_residual_currency' (if the reconciled account has a secondary currency set) field = self[0].account_id.currency_id and 'amount_residual_currency' or 'amount_residual' - #target the pair of move in self with smallest debit, credit - smallest_debit = smallest_credit = False - for aml in self: - if aml[field] > 0: - smallest_debit = (not smallest_debit or aml[field] < smallest_debit[field]) and aml or smallest_debit - elif aml[field] < 0: - smallest_credit = (not smallest_credit or aml[field] > smallest_credit[field]) and aml or smallest_credit - return smallest_debit, smallest_credit + #target the pair of move in self that are the oldest + sorted_moves = sorted(self, key=lambda a: a.date) + debit = credit = False + for aml in sorted_moves: + if credit != False and credit != False: + break + if aml[field] > 0 and debit == False: + debit = aml + elif aml[field] < 0 and credit == False: + credit = aml + return debit, credit def auto_reconcile_lines(self): """ This function iterates recursively on the recordset given as parameter as long as it diff --git a/addons/account/account_payment.py b/addons/account/account_payment.py index bd0fc240653..70d38d6978b 100644 --- a/addons/account/account_payment.py +++ b/addons/account/account_payment.py @@ -146,7 +146,7 @@ class account_register_payments(models.TransientModel): 'communication': self.communication, 'invoice_ids': [(4, inv.id, None) for inv in self._get_invoices()], 'payment_type': self.payment_type, - 'amount': self._compute_total_invoices_amount(), + 'amount': self.amount, 'currency_id': self.currency_id.id, 'partner_id': self.partner_id.id, 'partner_type': self.partner_type, @@ -175,11 +175,7 @@ class account_payment(models.Model): def _compute_payment_difference(self): if len(self.invoice_ids) == 0: return - # A payment on multiple invoices must pay them entirely (and amount be readonly of course) - if len(self.invoice_ids) != 1: - self.payment_difference = 0 - else: - self.payment_difference = self._compute_total_invoices_amount() - self.amount + self.payment_difference = self._compute_total_invoices_amount() - self.amount company_id = fields.Many2one(store=True) @@ -314,7 +310,7 @@ class account_payment(models.Model): @api.multi def unlink(self): if any(rec.state != 'draft' for rec in self): - raise UserError(_("In order to delete a payment, it must first be canceled.")) + raise UserError(_("You can not delete a payment that is already posted")) return super(account_payment, self).unlink() @api.multi @@ -367,42 +363,24 @@ class account_payment(models.Model): Return the journal entry. """ aml_obj = self.env['account.move.line'].with_context(check_move_validity=False) - invoice_id = len(self.invoice_ids) == 1 and self.invoice_ids[0] or False - total_debit, total_credit, total_amount_currency = aml_obj.with_context(date=self.payment_date).compute_amount_fields(amount, self.currency_id, self.company_id.currency_id) + debit, credit, amount_currency = aml_obj.with_context(date=self.payment_date).compute_amount_fields(amount, self.currency_id, self.company_id.currency_id) move = self.env['account.move'].create(self._get_move_vals()) - if len(self.invoice_ids) > 1: - total_amount = 0 - for invoice_id in self.invoice_ids: - # Create a reconciliable journal item corresponding to the invoice - inv_amount = -invoice_id.residual * MAP_INVOICE_TYPE_PAYMENT_SIGN[invoice_id.type] - debit = inv_amount > 0 and inv_amount or 0 - credit = inv_amount < 0 and -inv_amount or 0 - amount_currency = self.currency_id != self.company_id.currency_id and self.company_id.currency_id.with_context(date=self.payment_date).compute(inv_amount, self.currency_id) or 0 - # Avoid unbalanced journal entry due to rounding error - total_amount = total_amount + debit - credit - counterpart_aml_dict = self._get_shared_move_line_vals(debit, credit, amount_currency, move.id, invoice_id) - counterpart_aml_dict.update(self._get_counterpart_move_line_vals(invoice_id)) - counterpart_aml_dict.update({'currency_id': self.currency_id != self.company_id.currency_id and self.currency_id.id or False}) - counterpart_aml = aml_obj.create(counterpart_aml_dict) - invoice_id.register_payment(counterpart_aml) - total_debit = total_amount > 0 and total_amount or 0 - total_credit = total_amount < 0 and -total_amount or 0 + #Write line corresponding to invoice payment + counterpart_aml_dict = self._get_shared_move_line_vals(debit, credit, amount_currency, move.id, False) + counterpart_aml_dict.update(self._get_counterpart_move_line_vals(self.invoice_ids)) + counterpart_aml_dict.update({'currency_id': self.currency_id != self.company_id.currency_id and self.currency_id.id or False}) + counterpart_aml = aml_obj.create(counterpart_aml_dict) + + #Reconcile with the invoices + if self.payment_difference_handling == 'reconcile': + self.invoice_ids.register_payment(counterpart_aml, self.writeoff_account, self.journal_id) else: - # Create reconciliable journal item - counterpart_aml_dict = self._get_shared_move_line_vals(total_debit, total_credit, total_amount_currency, move.id, invoice_id) - counterpart_aml_dict.update(self._get_counterpart_move_line_vals(invoice_id)) - counterpart_aml = aml_obj.create(counterpart_aml_dict) + self.invoice_ids.register_payment(counterpart_aml) - # Reconcile it with the invoice if present - if invoice_id: - if self.payment_difference_handling == 'reconcile': - invoice_id.register_payment(counterpart_aml, self.writeoff_account, self.journal_id) - else: - invoice_id.register_payment(counterpart_aml) - - liquidity_aml_dict = self._get_shared_move_line_vals(total_credit, total_debit, -total_amount_currency, move.id, invoice_id) + #Write counterpart lines + liquidity_aml_dict = self._get_shared_move_line_vals(credit, debit, -amount_currency, move.id, False) liquidity_aml_dict.update(self._get_liquidity_move_line_vals(-amount)) aml_obj.create(liquidity_aml_dict) @@ -475,7 +453,7 @@ class account_payment(models.Model): if self.payment_type == 'transfer': name = self.name else: - name = invoice and invoice.number + ': ' or '' + name = '' if self.partner_type == 'customer': if self.payment_type == 'inbound': name += _("Customer Payment") @@ -486,6 +464,11 @@ class account_payment(models.Model): name += _("Supplier Refund") elif self.payment_type == 'outbound': name += _("Supplier Payment") + if invoice: + name += ': ' + for inv in invoice: + name += inv.number+', ' + name = name[:len(name)-2] return { 'name': name, 'account_id': self.destination_account_id.id, diff --git a/addons/account/views/account_payment_view.xml b/addons/account/views/account_payment_view.xml index d15c91629c1..0ff503e29fe 100644 --- a/addons/account/views/account_payment_view.xml +++ b/addons/account/views/account_payment_view.xml @@ -244,7 +244,7 @@ - +