mirror of
https://github.com/bringout/oca-ocb-accounting.git
synced 2026-04-24 04:42:01 +02:00
19.0 vanilla
This commit is contained in:
parent
ba20ce7443
commit
768b70e05e
2357 changed files with 1057103 additions and 712486 deletions
|
|
@ -1,8 +1,13 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import base64
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import format_date, str2bool
|
||||
from odoo.tools.translate import _
|
||||
|
||||
from odoo.addons.payment import utils as payment_utils
|
||||
from odoo.tools.image import image_data_uri
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
|
|
@ -14,7 +19,11 @@ class AccountMove(models.Model):
|
|||
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='_compute_authorized_transaction_ids', readonly=True, copy=False,
|
||||
compute_sudo=True)
|
||||
transaction_count = fields.Integer(
|
||||
string="Transaction Count", compute='_compute_transaction_count'
|
||||
)
|
||||
amount_paid = fields.Monetary(
|
||||
string="Amount paid",
|
||||
compute='_compute_amount_paid'
|
||||
|
|
@ -27,6 +36,11 @@ class AccountMove(models.Model):
|
|||
lambda tx: tx.state == 'authorized'
|
||||
)
|
||||
|
||||
@api.depends('transaction_ids')
|
||||
def _compute_transaction_count(self):
|
||||
for invoice in self:
|
||||
invoice.transaction_count = len(invoice.transaction_ids)
|
||||
|
||||
@api.depends('transaction_ids')
|
||||
def _compute_amount_paid(self):
|
||||
""" Sum all the transaction amount for which state is in 'authorized' or 'done'
|
||||
|
|
@ -41,34 +55,72 @@ class AccountMove(models.Model):
|
|||
def _has_to_be_paid(self):
|
||||
self.ensure_one()
|
||||
transactions = self.transaction_ids.filtered(lambda tx: tx.state in ('pending', 'authorized', 'done'))
|
||||
pending_manual_txs = transactions.filtered(lambda tx: tx.state == 'pending' and tx.provider_code in ('none', 'custom'))
|
||||
return bool(
|
||||
(
|
||||
self.amount_residual
|
||||
or not transactions
|
||||
pending_transactions = transactions.filtered(
|
||||
lambda tx: tx.state in {'pending', 'authorized'}
|
||||
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 or not transactions)
|
||||
and self.state == 'posted'
|
||||
and self.payment_state in ('not_paid', 'partial')
|
||||
and self.payment_state in ('not_paid', 'in_payment', 'partial')
|
||||
and not self.currency_id.is_zero(self.amount_residual)
|
||||
and self.amount_total
|
||||
and self.move_type == 'out_invoice'
|
||||
and (pending_manual_txs or not transactions or self.amount_paid < self.amount_total)
|
||||
and not pending_transactions
|
||||
)
|
||||
|
||||
def _get_online_payment_error(self):
|
||||
"""
|
||||
Returns the appropriate error message to be displayed if _has_to_be_paid() method returns False.
|
||||
"""
|
||||
self.ensure_one()
|
||||
transactions = self.transaction_ids.filtered(lambda tx: tx.state in ('pending', 'authorized', 'done'))
|
||||
pending_transactions = transactions.filtered(
|
||||
lambda tx: tx.state in {'pending', 'authorized'}
|
||||
and tx.provider_code not in {'none', 'custom'})
|
||||
enabled_feature = str2bool(
|
||||
self.env['ir.config_parameter'].sudo().get_param(
|
||||
'account_payment.enable_portal_payment'
|
||||
)
|
||||
)
|
||||
errors = []
|
||||
if not enabled_feature:
|
||||
errors.append(_("This invoice cannot be paid online."))
|
||||
if transactions or self.currency_id.is_zero(self.amount_residual):
|
||||
errors.append(_("There is no amount to be paid."))
|
||||
if self.state != 'posted':
|
||||
errors.append(_("This invoice isn't posted."))
|
||||
if self.currency_id.is_zero(self.amount_residual):
|
||||
errors.append(_("This invoice has already been paid."))
|
||||
if self.move_type != 'out_invoice':
|
||||
errors.append(_("This is not an outgoing invoice."))
|
||||
if pending_transactions:
|
||||
errors.append(_("There are pending transactions for this invoice."))
|
||||
return '\n'.join(errors)
|
||||
|
||||
@api.private
|
||||
def get_portal_last_transaction(self):
|
||||
self.ensure_one()
|
||||
return self.with_context(active_test=False).transaction_ids._get_last()
|
||||
return self.with_context(active_test=False).sudo().transaction_ids._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 because we need to be able to read on provider fields.
|
||||
self.authorized_transaction_ids.sudo().action_capture()
|
||||
|
||||
# In sudo mode to bypass the checks on the rights on the transactions.
|
||||
return self.sudo().transaction_ids.action_capture()
|
||||
|
||||
def payment_action_void(self):
|
||||
""" Void all transactions linked to this invoice. """
|
||||
payment_utils.check_rights_on_recordset(self)
|
||||
# In sudo mode because we need to be able to read on provider fields.
|
||||
self.authorized_transaction_ids.sudo().action_void()
|
||||
|
||||
# In sudo mode to bypass the checks on the rights on the transactions.
|
||||
self.sudo().authorized_transaction_ids.action_void()
|
||||
|
||||
def action_view_payment_transactions(self):
|
||||
action = self.env['ir.actions.act_window']._for_xml_id('payment.action_payment_transaction')
|
||||
|
|
@ -83,11 +135,48 @@ class AccountMove(models.Model):
|
|||
return action
|
||||
|
||||
def _get_default_payment_link_values(self):
|
||||
self.ensure_one()
|
||||
next_payment_values = self._get_invoice_next_payment_values()
|
||||
amount_max = next_payment_values.get('amount_due')
|
||||
additional_info = {}
|
||||
open_installments = []
|
||||
installment_state = next_payment_values.get('installment_state')
|
||||
next_amount_to_pay = next_payment_values.get('next_amount_to_pay')
|
||||
if installment_state in ('next', 'overdue'):
|
||||
open_installments = []
|
||||
for installment in next_payment_values.get('not_reconciled_installments'):
|
||||
data = {
|
||||
'type': installment['type'],
|
||||
'number': installment['number'],
|
||||
'amount': installment['amount_residual_currency_unsigned'],
|
||||
'date_maturity': format_date(self.env, installment['date_maturity']),
|
||||
}
|
||||
open_installments.append(data)
|
||||
|
||||
elif installment_state == 'epd':
|
||||
amount_max = next_amount_to_pay # with epd, next_amount_to_pay is the invoice amount residual
|
||||
additional_info.update({
|
||||
'has_eligible_epd': True,
|
||||
'discount_date': next_payment_values.get('discount_date')
|
||||
})
|
||||
|
||||
return {
|
||||
'description': self.payment_reference,
|
||||
'amount': self.amount_residual,
|
||||
'currency_id': self.currency_id.id,
|
||||
'partner_id': self.partner_id.id,
|
||||
'amount_max': self.amount_residual,
|
||||
'open_installments': open_installments,
|
||||
'amount': next_amount_to_pay,
|
||||
'amount_max': amount_max,
|
||||
**additional_info
|
||||
}
|
||||
|
||||
def _generate_portal_payment_qr(self):
|
||||
self.ensure_one()
|
||||
portal_url = self._get_portal_payment_link()
|
||||
barcode = self.env['ir.actions.report'].barcode(barcode_type="QR", value=portal_url, width=128, height=128, quiet=False)
|
||||
return image_data_uri(base64.b64encode(barcode))
|
||||
|
||||
def _get_portal_payment_link(self):
|
||||
self.ensure_one()
|
||||
payment_link_wizard = self.env['payment.link.wizard'].with_context(
|
||||
active_id=self.id, active_model=self._name
|
||||
).create({})
|
||||
return payment_link_wizard.link
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue