diff --git a/combo/apps/lingo/migrations/0008_auto_20150908_1538.py b/combo/apps/lingo/migrations/0008_auto_20150908_1538.py new file mode 100644 index 00000000..d88b3df3 --- /dev/null +++ b/combo/apps/lingo/migrations/0008_auto_20150908_1538.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import ckeditor.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0001_initial'), + ('data', '0010_feedcell'), + ('lingo', '0007_lingobasketlinkcell'), + ] + + operations = [ + migrations.CreateModel( + name='ActiveItems', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('placeholder', models.CharField(max_length=20)), + ('order', models.PositiveIntegerField()), + ('slug', models.SlugField(verbose_name='Slug', blank=True)), + ('public', models.BooleanField(default=True, verbose_name='Public')), + ('regie', models.CharField(max_length=50, verbose_name='Regie', blank=True)), + ('title', ckeditor.fields.RichTextField(verbose_name='Title', blank=True)), + ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)), + ('page', models.ForeignKey(to='data.Page')), + ], + options={ + 'verbose_name': 'Active Items Cell', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='ItemsHistory', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('placeholder', models.CharField(max_length=20)), + ('order', models.PositiveIntegerField()), + ('slug', models.SlugField(verbose_name='Slug', blank=True)), + ('public', models.BooleanField(default=True, verbose_name='Public')), + ('regie', models.CharField(max_length=50, verbose_name='Regie', blank=True)), + ('title', ckeditor.fields.RichTextField(verbose_name='Title', blank=True)), + ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)), + ('page', models.ForeignKey(to='data.Page')), + ], + options={ + 'verbose_name': 'Items History Cell', + }, + bases=(models.Model,), + ), + migrations.AddField( + model_name='regie', + name='webservice_url', + field=models.URLField(verbose_name='Webservice URL to retrieve remote items', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='regie', + name='service', + field=models.CharField(max_length=64, verbose_name='Payment Service', choices=[(b'dummy', 'Dummy (for tests)'), (b'systempayv2', b'systempay (Banque Populaire)'), (b'sips', b'SIPS'), (b'spplus', "SP+ (Caisse d'epargne)"), (b'ogone', 'Ingenico (formerly Ogone)'), (b'paybox', 'Paybox')]), + preserve_default=True, + ), + ] diff --git a/combo/apps/lingo/models.py b/combo/apps/lingo/models.py index df236a5c..cec8bfc8 100644 --- a/combo/apps/lingo/models.py +++ b/combo/apps/lingo/models.py @@ -17,6 +17,8 @@ import datetime import json import requests +import urllib +from dateutil import parser import eopayment from jsonfield import JSONField @@ -24,12 +26,15 @@ from jsonfield import JSONField from django import template from django.conf import settings from django.db import models +from django.forms import models as model_forms, Select from django.utils.translation import ugettext_lazy as _ from django.utils import timezone +from ckeditor.fields import RichTextField + from combo.data.models import CellBase from combo.data.library import register_cell_class -from combo.utils import sign_url +from combo.utils import NothingInCacheException, sign_url SERVICES = [ @@ -41,6 +46,15 @@ SERVICES = [ (eopayment.PAYBOX, _('Paybox')), ] +def build_remote_item(data, regie): + return RemoteItem(id=data.get('id'), regie=regie, + creation_date=data['created'], + display_id=data['display_id'], + total_amount=data.get('total_amount'), + amount=data.get('amount'), + subject=data.get('label')) + + class Regie(models.Model): label = models.CharField(verbose_name=_('Label'), max_length=64) slug = models.SlugField(unique=True) @@ -49,6 +63,11 @@ class Regie(models.Model): max_length=64, choices=SERVICES) service_options = JSONField(blank=True, verbose_name=_('Payment Service Options')) + webservice_url = models.URLField(_('Webservice URL to retrieve remote items'), + blank=True) + + def is_remote(self): + return self.webservice_url != '' class Meta: verbose_name = _('Regie') @@ -59,11 +78,46 @@ class Regie(models.Model): def __unicode__(self): return self.label + def get_past_items(self, context): + """ + returns past items + """ + return self.get_items(context, past=True) + + + def get_items(self, context, past=False): + """ + returns current or past items + """ + if not self.is_remote(): + payed = not past + return self.basketitem_set.filter(payment_date__isnull=payed, + user=context.get('user')) + if context.get('user'): + if context.get('request') and hasattr(context['request'], 'session') and \ + context['request'].session.get('mellon_session'): + mellon = context.get('request').session['mellon_session'] + url = self.webservice_url + '/invoices/' + if past: + url += 'history' + items = self.get_url(context['request'], url, + NameID=mellon['name_id_content']).json() + if items.get('data'): + return [build_remote_item(item, self) for item in items.get('data')] + return [] + def as_api_dict(self): return {'slug': self.slug, 'label': self.label, 'description': self.description} + def get_url(self, request, url, **params): + orig = request.get_host() + url += '?orig=' + orig +'&' + urllib.urlencode(params) + signature_key = settings.LINGO_SIGNATURE_KEY + url = sign_url(url, key=signature_key) + return requests.get(url) + class BasketItem(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL) @@ -88,6 +142,18 @@ class BasketItem(models.Model): self.save() +class RemoteItem(object): + def __init__(self, id, regie, creation_date, total_amount, + amount, display_id, subject): + self.id = id + self.regie = regie + self.creation_date = parser.parse(creation_date) + self.total_amount = total_amount + self.display_id = display_id + self.amount = amount + self.subject = subject + + class Transaction(models.Model): items = models.ManyToManyField(BasketItem, blank=True) start_date = models.DateTimeField(auto_now_add=True) @@ -189,3 +255,77 @@ class LingoBasketLinkCell(CellBase): ).exclude(cancellation_date__isnull=False) context['total'] = sum([x.amount for x in context['items']]) return basket_template.render(context) + + +class Items(CellBase): + regie = models.CharField(_('Regie'), max_length=50, blank=True) + title = RichTextField(_('Title'), blank=True) + + user_dependant = True + template_name = 'lingo/combo/items.html' + + class Meta: + abstract = True + + + 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 + + def get_default_form_class(self): + if Regie.objects.count() == 1: + return None + regies = [('', _('All'))] + regies.extend([(r.slug, r.label) for r in Regie.objects.all()]) + return model_forms.modelform_factory(self.__class__, + fields=['regie', 'title'], + widgets={'regie': Select(choices=regies)}) + + def get_regies(self): + if self.regie: + return [Regie.objects.get(slug=self.regie)] + return Regie.objects.all() + + def get_cell_extra_context(self): + ctx = {'title': self.title} + items = self.get_items() + # sort items by creation date + items.sort(key=lambda i: i.creation_date, reverse=True) + ctx.update({'items': items}) + return ctx + + def render(self, context): + self.context = context + if not context.get('synchronous'): + raise NothingInCacheException() + return super(Items, self).render(context) + + +@register_cell_class +class ItemsHistory(Items): + + class Meta: + verbose_name = _('Items History Cell') + + def get_items(self): + items = [] + for r in self.get_regies(): + items.extend(r.get_past_items(self.context)) + return items + + +@register_cell_class +class ActiveItems(Items): + + class Meta: + verbose_name = _('Active Items Cell') + + def get_items(self): + items = [] + for r in self.get_regies(): + items.extend(r.get_items(self.context)) + return items diff --git a/combo/apps/lingo/templates/lingo/combo/items.html b/combo/apps/lingo/templates/lingo/combo/items.html new file mode 100644 index 00000000..4e249c44 --- /dev/null +++ b/combo/apps/lingo/templates/lingo/combo/items.html @@ -0,0 +1,30 @@ +{% load i18n %} + +

{{ title|safe }}

+{% if items %} + + + + + + + + + + + {% for item in items %} + + + + + + + {% endfor %} + +
{% trans "Number" %}{% trans "Label" %}{% trans "Issue date" %}{% trans "Amount" %}
{{ item.display_id }}{{ item.subject }}{{ item.creation_date|date:"SHORT_DATE_FORMAT" }}{% blocktrans with amount=item.total_amount %} + {{ amount }}€ + {% endblocktrans %} +
+{% else %} +{% trans "No items yet" %} +{% endif %}