Files
odoo_source/addons/account_payment/models/account_move.py
T
Anita (anko) 4d1a1f1c99 [IMP] payment, *: verify and reroute payment flows
This commit changes the way transactions linked to a document (sales
order, invoice...) are created in a payment flow. Rather than receiving
and trusting the transaction values from the controller, they are now
read from the linked document, and the payment flow is rerouted to use
the document's module's controllers instead of that of `payment`.

This ensures that no unexpected value can be passed to the `create`
method of a transaction, and simplifies the implementation of the
payment flows of linked documents.

task-3136240

closes odoo/odoo#126425

Related: odoo/enterprise#43212
Related: odoo/upgrade#5124
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
2023-09-23 21:08:01 +00:00

105 lines
3.9 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
from odoo.tools import str2bool
from odoo.addons.payment import utils as payment_utils
class AccountMove(models.Model):
_inherit = 'account.move'
transaction_ids = fields.Many2many(
string="Transactions", comodel_name='payment.transaction',
relation='account_invoice_transaction_rel', column1='invoice_id', column2='transaction_id',
readonly=True, copy=False)
authorized_transaction_ids = fields.Many2many(
string="Authorized Transactions", comodel_name='payment.transaction',
compute='_compute_authorized_transaction_ids', readonly=True, copy=False,
compute_sudo=True)
amount_paid = fields.Monetary(
string="Amount paid",
compute='_compute_amount_paid'
)
@api.depends('transaction_ids')
def _compute_authorized_transaction_ids(self):
for invoice in self:
invoice.authorized_transaction_ids = invoice.transaction_ids.filtered(
lambda tx: tx.state == 'authorized'
)
@api.depends('transaction_ids')
def _compute_amount_paid(self):
""" Sum all the transaction amount for which state is in 'authorized' or 'done'
"""
for invoice in self:
invoice.amount_paid = sum(
invoice.transaction_ids.filtered(
lambda tx: tx.state in ('authorized', 'done')
).mapped('amount')
)
def _has_to_be_paid(self):
self.ensure_one()
transactions = self.transaction_ids.filtered(lambda tx: tx.state in ('authorized', 'done'))
pending_transactions = self.transaction_ids.filtered(
lambda tx: tx.state == 'pending' and tx.provider_code not in ('none', 'custom'))
enabled_feature = str2bool(
self.env['ir.config_parameter'].sudo().get_param(
'account_payment.enable_portal_payment'
)
)
return enabled_feature and bool(
(
self.amount_residual
# FIXME someplace we check amount_residual and some other amount_paid < amount_total
# what is the correct heuristic to check ?
or not (transactions or pending_transactions)
)
and self.state == 'posted'
and self.payment_state in ('not_paid', 'partial')
and self.amount_total
and self.move_type == 'out_invoice'
)
def get_portal_last_transaction(self):
self.ensure_one()
return self.with_context(active_test=False).transaction_ids.sudo()._get_last()
def payment_action_capture(self):
""" Capture all transactions linked to this invoice. """
self.ensure_one()
payment_utils.check_rights_on_recordset(self)
# In sudo mode to bypass the checks on the rights on the transactions.
return self.transaction_ids.sudo().action_capture()
def payment_action_void(self):
""" Void all transactions linked to this invoice. """
payment_utils.check_rights_on_recordset(self)
# In sudo mode to bypass the checks on the rights on the transactions.
self.authorized_transaction_ids.sudo().action_void()
def action_view_payment_transactions(self):
action = self.env['ir.actions.act_window']._for_xml_id('payment.action_payment_transaction')
if len(self.transaction_ids) == 1:
action['view_mode'] = 'form'
action['res_id'] = self.transaction_ids.id
action['views'] = []
else:
action['domain'] = [('id', 'in', self.transaction_ids.ids)]
return action
def _get_default_payment_link_values(self):
self.ensure_one()
return {
'amount': self.amount_residual,
'currency_id': self.currency_id.id,
'partner_id': self.partner_id.id,
'amount_max': self.amount_residual,
}