lingo: make it possible to cancel a basket item (#10236)

This commit is contained in:
Frédéric Péters 2016-03-08 15:35:55 +01:00
parent 6abb1b30c0
commit 7b31d6bfe8
5 changed files with 70 additions and 7 deletions

View File

@ -178,7 +178,7 @@ class BasketItem(models.Model):
payment_date = models.DateTimeField(null=True)
notification_date = models.DateTimeField(null=True)
def notify(self, request):
def notify(self, status):
source_server = urlparse.urlparse(self.source_url).netloc.split(':')[0]
service_dict = None
for services in settings.KNOWN_SERVICES.values():
@ -196,13 +196,22 @@ class BasketItem(models.Model):
'failed to find data for server %s', source_server)
raise RuntimeError('failed to find data for server')
params = urlencode({'orig': service_dict.get('orig')})
url = self.source_url + 'jump/trigger/paid?' + params
url = self.source_url + 'jump/trigger/%s?%s' % (status, params)
url = sign_url(url, key=service_dict.get('secret'))
message = {'result': 'ok'}
r = requests.post(url, data=json.dumps(message), timeout=3)
r.raise_for_status()
def notify_payment(self):
self.notify('paid')
self.notification_date = timezone.now()
self.save()
def notify_cancellation(self):
self.notify('cancelled')
self.cancellation_date = timezone.now()
self.save()
class RemoteItem(object):
def __init__(self, id, regie, creation_date, payment_limit_date,
@ -252,6 +261,10 @@ class LingoBasketCell(CellBase):
class Meta:
verbose_name = _('Basket')
class Media:
js = ('xstatic/jquery-ui.min.js', 'js/gadjo.js',)
css = {'all': ('xstatic/themes/smoothness/jquery-ui.min.css', )}
@classmethod
def is_enabled(cls):
return Regie.objects.count() > 0

View File

@ -6,7 +6,9 @@
<input type="hidden" name="next_url" value="{{ cell.page.get_online_url }}" />
<ul>
{% for item in items %}
<li><label><input type="checkbox" name="item" value="{{ item.id }}" checked/> {{ item.subject }}: {{ item.amount }} €</label> (<a href="{{ item.source_url}}">voir</a>)</li>
<li><label><input type="checkbox" name="item" value="{{ item.id }}" checked/>
<a href="{{ item.source_url }}">{{ item.subject }}</a>: {{ item.amount }} €</label>
<a rel="popup" href="{% url 'lingo-cancel-item' pk=item.id %}">({% trans 'remove' %}</a>)</li>
{% endfor %}
<li><strong>{% trans "Total:" %}</strong> {{ total }} €</li>
</ul>

View File

@ -0,0 +1,20 @@
{% load i18n %}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<div>
<form method="POST" action="{% url 'lingo-cancel-item' pk=object.id %}">
{% csrf_token %}
{% blocktrans with subject=object.subject %}
Are you really sure you want to remove "{{subject}}"?
{% endblocktrans %}
<div class="buttons">
<button>{% trans 'Remove' %}</button>
<a class="cancel" href="{{ basket_url }}">{% trans 'Cancel' %}</a>
</div>
</form>
</div>
</body>
</html>

View File

@ -19,7 +19,7 @@ from django.conf.urls import patterns, url, include
from combo.urls_utils import decorated_includes, manager_required
from .views import (RegiesApiView, AddBasketItemApiView, PayView, CallbackView,
ReturnView, ItemDownloadView, ItemView)
ReturnView, ItemDownloadView, ItemView, CancelItemView)
from .manager_views import (RegieListView, RegieCreateView, RegieUpdateView,
RegieDeleteView, TransactionListView, ManagerHomeView)
@ -39,6 +39,7 @@ urlpatterns = patterns('',
url('^api/lingo/add-basket-item$', AddBasketItemApiView.as_view(),
name='api-add-basket-item'),
url(r'^lingo/pay$', PayView.as_view(), name='lingo-pay'),
url(r'^lingo/cancel/(?P<pk>\w+)/$', CancelItemView.as_view(), name='lingo-cancel-item'),
url(r'^lingo/callback/(?P<regie_pk>\w+)/$', CallbackView.as_view(), name='lingo-callback'),
url(r'^lingo/return/(?P<regie_pk>\w+)/$', ReturnView.as_view(), name='lingo-return'),
url(r'^manage/lingo/', decorated_includes(manager_required,

View File

@ -17,6 +17,7 @@
from decimal import Decimal, ROUND_HALF_UP
import json
import requests
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
@ -25,7 +26,7 @@ from django.http import HttpResponseForbidden, Http404
from django.template.response import TemplateResponse
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View, ListView, TemplateView
from django.views.generic import View, DetailView, ListView, TemplateView
from django.conf import settings
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
@ -39,7 +40,7 @@ try:
except ImportError:
UserSAMLIdentifier = None
from .models import Regie, BasketItem, Transaction
from .models import Regie, BasketItem, Transaction, LingoBasketCell
def get_eopayment_object(request, regie):
options = regie.service_options
@ -52,6 +53,10 @@ def get_eopayment_object(request, regie):
return eopayment.Payment(regie.service, options)
def get_basket_url():
return LingoBasketCell.objects.all()[0].page.get_online_url()
class RegiesApiView(ListView):
model = Regie
@ -224,7 +229,7 @@ class CallbackView(View):
item.payment_date = transaction.end_date
item.save()
try:
item.notify(request)
item.notify_payment()
except RuntimeError:
# ignore errors, it should be retried later on if it fails
pass
@ -298,3 +303,25 @@ class ItemView(TemplateView):
regie = Regie.objects.get(pk=kwargs['regie_id'])
item = regie.get_item(self.request, kwargs['item_id'])
return {'item': item, 'regie': regie}
class CancelItemView(DetailView):
model = BasketItem
template_name = 'lingo/combo/cancel-item.html'
def get_context_data(self, **kwargs):
context = super(CancelItemView, self).get_context_data(**kwargs)
context['basket_url'] = get_basket_url()
return context
def get_queryset(self):
return BasketItem.objects.filter(user=self.request.user,
payment_date__isnull=True,
cancellation_date__isnull=True)
def post(self, request, *args, **kwargs):
try:
self.get_object().notify_cancellation()
except requests.exceptions.HTTPError:
messages.error(request, _('An error occured when removing the item.'))
return HttpResponseRedirect(get_basket_url())