diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 45b159f692c..aed9564d234 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -71,6 +71,7 @@ class PaymentAcquirer(models.Model): help="Make this payment acquirer available (Customer invoices, etc.)") auto_confirm = fields.Selection([ ('none', 'No automatic confirmation'), + ('authorize', 'Authorize the amount and confirm the SO on acquirer confirmation'), ('confirm_so', 'Confirm the SO on acquirer confirmation'), ('generate_and_pay_invoice', 'On acquirer confirmation, confirm the SO, generate the invoice and pay it')], string='Order Confirmation', default='confirm_so', required=True) @@ -374,6 +375,7 @@ class PaymentTransaction(models.Model): state = fields.Selection([ ('draft', 'Draft'), ('pending', 'Pending'), + ('authorized', 'Authorized'), ('done', 'Done'), ('error', 'Error'), ('cancel', 'Canceled')], 'Status', @@ -558,15 +560,40 @@ class PaymentTransaction(models.Model): if hasattr(self, custom_method_name): return getattr(self, custom_method_name)(**kwargs) + @api.multi + def s2s_capture_transaction(self, **kwargs): + custom_method_name = '%s_s2s_capture_transaction' % self.acquirer_id.provider + if hasattr(self, custom_method_name): + return getattr(self, custom_method_name)(**kwargs) + + @api.multi + def s2s_void_transaction(self, **kwargs): + custom_method_name = '%s_s2s_void_transaction' % self.acquirer_id.provider + if hasattr(self, custom_method_name): + return getattr(self, custom_method_name)(**kwargs) + @api.multi def s2s_get_tx_status(self): """ Get the tx status. """ invalid_param_method_name = '_%s_s2s_get_tx_status' % self.acquirer_id.provider if hasattr(self, invalid_param_method_name): return getattr(self, invalid_param_method_name)() - return True + @api.multi + def action_capture(self): + if any(self.mapped(lambda tx: tx.state != 'authorized')): + raise ValidationError('Only transactions in the Authorized status can be captured.') + for tx in self: + tx.s2s_capture_transaction() + + @api.multi + def action_void(self): + if any(self.mapped(lambda tx: tx.state != 'authorized')): + raise ValidationError('Only transactions in the Authorized status can be voided.') + for tx in self: + tx.s2s_void_transaction() + class PaymentToken(models.Model): _name = 'payment.token' diff --git a/addons/payment/views/payment_views.xml b/addons/payment/views/payment_views.xml index 448de81273b..51bf831a719 100644 --- a/addons/payment/views/payment_views.xml +++ b/addons/payment/views/payment_views.xml @@ -208,6 +208,8 @@
+
diff --git a/addons/website_portal_sale/models/payment.py b/addons/website_portal_sale/models/payment.py index 2b2ceeaa6f1..8170cc37139 100644 --- a/addons/website_portal_sale/models/payment.py +++ b/addons/website_portal_sale/models/payment.py @@ -52,6 +52,9 @@ class PaymentTransaction(models.Model): # verify SO/TX match, excluding tx.fees which are currently not included in SO amount_matches = float_compare(tx.amount, tx.sale_order_id.amount_total, 2) == 0 if amount_matches: + if tx.state == 'authorized' and tx.acquirer_id.auto_confirm == 'authorize': + _logger.info('<%s> transaction authorized, auto-confirming order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id) + tx.sale_order_id.with_context(send_email=True).action_confirm() if tx.state == 'done' and tx.acquirer_id.auto_confirm in ['confirm_so', 'generate_and_pay_invoice']: _logger.info('<%s> transaction completed, auto-confirming order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id) tx.sale_order_id.with_context(send_email=True).action_confirm() diff --git a/addons/website_quote/views/website_quote_templates.xml b/addons/website_quote/views/website_quote_templates.xml index 4e1e1a20a33..7505867f21d 100644 --- a/addons/website_quote/views/website_quote_templates.xml +++ b/addons/website_quote/views/website_quote_templates.xml @@ -271,6 +271,11 @@ Your transaction is waiting confirmation. +
+ + Your payment has been authorized. + +
This order diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index a756173183e..6db1998fcde 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -748,7 +748,8 @@ class WebsiteSale(http.Controller): tx.partner_id == tx.sale_order_id.partner_id): try: s2s_result = tx.s2s_do_transaction() - if not s2s_result or tx.state != 'done': + valid_state = 'authorized' if tx.acquirer_id.auto_confirm == 'authorize' else 'done' + if not s2s_result or tx.state != valid_state: return dict(success=False, error=_("Payment transaction failed (%s)") % tx.state_message) return dict(success=True, url='/shop/payment/validate') except Exception, e: @@ -884,7 +885,7 @@ class WebsiteSale(http.Controller): if not order or (order.amount_total and not tx): return request.redirect('/shop') - if (not order.amount_total and not tx) or tx.state in ['pending', 'done']: + if (not order.amount_total and not tx) or tx.state in ['pending', 'done', 'authorized']: if (not order.amount_total and not tx): # Orders are confirmed by payment transactions, but there is none for free orders, # (e.g. free events), so confirm immediately diff --git a/addons/website_sale/views/sale_order.xml b/addons/website_sale/views/sale_order.xml index a77bc74de35..0040ac33fe3 100644 --- a/addons/website_sale/views/sale_order.xml +++ b/addons/website_sale/views/sale_order.xml @@ -8,7 +8,7 @@ - + diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 3f54c9eb319..f3782fdb109 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -1535,6 +1535,9 @@

Your payment has been received.

+ +

Your payment has been authorized.

+

The payment seems to have been canceled.

@@ -1547,7 +1550,7 @@
- +

Your transaction is waiting confirmation.