From 46c5f93b6cfa2b348078e674cd9e271ef5f81292 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 13 Apr 2016 12:51:20 +0200 Subject: [PATCH] [FIX] website_sale: verify match between TX and SO amount When processing a payment transaction, double-check the match between the amount of the transaction and the amount of the SO, to be sure that we won't be validating a SO that has been modified since the payment. Such cases have to be double-checked manually. Also add a bit of extra logging to make auditing ecommerce transactions easier. --- addons/website_sale/models/payment.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/addons/website_sale/models/payment.py b/addons/website_sale/models/payment.py index 6129de092aa..f38b9463d05 100644 --- a/addons/website_sale/models/payment.py +++ b/addons/website_sale/models/payment.py @@ -3,6 +3,7 @@ import logging from openerp import SUPERUSER_ID from openerp.osv import orm, fields +from openerp.tools import float_compare _logger = logging.getLogger(__name__) @@ -26,10 +27,20 @@ class PaymentTransaction(orm.Model): tx_find_method_name = '_%s_form_get_tx_from_data' % acquirer_name if hasattr(self, tx_find_method_name): tx = getattr(self, tx_find_method_name)(cr, uid, data, context=context) - if tx and tx.state == 'done' and tx.sale_order_id and tx.sale_order_id.state in ['draft', 'sent']: - self.pool['sale.order'].action_button_confirm(cr, SUPERUSER_ID, [tx.sale_order_id.id], context=dict(context, send_email=True)) - elif tx and tx.state not in ['cancel'] and tx.sale_order_id and tx.sale_order_id.state in ['draft']: - self.pool['sale.order'].force_quotation_send(cr, SUPERUSER_ID, [tx.sale_order_id.id], context=context) + _logger.info('<%s> transaction processed: tx ref:%s, tx amount: %s', acquirer_name, tx.reference if tx else 'n/a', tx.amount if tx else 'n/a') + + if tx and tx.sale_order_id: + # verify SO/TX match, excluding tx.fees which are currently not included in SO + amount_matches = (tx.sale_order_id.state in ['draft', 'sent'] and float_compare(tx.amount, tx.sale_order_id.amount_total, 2) == 0) + if amount_matches: + if tx.state == 'done': + _logger.info('<%s> transaction completed, confirming order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id) + self.pool['sale.order'].action_button_confirm(cr, SUPERUSER_ID, [tx.sale_order_id.id], context=dict(context, send_email=True)) + elif tx.state != 'cancel' and tx.sale_order_id.state == 'draft': + _logger.info('<%s> transaction pending, sending quote email for order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id) + self.pool['sale.order'].force_quotation_send(cr, SUPERUSER_ID, [tx.sale_order_id.id], context=context) + else: + _logger.warning('<%s> transaction MISMATCH for order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id) except Exception: _logger.exception('Fail to confirm the order or send the confirmation email%s', tx and ' for the transaction %s' % tx.reference or '')