From 516b80fc07eb6ea5e2152d74739c59f05b49022e Mon Sep 17 00:00:00 2001 From: Laurent Smet Date: Tue, 20 Oct 2020 06:33:23 +0000 Subject: [PATCH] [FIX] account,payment: Fix payment token flow after payment refactoring - The field 'invoice_ids' no longer exists on account.payment. - When registering a payment using a payment token, the payment is not posted directly but the payment transaction is processed instead. It means the payment is not posted until the CRON call. Since 14.0, the journal items can't be reconciled if not posted and then, we can't wait the CRON to update the payment state. - The payment token is no longer available when registering a payment for invoices. closes odoo/odoo#60918 Task: 2352628 X-original-commit: 0ad8979cb345805b7b1bdc330621b42e1d625593 Signed-off-by: Quentin De Paoli (qdp) Signed-off-by: Laurent Smet --- .../wizard/account_payment_register.py | 6 ++ addons/payment/__manifest__.py | 1 + addons/payment/models/account_payment.py | 9 ++- addons/payment/models/payment_acquirer.py | 5 +- addons/payment/wizards/__init__.py | 1 + .../wizards/account_payment_register.py | 71 +++++++++++++++++++ .../account_payment_register_views.xml | 23 ++++++ 7 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 addons/payment/wizards/account_payment_register.py create mode 100644 addons/payment/wizards/account_payment_register_views.xml diff --git a/addons/account/wizard/account_payment_register.py b/addons/account/wizard/account_payment_register.py index 8efd850c9bb..df9f6875b81 100644 --- a/addons/account/wizard/account_payment_register.py +++ b/addons/account/wizard/account_payment_register.py @@ -472,6 +472,12 @@ class AccountPaymentRegister(models.TransientModel): domain = [('account_internal_type', 'in', ('receivable', 'payable')), ('reconciled', '=', False)] for payment, lines in zip(payments, to_reconcile): + + # When using the payment tokens, the payment could not be posted at this point (e.g. the transaction failed) + # and then, we can't perform the reconciliation. + if payment.state != 'posted': + continue + payment_lines = payment.line_ids.filtered_domain(domain) for account in payment_lines.account_id: (payment_lines + lines)\ diff --git a/addons/payment/__manifest__.py b/addons/payment/__manifest__.py index ed34d0a3768..fb69b3b1e63 100644 --- a/addons/payment/__manifest__.py +++ b/addons/payment/__manifest__.py @@ -24,6 +24,7 @@ 'security/ir.model.access.csv', 'security/payment_security.xml', 'wizards/payment_link_wizard_views.xml', + 'wizards/account_payment_register_views.xml', ], 'installable': True, 'auto_install': True, diff --git a/addons/payment/models/account_payment.py b/addons/payment/models/account_payment.py index efde15eaf68..0bc1e179856 100644 --- a/addons/payment/models/account_payment.py +++ b/addons/payment/models/account_payment.py @@ -51,10 +51,10 @@ class AccountPayment(models.Model): self.ensure_one() return { 'amount': self.amount, + 'reference': self.ref, 'currency_id': self.currency_id.id, 'partner_id': self.partner_id.id, 'partner_country_id': self.partner_id.country_id.id, - 'invoice_ids': [(6, 0, self.invoice_ids.ids)], 'payment_token_id': self.payment_token_id.id, 'acquirer_id': self.payment_token_id.acquirer_id.id, 'payment_id': self.id, @@ -108,4 +108,11 @@ class AccountPayment(models.Model): transactions.s2s_do_transaction() + # Post payments for issued transactions. + transactions._post_process_after_done() + payments_trans_done = payments_need_trans.filtered(lambda pay: pay.payment_transaction_id.state == 'done') + super(AccountPayment, payments_trans_done).action_post() + payments_trans_not_done = payments_need_trans.filtered(lambda pay: pay.payment_transaction_id.state != 'done') + payments_trans_not_done.action_cancel() + return res diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index d51bb7466bb..69f0638a427 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -903,9 +903,8 @@ class PaymentTransaction(models.Model): :return: A unique reference for the transaction. ''' if not prefix: - if values: - prefix = self._compute_reference_prefix(values) - else: + prefix = self._compute_reference_prefix(values) + if not prefix: prefix = 'tx' # Fetch the last reference diff --git a/addons/payment/wizards/__init__.py b/addons/payment/wizards/__init__.py index 938cc12dadf..16b6190c243 100644 --- a/addons/payment/wizards/__init__.py +++ b/addons/payment/wizards/__init__.py @@ -3,3 +3,4 @@ from . import payment_acquirer_onboarding_wizard from . import payment_link_wizard +from . import account_payment_register diff --git a/addons/payment/wizards/account_payment_register.py b/addons/payment/wizards/account_payment_register.py new file mode 100644 index 00000000000..09359ea3063 --- /dev/null +++ b/addons/payment/wizards/account_payment_register.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api, _ + + +class AccountPaymentRegister(models.TransientModel): + _inherit = 'account.payment.register' + + # == Business fields == + payment_token_id = fields.Many2one( + comodel_name='payment.token', + string="Saved payment token", + store=True, readonly=False, + compute='_compute_payment_token_id', + domain='''[ + (payment_method_code == 'electronic', '=', 1), + ('company_id', '=', company_id), + ('acquirer_id.capture_manually', '=', False), + ('acquirer_id.journal_id', '=', journal_id), + ('partner_id', 'in', suitable_payment_token_partner_ids), + ]''', + help="Note that tokens from acquirers set to only authorize transactions (instead of capturing the amount) are " + "not available.") + + # == Display purpose fields == + suitable_payment_token_partner_ids = fields.Many2many( + comodel_name='res.partner', + compute='_compute_suitable_payment_token_partner_ids') + payment_method_code = fields.Char( + related='payment_method_id.code') + + # ------------------------------------------------------------------------- + # COMPUTE METHODS + # ------------------------------------------------------------------------- + + @api.depends('can_edit_wizard') + def _compute_suitable_payment_token_partner_ids(self): + for wizard in self: + if wizard.can_edit_wizard: + lines = wizard._get_batches()[0]['lines'] + partners = lines.partner_id + commercial_partners = partners.commercial_partner_id + children_partners = commercial_partners.child_ids + wizard.suitable_payment_token_partner_ids = (partners + commercial_partners + children_partners)._origin + else: + wizard.suitable_payment_token_partner_ids = False + + @api.onchange('can_edit_wizard', 'payment_method_id', 'journal_id') + def _compute_payment_token_id(self): + for wizard in self: + if wizard.can_edit_wizard \ + and wizard.payment_method_id.code == 'electronic' \ + and wizard.journal_id \ + and wizard.suitable_payment_token_partner_ids: + wizard.payment_token_id = self.env['payment.token'].search([ + ('partner_id', 'in', wizard.suitable_payment_token_partner_ids.ids), + ('acquirer_id.capture_manually', '=', False), + ('acquirer_id.journal_id', '=', wizard.journal_id.id), + ], limit=1) + else: + wizard.payment_token_id = False + + # ------------------------------------------------------------------------- + # BUSINESS METHODS + # ------------------------------------------------------------------------- + + def _create_payment_vals_from_wizard(self): + # OVERRIDE + payment_vals = super()._create_payment_vals_from_wizard() + payment_vals['payment_token_id'] = self.payment_token_id.id + return payment_vals diff --git a/addons/payment/wizards/account_payment_register_views.xml b/addons/payment/wizards/account_payment_register_views.xml new file mode 100644 index 00000000000..989eed10ee5 --- /dev/null +++ b/addons/payment/wizards/account_payment_register_views.xml @@ -0,0 +1,23 @@ + + + + + + account.payment.register.form.inherit.payment + account.payment.register + + + + + + + + + + + + + +