lingo: poll backend during asynchronous rendering (#57790)
This commit is contained in:
parent
0aac640e37
commit
f92b855774
|
@ -638,13 +638,16 @@ class BasketItem(models.Model):
|
||||||
ordering = ['regie', 'extra_fee', 'subject']
|
ordering = ['regie', 'extra_fee', 'subject']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_items_to_be_paid(cls, user):
|
def get_items_to_be_paid(cls, user, poll=False, raise_on_poll=False):
|
||||||
qs = cls.objects.filter(
|
qs = cls.objects.filter(
|
||||||
user=user, payment_date__isnull=True, waiting_date__isnull=True, cancellation_date__isnull=True
|
user=user, payment_date__isnull=True, waiting_date__isnull=True, cancellation_date__isnull=True
|
||||||
)
|
)
|
||||||
for transaction in Transaction.objects.filter(items__in=qs):
|
if poll:
|
||||||
if transaction.can_poll_backend():
|
for transaction in Transaction.objects.filter(items__in=qs):
|
||||||
transaction.poll_backend()
|
if transaction.can_poll_backend():
|
||||||
|
if raise_on_poll:
|
||||||
|
raise NothingInCacheException
|
||||||
|
transaction.poll_backend()
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
def notify(self, status):
|
def notify(self, status):
|
||||||
|
@ -1087,7 +1090,9 @@ class LingoBasketCell(CellBase):
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
basket_template = template.loader.get_template('lingo/combo/basket.html')
|
basket_template = template.loader.get_template('lingo/combo/basket.html')
|
||||||
items = BasketItem.get_items_to_be_paid(context['request'].user)
|
items = BasketItem.get_items_to_be_paid(
|
||||||
|
context['request'].user, poll=True, raise_on_poll=not context.get('synchronous')
|
||||||
|
)
|
||||||
regies = {}
|
regies = {}
|
||||||
for item in items:
|
for item in items:
|
||||||
if not item.regie_id in regies:
|
if not item.regie_id in regies:
|
||||||
|
@ -1112,7 +1117,7 @@ class LingoRecentTransactionsCell(CellBase):
|
||||||
def is_enabled(cls):
|
def is_enabled(cls):
|
||||||
return Regie.objects.exists()
|
return Regie.objects.exists()
|
||||||
|
|
||||||
def get_transactions_queryset(self, context):
|
def get_transactions_queryset(self, context, poll=False):
|
||||||
user = context['request'].user
|
user = context['request'].user
|
||||||
# list transactions :
|
# list transactions :
|
||||||
# * paid by the user
|
# * paid by the user
|
||||||
|
@ -1120,9 +1125,12 @@ class LingoRecentTransactionsCell(CellBase):
|
||||||
qs = Transaction.objects.filter(models.Q(user=user) | models.Q(items__user=user)).filter(
|
qs = Transaction.objects.filter(models.Q(user=user) | models.Q(items__user=user)).filter(
|
||||||
start_date__gte=timezone.now() - datetime.timedelta(days=7)
|
start_date__gte=timezone.now() - datetime.timedelta(days=7)
|
||||||
)
|
)
|
||||||
for transaction in qs:
|
if poll:
|
||||||
if transaction.can_poll_backend() and transaction.is_running():
|
for transaction in qs:
|
||||||
transaction.poll_backend()
|
if transaction.can_poll_backend() and transaction.is_running():
|
||||||
|
if not context.get('synchronous'):
|
||||||
|
raise NothingInCacheException
|
||||||
|
transaction.poll_backend()
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
def is_relevant(self, context):
|
def is_relevant(self, context):
|
||||||
|
@ -1132,7 +1140,9 @@ class LingoRecentTransactionsCell(CellBase):
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
recent_transactions_template = template.loader.get_template('lingo/combo/recent_transactions.html')
|
recent_transactions_template = template.loader.get_template('lingo/combo/recent_transactions.html')
|
||||||
context['transactions'] = self.get_transactions_queryset(context).distinct().order_by('-start_date')
|
context['transactions'] = (
|
||||||
|
self.get_transactions_queryset(context, poll=True).distinct().order_by('-start_date')
|
||||||
|
)
|
||||||
return recent_transactions_template.render(context)
|
return recent_transactions_template.render(context)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,4 +70,14 @@ def nocache(settings):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def synchronous_cells(settings):
|
def synchronous_cells(settings):
|
||||||
settings.COMBO_TEST_ALWAYS_RENDER_CELLS_SYNCHRONOUSLY = True
|
class M:
|
||||||
|
@staticmethod
|
||||||
|
def on():
|
||||||
|
settings.COMBO_TEST_ALWAYS_RENDER_CELLS_SYNCHRONOUSLY = True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def off():
|
||||||
|
settings.COMBO_TEST_ALWAYS_RENDER_CELLS_SYNCHRONOUSLY = False
|
||||||
|
|
||||||
|
M.on()
|
||||||
|
return M
|
||||||
|
|
|
@ -2153,6 +2153,8 @@ class TestPolling:
|
||||||
self,
|
self,
|
||||||
payment_status,
|
payment_status,
|
||||||
app,
|
app,
|
||||||
|
user,
|
||||||
|
synchronous_cells,
|
||||||
):
|
):
|
||||||
# Try to pay
|
# Try to pay
|
||||||
pay_resp = app.get('/test_basket_cell/')
|
pay_resp = app.get('/test_basket_cell/')
|
||||||
|
@ -2171,15 +2173,40 @@ class TestPolling:
|
||||||
order_id=transaction.order_id,
|
order_id=transaction.order_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Try to pay again
|
# check get_items_to_be_paid() does not poll anymore
|
||||||
|
BasketItem.get_items_to_be_paid(user)
|
||||||
|
assert payment_status.call_count == 0
|
||||||
|
|
||||||
|
# Try to pay again, only with current information
|
||||||
|
synchronous_cells.off()
|
||||||
resp = app.get('/test_basket_cell/')
|
resp = app.get('/test_basket_cell/')
|
||||||
assert 'foo item' not in resp
|
assert 'Loading' in resp.pyquery('.lingo-basket-cell').text()
|
||||||
assert 'Pay' not in resp
|
assert 'Loading' in resp.pyquery('.lingo-recent-transactions-cell').text()
|
||||||
assert 'Running' in resp
|
|
||||||
resp = pay_resp.click('Pay').follow()
|
resp = pay_resp.click('Pay').follow()
|
||||||
assert 'Some items are already paid or' in resp
|
assert 'Some items are already paid or' in resp
|
||||||
assert 'foo item' not in resp
|
assert len(resp.pyquery('.lingo-basket-cell')) == 0
|
||||||
assert 'Running' in resp
|
assert 'Loading' in resp.pyquery('.lingo-recent-transactions-cell').text()
|
||||||
|
assert payment_status.call_count == 1 # pay made a call to payfip backend
|
||||||
|
payment_status.reset_mock()
|
||||||
|
|
||||||
|
# Make rendering synchronous and retry
|
||||||
|
synchronous_cells.on()
|
||||||
|
resp = app.get('/test_basket_cell/')
|
||||||
|
assert len(resp.pyquery('.lingo-basket-cell')) == 0
|
||||||
|
assert 'Running' in resp.pyquery('.lingo-recent-transactions-cell').text()
|
||||||
|
assert payment_status.call_count == 1 # transactions cell polled
|
||||||
|
payment_status.reset_mock()
|
||||||
|
|
||||||
|
resp = pay_resp.click('Pay')
|
||||||
|
assert payment_status.call_count == 1 # pay polled
|
||||||
|
payment_status.reset_mock()
|
||||||
|
|
||||||
|
resp = resp.follow()
|
||||||
|
assert 'Some items are already paid or' in resp
|
||||||
|
assert len(resp.pyquery('.lingo-basket-cell')) == 0
|
||||||
|
assert 'Running' in resp.pyquery('.lingo-recent-transactions-cell').text()
|
||||||
|
assert payment_status.call_count == 1 # transactions cell polled
|
||||||
|
payment_status.reset_mock()
|
||||||
|
|
||||||
# Simulate paid status on polling
|
# Simulate paid status on polling
|
||||||
payment_status.return_value = eopayment.common.PaymentResponse(
|
payment_status.return_value = eopayment.common.PaymentResponse(
|
||||||
|
@ -2193,12 +2220,17 @@ class TestPolling:
|
||||||
assert 'foo item: 42.00' in resp
|
assert 'foo item: 42.00' in resp
|
||||||
assert 'Pay' not in resp
|
assert 'Pay' not in resp
|
||||||
assert 'Running' not in resp
|
assert 'Running' not in resp
|
||||||
|
assert len(resp.pyquery('.lingo-basket-cell')) == 0
|
||||||
|
assert '42.00' in resp.pyquery('.lingo-recent-transactions-cell').text()
|
||||||
|
assert payment_status.call_count == 1 # transactions cell polled
|
||||||
|
payment_status.reset_mock()
|
||||||
|
|
||||||
@mock.patch('eopayment.payfip_ws.Payment.payment_status')
|
@mock.patch('eopayment.payfip_ws.Payment.payment_status')
|
||||||
def test_exception_during_polling(
|
def test_exception_during_polling(
|
||||||
self,
|
self,
|
||||||
payment_status,
|
payment_status,
|
||||||
app,
|
app,
|
||||||
|
synchronous_cells,
|
||||||
caplog,
|
caplog,
|
||||||
):
|
):
|
||||||
# Try to pay
|
# Try to pay
|
||||||
|
|
Loading…
Reference in New Issue