diff --git a/core/templates/core/user_account.jinja b/core/templates/core/user_account.jinja
index dfc3cdd8..3b459fc1 100644
--- a/core/templates/core/user_account.jinja
+++ b/core/templates/core/user_account.jinja
@@ -46,6 +46,14 @@
{% trans %}Eboutic invoices{% endtrans %}
{{ monthly(invoices_month) }}
{% endif %}
+{% if etickets %}
+{% trans %}Etickets{% endtrans %}
+
+{% endif %}
{% else %}
{% trans %}User has no account{% endtrans %}
{% endif %}
diff --git a/core/views/user.py b/core/views/user.py
index 00b5179c..c5f83d1b 100644
--- a/core/views/user.py
+++ b/core/views/user.py
@@ -368,7 +368,6 @@ class UserAccountBase(UserTabsMixin, DetailView):
"""
Base class for UserAccount
"""
-
model = User
pk_url_kwarg = "user_id"
current_tab = "account"
@@ -386,7 +385,6 @@ class UserAccountView(UserAccountBase):
"""
Display a user's account
"""
-
template_name = "core/user_account.jinja"
def expense_by_month(self, obj, calc):
@@ -406,7 +404,6 @@ class UserAccountView(UserAccountBase):
month
))
i += 1
-
return stats
def invoices_calc(self, query):
@@ -432,18 +429,15 @@ class UserAccountView(UserAccountBase):
self.object.customer.refillings,
(lambda q: q.amount)
)
+ kwargs['etickets'] = self.object.customer.buyings.exclude(product__eticket=None).all()
except:
pass
- # TODO: add list of month where account has activity
return kwargs
-
-
class UserAccountDetailView(UserAccountBase, YearMixin, MonthMixin):
"""
Display a user's account for month
"""
-
template_name = "core/user_account_detail.jinja"
def get_context_data(self, **kwargs):
diff --git a/counter/admin.py b/counter/admin.py
index 7361dc6f..b975ab58 100644
--- a/counter/admin.py
+++ b/counter/admin.py
@@ -11,4 +11,5 @@ admin.site.register(Refilling)
admin.site.register(Selling)
admin.site.register(Permanency)
admin.site.register(CashRegisterSummary)
+admin.site.register(Eticket)
diff --git a/counter/migrations/0009_eticket.py b/counter/migrations/0009_eticket.py
new file mode 100644
index 00000000..b59038b4
--- /dev/null
+++ b/counter/migrations/0009_eticket.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('counter', '0008_counter_token'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Eticket',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
+ ('banner', models.ImageField(null=True, upload_to='etickets', blank=True)),
+ ('secret', models.CharField(unique=True, verbose_name='secret', max_length=64)),
+ ('product', models.OneToOneField(verbose_name='product', related_name='eticket', to='counter.Product')),
+ ],
+ ),
+ ]
diff --git a/counter/migrations/0010_auto_20161003_1900.py b/counter/migrations/0010_auto_20161003_1900.py
new file mode 100644
index 00000000..9f1d73c4
--- /dev/null
+++ b/counter/migrations/0010_auto_20161003_1900.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('counter', '0009_eticket'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='eticket',
+ name='event_date',
+ field=models.DateField(blank=True, verbose_name='event date', null=True),
+ ),
+ migrations.AddField(
+ model_name='eticket',
+ name='event_title',
+ field=models.CharField(blank=True, max_length=64, verbose_name='event title', null=True),
+ ),
+ ]
diff --git a/counter/models.py b/counter/models.py
index cb6f4268..d66211e9 100644
--- a/counter/models.py
+++ b/counter/models.py
@@ -8,6 +8,8 @@ from django.forms import ValidationError
from datetime import timedelta
import random
import string
+import os
+import base64
from club.models import Club
from accounting.models import CurrencyField
@@ -282,6 +284,9 @@ class Selling(models.Model):
def is_owned_by(self, user):
return user.is_owner(self.counter) and self.payment_method != "CARD"
+ def can_be_viewed_by(self, user):
+ return user == self.customer.user
+
def delete(self, *args, **kwargs):
self.customer.amount += self.quantity * self.unit_price
self.customer.save()
@@ -427,3 +432,34 @@ class CashRegisterSummaryItem(models.Model):
class Meta:
verbose_name = _("cash register summary item")
+class Eticket(models.Model):
+ """
+ Eticket can be linked to a product an allows PDF generation
+ """
+ product = models.OneToOneField(Product, related_name='eticket', verbose_name=_("product"))
+ banner = models.ImageField(upload_to='etickets', null=True, blank=True, verbose_name=_("banner"))
+ event_date = models.DateField(_('event date'), null=True, blank=True)
+ event_title = models.CharField(_('event title'), max_length=64, null=True, blank=True)
+ secret = models.CharField(_('secret'), max_length=64, unique=True)
+
+ def __str__(self):
+ return "%s" % (self.product.name)
+
+ def get_absolute_url(self):
+ return reverse('counter:eticket_list')
+
+ def save(self, *args, **kwargs):
+ if not self.id:
+ self.secret = base64.b64encode(os.urandom(32))
+ return super(Eticket, self).save(*args, **kwargs)
+
+ def is_owned_by(self, user):
+ """
+ Method to see if that object can be edited by the given user
+ """
+ return user.is_in_group(settings.SITH_GROUPS['counter-admin']['name'])
+
+ def get_hash(self, string):
+ import hashlib, hmac
+ return hmac.new(bytes(self.secret, 'utf-8'), bytes(string, 'utf-8'), hashlib.sha1).hexdigest()
+
diff --git a/counter/templates/counter/eticket_list.jinja b/counter/templates/counter/eticket_list.jinja
new file mode 100644
index 00000000..6c6f0b51
--- /dev/null
+++ b/counter/templates/counter/eticket_list.jinja
@@ -0,0 +1,24 @@
+{% extends "core/base.jinja" %}
+
+{% block title %}
+{% trans %}Eticket list{% endtrans %}
+{% endblock %}
+
+{% block content %}
+{% trans %}New eticket{% endtrans %}
+{% if eticket_list %}
+{% trans %}Eticket list{% endtrans %}
+
+{% else %}
+{% trans %}There is no eticket in this website.{% endtrans %}
+{% endif %}
+{% endblock %}
+
+
+
+
+
diff --git a/counter/urls.py b/counter/urls.py
index 83b735df..72b53406 100644
--- a/counter/urls.py
+++ b/counter/urls.py
@@ -11,6 +11,7 @@ urlpatterns = [
url(r'^(?P[0-9]+)/stats$', CounterStatView.as_view(), name='stats'),
url(r'^(?P[0-9]+)/login$', CounterLogin.as_view(), name='login'),
url(r'^(?P[0-9]+)/logout$', CounterLogout.as_view(), name='logout'),
+ url(r'^eticket/(?P[0-9]+)/pdf$', EticketPDFView.as_view(), name='eticket_pdf'),
url(r'^admin/(?P[0-9]+)$', CounterEditView.as_view(), name='admin'),
url(r'^admin/(?P[0-9]+)/prop$', CounterEditPropView.as_view(), name='prop_admin'),
url(r'^admin$', CounterListView.as_view(), name='admin_list'),
@@ -26,6 +27,9 @@ urlpatterns = [
url(r'^admin/producttype/list$', ProductTypeListView.as_view(), name='producttype_list'),
url(r'^admin/producttype/create$', ProductTypeCreateView.as_view(), name='new_producttype'),
url(r'^admin/producttype/(?P[0-9]+)$', ProductTypeEditView.as_view(), name='producttype_edit'),
+ url(r'^admin/eticket/list$', EticketListView.as_view(), name='eticket_list'),
+ url(r'^admin/eticket/new$', EticketCreateView.as_view(), name='new_eticket'),
+ url(r'^admin/eticket/(?P[0-9]+)$', EticketEditView.as_view(), name='edit_eticket'),
url(r'^admin/selling/(?P[0-9]+)/delete$', SellingDeleteView.as_view(), name='selling_delete'),
url(r'^admin/refilling/(?P[0-9]+)/delete$', RefillingDeleteView.as_view(), name='refilling_delete'),
]
diff --git a/counter/views.py b/counter/views.py
index 3a8bb554..ac4f2e50 100644
--- a/counter/views.py
+++ b/counter/views.py
@@ -6,7 +6,7 @@ from django.forms.models import modelform_factory
from django.forms import CheckboxSelectMultiple
from django.core.urlresolvers import reverse_lazy, reverse
from django.core.exceptions import PermissionDenied
-from django.http import HttpResponseRedirect
+from django.http import HttpResponseRedirect, HttpResponse
from django.utils import timezone
from django import forms
from django.utils.translation import ugettext_lazy as _
@@ -20,11 +20,11 @@ from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultip
from ajax_select import make_ajax_form, make_ajax_field
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin, TabedViewMixin
-from core.views.forms import SelectUser, LoginForm
+from core.views.forms import SelectUser, LoginForm, SelectDate
from core.models import User
from subscription.models import Subscriber, Subscription
from subscription.views import get_subscriber
-from counter.models import Counter, Customer, Product, Selling, Refilling, ProductType, CashRegisterSummary, CashRegisterSummaryItem
+from counter.models import Counter, Customer, Product, Selling, Refilling, ProductType, CashRegisterSummary, CashRegisterSummaryItem, Eticket
from accounting.models import CurrencyField
class GetUserForm(forms.Form):
@@ -464,6 +464,11 @@ class CounterAdminTabsMixin(TabedViewMixin):
'slug': 'invoices_call',
'name': _("Invoices call"),
},
+ {
+ 'url': reverse_lazy('counter:eticket_list'),
+ 'slug': 'etickets',
+ 'name': _("Etickets"),
+ },
]
class CounterListView(CounterAdminTabsMixin, CanViewMixin, ListView):
@@ -940,4 +945,105 @@ class InvoiceCallView(CounterAdminTabsMixin, TemplateView):
)).exclude(selling_sum=None).order_by('-selling_sum')
return kwargs
- #).exclude(selling_sum=None).order_by('-selling_sum').all()[:100]
+class EticketListView(CounterAdminTabsMixin, CanEditPropMixin, ListView):
+ """
+ A list view for the admins
+ """
+ model = Eticket
+ template_name = 'counter/eticket_list.jinja'
+ ordering = ['id']
+ current_tab = "etickets"
+
+class EticketForm(forms.ModelForm):
+ class Meta:
+ model = Eticket
+ fields = ['product', 'banner', 'event_title', 'event_date']
+ widgets = {
+ 'event_date': SelectDate,
+ }
+ product = AutoCompleteSelectField('products', show_help_text=False, label=_("Product"), required=True)
+
+class EticketCreateView(CounterAdminTabsMixin, CanEditPropMixin, CreateView):
+ """
+ Create an eticket
+ """
+ model = Eticket
+ template_name = 'core/create.jinja'
+ form_class = EticketForm
+ current_tab = "etickets"
+
+class EticketEditView(CounterAdminTabsMixin, CanEditPropMixin, UpdateView):
+ """
+ Edit an eticket
+ """
+ model = Eticket
+ template_name = 'core/edit.jinja'
+ form_class = EticketForm
+ pk_url_kwarg = "eticket_id"
+ current_tab = "etickets"
+
+class EticketPDFView(CanViewMixin, DetailView):
+ """
+ Display the PDF of an eticket
+ """
+ model = Selling
+ pk_url_kwarg = "selling_id"
+
+ def get(self, request, *args, **kwargs):
+ from reportlab.pdfgen import canvas
+ from reportlab.lib.utils import ImageReader
+ from reportlab.lib.units import cm
+ from reportlab.graphics.shapes import Drawing
+ from reportlab.graphics.barcode.qr import QrCodeWidget
+ from reportlab.graphics import renderPDF
+ self.object = self.get_object()
+ eticket = self.object.product.eticket
+ user = self.object.customer.user
+ code = "%s %s %s" % (self.object.customer.user.id, self.object.quantity, self.object.product.id)
+ code += " " + eticket.get_hash(code)[:8].upper()
+ response = HttpResponse(content_type='application/pdf')
+ response['Content-Disposition'] = 'filename="eticket.pdf"'
+ p = canvas.Canvas(response)
+ p.setTitle("Eticket")
+ im = ImageReader("core/static/core/img/eticket.jpg")
+ width, height = im.getSize()
+ size = max(width, height)
+ width = 8 * cm * width / size
+ height = 8 * cm * height / size
+ p.drawImage(im, 10 * cm, 25 * cm, width, height)
+ if eticket.banner:
+ im = ImageReader(eticket.banner)
+ width, height = im.getSize()
+ size = max(width, height)
+ width = 6 * cm * width / size
+ height = 6 * cm * height / size
+ p.drawImage(im, 1 * cm, 25 * cm, width, height)
+ if user.profile_pict:
+ im = ImageReader(user.profile_pict.file)
+ width, height = im.getSize()
+ size = max(width, height)
+ width = 150 * width / size
+ height = 150 * height / size
+ p.drawImage(im, 10.5 * cm - width / 2, 16 * cm, width, height)
+ if eticket.event_title:
+ p.setFont("Helvetica-Bold", 20)
+ p.drawCentredString(10.5 * cm, 23.6 * cm, eticket.event_title)
+ if eticket.event_date:
+ p.setFont("Helvetica-Bold", 16)
+ p.drawCentredString(10.5 * cm, 22.6 * cm, eticket.event_date.strftime("%d %b %Y"))
+ p.setFont("Helvetica-Bold", 14)
+ p.drawCentredString(10.5 * cm, 15 * cm, user.get_display_name())
+ p.setFont("Courier-Bold", 14)
+ qrcode = QrCodeWidget(code)
+ bounds = qrcode.getBounds()
+ width = bounds[2] - bounds[0]
+ height = bounds[3] - bounds[1]
+ d = Drawing(260, 260, transform=[260./width, 0, 0, 260./height, 0, 0])
+ d.add(qrcode)
+ renderPDF.draw(d, p, 10.5 * cm - 130, 6.1 * cm)
+ p.drawCentredString(10.5 * cm, 6 * cm, code)
+
+ p.showPage()
+ p.save()
+ return response
+
diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo
index 2900a0b5..3f26652e 100644
Binary files a/locale/fr/LC_MESSAGES/django.mo and b/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 3efd0de9..d289f5c0 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-09-29 18:31+0200\n"
+"POT-Creation-Date: 2016-10-03 19:24+0200\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia \n"
"Language-Team: AE info \n"
@@ -17,8 +17,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: accounting/models.py:36 accounting/models.py:55 accounting/models.py:82
-#: accounting/models.py:132 club/models.py:19 counter/models.py:60
-#: counter/models.py:85 counter/models.py:120 launderette/models.py:15
+#: accounting/models.py:132 club/models.py:19 counter/models.py:62
+#: counter/models.py:87 counter/models.py:122 launderette/models.py:15
#: launderette/models.py:60 launderette/models.py:85
msgid "name"
msgstr "nom"
@@ -64,7 +64,7 @@ msgid "account number"
msgstr "numero de compte"
#: accounting/models.py:58 accounting/models.py:83 club/models.py:145
-#: counter/models.py:94 counter/models.py:121
+#: counter/models.py:96 counter/models.py:123
msgid "club"
msgstr "club"
@@ -85,12 +85,12 @@ msgstr "Compte club"
msgid "%(club_account)s on %(bank_account)s"
msgstr "%(club_account)s sur %(bank_account)s"
-#: accounting/models.py:130 club/models.py:146 counter/models.py:336
+#: accounting/models.py:130 club/models.py:146 counter/models.py:341
#: launderette/models.py:122
msgid "start date"
msgstr "date de début"
-#: accounting/models.py:131 club/models.py:147 counter/models.py:337
+#: accounting/models.py:131 club/models.py:147 counter/models.py:342
msgid "end date"
msgstr "date de fin"
@@ -102,8 +102,8 @@ msgstr "est fermé"
msgid "club account"
msgstr "compte club"
-#: accounting/models.py:135 accounting/models.py:178 counter/models.py:25
-#: counter/models.py:224
+#: accounting/models.py:135 accounting/models.py:178 counter/models.py:27
+#: counter/models.py:226
msgid "amount"
msgstr "montant"
@@ -124,16 +124,16 @@ msgid "journal"
msgstr "classeur"
#: accounting/models.py:179 core/models.py:479 core/models.py:757
-#: counter/models.py:227 counter/models.py:270 counter/models.py:353
+#: counter/models.py:229 counter/models.py:272 counter/models.py:358
#: eboutic/models.py:15 eboutic/models.py:48
msgid "date"
msgstr "date"
-#: accounting/models.py:180 counter/models.py:354
+#: accounting/models.py:180 counter/models.py:359
msgid "comment"
msgstr "commentaire"
-#: accounting/models.py:181 counter/models.py:228 counter/models.py:271
+#: accounting/models.py:181 counter/models.py:230 counter/models.py:273
#: subscription/models.py:57
msgid "payment method"
msgstr "méthode de paiement"
@@ -225,7 +225,7 @@ msgstr ""
"Vous devez fournir soit un type comptable simplifié ou un type comptable "
"standard"
-#: accounting/models.py:277 counter/models.py:89
+#: accounting/models.py:277 counter/models.py:91
msgid "code"
msgstr "code"
@@ -233,7 +233,7 @@ msgstr "code"
msgid "An accounting type code contains only numbers"
msgstr "Un code comptable ne contient que des numéros"
-#: accounting/models.py:282 accounting/models.py:308 counter/models.py:262
+#: accounting/models.py:282 accounting/models.py:308 counter/models.py:264
msgid "label"
msgstr "intitulé"
@@ -485,7 +485,7 @@ msgid "Done"
msgstr "Effectué"
#: accounting/templates/accounting/journal_details.jinja:34
-#: counter/templates/counter/cash_summary_list.jinja:32 counter/views.py:697
+#: counter/templates/counter/cash_summary_list.jinja:32 counter/views.py:702
msgid "Comment"
msgstr "Commentaire"
@@ -554,7 +554,7 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs"
msgid "A club with that unix_name already exists"
msgstr "Un club avec ce nom UNIX existe déjà."
-#: club/models.py:144 counter/models.py:334 counter/models.py:351
+#: club/models.py:144 counter/models.py:339 counter/models.py:356
#: eboutic/models.py:14 eboutic/models.py:47 launderette/models.py:89
#: launderette/models.py:126
msgid "user"
@@ -564,8 +564,8 @@ msgstr "nom d'utilisateur"
msgid "role"
msgstr "rôle"
-#: club/models.py:150 core/models.py:32 counter/models.py:61
-#: counter/models.py:86
+#: club/models.py:150 core/models.py:32 counter/models.py:63
+#: counter/models.py:88
msgid "description"
msgstr "description"
@@ -581,8 +581,7 @@ msgstr "L'utilisateur est déjà membre de ce club"
msgid "past member"
msgstr "Anciens membres"
-#: club/templates/club/club_list.jinja:4
-#: club/templates/club/club_list.jinja:24
+#: club/templates/club/club_list.jinja:4 club/templates/club/club_list.jinja:24
msgid "Club list"
msgstr "Liste des clubs"
@@ -760,6 +759,7 @@ msgid "End date"
msgstr "Date de fin"
#: club/views.py:178 core/templates/core/user_stats.jinja:27
+#: counter/views.py:964
msgid "Product"
msgstr "Produit"
@@ -1371,13 +1371,11 @@ msgstr "login"
msgid "Lost password?"
msgstr "Mot de passe perdu ?"
-#: core/templates/core/macros.jinja:27
-#: core/templates/core/user_detail.jinja:27
+#: core/templates/core/macros.jinja:27 core/templates/core/user_detail.jinja:27
msgid "Born: "
msgstr "Né le : "
-#: core/templates/core/macros.jinja:31
-#: core/templates/core/user_detail.jinja:48
+#: core/templates/core/macros.jinja:31 core/templates/core/user_detail.jinja:48
msgid "Promo: "
msgstr "Promo : "
@@ -1588,8 +1586,7 @@ msgstr "Résultat de la recherche"
msgid "Users"
msgstr "Utilisateurs"
-#: core/templates/core/search.jinja:18
-#: counter/templates/counter/stats.jinja:17
+#: core/templates/core/search.jinja:18 counter/templates/counter/stats.jinja:17
msgid "Clubs"
msgstr "Clubs"
@@ -1629,7 +1626,11 @@ msgstr "Achat sur compte utilisateur"
msgid "Eboutic invoices"
msgstr "Facture eboutic"
-#: core/templates/core/user_account.jinja:50
+#: core/templates/core/user_account.jinja:50 counter/views.py:470
+msgid "Etickets"
+msgstr ""
+
+#: core/templates/core/user_account.jinja:58
#: core/templates/core/user_account_detail.jinja:103
msgid "User has no account"
msgstr "L'utilisateur n'a pas de compte"
@@ -1790,7 +1791,7 @@ msgid "Subscriptions"
msgstr "Cotisations"
#: core/templates/core/user_tools.jinja:23 counter/views.py:440
-#: counter/views.py:584
+#: counter/views.py:589
msgid "Counters"
msgstr "Comptoirs"
@@ -1888,83 +1889,83 @@ msgstr "Fillot"
msgid "User already has a profile picture"
msgstr "L'utilisateur a déjà une photo de profil"
-#: counter/models.py:24
+#: counter/models.py:26
msgid "account id"
msgstr "numéro de compte"
-#: counter/models.py:28
+#: counter/models.py:30
msgid "customer"
msgstr "client"
-#: counter/models.py:29
+#: counter/models.py:31
msgid "customers"
msgstr "clients"
-#: counter/models.py:44 counter/templates/counter/counter_click.jinja:46
+#: counter/models.py:46 counter/templates/counter/counter_click.jinja:46
msgid "Not enough money"
msgstr "Solde insuffisant"
-#: counter/models.py:65 counter/models.py:87
+#: counter/models.py:67 counter/models.py:89
msgid "product type"
msgstr "type du produit"
-#: counter/models.py:90
+#: counter/models.py:92
msgid "purchase price"
msgstr "prix d'achat"
-#: counter/models.py:91
+#: counter/models.py:93
msgid "selling price"
msgstr "prix de vente"
-#: counter/models.py:92
+#: counter/models.py:94
msgid "special selling price"
msgstr "prix de vente spécial"
-#: counter/models.py:93
+#: counter/models.py:95
msgid "icon"
msgstr "icône"
-#: counter/models.py:95
+#: counter/models.py:97
msgid "limit age"
msgstr "âge limite"
-#: counter/models.py:96
+#: counter/models.py:98
msgid "tray price"
msgstr "prix plateau"
-#: counter/models.py:97
+#: counter/models.py:99
msgid "parent product"
msgstr "produit parent"
-#: counter/models.py:99
+#: counter/models.py:101
msgid "buying groups"
msgstr "groupe d'achat"
-#: counter/models.py:100
+#: counter/models.py:102
msgid "archived"
msgstr "archivé"
-#: counter/models.py:103
+#: counter/models.py:105 counter/models.py:439
msgid "product"
msgstr "produit"
-#: counter/models.py:122
+#: counter/models.py:124
msgid "products"
msgstr "produits"
-#: counter/models.py:123
+#: counter/models.py:125
msgid "counter type"
msgstr "type de comptoir"
-#: counter/models.py:125
+#: counter/models.py:127
msgid "Bar"
msgstr "Bar"
-#: counter/models.py:125
+#: counter/models.py:127
msgid "Office"
msgstr "Bureau"
-#: counter/models.py:125 counter/templates/counter/counter_list.jinja:11
+#: counter/models.py:127 counter/templates/counter/counter_list.jinja:11
#: eboutic/templates/eboutic/eboutic_main.jinja:4
#: eboutic/templates/eboutic/eboutic_main.jinja:24
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8
@@ -1973,84 +1974,100 @@ msgstr "Bureau"
msgid "Eboutic"
msgstr "Eboutic"
-#: counter/models.py:126
+#: counter/models.py:128
msgid "sellers"
msgstr "vendeurs"
-#: counter/models.py:129 launderette/models.py:125
+#: counter/models.py:131 launderette/models.py:125
msgid "token"
msgstr "jeton"
-#: counter/models.py:132 counter/models.py:335 counter/models.py:352
+#: counter/models.py:134 counter/models.py:340 counter/models.py:357
#: launderette/models.py:16
msgid "counter"
msgstr "comptoir"
-#: counter/models.py:230
+#: counter/models.py:232
msgid "bank"
msgstr "banque"
-#: counter/models.py:232 counter/models.py:273
+#: counter/models.py:234 counter/models.py:275
msgid "is validated"
msgstr "est validé"
-#: counter/models.py:235
+#: counter/models.py:237
msgid "refilling"
msgstr "rechargement"
-#: counter/models.py:266 eboutic/models.py:103
+#: counter/models.py:268 eboutic/models.py:103
msgid "unit price"
msgstr "prix unitaire"
-#: counter/models.py:267 counter/models.py:424 eboutic/models.py:104
+#: counter/models.py:269 counter/models.py:429 eboutic/models.py:104
msgid "quantity"
msgstr "quantité"
-#: counter/models.py:272
+#: counter/models.py:274
msgid "Sith account"
msgstr "Compte utilisateur"
-#: counter/models.py:272 sith/settings.py:271 sith/settings.py:276
+#: counter/models.py:274 sith/settings.py:271 sith/settings.py:276
#: sith/settings.py:298
msgid "Credit card"
msgstr "Carte bancaire"
-#: counter/models.py:276
+#: counter/models.py:278
msgid "selling"
msgstr "vente"
-#: counter/models.py:338
+#: counter/models.py:343
msgid "last activity date"
msgstr "dernière activité"
-#: counter/models.py:341
+#: counter/models.py:346
msgid "permanency"
msgstr "permanence"
-#: counter/models.py:355
+#: counter/models.py:360
msgid "emptied"
msgstr "coffre vidée"
-#: counter/models.py:358
+#: counter/models.py:363
msgid "cash register summary"
msgstr "relevé de caisse"
-#: counter/models.py:422
+#: counter/models.py:427
msgid "cash summary"
msgstr "relevé"
-#: counter/models.py:423
+#: counter/models.py:428
msgid "value"
msgstr "valeur"
-#: counter/models.py:425
+#: counter/models.py:430
msgid "check"
msgstr "chèque"
-#: counter/models.py:428
+#: counter/models.py:433
msgid "cash register summary item"
msgstr "élément de relevé de caisse"
+#: counter/models.py:440
+msgid "banner"
+msgstr "bannière"
+
+#: counter/models.py:441
+msgid "event date"
+msgstr "date de l'événement"
+
+#: counter/models.py:442
+msgid "event title"
+msgstr "titre de l'événement"
+
+#: counter/models.py:443
+msgid "secret"
+msgstr "secret"
+
#: counter/templates/counter/activity.jinja:5
#: counter/templates/counter/activity.jinja:9
#, python-format
@@ -2074,7 +2091,7 @@ msgstr "Liste des relevés de caisse"
msgid "Theoric sums"
msgstr "Sommes théoriques"
-#: counter/templates/counter/cash_summary_list.jinja:31 counter/views.py:698
+#: counter/templates/counter/cash_summary_list.jinja:31 counter/views.py:703
msgid "Emptied"
msgstr "Coffre vidé"
@@ -2181,6 +2198,19 @@ msgstr "Merci de vous identifier"
msgid "Barman: "
msgstr "Barman : "
+#: counter/templates/counter/eticket_list.jinja:4
+#: counter/templates/counter/eticket_list.jinja:10
+msgid "Eticket list"
+msgstr "Liste des etickets"
+
+#: counter/templates/counter/eticket_list.jinja:8
+msgid "New eticket"
+msgstr "Nouveau eticket"
+
+#: counter/templates/counter/eticket_list.jinja:17
+msgid "There is no eticket in this website."
+msgstr "Il n'y a pas de eticket sur ce site web."
+
#: counter/templates/counter/invoices_call.jinja:4 counter/views.py:465
msgid "Invoices call"
msgstr "Appels à facture"
@@ -2305,61 +2335,61 @@ msgstr "Produits archivés"
msgid "Product types"
msgstr "Types de produit"
-#: counter/views.py:581
+#: counter/views.py:586
msgid "Parent product"
msgstr "Produit parent"
-#: counter/views.py:582
+#: counter/views.py:587
msgid "Buying groups"
msgstr "Groupes d'achat"
-#: counter/views.py:677
+#: counter/views.py:682
msgid "10 cents"
msgstr "10 centimes"
-#: counter/views.py:678
+#: counter/views.py:683
msgid "20 cents"
msgstr "20 centimes"
-#: counter/views.py:679
+#: counter/views.py:684
msgid "50 cents"
msgstr "50 centimes"
-#: counter/views.py:680
+#: counter/views.py:685
msgid "1 euro"
msgstr "1 €"
-#: counter/views.py:681
+#: counter/views.py:686
msgid "2 euros"
msgstr "2 €"
-#: counter/views.py:682
+#: counter/views.py:687
msgid "5 euros"
msgstr "5 €"
-#: counter/views.py:683
+#: counter/views.py:688
msgid "10 euros"
msgstr "10 €"
-#: counter/views.py:684
+#: counter/views.py:689
msgid "20 euros"
msgstr "20 €"
-#: counter/views.py:685
+#: counter/views.py:690
msgid "50 euros"
msgstr "50 €"
-#: counter/views.py:686
+#: counter/views.py:691
msgid "100 euros"
msgstr "100 €"
-#: counter/views.py:687 counter/views.py:689 counter/views.py:691
-#: counter/views.py:693 counter/views.py:695
+#: counter/views.py:692 counter/views.py:694 counter/views.py:696
+#: counter/views.py:698 counter/views.py:700
msgid "Check amount"
msgstr "Montant du chèque"
-#: counter/views.py:688 counter/views.py:690 counter/views.py:692
-#: counter/views.py:694 counter/views.py:696
+#: counter/views.py:693 counter/views.py:695 counter/views.py:697
+#: counter/views.py:699 counter/views.py:701
msgid "Check quantity"
msgstr "Nombre de chèque"
@@ -2720,5 +2750,14 @@ msgid "You must either choose an existing user or create a new one properly"
msgstr ""
"Vous devez soit choisir un utilisateur existant, ou en créer un proprement."
+#~ msgid "Last name"
+#~ msgstr "Nom"
+
+#~ msgid "First name"
+#~ msgstr "Prénom"
+
+#~ msgid "Nick name"
+#~ msgstr "Surnom"
+
#~ msgid "Display last operations"
#~ msgstr "Dernières opérations"
diff --git a/requirements.txt b/requirements.txt
index 04cfed6c..057a8460 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,4 +8,6 @@ pytz
djangorestframework
django-phonenumber-field
django-ajax-selects
+reportlab
# mysqlclient
+