mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 21:52:00 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
|
|
@ -1,13 +1,14 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
import psycopg2
|
||||
|
||||
from odoo import fields, http
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from odoo.tools.translate import LazyTranslate
|
||||
|
||||
_lt = LazyTranslate(__name__)
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
@ -22,118 +23,70 @@ class PaymentPostProcessing(http.Controller):
|
|||
their post-processing.
|
||||
"""
|
||||
|
||||
MONITORED_TX_IDS_KEY = '__payment_monitored_tx_ids__'
|
||||
MONITORED_TX_ID_KEY = '__payment_monitored_tx_id__'
|
||||
|
||||
@http.route('/payment/status', type='http', auth='public', website=True, sitemap=False)
|
||||
@http.route('/payment/status', type='http', auth='public', website=True, sitemap=False, list_as_website_content=_lt("Payment Status"))
|
||||
def display_status(self, **kwargs):
|
||||
""" Display the payment status page.
|
||||
""" Fetch the transaction and display it on the payment status page.
|
||||
|
||||
:param dict kwargs: Optional data. This parameter is not used here
|
||||
:return: The rendered status page
|
||||
:rtype: str
|
||||
"""
|
||||
return request.render('payment.payment_status')
|
||||
monitored_tx = self._get_monitored_transaction()
|
||||
# The session might have expired, or the transaction never existed.
|
||||
values = {'tx': monitored_tx} if monitored_tx else {'payment_not_found': True}
|
||||
return request.render('payment.payment_status', values)
|
||||
|
||||
@http.route('/payment/status/poll', type='json', auth='public')
|
||||
@http.route('/payment/status/poll', type='jsonrpc', auth='public')
|
||||
def poll_status(self, **_kwargs):
|
||||
""" Fetch the transactions to display on the status page and finalize their post-processing.
|
||||
""" Fetch the transaction and trigger its post-processing.
|
||||
|
||||
:return: The post-processing values of the transactions
|
||||
:return: The post-processing values of the transaction.
|
||||
:rtype: dict
|
||||
"""
|
||||
# Retrieve recent user's transactions from the session
|
||||
limit_date = fields.Datetime.now() - timedelta(days=1)
|
||||
monitored_txs = request.env['payment.transaction'].sudo().search([
|
||||
('id', 'in', self.get_monitored_transaction_ids()),
|
||||
('last_state_change', '>=', limit_date)
|
||||
])
|
||||
if not monitored_txs: # The transaction was not correctly created
|
||||
return {
|
||||
'success': False,
|
||||
'error': 'no_tx_found',
|
||||
}
|
||||
# We only poll the payment status if a payment was found, so the transaction should exist.
|
||||
monitored_tx = self._get_monitored_transaction()
|
||||
|
||||
# Build the list of display values with the display message and post-processing values
|
||||
display_values_list = []
|
||||
for tx in monitored_txs:
|
||||
display_message = None
|
||||
if tx.state == 'pending':
|
||||
display_message = tx.provider_id.pending_msg
|
||||
elif tx.state == 'done':
|
||||
display_message = tx.provider_id.done_msg
|
||||
elif tx.state == 'cancel':
|
||||
display_message = tx.provider_id.cancel_msg
|
||||
display_values_list.append({
|
||||
'display_message': display_message,
|
||||
**tx._get_post_processing_values(),
|
||||
})
|
||||
|
||||
# Stop monitoring already post-processed transactions
|
||||
post_processed_txs = monitored_txs.filtered('is_post_processed')
|
||||
self.remove_transactions(post_processed_txs)
|
||||
|
||||
# Finalize post-processing of transactions before displaying them to the user
|
||||
txs_to_post_process = (monitored_txs - post_processed_txs).filtered(
|
||||
lambda t: t.state == 'done'
|
||||
)
|
||||
success, error = True, None
|
||||
try:
|
||||
txs_to_post_process._finalize_post_processing()
|
||||
except psycopg2.OperationalError: # A collision of accounting sequences occurred
|
||||
request.env.cr.rollback() # Rollback and try later
|
||||
success = False
|
||||
error = 'tx_process_retry'
|
||||
except Exception as e:
|
||||
request.env.cr.rollback()
|
||||
success = False
|
||||
error = str(e)
|
||||
_logger.exception(
|
||||
"encountered an error while post-processing transactions with ids %s:\n%s",
|
||||
', '.join([str(tx_id) for tx_id in txs_to_post_process.ids]), e
|
||||
)
|
||||
# Post-process the transaction before redirecting the user to the landing route and its
|
||||
# document.
|
||||
if not monitored_tx.is_post_processed:
|
||||
try:
|
||||
monitored_tx._post_process()
|
||||
except (
|
||||
psycopg2.OperationalError, psycopg2.IntegrityError
|
||||
): # The database cursor could not be committed.
|
||||
request.env.cr.rollback() # Rollback and try later.
|
||||
raise Exception('retry')
|
||||
except Exception as e:
|
||||
request.env.cr.rollback()
|
||||
_logger.exception(
|
||||
"Encountered an error while post-processing transaction with id %s:\n%s",
|
||||
monitored_tx.id, e
|
||||
)
|
||||
raise
|
||||
|
||||
return {
|
||||
'success': success,
|
||||
'error': error,
|
||||
'display_values_list': display_values_list,
|
||||
'provider_code': monitored_tx.provider_code,
|
||||
'state': monitored_tx.state,
|
||||
'landing_route': monitored_tx.landing_route,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def monitor_transactions(cls, transactions):
|
||||
""" Add the ids of the provided transactions to the list of monitored transaction ids.
|
||||
def monitor_transaction(cls, transaction):
|
||||
""" Make the provided transaction id monitored.
|
||||
|
||||
:param recordset transactions: The transactions to monitor, as a `payment.transaction`
|
||||
recordset
|
||||
:param payment.transaction transaction: The transaction to monitor.
|
||||
:return: None
|
||||
"""
|
||||
if transactions:
|
||||
monitored_tx_ids = request.session.get(cls.MONITORED_TX_IDS_KEY, [])
|
||||
request.session[cls.MONITORED_TX_IDS_KEY] = list(
|
||||
set(monitored_tx_ids).union(transactions.ids)
|
||||
)
|
||||
request.session[cls.MONITORED_TX_ID_KEY] = transaction.id
|
||||
|
||||
@classmethod
|
||||
def get_monitored_transaction_ids(cls):
|
||||
""" Return the ids of transactions being monitored.
|
||||
def _get_monitored_transaction(self):
|
||||
""" Retrieve the user's last transaction from the session (the transaction being monitored).
|
||||
|
||||
Only the ids and not the recordset itself is returned to allow the caller browsing the
|
||||
recordset with sudo privileges, and using the ids in a custom query.
|
||||
|
||||
:return: The ids of transactions being monitored
|
||||
:rtype: list
|
||||
:return: the user's last transaction
|
||||
:rtype: payment.transaction
|
||||
"""
|
||||
return request.session.get(cls.MONITORED_TX_IDS_KEY, [])
|
||||
|
||||
@classmethod
|
||||
def remove_transactions(cls, transactions):
|
||||
""" Remove the ids of the provided transactions from the list of monitored transaction ids.
|
||||
|
||||
:param recordset transactions: The transactions to remove, as a `payment.transaction`
|
||||
recordset
|
||||
:return: None
|
||||
"""
|
||||
if transactions:
|
||||
monitored_tx_ids = request.session.get(cls.MONITORED_TX_IDS_KEY, [])
|
||||
request.session[cls.MONITORED_TX_IDS_KEY] = [
|
||||
tx_id for tx_id in monitored_tx_ids if tx_id not in transactions.ids
|
||||
]
|
||||
return request.env['payment.transaction'].sudo().browse(
|
||||
request.session.get(self.MONITORED_TX_ID_KEY)
|
||||
).exists()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue