active and history items cells (#7994)
This commit is contained in:
parent
55d43ce5ae
commit
764199ed2a
|
@ -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,
|
||||
),
|
||||
]
|
142
lingo/models.py
142
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
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
{% load i18n %}
|
||||
|
||||
<h3>{{ title|safe }}</h3>
|
||||
{% if items %}
|
||||
<table id="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{% trans "Number" %}</td>
|
||||
<td>{% trans "Label" %}</td>
|
||||
<td>{% trans "Issue date" %}</td>
|
||||
<td>{% trans "Amount" %}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr class="{% cycle 'lightgrey' 'white' %}">
|
||||
<td>{{ item.display_id }}</td>
|
||||
<td>{{ item.subject }}</td>
|
||||
<td>{{ item.creation_date|date:"SHORT_DATE_FORMAT" }}</td>
|
||||
<td>{% blocktrans with amount=item.total_amount %}
|
||||
{{ amount }}€
|
||||
{% endblocktrans %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
{% trans "No items yet" %}
|
||||
{% endif %}
|
Reference in New Issue