From 40cf03e4a04152b657ade0c8a490feee70a5249b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 15 May 2017 14:53:55 +0200 Subject: [PATCH] [IMP] sale_payment: add tools methods for sales and payments This commit adds tools method in sale_payment related to sale order confirmation, token and transaction management. Purpose is to be able to use them in frontend sale module like eCommerce and Online Quote and have it standardized at model-level instead of done custom in controllers. --- addons/sale_payment/models/payment.py | 94 ++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/addons/sale_payment/models/payment.py b/addons/sale_payment/models/payment.py index ca0bdb59a22..8553672a71e 100644 --- a/addons/sale_payment/models/payment.py +++ b/addons/sale_payment/models/payment.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import logging -from odoo import api, fields, models + +from odoo import api, fields, models, _ from odoo.tools import float_compare _logger = logging.getLogger(__name__) @@ -91,3 +92,94 @@ class PaymentTransaction(models.Model): else: _logger.warning('<%s> transaction completed, could not auto-generate invoice for %s (ID %s)', self.acquirer_id.provider, self.sale_order_id.name, self.sale_order_id.id) + + # -------------------------------------------------- + # Tools for payment + # -------------------------------------------------- + + def confirm_sale_token(self): + """ Confirm a transaction token and call SO confirmation if it is a success. + + :return: True if success; error string otherwise """ + self.ensure_one() + if self.payment_token_id and self.partner_id == self.sale_order_id.partner_id: + try: + s2s_result = self.s2s_do_transaction() + except Exception as e: + _logger.warning(_("Payment transaction (%s) failed : <%s>") % (self.id, str(e))) + return _("Payment transaction failed (Contact Administrator)") + + valid_state = 'authorized' if self.acquirer_id.capture_manually else 'done' + if not s2s_result or self.state != valid_state: + return _("Payment transaction failed (%s)" % self.state_message) + try: + # Auto-confirm SO if necessary + self._confirm_so() + return True + except Exception as e: + _logger.warning(_("Payment transaction (%s) failed : <%s>") % (self.id, str(e))) + return _("Payment transaction / SO Confirmation failed (Contact Administrator)") + return _('Tx missmatch') + + def check_or_create_sale_tx(self, order, acquirer, payment_token=None, tx_type='form', add_tx_values=None, reset_draft=True): + tx = self + # incorrect state or unexisting tx + if not self or self.state in ['error', 'cancel']: + tx = False + # unmatching + if (self and acquirer and self.acquirer_id != acquirer) or (self and self.sale_order_id != order): + tx = False + # new or distinct token + if payment_token and tx.payment_token_id and payment_token != self.payment_token_id: + tx = False + + # still draft tx, no more info -> rewrite on tx or create a new one depending on parameter + if tx and tx.state == 'draft': + if reset_draft: + tx.write(dict( + self.on_change_partner_id(order.partner_id.id).get('value', {}), + amount=order.amount_total, + type=tx_type) + ) + else: + tx = False + + if not tx: + tx_values = { + 'acquirer_id': acquirer.id, + 'type': tx_type, + 'amount': order.amount_total, + 'currency_id': order.pricelist_id.currency_id.id, + 'partner_id': order.partner_id.id, + 'partner_country_id': order.partner_id.country_id.id, + 'reference': self.get_next_reference(order.name), + 'sale_order_id': order.id, + } + if add_tx_values: + tx_values.update(add_tx_values) + if payment_token and payment_token.sudo().partner_id == order.partner_id: + tx_values['payment_token_id'] = payment_token.id + + tx = self.create(tx_values) + + # update quotation + order.write({ + 'payment_tx_id': tx.id, + }) + + return tx + + def render_sale_button(self, order, return_url, submit_txt=None, render_values=None): + values = { + 'return_url': return_url, + 'partner_id': order.partner_shipping_id.id or order.partner_invoice_id.id, + 'billing_partner_id': order.partner_invoice_id.id, + } + if render_values: + values.update(render_values) + return self.acquirer_id.with_context(submit_class='btn btn-primary', submit_txt=submit_txt or _('Pay Now')).sudo().render( + self.reference, + order.amount_total, + order.pricelist_id.currency_id.id, + values=values, + )