It was very confusing for the user to distinct account.payment and payment.transaction. From now on, the transactions are technical objects and, in the backend, we only refer to it in log messages (Front end will be adapted in the same fashion later on). They are hidden in debug mode in accounting\configuration\payments as their purpose is now purely technical/log This commit also aims to reduce the gap between the accounting app and the transactions: account.payment objects are created/validated upon completion of transaction. To ease the capture/voiding of pending transactions, the related buttons are now displayed directly on the SO/invoice instead of the transactions. Was task: https://www.odoo.com/web#id=35857&view_type=form&model=project.task&action=333&active_id=967&menu_id=4720 Was PR #24043 [FIX] add domain based on journal to payment tokens Was opw: https://www.odoo.com/web?debug#id=1828206&view_type=form&model=project.task&menu_id=5200
99 lines
4.2 KiB
Python
99 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class AccountInvoice(models.Model):
|
|
_inherit = 'account.invoice'
|
|
|
|
transaction_ids = fields.Many2many('payment.transaction', 'account_invoice_transaction_rel', 'invoice_id', 'transaction_id',
|
|
string='Transactions', copy=False, readonly=True)
|
|
authorized_transaction_ids = fields.Many2many('payment.transaction', compute='_compute_authorized_transaction_ids',
|
|
string='Authorized Transactions', copy=False, readonly=True)
|
|
|
|
@api.depends('transaction_ids')
|
|
def _compute_authorized_transaction_ids(self):
|
|
for trans in self:
|
|
trans.authorized_transaction_ids = trans.transaction_ids.filtered(lambda t: t.state == 'authorized')
|
|
|
|
@api.multi
|
|
def get_portal_last_transaction(self):
|
|
self.ensure_one()
|
|
return self.transaction_ids.get_last_transaction()
|
|
|
|
@api.multi
|
|
def _create_payment_transaction(self, vals):
|
|
'''Similar to self.env['payment.transaction'].create(vals) but the values are filled with the
|
|
current invoices fields (e.g. the partner or the currency).
|
|
:param vals: The values to create a new payment.transaction.
|
|
:return: The newly created payment.transaction record.
|
|
'''
|
|
# Ensure the currencies are the same.
|
|
currency = self[0].currency_id
|
|
if any([inv.currency_id != currency for inv in self]):
|
|
raise ValidationError(_('A transaction can\'t be linked to invoices having different currencies.'))
|
|
|
|
# Ensure the partner are the same.
|
|
partner = self[0].partner_id
|
|
if any([inv.partner_id != partner for inv in self]):
|
|
raise ValidationError(_('A transaction can\'t be linked to invoices having different partners.'))
|
|
|
|
# Try to retrieve the acquirer. However, fallback to the token's acquirer.
|
|
acquirer_id = vals.get('acquirer_id')
|
|
acquirer = None
|
|
payment_token_id = vals.get('payment_token_id')
|
|
|
|
if payment_token_id:
|
|
payment_token = self.env['payment.token'].sudo().browse(payment_token_id)
|
|
|
|
# Check payment_token/acquirer matching or take the acquirer from token
|
|
if acquirer_id:
|
|
acquirer = self.env['payment.acquirer'].browse(acquirer_id)
|
|
if payment_token and payment_token.acquirer_id != acquirer:
|
|
raise ValidationError(_('Invalid token found! Token acquirer %s != %s') % (
|
|
payment_token.acquirer_id.name, acquirer.name))
|
|
if payment_token and payment_token.partner_id != partner:
|
|
raise ValidationError(_('Invalid token found! Token partner %s != %s') % (
|
|
payment_token.partner.name, partner.name))
|
|
else:
|
|
acquirer = payment_token.acquirer_id
|
|
|
|
# Check an acquirer is there.
|
|
if not acquirer_id and not acquirer:
|
|
raise ValidationError(_('A payment acquirer is required to create a transaction.'))
|
|
|
|
if not acquirer:
|
|
acquirer = self.env['payment.acquirer'].browse(acquirer_id)
|
|
|
|
# Check a journal is set on acquirer.
|
|
if not acquirer.journal_id:
|
|
raise ValidationError(_('A journal must be specified of the acquirer %s.' % acquirer.name))
|
|
|
|
if not acquirer_id and acquirer:
|
|
vals['acquirer_id'] = acquirer.id
|
|
|
|
vals.update({
|
|
'amount': sum(self.mapped('amount_total')),
|
|
'currency_id': currency.id,
|
|
'partner_id': partner.id,
|
|
'invoice_ids': [(6, 0, self.ids)],
|
|
})
|
|
|
|
transaction = self.env['payment.transaction'].create(vals)
|
|
|
|
# Process directly if payment_token
|
|
if transaction.payment_token_id:
|
|
transaction.s2s_do_transaction()
|
|
|
|
return transaction
|
|
|
|
@api.multi
|
|
def payment_action_capture(self):
|
|
self.authorized_transaction_ids.s2s_capture_transaction()
|
|
|
|
@api.multi
|
|
def payment_action_void(self):
|
|
self.authorized_transaction_ids.s2s_void_transaction()
|