204 lines
7.0 KiB
Python
204 lines
7.0 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import base64
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
_inherit = 'account.move'
|
|
|
|
poynt_refunded = fields.Boolean(
|
|
string="Refunded via Poynt",
|
|
readonly=True,
|
|
copy=False,
|
|
default=False,
|
|
)
|
|
poynt_refund_count = fields.Integer(
|
|
string="Poynt Refund Count",
|
|
compute='_compute_poynt_refund_count',
|
|
)
|
|
has_poynt_receipt = fields.Boolean(
|
|
string="Has Poynt Receipt",
|
|
compute='_compute_has_poynt_receipt',
|
|
)
|
|
|
|
@api.depends('reversal_move_ids')
|
|
def _compute_poynt_refund_count(self):
|
|
for move in self:
|
|
if move.move_type == 'out_invoice':
|
|
move.poynt_refund_count = len(move.reversal_move_ids.filtered(
|
|
lambda r: r.poynt_refunded
|
|
))
|
|
else:
|
|
move.poynt_refund_count = 0
|
|
|
|
def _compute_has_poynt_receipt(self):
|
|
for move in self:
|
|
move.has_poynt_receipt = bool(move._get_poynt_transaction_for_receipt())
|
|
|
|
def action_view_poynt_refunds(self):
|
|
"""Open the credit notes linked to this invoice that were refunded via Poynt."""
|
|
self.ensure_one()
|
|
refund_moves = self.reversal_move_ids.filtered(lambda r: r.poynt_refunded)
|
|
action = {
|
|
'name': _("Poynt Refunds"),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'account.move',
|
|
'view_mode': 'list,form',
|
|
'domain': [('id', 'in', refund_moves.ids)],
|
|
'context': {'default_move_type': 'out_refund'},
|
|
}
|
|
if len(refund_moves) == 1:
|
|
action['view_mode'] = 'form'
|
|
action['res_id'] = refund_moves.id
|
|
return action
|
|
|
|
def _get_poynt_transaction_for_receipt(self):
|
|
"""Find the Poynt transaction linked to this invoice or credit note."""
|
|
self.ensure_one()
|
|
domain = [
|
|
('provider_id.code', '=', 'poynt'),
|
|
('poynt_transaction_id', '!=', False),
|
|
('state', '=', 'done'),
|
|
]
|
|
if self.move_type == 'out_invoice':
|
|
domain.append(('invoice_ids', 'in', self.ids))
|
|
elif self.move_type == 'out_refund':
|
|
domain += [
|
|
('operation', '=', 'refund'),
|
|
('invoice_ids', 'in', self.ids),
|
|
]
|
|
else:
|
|
return self.env['payment.transaction']
|
|
|
|
return self.env['payment.transaction'].sudo().search(
|
|
domain, order='id desc', limit=1,
|
|
)
|
|
|
|
def action_resend_poynt_receipt(self):
|
|
"""Resend the Poynt payment/refund receipt email to the customer."""
|
|
self.ensure_one()
|
|
tx = self._get_poynt_transaction_for_receipt()
|
|
if not tx:
|
|
raise UserError(_(
|
|
"No completed Poynt transaction found for this document."
|
|
))
|
|
|
|
template = self.env.ref(
|
|
'fusion_poynt.mail_template_poynt_receipt',
|
|
raise_if_not_found=False,
|
|
)
|
|
if not template:
|
|
raise UserError(_("Receipt email template not found."))
|
|
|
|
report = self.env.ref(
|
|
'fusion_poynt.action_report_poynt_receipt',
|
|
raise_if_not_found=False,
|
|
)
|
|
attachment_ids = []
|
|
if report:
|
|
pdf_content, _content_type = report.sudo()._render_qweb_pdf(
|
|
report_ref='fusion_poynt.action_report_poynt_receipt',
|
|
res_ids=tx.ids,
|
|
)
|
|
prefix = "Refund_Receipt" if self.move_type == 'out_refund' else "Payment_Receipt"
|
|
filename = f"{prefix}_{tx.reference}.pdf"
|
|
att = self.env['ir.attachment'].create({
|
|
'name': filename,
|
|
'type': 'binary',
|
|
'datas': base64.b64encode(pdf_content),
|
|
'res_model': self._name,
|
|
'res_id': self.id,
|
|
'mimetype': 'application/pdf',
|
|
})
|
|
attachment_ids = [att.id]
|
|
|
|
template.send_mail(tx.id, force_send=True)
|
|
|
|
is_refund = self.move_type == 'out_refund'
|
|
label = _("Refund") if is_refund else _("Payment")
|
|
self.message_post(
|
|
body=_(
|
|
"%(label)s receipt resent to %(email)s.",
|
|
label=label,
|
|
email=tx.partner_id.email,
|
|
),
|
|
message_type='notification',
|
|
subtype_xmlid='mail.mt_note',
|
|
attachment_ids=attachment_ids,
|
|
)
|
|
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'title': _("Receipt Sent"),
|
|
'message': _("The receipt has been sent to %s.",
|
|
tx.partner_id.email),
|
|
'type': 'success',
|
|
'sticky': False,
|
|
},
|
|
}
|
|
|
|
def action_open_poynt_payment_wizard(self):
|
|
"""Open the Poynt payment collection wizard for this invoice."""
|
|
self.ensure_one()
|
|
return {
|
|
'name': _("Collect Poynt Payment"),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'poynt.payment.wizard',
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
'context': {
|
|
'active_model': 'account.move',
|
|
'active_id': self.id,
|
|
},
|
|
}
|
|
|
|
def action_open_poynt_refund_wizard(self):
|
|
"""Open the Poynt refund wizard for this credit note."""
|
|
self.ensure_one()
|
|
return {
|
|
'name': _("Refund via Poynt"),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'poynt.refund.wizard',
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
'context': {
|
|
'active_model': 'account.move',
|
|
'active_id': self.id,
|
|
},
|
|
}
|
|
|
|
def _get_original_poynt_transaction(self):
|
|
"""Find the Poynt payment transaction from the reversed invoice.
|
|
|
|
For credit notes created via the "Reverse" action, the
|
|
``reversed_entry_id`` links back to the original invoice.
|
|
We look for a confirmed Poynt transaction on that invoice.
|
|
"""
|
|
self.ensure_one()
|
|
origin_invoice = self.reversed_entry_id
|
|
if not origin_invoice:
|
|
return self.env['payment.transaction']
|
|
|
|
tx = self.env['payment.transaction'].sudo().search([
|
|
('invoice_ids', 'in', origin_invoice.ids),
|
|
('state', '=', 'done'),
|
|
('provider_id.code', '=', 'poynt'),
|
|
('poynt_transaction_id', '!=', False),
|
|
('poynt_voided', '=', False),
|
|
], order='id desc', limit=1)
|
|
|
|
if not tx:
|
|
tx = self.env['payment.transaction'].sudo().search([
|
|
('invoice_ids', 'in', origin_invoice.ids),
|
|
('state', 'in', ('done', 'cancel')),
|
|
('provider_id.code', '=', 'poynt'),
|
|
('poynt_transaction_id', '!=', False),
|
|
], order='id desc', limit=1)
|
|
|
|
return tx
|