forked from DGNum/gestioCOF
Merge branch 'master' of https://git.eleves.ens.fr/cof-geek/gestioCOF into Aufinal/bda_revente
This commit is contained in:
commit
0282f62886
148 changed files with 18206 additions and 11 deletions
0
apache/__init__.py
Normal file
0
apache/__init__.py
Normal file
6
apache/asgi.py
Normal file
6
apache/asgi.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
import os
|
||||
from channels.asgi import get_channel_layer
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings")
|
||||
|
||||
channel_layer = get_channel_layer()
|
103
bda/migrations/0008_py3.py
Normal file
103
bda/migrations/0008_py3.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('bda', '0007_extends_spectacle'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='choixspectacle',
|
||||
name='double_choice',
|
||||
field=models.CharField(
|
||||
verbose_name='Nombre de places',
|
||||
choices=[('1', '1 place'),
|
||||
('autoquit', '2 places si possible, 1 sinon'),
|
||||
('double', '2 places sinon rien')],
|
||||
max_length=10, default='1'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='participant',
|
||||
name='paymenttype',
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[('cash', 'Cash'), ('cb', 'CB'),
|
||||
('cheque', 'Chèque'), ('autre', 'Autre')],
|
||||
max_length=6, verbose_name='Moyen de paiement'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='salle',
|
||||
name='address',
|
||||
field=models.TextField(verbose_name='Adresse'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='salle',
|
||||
name='name',
|
||||
field=models.CharField(verbose_name='Nom', max_length=300),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='date',
|
||||
field=models.DateTimeField(verbose_name='Date & heure'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='description',
|
||||
field=models.TextField(verbose_name='Description', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='listing',
|
||||
field=models.BooleanField(
|
||||
verbose_name='Les places sont sur listing'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='price',
|
||||
field=models.FloatField(verbose_name="Prix d'une place"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='slots',
|
||||
field=models.IntegerField(verbose_name='Places'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='slots_description',
|
||||
field=models.TextField(verbose_name='Description des places',
|
||||
blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='title',
|
||||
field=models.CharField(verbose_name='Titre', max_length=300),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tirage',
|
||||
name='active',
|
||||
field=models.BooleanField(verbose_name='Tirage actif',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tirage',
|
||||
name='fermeture',
|
||||
field=models.DateTimeField(
|
||||
verbose_name='Date et heure de fermerture du tirage'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tirage',
|
||||
name='ouverture',
|
||||
field=models.DateTimeField(
|
||||
verbose_name="Date et heure d'ouverture du tirage"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tirage',
|
||||
name='title',
|
||||
field=models.CharField(verbose_name='Titre', max_length=300),
|
||||
),
|
||||
]
|
|
@ -20,6 +20,7 @@
|
|||
.descTable{
|
||||
width: auto;
|
||||
margin: 0 auto 1em;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
font-size: 14px;
|
||||
|
@ -46,10 +47,7 @@
|
|||
<td><p style="text-align: left;">{{ show.location }}</p></td><td class="column-2"><p style="text-align: right;">{{ show.category }}</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p style="text-align: left;">{{ show.date }}</p></td><td class="column-2"><p style="text-align: right;">{{ show.slots }} place{{ show.slots|pluralize}} {% if show.slots_description != "" %}({{ show.slots_description }}){% endif %}- {{ show.price }}</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><p style="text-align: justify;">{{ show.category }}</p></td>
|
||||
<td><p style="text-align: left;">{{ show.date|date:"l j F Y - H\hi" }}</p></td><td class="column-2"><p style="text-align: right;">{{ show.slots }} place{{ show.slots|pluralize}} {% if show.slots_description != "" %}({{ show.slots_description }}){% endif %} - {{ show.price }} euro{{ show.price|pluralize}}</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
|
@ -61,7 +59,7 @@
|
|||
</tr>
|
||||
{% if show.image %}
|
||||
<tr>
|
||||
<td colspan="2"><p style="text-align:center;"><a href="{{ show.ext_link }}"><img style="display: inline;" src="{{ MEDIA_URL }}{{ show.image }}" alt="{{ show.title }}" width="200px"></a></p></td>
|
||||
<td colspan="2"><p style="text-align:center;"><a href="{{ show.ext_link }}"><img style="display: inline;" src="{{ MEDIA_URL }}{{ show.image }}" alt="{{ show.title }}" height="500px"></a></p></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
|
|
3
cof/routing.py
Normal file
3
cof/routing.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from kfet.routing import channel_routing as kfet_channel_routings
|
||||
|
||||
channel_routing = kfet_channel_routings
|
|
@ -50,6 +50,9 @@ INSTALLED_APPS = (
|
|||
'django_cas_ng',
|
||||
'debug_toolbar',
|
||||
'bootstrapform',
|
||||
'kfet',
|
||||
'channels',
|
||||
'widget_tweaks',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
|
@ -58,6 +61,7 @@ MIDDLEWARE_CLASSES = (
|
|||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'kfet.middleware.KFetAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
|
@ -80,6 +84,7 @@ TEMPLATES = [
|
|||
'django.core.context_processors.media',
|
||||
'django.core.context_processors.static',
|
||||
'gestioncof.shared.context_processor',
|
||||
'kfet.context_processors.auth',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
@ -87,7 +92,6 @@ TEMPLATES = [
|
|||
|
||||
# WSGI_APPLICATION = 'cof.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||
|
||||
|
@ -120,6 +124,10 @@ USE_TZ = True
|
|||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
STATICFILES_DIRS = (
|
||||
os.path.join(BASE_DIR, 'static/'),
|
||||
)
|
||||
|
||||
# Media upload (through ImageField, SiteField)
|
||||
# https://docs.djangoproject.com/en/1.9/ref/models/fields/
|
||||
|
||||
|
@ -164,6 +172,17 @@ RECAPTCHA_PUBLIC_KEY = "DUMMY"
|
|||
RECAPTCHA_PRIVATE_KEY = "DUMMY"
|
||||
RECAPTCHA_USE_SSL = True
|
||||
|
||||
# Channels settings
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "asgi_redis.RedisChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [("redis://:password_redis@127.0.0.1:6379/0")],
|
||||
},
|
||||
"ROUTING": "cof.routing.channel_routing",
|
||||
}
|
||||
}
|
||||
|
||||
def show_toolbar(request):
|
||||
"""
|
||||
|
|
|
@ -81,6 +81,7 @@ urlpatterns = [
|
|||
url(r'^utile_bda/bda_diff$', gestioncof_views.liste_bdadiff),
|
||||
url(r'^utile_cof/diff_cof$', gestioncof_views.liste_diffcof),
|
||||
url(r'^utile_bda/bda_revente$', gestioncof_views.liste_bdarevente),
|
||||
url(r'^k-fet/', include('kfet.urls'))
|
||||
] + \
|
||||
(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
if settings.DEBUG
|
||||
|
|
253
gestioncof/migrations/0008_py3.py
Normal file
253
gestioncof/migrations/0008_py3.py
Normal file
|
@ -0,0 +1,253 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
def forwards(apps, schema_editor):
|
||||
Profile = apps.get_model("gestioncof", "CofProfile")
|
||||
Profile.objects.update(comments="")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gestioncof', '0007_alter_club'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='clipper',
|
||||
name='fullname',
|
||||
field=models.CharField(verbose_name='Nom complet', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='clipper',
|
||||
name='username',
|
||||
field=models.CharField(verbose_name='Identifiant', max_length=20),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='comments',
|
||||
field=models.TextField(
|
||||
verbose_name="Commentaires visibles par l'utilisateur",
|
||||
blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='is_cof',
|
||||
field=models.BooleanField(verbose_name='Membre du COF',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='login_clipper',
|
||||
field=models.CharField(verbose_name='Login clipper', max_length=8,
|
||||
blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='mailing_bda',
|
||||
field=models.BooleanField(verbose_name='Recevoir les mails BdA',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='mailing_bda_revente',
|
||||
field=models.BooleanField(
|
||||
verbose_name='Recevoir les mails de revente de places BdA',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='mailing_cof',
|
||||
field=models.BooleanField(verbose_name='Recevoir les mails COF',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='occupation',
|
||||
field=models.CharField(verbose_name='Occupation',
|
||||
choices=[('exterieur', 'Extérieur'),
|
||||
('1A', '1A'),
|
||||
('2A', '2A'),
|
||||
('3A', '3A'),
|
||||
('4A', '4A'),
|
||||
('archicube', 'Archicube'),
|
||||
('doctorant', 'Doctorant'),
|
||||
('CST', 'CST')],
|
||||
max_length=9, default='1A'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='petits_cours_accept',
|
||||
field=models.BooleanField(verbose_name='Recevoir des petits cours',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='petits_cours_remarques',
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
verbose_name='Remarques et précisions pour les petits cours',
|
||||
default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cofprofile',
|
||||
name='type_cotiz',
|
||||
field=models.CharField(
|
||||
verbose_name='Type de cotisation',
|
||||
choices=[('etudiant', 'Normalien étudiant'),
|
||||
('normalien', 'Normalien élève'),
|
||||
('exterieur', 'Extérieur')],
|
||||
max_length=9, default='normalien'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='custommail',
|
||||
name='comments',
|
||||
field=models.TextField(
|
||||
verbose_name='Informations contextuelles sur le mail',
|
||||
blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='custommail',
|
||||
name='content',
|
||||
field=models.TextField(verbose_name='Contenu'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='custommail',
|
||||
name='title',
|
||||
field=models.CharField(verbose_name='Titre', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='description',
|
||||
field=models.TextField(verbose_name='Description', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='end_date',
|
||||
field=models.DateTimeField(null=True, verbose_name='Date de fin',
|
||||
blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='image',
|
||||
field=models.ImageField(upload_to='imgs/events/', null=True,
|
||||
verbose_name='Image', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='location',
|
||||
field=models.CharField(verbose_name='Lieu', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='registration_open',
|
||||
field=models.BooleanField(verbose_name='Inscriptions ouvertes',
|
||||
default=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='title',
|
||||
field=models.CharField(verbose_name='Titre', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventcommentfield',
|
||||
name='fieldtype',
|
||||
field=models.CharField(verbose_name='Type',
|
||||
choices=[('text', 'Texte long'),
|
||||
('char', 'Texte court')],
|
||||
max_length=10, default='text'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventcommentfield',
|
||||
name='name',
|
||||
field=models.CharField(verbose_name='Champ', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventcommentvalue',
|
||||
name='content',
|
||||
field=models.TextField(null=True, verbose_name='Contenu',
|
||||
blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventoption',
|
||||
name='multi_choices',
|
||||
field=models.BooleanField(verbose_name='Choix multiples',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventoption',
|
||||
name='name',
|
||||
field=models.CharField(verbose_name='Option', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventoptionchoice',
|
||||
name='value',
|
||||
field=models.CharField(verbose_name='Valeur', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='petitcoursability',
|
||||
name='niveau',
|
||||
field=models.CharField(
|
||||
choices=[('college', 'Collège'), ('lycee', 'Lycée'),
|
||||
('prepa1styear', 'Prépa 1ère année / L1'),
|
||||
('prepa2ndyear', 'Prépa 2ème année / L2'),
|
||||
('licence3', 'Licence 3'),
|
||||
('other', 'Autre (préciser dans les commentaires)')],
|
||||
max_length=12, verbose_name='Niveau'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='petitcoursattribution',
|
||||
name='rank',
|
||||
field=models.IntegerField(verbose_name="Rang dans l'email"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='petitcoursattributioncounter',
|
||||
name='count',
|
||||
field=models.IntegerField(verbose_name="Nombre d'envois",
|
||||
default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='petitcoursdemande',
|
||||
name='niveau',
|
||||
field=models.CharField(
|
||||
verbose_name='Niveau',
|
||||
choices=[('college', 'Collège'), ('lycee', 'Lycée'),
|
||||
('prepa1styear', 'Prépa 1ère année / L1'),
|
||||
('prepa2ndyear', 'Prépa 2ème année / L2'),
|
||||
('licence3', 'Licence 3'),
|
||||
('other', 'Autre (préciser dans les commentaires)')],
|
||||
max_length=12, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='survey',
|
||||
name='old',
|
||||
field=models.BooleanField(verbose_name='Archiver (sondage fini)',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='survey',
|
||||
name='survey_open',
|
||||
field=models.BooleanField(verbose_name='Sondage ouvert',
|
||||
default=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='survey',
|
||||
name='title',
|
||||
field=models.CharField(verbose_name='Titre', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='surveyquestion',
|
||||
name='multi_answers',
|
||||
field=models.BooleanField(verbose_name='Choix multiples',
|
||||
default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='surveyquestion',
|
||||
name='question',
|
||||
field=models.CharField(verbose_name='Question', max_length=200),
|
||||
),
|
||||
migrations.RunPython(forwards, migrations.RunPython.noop),
|
||||
]
|
|
@ -62,7 +62,7 @@ class CofProfile(models.Model):
|
|||
mailing_bda_revente = models.BooleanField(
|
||||
"Recevoir les mails de revente de places BdA", default=False)
|
||||
comments = models.TextField(
|
||||
"Commentaires visibles uniquement par le Buro", blank=True)
|
||||
"Commentaires visibles par l'utilisateur", blank=True)
|
||||
is_buro = models.BooleanField("Membre du Burô", default=False)
|
||||
petits_cours_accept = models.BooleanField(
|
||||
"Recevoir des petits cours", default=False)
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr">
|
||||
<head>
|
||||
<title>{{ site.name }}</title>
|
||||
<link type="text/css" rel="stylesheet" href="{% static "css/bootstrap.min.css" %}" />
|
||||
<link type="text/css" rel="stylesheet" href="{% static "css/cof.css" %}" />
|
||||
<link type="text/css" rel="stylesheet" href="{% static "css/bootstrap.min.css" %}" />
|
||||
<link type="text/css" rel="stylesheet" href="{% static "css/cof.css" %}" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Dosis|Dosis:700|Raleway|Roboto:300,300i,700" rel="stylesheet">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{% block extra_head %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -13,10 +13,18 @@
|
|||
{% csrf_token %}
|
||||
<fieldset"center-block">
|
||||
{% for field in form %}
|
||||
{{ field | bootstrap}}
|
||||
{{ field | bootstrap }}
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
</div>
|
||||
{% if user.profile.comments %}
|
||||
<div class="row" style="margin: 0 15%;">
|
||||
<h4>Commentaires</h4>
|
||||
<p>
|
||||
{{ user.profile.comments }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-actions">
|
||||
<input type="submit" class="btn btn-primary pull-right" value="Enregistrer" />
|
||||
</div>
|
||||
|
|
0
kfet/__init__.py
Normal file
0
kfet/__init__.py
Normal file
3
kfet/admin.py
Normal file
3
kfet/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
80
kfet/autocomplete.py
Normal file
80
kfet/autocomplete.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.http import Http404
|
||||
from django.db.models import Q
|
||||
from gestioncof.models import User, Clipper
|
||||
from kfet.models import Account
|
||||
|
||||
def account_create(request):
|
||||
if "q" not in request.GET:
|
||||
raise Http404
|
||||
q = request.GET.get("q")
|
||||
|
||||
if (len(q) == 0):
|
||||
return render(request, "kfet/account_create_autocomplete.html")
|
||||
|
||||
data = {'q': q}
|
||||
|
||||
queries = {}
|
||||
search_words = q.split()
|
||||
|
||||
queries['kfet'] = Account.objects
|
||||
queries['users_cof'] = User.objects.filter(Q(profile__is_cof = True))
|
||||
queries['users_notcof'] = User.objects.filter(Q(profile__is_cof = False))
|
||||
queries['clippers'] = Clipper.objects
|
||||
|
||||
for word in search_words:
|
||||
queries['kfet'] = queries['kfet'].filter(
|
||||
Q(cofprofile__user__username__icontains = word)
|
||||
| Q(cofprofile__user__first_name__icontains = word)
|
||||
| Q(cofprofile__user__last_name__icontains = word)
|
||||
)
|
||||
queries['users_cof'] = queries['users_cof'].filter(
|
||||
Q(username__icontains = word)
|
||||
| Q(first_name__icontains = word)
|
||||
| Q(last_name__icontains = word)
|
||||
)
|
||||
queries['users_notcof'] = queries['users_notcof'].filter(
|
||||
Q(username__icontains = word)
|
||||
| Q(first_name__icontains = word)
|
||||
| Q(last_name__icontains = word)
|
||||
)
|
||||
queries['clippers'] = queries['clippers'].filter(
|
||||
Q(username__icontains = word)
|
||||
| Q(fullname__icontains = word)
|
||||
)
|
||||
|
||||
queries['kfet'] = queries['kfet'].distinct()
|
||||
|
||||
usernames = list( \
|
||||
queries['kfet'].values_list('cofprofile__user__username', flat=True))
|
||||
|
||||
queries['kfet'] = [ (account, account.cofprofile.user) \
|
||||
for account in queries['kfet'] ]
|
||||
|
||||
queries['users_cof'] = \
|
||||
queries['users_cof'].exclude(username__in=usernames).distinct()
|
||||
queries['users_notcof'] = \
|
||||
queries['users_notcof'].exclude(username__in=usernames).distinct()
|
||||
|
||||
usernames += list( \
|
||||
queries['users_cof'].values_list('username', flat=True))
|
||||
usernames += list( \
|
||||
queries['users_notcof'].values_list('username', flat=True))
|
||||
|
||||
queries['clippers'] = \
|
||||
queries['clippers'].exclude(username__in=usernames).distinct()
|
||||
|
||||
data.update(queries)
|
||||
|
||||
options = 0
|
||||
for query in queries.values():
|
||||
options += len(query)
|
||||
data['options'] = options
|
||||
|
||||
return render(request, "kfet/account_create_autocomplete.html", data)
|
43
kfet/backends.py
Normal file
43
kfet/backends.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
import hashlib
|
||||
|
||||
from django.contrib.auth.models import User, Permission
|
||||
from gestioncof.models import CofProfile
|
||||
from kfet.models import Account, GenericTeamToken
|
||||
|
||||
class KFetBackend(object):
|
||||
def authenticate(self, request):
|
||||
password = request.POST.get('KFETPASSWORD', '')
|
||||
password = request.META.get('HTTP_KFETPASSWORD', password)
|
||||
if not password:
|
||||
return None
|
||||
|
||||
try:
|
||||
password_sha256 = hashlib.sha256(password.encode()).hexdigest()
|
||||
account = Account.objects.get(password=password_sha256)
|
||||
user = account.cofprofile.user
|
||||
except Account.DoesNotExist:
|
||||
return None
|
||||
|
||||
return user
|
||||
|
||||
class GenericTeamBackend(object):
|
||||
def authenticate(self, username=None, token=None):
|
||||
valid_token = GenericTeamToken.objects.get(token=token)
|
||||
if username == 'kfet_genericteam' and valid_token:
|
||||
user, created = User.objects.get_or_create(username='kfet_genericteam')
|
||||
perm_is_team = Permission.objects.get(codename='is_team')
|
||||
user.user_permissions.add(perm_is_team)
|
||||
return user
|
||||
return None
|
||||
|
||||
def get_user(self, user_id):
|
||||
try:
|
||||
return User.objects.get(pk=user_id)
|
||||
except User.DoesNotExist:
|
||||
return None
|
26
kfet/consumers.py
Normal file
26
kfet/consumers.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from channels import Group
|
||||
from channels.generic.websockets import JsonWebsocketConsumer
|
||||
|
||||
class KPsul(JsonWebsocketConsumer):
|
||||
|
||||
# Set to True if you want them, else leave out
|
||||
strict_ordering = False
|
||||
slight_ordering = False
|
||||
|
||||
def connection_groups(self, **kwargs):
|
||||
return ['kfet.kpsul']
|
||||
|
||||
def connect(self, message, **kwargs):
|
||||
pass
|
||||
|
||||
def receive(self, content, **kwargs):
|
||||
pass
|
||||
|
||||
def disconnect(self, message, **kwargs):
|
||||
pass
|
15
kfet/context_processors.py
Normal file
15
kfet/context_processors.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from django.contrib.auth.context_processors import PermWrapper
|
||||
|
||||
def auth(request):
|
||||
if hasattr(request, 'real_user'):
|
||||
return {
|
||||
'user': request.real_user,
|
||||
'perms': PermWrapper(request.real_user),
|
||||
}
|
||||
return {}
|
12
kfet/decorators.py
Normal file
12
kfet/decorators.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from django_cas_ng.decorators import user_passes_test
|
||||
|
||||
def kfet_is_team(user):
|
||||
return user.has_perm('kfet.is_team')
|
||||
|
||||
teamkfet_required = user_passes_test(lambda u: kfet_is_team(u))
|
516
kfet/forms.py
Normal file
516
kfet/forms.py
Normal file
|
@ -0,0 +1,516 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from decimal import Decimal
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MinLengthValidator
|
||||
from django.contrib.auth.models import User, Group, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.forms import modelformset_factory, inlineformset_factory
|
||||
from django.forms.models import BaseInlineFormSet
|
||||
from django.utils import timezone
|
||||
from kfet.models import (Account, Checkout, Article, OperationGroup, Operation,
|
||||
CheckoutStatement, ArticleCategory, Settings, AccountNegative, Transfer,
|
||||
TransferGroup, Supplier, Inventory, InventoryArticle)
|
||||
from gestioncof.models import CofProfile
|
||||
|
||||
# -----
|
||||
# Widgets
|
||||
# -----
|
||||
|
||||
class DateTimeWidget(forms.DateTimeInput):
|
||||
def __init__(self, attrs = None):
|
||||
super(DateTimeWidget, self).__init__(attrs)
|
||||
self.attrs['format'] = '%Y-%m-%d %H:%M'
|
||||
class Media:
|
||||
css = {
|
||||
'all': ('kfet/css/bootstrap-datetimepicker.min.css',)
|
||||
}
|
||||
js = (
|
||||
'kfet/js/moment.js',
|
||||
'kfet/js/moment-fr.js',
|
||||
'kfet/js/bootstrap-datetimepicker.min.js',
|
||||
)
|
||||
# -----
|
||||
# Account forms
|
||||
# -----
|
||||
|
||||
class AccountForm(forms.ModelForm):
|
||||
|
||||
# Surcharge pour passer data à Account.save()
|
||||
def save(self, data = {}, *args, **kwargs):
|
||||
obj = super(AccountForm, self).save(commit = False, *args, **kwargs)
|
||||
obj.save(data = data)
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['trigramme', 'promo', 'nickname', 'is_frozen']
|
||||
widgets = {
|
||||
'trigramme': forms.TextInput(attrs={'autocomplete': 'off'}),
|
||||
}
|
||||
|
||||
class AccountBalanceForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['balance']
|
||||
|
||||
class AccountTriForm(AccountForm):
|
||||
|
||||
def clean_trigramme(self):
|
||||
trigramme = self.cleaned_data['trigramme']
|
||||
return trigramme.upper()
|
||||
|
||||
class Meta(AccountForm.Meta):
|
||||
fields = ['trigramme']
|
||||
|
||||
class AccountNoTriForm(AccountForm):
|
||||
class Meta(AccountForm.Meta):
|
||||
exclude = ['trigramme']
|
||||
|
||||
class AccountRestrictForm(AccountForm):
|
||||
class Meta(AccountForm.Meta):
|
||||
fields = ['is_frozen']
|
||||
|
||||
class AccountPwdForm(forms.Form):
|
||||
pwd1 = forms.CharField(
|
||||
widget=forms.PasswordInput)
|
||||
pwd2 = forms.CharField(
|
||||
widget=forms.PasswordInput)
|
||||
|
||||
def clean(self):
|
||||
pwd1 = self.cleaned_data.get('pwd1', '')
|
||||
pwd2 = self.cleaned_data.get('pwd2', '')
|
||||
if len(pwd1) < 8:
|
||||
raise ValidationError("Mot de passe trop court")
|
||||
if pwd1 != pwd2:
|
||||
raise ValidationError("Les mots de passes sont différents")
|
||||
super(AccountPwdForm, self).clean()
|
||||
|
||||
class CofForm(forms.ModelForm):
|
||||
def clean_is_cof(self):
|
||||
instance = getattr(self, 'instance', None)
|
||||
if instance and instance.pk:
|
||||
return instance.is_cof
|
||||
else:
|
||||
return False
|
||||
class Meta:
|
||||
model = CofProfile
|
||||
fields = ['login_clipper', 'is_cof', 'departement']
|
||||
|
||||
class CofRestrictForm(CofForm):
|
||||
class Meta(CofForm.Meta):
|
||||
fields = ['departement']
|
||||
|
||||
class UserForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
from_clipper = kwargs.pop('from_clipper', False)
|
||||
new_user = kwargs.get('instance') is None and not from_clipper
|
||||
super(UserForm, self).__init__(*args, **kwargs)
|
||||
if new_user:
|
||||
self.fields['username'].validators = [MinLengthValidator(9)]
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['username', 'first_name', 'last_name', 'email']
|
||||
help_texts = {
|
||||
'username': ''
|
||||
}
|
||||
|
||||
class UserRestrictForm(UserForm):
|
||||
class Meta(UserForm.Meta):
|
||||
fields = ['first_name', 'last_name']
|
||||
|
||||
class UserRestrictTeamForm(UserForm):
|
||||
class Meta(UserForm.Meta):
|
||||
fields = ['first_name', 'last_name', 'email']
|
||||
|
||||
class UserGroupForm(forms.ModelForm):
|
||||
groups = forms.ModelMultipleChoiceField(
|
||||
Group.objects.filter(name__icontains='K-Fêt'))
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['groups']
|
||||
|
||||
class GroupForm(forms.ModelForm):
|
||||
permissions = forms.ModelMultipleChoiceField(
|
||||
queryset= Permission.objects.filter(content_type__in=
|
||||
ContentType.objects.filter(app_label='kfet')))
|
||||
|
||||
def clean_name(self):
|
||||
name = self.cleaned_data['name']
|
||||
return 'K-Fêt %s' % name
|
||||
|
||||
class Meta:
|
||||
model = Group
|
||||
fields = ['name', 'permissions']
|
||||
|
||||
class AccountNegativeForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AccountNegative
|
||||
fields = ['authz_overdraft_amount', 'authz_overdraft_until',
|
||||
'balance_offset', 'comment']
|
||||
widgets = {
|
||||
'authz_overdraft_until': DateTimeWidget(),
|
||||
}
|
||||
|
||||
# -----
|
||||
# Checkout forms
|
||||
# -----
|
||||
|
||||
class CheckoutForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Checkout
|
||||
fields = ['name', 'valid_from', 'valid_to', 'balance', 'is_protected']
|
||||
widgets = {
|
||||
'valid_from': DateTimeWidget(),
|
||||
'valid_to' : DateTimeWidget(),
|
||||
}
|
||||
|
||||
class CheckoutRestrictForm(CheckoutForm):
|
||||
class Meta(CheckoutForm.Meta):
|
||||
fields = ['name', 'valid_from', 'valid_to']
|
||||
|
||||
|
||||
class CheckoutStatementCreateForm(forms.ModelForm):
|
||||
balance_001 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_002 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_005 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_01 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_02 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_05 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_1 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_2 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_5 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_10 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_20 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_50 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_100 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_200 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
balance_500 = forms.IntegerField(min_value=0, initial=0, required=False)
|
||||
|
||||
class Meta:
|
||||
model = CheckoutStatement
|
||||
exclude = ['by', 'at', 'checkout', 'amount_error', 'amount_taken',
|
||||
'balance_old', 'balance_new']
|
||||
|
||||
def clean(self):
|
||||
not_count = self.cleaned_data['not_count']
|
||||
if not not_count and (
|
||||
self.cleaned_data['balance_001'] is None
|
||||
or self.cleaned_data['balance_002'] is None
|
||||
or self.cleaned_data['balance_005'] is None
|
||||
or self.cleaned_data['balance_01'] is None
|
||||
or self.cleaned_data['balance_02'] is None
|
||||
or self.cleaned_data['balance_05'] is None
|
||||
or self.cleaned_data['balance_1'] is None
|
||||
or self.cleaned_data['balance_2'] is None
|
||||
or self.cleaned_data['balance_5'] is None
|
||||
or self.cleaned_data['balance_10'] is None
|
||||
or self.cleaned_data['balance_20'] is None
|
||||
or self.cleaned_data['balance_50'] is None
|
||||
or self.cleaned_data['balance_100'] is None
|
||||
or self.cleaned_data['balance_200'] is None
|
||||
or self.cleaned_data['balance_500'] is None):
|
||||
raise ValidationError("Y'a un problème. Si tu comptes la caisse, mets au moins des 0 stp (et t'as pas idée de comment c'est long de vérifier que t'as mis des valeurs de partout...)")
|
||||
super(CheckoutStatementCreateForm, self).clean()
|
||||
|
||||
class CheckoutStatementUpdateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = CheckoutStatement
|
||||
exclude = ['by', 'at', 'checkout', 'amount_error', 'amount_taken']
|
||||
|
||||
# -----
|
||||
# Article forms
|
||||
# -----
|
||||
|
||||
class ArticleForm(forms.ModelForm):
|
||||
category_new = forms.CharField(
|
||||
max_length=45,
|
||||
required = False)
|
||||
category = forms.ModelChoiceField(
|
||||
queryset = ArticleCategory.objects.all(),
|
||||
required = False)
|
||||
|
||||
suppliers = forms.ModelMultipleChoiceField(
|
||||
queryset = Supplier.objects.all(),
|
||||
required = False)
|
||||
supplier_new = forms.CharField(
|
||||
max_length = 45,
|
||||
required = False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ArticleForm, self).__init__(*args, **kwargs)
|
||||
if self.instance.pk:
|
||||
self.initial['suppliers'] = self.instance.suppliers.values_list('pk', flat=True)
|
||||
|
||||
def clean(self):
|
||||
category = self.cleaned_data.get('category')
|
||||
category_new = self.cleaned_data.get('category_new')
|
||||
|
||||
if not category and not category_new:
|
||||
raise ValidationError('Sélectionnez une catégorie ou créez en une')
|
||||
elif not category:
|
||||
category, _ = ArticleCategory.objects.get_or_create(name=category_new)
|
||||
self.cleaned_data['category'] = category
|
||||
|
||||
super(ArticleForm, self).clean()
|
||||
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = ['name', 'is_sold', 'price', 'stock', 'category', 'box_type',
|
||||
'box_capacity']
|
||||
|
||||
class ArticleRestrictForm(ArticleForm):
|
||||
class Meta(ArticleForm.Meta):
|
||||
fields = ['name', 'is_sold', 'price', 'category', 'box_type',
|
||||
'box_capacity']
|
||||
|
||||
# -----
|
||||
# K-Psul forms
|
||||
# -----
|
||||
|
||||
class KPsulOperationGroupForm(forms.ModelForm):
|
||||
checkout = forms.ModelChoiceField(
|
||||
queryset = Checkout.objects.filter(
|
||||
is_protected=False, valid_from__lte=timezone.now(),
|
||||
valid_to__gte=timezone.now()),
|
||||
widget = forms.HiddenInput())
|
||||
class Meta:
|
||||
model = OperationGroup
|
||||
fields = ['on_acc', 'checkout', 'comment']
|
||||
widgets = {
|
||||
'on_acc' : forms.HiddenInput(),
|
||||
}
|
||||
|
||||
class KPsulAccountForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['trigramme']
|
||||
widgets = {
|
||||
'trigramme': forms.TextInput(
|
||||
attrs={
|
||||
'autocomplete': 'off',
|
||||
'spellcheck': 'false',
|
||||
}),
|
||||
}
|
||||
|
||||
class KPsulCheckoutForm(forms.Form):
|
||||
checkout = forms.ModelChoiceField(
|
||||
queryset=Checkout.objects.filter(
|
||||
is_protected=False, valid_from__lte=timezone.now(),
|
||||
valid_to__gte=timezone.now()),
|
||||
widget=forms.Select(attrs={'id':'id_checkout_select'}))
|
||||
|
||||
class KPsulOperationForm(forms.ModelForm):
|
||||
article = forms.ModelChoiceField(
|
||||
queryset=Article.objects.select_related('category').all(),
|
||||
required=False,
|
||||
widget = forms.HiddenInput())
|
||||
class Meta:
|
||||
model = Operation
|
||||
fields = ['type', 'amount', 'is_checkout', 'article', 'article_nb']
|
||||
widgets = {
|
||||
'type': forms.HiddenInput(),
|
||||
'amount': forms.HiddenInput(),
|
||||
'is_checkout': forms.HiddenInput(),
|
||||
'article_nb': forms.HiddenInput(),
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
super(KPsulOperationForm, self).clean()
|
||||
type_ope = self.cleaned_data.get('type')
|
||||
amount = self.cleaned_data.get('amount')
|
||||
article = self.cleaned_data.get('article')
|
||||
article_nb = self.cleaned_data.get('article_nb')
|
||||
if type_ope and type_ope == Operation.PURCHASE:
|
||||
if not article or not article_nb:
|
||||
raise ValidationError(
|
||||
"Un achat nécessite un article et une quantité")
|
||||
if article_nb < 1:
|
||||
raise ValidationError("Impossible d'acheter moins de 1 article")
|
||||
self.cleaned_data['is_checkout'] = True
|
||||
elif type_ope and type_ope in [Operation.DEPOSIT, Operation.WITHDRAW]:
|
||||
if not amount or article or article_nb:
|
||||
raise ValidationError("Bad request")
|
||||
if type_ope == Operation.DEPOSIT and amount <= 0:
|
||||
raise ValidationError("Charge non positive")
|
||||
if type_ope == Operation.WITHDRAW and amount >= 0:
|
||||
raise ValidationError("Retrait non négatif")
|
||||
self.cleaned_data['article'] = None
|
||||
self.cleaned_data['article_nb'] = None
|
||||
|
||||
KPsulOperationFormSet = modelformset_factory(
|
||||
Operation,
|
||||
form = KPsulOperationForm,
|
||||
can_delete = True,
|
||||
extra = 0,
|
||||
min_num = 1, validate_min = True)
|
||||
|
||||
class AddcostForm(forms.Form):
|
||||
trigramme = forms.CharField(required = False)
|
||||
amount = forms.DecimalField(
|
||||
required = False,
|
||||
max_digits=6,decimal_places=2,min_value=Decimal(0))
|
||||
|
||||
def clean(self):
|
||||
trigramme = self.cleaned_data.get('trigramme')
|
||||
if trigramme:
|
||||
try:
|
||||
Account.objects.get(trigramme=trigramme)
|
||||
except Account.DoesNotExist:
|
||||
raise ValidationError('Compte invalide')
|
||||
else:
|
||||
self.cleaned_data['amount'] = 0
|
||||
super(AddcostForm, self).clean()
|
||||
|
||||
# -----
|
||||
# Settings forms
|
||||
# -----
|
||||
|
||||
class SettingsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Settings
|
||||
fields = ['value_decimal', 'value_account', 'value_duration']
|
||||
|
||||
def clean(self):
|
||||
name = self.instance.name
|
||||
value_decimal = self.cleaned_data.get('value_decimal')
|
||||
value_account = self.cleaned_data.get('value_account')
|
||||
value_duration = self.cleaned_data.get('value_duration')
|
||||
|
||||
type_decimal = ['SUBVENTION_COF', 'ADDCOST_AMOUNT', 'OVERDRAFT_AMOUNT']
|
||||
type_account = ['ADDCOST_FOR']
|
||||
type_duration = ['OVERDRAFT_DURATION', 'CANCEL_DURATION']
|
||||
|
||||
self.cleaned_data['name'] = name
|
||||
if name in type_decimal:
|
||||
if not value_decimal:
|
||||
raise ValidationError('Renseignez une valeur décimale')
|
||||
self.cleaned_data['value_account'] = None
|
||||
self.cleaned_data['value_duration'] = None
|
||||
elif name in type_account:
|
||||
self.cleaned_data['value_decimal'] = None
|
||||
self.cleaned_data['value_duration'] = None
|
||||
elif name in type_duration:
|
||||
if not value_duration:
|
||||
raise ValidationError('Renseignez une durée')
|
||||
self.cleaned_data['value_decimal'] = None
|
||||
self.cleaned_data['value_account'] = None
|
||||
super(SettingsForm, self).clean()
|
||||
|
||||
class FilterHistoryForm(forms.Form):
|
||||
checkouts = forms.ModelMultipleChoiceField(queryset = Checkout.objects.all())
|
||||
accounts = forms.ModelMultipleChoiceField(queryset = Account.objects.all())
|
||||
|
||||
# -----
|
||||
# Transfer forms
|
||||
# -----
|
||||
|
||||
class TransferGroupForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = TransferGroup
|
||||
fields = ['comment']
|
||||
|
||||
class TransferForm(forms.ModelForm):
|
||||
from_acc = forms.ModelChoiceField(
|
||||
queryset = Account.objects.exclude(trigramme__in=['LIQ', '#13']),
|
||||
widget = forms.HiddenInput()
|
||||
)
|
||||
to_acc = forms.ModelChoiceField(
|
||||
queryset = Account.objects.exclude(trigramme__in=['LIQ', '#13']),
|
||||
widget = forms.HiddenInput()
|
||||
)
|
||||
|
||||
def clean_amount(self):
|
||||
amount = self.cleaned_data['amount']
|
||||
if amount <= 0:
|
||||
raise forms.ValidationError("Montant invalide")
|
||||
return amount
|
||||
|
||||
class Meta:
|
||||
model = Transfer
|
||||
fields = ['from_acc', 'to_acc', 'amount']
|
||||
|
||||
TransferFormSet = modelformset_factory(
|
||||
Transfer,
|
||||
form = TransferForm,
|
||||
min_num = 1, validate_min = True,
|
||||
extra = 9,
|
||||
)
|
||||
|
||||
# -----
|
||||
# Inventory forms
|
||||
# -----
|
||||
|
||||
class InventoryArticleForm(forms.Form):
|
||||
article = forms.ModelChoiceField(
|
||||
queryset = Article.objects.all(),
|
||||
widget = forms.HiddenInput(),
|
||||
)
|
||||
stock_new = forms.IntegerField(required = False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InventoryArticleForm, self).__init__(*args, **kwargs)
|
||||
if 'initial' in kwargs:
|
||||
self.name = kwargs['initial']['name']
|
||||
self.stock_old = kwargs['initial']['stock_old']
|
||||
self.category = kwargs['initial']['category']
|
||||
self.category_name = kwargs['initial']['category__name']
|
||||
|
||||
# -----
|
||||
# Order forms
|
||||
# -----
|
||||
|
||||
class OrderArticleForm(forms.Form):
|
||||
article = forms.ModelChoiceField(
|
||||
queryset = Article.objects.all(),
|
||||
widget = forms.HiddenInput(),
|
||||
)
|
||||
quantity_ordered = forms.IntegerField(required = False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OrderArticleForm, self).__init__(*args, **kwargs)
|
||||
if 'initial' in kwargs:
|
||||
self.name = kwargs['initial']['name']
|
||||
self.stock = kwargs['initial']['stock']
|
||||
self.category = kwargs['initial']['category']
|
||||
self.category_name = kwargs['initial']['category__name']
|
||||
self.box_capacity = kwargs['initial']['box_capacity']
|
||||
self.v_s1 = kwargs['initial']['v_s1']
|
||||
self.v_s2 = kwargs['initial']['v_s2']
|
||||
self.v_s3 = kwargs['initial']['v_s3']
|
||||
self.v_s4 = kwargs['initial']['v_s4']
|
||||
self.v_s5 = kwargs['initial']['v_s5']
|
||||
self.v_moy = kwargs['initial']['v_moy']
|
||||
self.v_et = kwargs['initial']['v_et']
|
||||
self.v_prev = kwargs['initial']['v_prev']
|
||||
self.c_rec = kwargs['initial']['c_rec']
|
||||
|
||||
class OrderArticleToInventoryForm(forms.Form):
|
||||
article = forms.ModelChoiceField(
|
||||
queryset = Article.objects.all(),
|
||||
widget = forms.HiddenInput(),
|
||||
)
|
||||
price_HT = forms.DecimalField(
|
||||
max_digits = 7, decimal_places = 4,
|
||||
required = False)
|
||||
TVA = forms.DecimalField(
|
||||
max_digits = 7, decimal_places = 2,
|
||||
required = False)
|
||||
rights = forms.DecimalField(
|
||||
max_digits = 7, decimal_places = 4,
|
||||
required = False)
|
||||
quantity_received = forms.IntegerField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OrderArticleToInventoryForm, self).__init__(*args, **kwargs)
|
||||
if 'initial' in kwargs:
|
||||
self.name = kwargs['initial']['name']
|
||||
self.category = kwargs['initial']['category']
|
||||
self.category_name = kwargs['initial']['category__name']
|
||||
self.quantity_ordered = kwargs['initial']['quantity_ordered']
|
17
kfet/middleware.py
Normal file
17
kfet/middleware.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from django.http import HttpResponseForbidden
|
||||
from kfet.backends import KFetBackend
|
||||
from kfet.models import Account
|
||||
|
||||
class KFetAuthenticationMiddleware(object):
|
||||
def process_request(self, request):
|
||||
kfet_backend = KFetBackend()
|
||||
temp_request_user = kfet_backend.authenticate(request)
|
||||
if temp_request_user:
|
||||
request.real_user = request.user
|
||||
request.user = temp_request_user
|
257
kfet/migrations/0001_initial.py
Normal file
257
kfet/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,257 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
import django.core.validators
|
||||
import datetime
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gestioncof', '0007_alter_club'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Account',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('trigramme', models.CharField(max_length=3, validators=[django.core.validators.RegexValidator(regex='^[^a-z]{3}$')], unique=True)),
|
||||
('balance', models.DecimalField(decimal_places=2, default=0, max_digits=6)),
|
||||
('frozen', models.BooleanField(default=False)),
|
||||
('promo', models.IntegerField(null=True, blank=True, choices=[(1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016)], default=2015)),
|
||||
('nickname', models.CharField(max_length=255, blank=True, default='')),
|
||||
('password', models.CharField(max_length=255, blank=True, null=True, unique=True, default=None)),
|
||||
('cofprofile', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='account_kfet', to='gestioncof.CofProfile')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AccountNegative',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('start', models.DateTimeField(default=datetime.datetime(2016, 8, 2, 10, 22, 1, 569492))),
|
||||
('balance_offset', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('authorized_overdraft', models.DecimalField(decimal_places=2, default=0, max_digits=6)),
|
||||
('comment', models.CharField(max_length=255, blank=True)),
|
||||
('account', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='negative', to='kfet.Account')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Article',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=45)),
|
||||
('is_sold', models.BooleanField(default=True)),
|
||||
('price', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('stock', models.IntegerField(default=0)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ArticleCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=45)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ArticleRule',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('ratio', models.PositiveSmallIntegerField()),
|
||||
('article_on', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='rule_on', to='kfet.Article')),
|
||||
('article_to', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='rule_to', to='kfet.Article')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Checkout',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=45)),
|
||||
('valid_from', models.DateTimeField()),
|
||||
('valid_to', models.DateTimeField()),
|
||||
('balance', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('is_protected', models.BooleanField(default=False)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='kfet.Account')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CheckoutTransfer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('amount', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('from_checkout', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transfers_from', to='kfet.Checkout')),
|
||||
('to_checkout', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transfers_to', to='kfet.Checkout')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Inventory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='InventoryArticle',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('stock_old', models.IntegerField()),
|
||||
('stock_new', models.IntegerField()),
|
||||
('stock_error', models.IntegerField(default=0)),
|
||||
('article', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='kfet.Article')),
|
||||
('inventory', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='kfet.Inventory')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Operation',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.CharField(max_length=8, choices=[('purchase', 'Achat'), ('deposit', 'Charge'), ('withdraw', 'Retrait')])),
|
||||
('amount', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('on_checkout', models.BooleanField(default=True)),
|
||||
('canceled_at', models.DateTimeField(blank=True, null=True, default=None)),
|
||||
('addcost_amount', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('addcost_for', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='addcosts', to='kfet.Account', null=True, default=None)),
|
||||
('article', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='operations', to='kfet.Article', null=True, default=None)),
|
||||
('canceled_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='+', to='kfet.Account', null=True, default=None)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='OperationGroup',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('at', models.DateTimeField(auto_now_add=True)),
|
||||
('amount', models.IntegerField()),
|
||||
('is_cof', models.BooleanField(default=False)),
|
||||
('comment', models.CharField(max_length=255, blank=True, default='')),
|
||||
('checkout', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='operations', to='kfet.Checkout')),
|
||||
('on_acc', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='operations', to='kfet.Account')),
|
||||
('valid_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='+', to='kfet.Account', null=True, default=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Order',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('at', models.DateTimeField(auto_now_add=True)),
|
||||
('amount', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='OrderArticle',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('quantity_ordered', models.IntegerField()),
|
||||
('quantity_received', models.IntegerField()),
|
||||
('article', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='kfet.Article')),
|
||||
('order', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='kfet.Order')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Statement',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('balance_old', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('balance_new', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('amount_taken', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('amount_error', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('at', models.DateTimeField(auto_now_add=True)),
|
||||
('by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='kfet.Account')),
|
||||
('checkout', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='statements', to='kfet.Checkout')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Supplier',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=45)),
|
||||
('address', models.TextField()),
|
||||
('email', models.EmailField(max_length=254)),
|
||||
('phone', models.CharField(max_length=10)),
|
||||
('comment', models.TextField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SupplierArticle',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('box_type', models.CharField(max_length=7, choices=[('caisse', 'Caisse'), ('carton', 'Carton'), ('palette', 'Palette'), ('fût', 'Fût')])),
|
||||
('box_capacity', models.PositiveSmallIntegerField()),
|
||||
('price_HT', models.DecimalField(decimal_places=4, max_digits=7)),
|
||||
('TVA', models.DecimalField(decimal_places=2, max_digits=4)),
|
||||
('rights', models.DecimalField(decimal_places=4, max_digits=7)),
|
||||
('article', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='kfet.Article')),
|
||||
('supplier', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='kfet.Supplier')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Transfer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('amount', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('canceled_at', models.DateTimeField(blank=True, null=True, default=None)),
|
||||
('canceled_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='+', to='kfet.Account', null=True, default=None)),
|
||||
('from_acc', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transfers_from', to='kfet.Account')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TransferGroup',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('at', models.DateTimeField(auto_now_add=True)),
|
||||
('comment', models.CharField(max_length=255, blank=True, default='')),
|
||||
('valid_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='+', to='kfet.Account', null=True, default=None)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='transfer',
|
||||
name='group',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transfers', to='kfet.TransferGroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='transfer',
|
||||
name='to_acc',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transfers_to', to='kfet.Account'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='supplier',
|
||||
name='articles',
|
||||
field=models.ManyToManyField(related_name='suppliers', through='kfet.SupplierArticle', to='kfet.Article'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='articles',
|
||||
field=models.ManyToManyField(related_name='orders', through='kfet.OrderArticle', to='kfet.Article'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='supplier',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='orders', to='kfet.Supplier'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operation',
|
||||
name='group',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='kfet.OperationGroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventory',
|
||||
name='articles',
|
||||
field=models.ManyToManyField(related_name='inventories', through='kfet.InventoryArticle', to='kfet.Article'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventory',
|
||||
name='by',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='kfet.Account'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventory',
|
||||
name='order',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, blank=True, related_name='inventory', to='kfet.Order', null=True, default=None),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='category',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='articles', to='kfet.ArticleCategory'),
|
||||
),
|
||||
]
|
24
kfet/migrations/0002_auto_20160802_2139.py
Normal file
24
kfet/migrations/0002_auto_20160802_2139.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import datetime
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='account',
|
||||
options={'permissions': (('is_team', 'Is part of the team'),)},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='start',
|
||||
field=models.DateTimeField(default=datetime.datetime(2016, 8, 2, 21, 39, 30, 52279)),
|
||||
),
|
||||
]
|
20
kfet/migrations/0003_auto_20160802_2142.py
Normal file
20
kfet/migrations/0003_auto_20160802_2142.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import datetime
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0002_auto_20160802_2139'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='start',
|
||||
field=models.DateTimeField(default=datetime.datetime.now),
|
||||
),
|
||||
]
|
19
kfet/migrations/0004_auto_20160802_2144.py
Normal file
19
kfet/migrations/0004_auto_20160802_2144.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0003_auto_20160802_2142'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='balance_offset',
|
||||
field=models.DecimalField(decimal_places=2, max_digits=6, default=0),
|
||||
),
|
||||
]
|
28
kfet/migrations/0005_auto_20160802_2154.py
Normal file
28
kfet/migrations/0005_auto_20160802_2154.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0004_auto_20160802_2144'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='GlobalPermissions',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, verbose_name='ID', auto_created=True)),
|
||||
],
|
||||
options={
|
||||
'permissions': (('is_team', 'Is part of the team'),),
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='account',
|
||||
options={},
|
||||
),
|
||||
]
|
28
kfet/migrations/0006_auto_20160804_0600.py
Normal file
28
kfet/migrations/0006_auto_20160804_0600.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0005_auto_20160802_2154'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='checkout',
|
||||
options={'ordering': ['-valid_to']},
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='account',
|
||||
old_name='frozen',
|
||||
new_name='is_frozen',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='checkout',
|
||||
name='balance',
|
||||
field=models.DecimalField(max_digits=6, default=0, decimal_places=2),
|
||||
),
|
||||
]
|
19
kfet/migrations/0007_auto_20160804_0641.py
Normal file
19
kfet/migrations/0007_auto_20160804_0641.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0006_auto_20160804_0600'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='price',
|
||||
field=models.DecimalField(default=0, max_digits=6, decimal_places=2),
|
||||
),
|
||||
]
|
20
kfet/migrations/0008_auto_20160804_1736.py
Normal file
20
kfet/migrations/0008_auto_20160804_1736.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0007_auto_20160804_0641'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='trigramme',
|
||||
field=models.CharField(unique=True, validators=[django.core.validators.RegexValidator(regex='^[^a-z]{3}$')], db_index=True, max_length=3),
|
||||
),
|
||||
]
|
24
kfet/migrations/0009_auto_20160805_0720.py
Normal file
24
kfet/migrations/0009_auto_20160805_0720.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0008_auto_20160804_1736'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='operation',
|
||||
old_name='on_checkout',
|
||||
new_name='is_checkout',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operation',
|
||||
name='article_nb',
|
||||
field=models.PositiveSmallIntegerField(default=None, null=True, blank=True),
|
||||
),
|
||||
]
|
30
kfet/migrations/0010_auto_20160806_2343.py
Normal file
30
kfet/migrations/0010_auto_20160806_2343.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0009_auto_20160805_0720'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='operation',
|
||||
name='addcost_amount',
|
||||
field=models.DecimalField(max_digits=6, default=0, decimal_places=2),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationgroup',
|
||||
name='amount',
|
||||
field=models.DecimalField(max_digits=6, default=0, decimal_places=2),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationgroup',
|
||||
name='valid_by',
|
||||
field=models.ForeignKey(default=None, related_name='+', to='kfet.Account', blank=True, null=True, on_delete=django.db.models.deletion.PROTECT),
|
||||
),
|
||||
]
|
19
kfet/migrations/0011_auto_20160807_1720.py
Normal file
19
kfet/migrations/0011_auto_20160807_1720.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0010_auto_20160806_2343'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='operation',
|
||||
name='amount',
|
||||
field=models.DecimalField(decimal_places=2, max_digits=6, default=0, blank=True),
|
||||
),
|
||||
]
|
22
kfet/migrations/0012_settings.py
Normal file
22
kfet/migrations/0012_settings.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0011_auto_20160807_1720'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Settings',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=45)),
|
||||
('value_decimal', models.DecimalField(null=True, max_digits=6, decimal_places=2, blank=True, default=None)),
|
||||
],
|
||||
),
|
||||
]
|
19
kfet/migrations/0013_auto_20160807_1840.py
Normal file
19
kfet/migrations/0013_auto_20160807_1840.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0012_settings'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='settings',
|
||||
name='name',
|
||||
field=models.CharField(unique=True, max_length=45),
|
||||
),
|
||||
]
|
18
kfet/migrations/0014_auto_20160807_2314.py
Normal file
18
kfet/migrations/0014_auto_20160807_2314.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0013_auto_20160807_1840'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('can_perform_deposit', 'Peut effectuer une charge')), 'managed': False},
|
||||
),
|
||||
]
|
18
kfet/migrations/0015_auto_20160807_2324.py
Normal file
18
kfet/migrations/0015_auto_20160807_2324.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0014_auto_20160807_2314'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('can_perform_deposit', 'Peut effectuer une charge'), ('can_perform_negative_operations', 'Peut enregistrer des commandes en négatif')), 'managed': False},
|
||||
),
|
||||
]
|
20
kfet/migrations/0016_settings_value_account.py
Normal file
20
kfet/migrations/0016_settings_value_account.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0015_auto_20160807_2324'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='settings',
|
||||
name='value_account',
|
||||
field=models.ForeignKey(to='kfet.Account', on_delete=django.db.models.deletion.PROTECT, default=None, null=True, blank=True),
|
||||
),
|
||||
]
|
19
kfet/migrations/0017_auto_20160808_0234.py
Normal file
19
kfet/migrations/0017_auto_20160808_0234.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0016_settings_value_account'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='operation',
|
||||
name='addcost_amount',
|
||||
field=models.DecimalField(blank=True, null=True, decimal_places=2, default=None, max_digits=6),
|
||||
),
|
||||
]
|
18
kfet/migrations/0018_auto_20160808_0341.py
Normal file
18
kfet/migrations/0018_auto_20160808_0341.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0017_auto_20160808_0234'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('can_perform_deposit', 'Effectuer une charge'), ('can_perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte")), 'managed': False},
|
||||
),
|
||||
]
|
18
kfet/migrations/0019_auto_20160808_0343.py
Normal file
18
kfet/migrations/0019_auto_20160808_0343.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0018_auto_20160808_0341'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'managed': False, 'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"))},
|
||||
),
|
||||
]
|
20
kfet/migrations/0020_auto_20160808_0450.py
Normal file
20
kfet/migrations/0020_auto_20160808_0450.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import datetime
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0019_auto_20160808_0343'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='start',
|
||||
field=models.DateTimeField(default=datetime.datetime.now, blank=True, null=True),
|
||||
),
|
||||
]
|
19
kfet/migrations/0021_auto_20160808_0506.py
Normal file
19
kfet/migrations/0021_auto_20160808_0506.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0020_auto_20160808_0450'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='start',
|
||||
field=models.DateTimeField(default=None, blank=True, null=True),
|
||||
),
|
||||
]
|
24
kfet/migrations/0022_auto_20160808_0512.py
Normal file
24
kfet/migrations/0022_auto_20160808_0512.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0021_auto_20160808_0506'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='authorized_overdraft',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, null=True, default=None, max_digits=6),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='accountnegative',
|
||||
name='balance_offset',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, null=True, default=None, max_digits=6),
|
||||
),
|
||||
]
|
24
kfet/migrations/0023_auto_20160808_0535.py
Normal file
24
kfet/migrations/0023_auto_20160808_0535.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0022_auto_20160808_0512'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='accountnegative',
|
||||
old_name='authorized_overdraft',
|
||||
new_name='authz_overdraft_amount',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='accountnegative',
|
||||
name='authz_overdraft_until',
|
||||
field=models.DateTimeField(null=True, default=None, blank=True),
|
||||
),
|
||||
]
|
19
kfet/migrations/0024_settings_value_duration.py
Normal file
19
kfet/migrations/0024_settings_value_duration.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0023_auto_20160808_0535'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='settings',
|
||||
name='value_duration',
|
||||
field=models.DurationField(null=True, default=None, blank=True),
|
||||
),
|
||||
]
|
18
kfet/migrations/0025_auto_20160809_0750.py
Normal file
18
kfet/migrations/0025_auto_20160809_0750.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0024_settings_value_duration'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes')), 'managed': False},
|
||||
),
|
||||
]
|
19
kfet/migrations/0026_auto_20160809_0810.py
Normal file
19
kfet/migrations/0026_auto_20160809_0810.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0025_auto_20160809_0750'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='settings',
|
||||
name='name',
|
||||
field=models.CharField(db_index=True, max_length=45, unique=True),
|
||||
),
|
||||
]
|
39
kfet/migrations/0027_auto_20160811_0648.py
Normal file
39
kfet/migrations/0027_auto_20160811_0648.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0026_auto_20160809_0810'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CheckoutStatement',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
|
||||
('balance_old', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('balance_new', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('amount_taken', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('amount_error', models.DecimalField(decimal_places=2, max_digits=6)),
|
||||
('at', models.DateTimeField(auto_now_add=True)),
|
||||
('by', models.ForeignKey(to='kfet.Account', on_delete=django.db.models.deletion.PROTECT, related_name='+')),
|
||||
('checkout', models.ForeignKey(to='kfet.Checkout', on_delete=django.db.models.deletion.PROTECT, related_name='statements')),
|
||||
],
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='statement',
|
||||
name='by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='statement',
|
||||
name='checkout',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Statement',
|
||||
),
|
||||
]
|
30
kfet/migrations/0028_auto_20160820_0146.py
Normal file
30
kfet/migrations/0028_auto_20160820_0146.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0027_auto_20160811_0648'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='operation',
|
||||
name='group',
|
||||
field=models.ForeignKey(to='kfet.OperationGroup', on_delete=django.db.models.deletion.PROTECT, related_name='opes'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationgroup',
|
||||
name='checkout',
|
||||
field=models.ForeignKey(to='kfet.Checkout', on_delete=django.db.models.deletion.PROTECT, related_name='opesgroup'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationgroup',
|
||||
name='on_acc',
|
||||
field=models.ForeignKey(to='kfet.Account', on_delete=django.db.models.deletion.PROTECT, related_name='opesgroup'),
|
||||
),
|
||||
]
|
21
kfet/migrations/0029_genericteamtoken.py
Normal file
21
kfet/migrations/0029_genericteamtoken.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0028_auto_20160820_0146'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='GenericTeamToken',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
|
||||
('token', models.CharField(unique=True, max_length=50)),
|
||||
],
|
||||
),
|
||||
]
|
18
kfet/migrations/0030_auto_20160821_0029.py
Normal file
18
kfet/migrations/0030_auto_20160821_0029.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0029_genericteamtoken'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes'), ('manage_perms', 'Gérer les permissions K-Fêt')), 'managed': False},
|
||||
),
|
||||
]
|
18
kfet/migrations/0031_auto_20160822_0523.py
Normal file
18
kfet/migrations/0031_auto_20160822_0523.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0030_auto_20160821_0029'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes'), ('manage_perms', 'Gérer les permissions K-Fêt'), ('manage_addcosts', 'Gérer les majorations')), 'managed': False},
|
||||
),
|
||||
]
|
94
kfet/migrations/0032_auto_20160822_2350.py
Normal file
94
kfet/migrations/0032_auto_20160822_2350.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0031_auto_20160822_0523'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_001',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_002',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_005',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_01',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_02',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_05',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_1',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_10',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_100',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_2',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_20',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_200',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_5',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_50',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_500',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_cheque',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
]
|
19
kfet/migrations/0033_checkoutstatement_not_count.py
Normal file
19
kfet/migrations/0033_checkoutstatement_not_count.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0032_auto_20160822_2350'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='checkoutstatement',
|
||||
name='not_count',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
19
kfet/migrations/0034_auto_20160823_0206.py
Normal file
19
kfet/migrations/0034_auto_20160823_0206.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0033_checkoutstatement_not_count'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='checkoutstatement',
|
||||
name='taken_cheque',
|
||||
field=models.DecimalField(max_digits=6, decimal_places=2, default=0),
|
||||
),
|
||||
]
|
18
kfet/migrations/0035_auto_20160823_1505.py
Normal file
18
kfet/migrations/0035_auto_20160823_1505.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0034_auto_20160823_0206'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'managed': False, 'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes'), ('manage_perms', 'Gérer les permissions K-Fêt'), ('manage_addcosts', 'Gérer les majorations'), ('perform_commented_operations', 'Enregistrer des commandes avec commentaires'))},
|
||||
),
|
||||
]
|
18
kfet/migrations/0036_auto_20160823_1910.py
Normal file
18
kfet/migrations/0036_auto_20160823_1910.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0035_auto_20160823_1505'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'managed': False, 'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes'), ('manage_perms', 'Gérer les permissions K-Fêt'), ('manage_addcosts', 'Gérer les majorations'), ('perform_commented_operations', 'Enregistrer des commandes avec commentaires'), ('view_negs', 'Voir la liste des négatifs'))},
|
||||
),
|
||||
]
|
39
kfet/migrations/0037_auto_20160826_2333.py
Normal file
39
kfet/migrations/0037_auto_20160826_2333.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0036_auto_20160823_1910'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='supplierarticle',
|
||||
name='TVA',
|
||||
field=models.DecimalField(null=True, max_digits=4, decimal_places=2, default=None, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='supplierarticle',
|
||||
name='box_capacity',
|
||||
field=models.PositiveSmallIntegerField(null=True, default=None, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='supplierarticle',
|
||||
name='box_type',
|
||||
field=models.CharField(null=True, max_length=7, choices=[('caisse', 'Caisse'), ('carton', 'Carton'), ('palette', 'Palette'), ('fût', 'Fût')], default=None, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='supplierarticle',
|
||||
name='price_HT',
|
||||
field=models.DecimalField(null=True, max_digits=7, decimal_places=4, default=None, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='supplierarticle',
|
||||
name='rights',
|
||||
field=models.DecimalField(null=True, max_digits=7, decimal_places=4, default=None, blank=True),
|
||||
),
|
||||
]
|
36
kfet/migrations/0038_auto_20160828_0402.py
Normal file
36
kfet/migrations/0038_auto_20160828_0402.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0037_auto_20160826_2333'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='inventory',
|
||||
options={'ordering': ['-at']},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='supplierarticle',
|
||||
name='box_capacity',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='supplierarticle',
|
||||
name='box_type',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='box_capacity',
|
||||
field=models.PositiveSmallIntegerField(blank=True, null=True, default=None),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='box_type',
|
||||
field=models.CharField(max_length=7, blank=True, null=True, default=None, choices=[('caisse', 'Caisse'), ('carton', 'Carton'), ('palette', 'Palette'), ('fût', 'Fût')]),
|
||||
),
|
||||
]
|
24
kfet/migrations/0039_auto_20160828_0430.py
Normal file
24
kfet/migrations/0039_auto_20160828_0430.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0038_auto_20160828_0402'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='amount',
|
||||
field=models.DecimalField(default=0, decimal_places=2, max_digits=6),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='orderarticle',
|
||||
name='quantity_received',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
31
kfet/migrations/0040_auto_20160829_2035.py
Normal file
31
kfet/migrations/0040_auto_20160829_2035.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import datetime
|
||||
from django.utils.timezone import utc
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0039_auto_20160828_0430'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='order',
|
||||
options={'ordering': ['-at']},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='supplierarticle',
|
||||
name='at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 8, 29, 18, 35, 3, 419033, tzinfo=utc)),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='box_type',
|
||||
field=models.CharField(choices=[('caisse', 'caisse'), ('carton', 'carton'), ('palette', 'palette'), ('fût', 'fût')], null=True, max_length=7, blank=True, default=None),
|
||||
),
|
||||
]
|
18
kfet/migrations/0041_auto_20160830_1502.py
Normal file
18
kfet/migrations/0041_auto_20160830_1502.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0040_auto_20160829_2035'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes'), ('manage_perms', 'Gérer les permissions K-Fêt'), ('manage_addcosts', 'Gérer les majorations'), ('perform_commented_operations', 'Enregistrer des commandes avec commentaires'), ('view_negs', 'Voir la liste des négatifs'), ('order_to_inventory', "Générer un inventaire à partir d'une commande")), 'managed': False},
|
||||
),
|
||||
]
|
18
kfet/migrations/0042_auto_20160831_0126.py
Normal file
18
kfet/migrations/0042_auto_20160831_0126.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0041_auto_20160830_1502'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'managed': False, 'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en négatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non récentes'), ('manage_perms', 'Gérer les permissions K-Fêt'), ('manage_addcosts', 'Gérer les majorations'), ('perform_commented_operations', 'Enregistrer des commandes avec commentaires'), ('view_negs', 'Voir la liste des négatifs'), ('order_to_inventory', "Générer un inventaire à partir d'une commande"), ('edit_balance_account', "Modifier la balance d'un compte"))},
|
||||
),
|
||||
]
|
19
kfet/migrations/0043_auto_20160901_0046.py
Normal file
19
kfet/migrations/0043_auto_20160901_0046.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0042_auto_20160831_0126'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='promo',
|
||||
field=models.IntegerField(blank=True, default=2016, null=True, choices=[(1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016)]),
|
||||
),
|
||||
]
|
18
kfet/migrations/0044_auto_20160901_1614.py
Normal file
18
kfet/migrations/0044_auto_20160901_1614.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0043_auto_20160901_0046'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'managed': False, 'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en n\xe9gatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non r\xe9centes'), ('manage_perms', 'G\xe9rer les permissions K-F\xeat'), ('manage_addcosts', 'G\xe9rer les majorations'), ('perform_commented_operations', 'Enregistrer des commandes avec commentaires'), ('view_negs', 'Voir la liste des n\xe9gatifs'), ('order_to_inventory', "G\xe9n\xe9rer un inventaire \xe0 partir d'une commande"), ('edit_balance_account', "Modifier la balance d'un compte"), ('change_account_password', "Modifier le mot de passe d'une personne de l'\xe9quipe"))},
|
||||
),
|
||||
]
|
23
kfet/migrations/0045_auto_20160905_0705.py
Normal file
23
kfet/migrations/0045_auto_20160905_0705.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0044_auto_20160901_1614'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='globalpermissions',
|
||||
options={'managed': False, 'permissions': (('is_team', 'Is part of the team'), ('perform_deposit', 'Effectuer une charge'), ('perform_negative_operations', 'Enregistrer des commandes en n\xe9gatif'), ('override_frozen_protection', "Forcer le gel d'un compte"), ('cancel_old_operations', 'Annuler des commandes non r\xe9centes'), ('manage_perms', 'G\xe9rer les permissions K-F\xeat'), ('manage_addcosts', 'G\xe9rer les majorations'), ('perform_commented_operations', 'Enregistrer des commandes avec commentaires'), ('view_negs', 'Voir la liste des n\xe9gatifs'), ('order_to_inventory', "G\xe9n\xe9rer un inventaire \xe0 partir d'une commande"), ('edit_balance_account', "Modifier la balance d'un compte"), ('change_account_password', "Modifier le mot de passe d'une personne de l'\xe9quipe"), ('special_add_account', 'Cr\xe9er un compte avec une balance initiale'))},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operation',
|
||||
name='type',
|
||||
field=models.CharField(max_length=8, choices=[('purchase', 'Achat'), ('deposit', 'Charge'), ('withdraw', 'Retrait'), ('initial', 'Initial')]),
|
||||
),
|
||||
]
|
19
kfet/migrations/0046_account_created_at.py
Normal file
19
kfet/migrations/0046_account_created_at.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0045_auto_20160905_0705'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='account',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, null=True),
|
||||
),
|
||||
]
|
0
kfet/migrations/__init__.py
Normal file
0
kfet/migrations/__init__.py
Normal file
684
kfet/models.py
Normal file
684
kfet/models.py
Normal file
|
@ -0,0 +1,684 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from django.db import models
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import PermissionDenied, ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.contrib.auth.models import User
|
||||
from gestioncof.models import CofProfile
|
||||
from django.utils.six.moves import reduce
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.db import transaction
|
||||
from django.db.models import F
|
||||
from django.core.cache import cache
|
||||
from datetime import date, timedelta
|
||||
import re
|
||||
|
||||
def choices_length(choices):
|
||||
return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0)
|
||||
|
||||
def default_promo():
|
||||
now = date.today()
|
||||
return now.month <= 8 and now.year-1 or now.year
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Account(models.Model):
|
||||
cofprofile = models.OneToOneField(
|
||||
CofProfile, on_delete = models.PROTECT,
|
||||
related_name = "account_kfet")
|
||||
trigramme = models.CharField(
|
||||
unique = True,
|
||||
max_length = 3,
|
||||
validators = [RegexValidator(regex='^[^a-z]{3}$')],
|
||||
db_index = True)
|
||||
balance = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
is_frozen = models.BooleanField(default = False)
|
||||
created_at = models.DateTimeField(auto_now_add = True, null = True)
|
||||
# Optional
|
||||
PROMO_CHOICES = [(r,r) for r in range(1980, date.today().year+1)]
|
||||
promo = models.IntegerField(
|
||||
choices = PROMO_CHOICES,
|
||||
blank = True, null = True, default = default_promo())
|
||||
nickname = models.CharField(
|
||||
max_length = 255,
|
||||
blank = True, default = "")
|
||||
password = models.CharField(
|
||||
max_length = 255,
|
||||
unique = True,
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
def __str__(self):
|
||||
return '%s (%s)' % (self.trigramme, self.name)
|
||||
|
||||
# Propriétés pour accéder aux attributs de user et cofprofile et user
|
||||
@property
|
||||
def user(self):
|
||||
return self.cofprofile.user
|
||||
@property
|
||||
def username(self):
|
||||
return self.cofprofile.user.username
|
||||
@property
|
||||
def first_name(self):
|
||||
return self.cofprofile.user.first_name
|
||||
@property
|
||||
def last_name(self):
|
||||
return self.cofprofile.user.last_name
|
||||
@property
|
||||
def email(self):
|
||||
return self.cofprofile.user.email
|
||||
@property
|
||||
def departement(self):
|
||||
return self.cofprofile.departement
|
||||
@property
|
||||
def is_cof(self):
|
||||
return self.cofprofile.is_cof
|
||||
|
||||
# Propriétés supplémentaires
|
||||
@property
|
||||
def real_balance(self):
|
||||
if (hasattr(self, 'negative')):
|
||||
return self.balance - self.negative.balance_offset
|
||||
return self.balance
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.user.get_full_name()
|
||||
|
||||
@property
|
||||
def is_cash(self):
|
||||
return self.trigramme == 'LIQ'
|
||||
|
||||
@property
|
||||
def need_comment(self):
|
||||
return self.trigramme == '#13'
|
||||
|
||||
@staticmethod
|
||||
def is_validandfree(trigramme):
|
||||
data = { 'is_valid' : False, 'is_free' : False }
|
||||
pattern = re.compile("^[^a-z]{3}$")
|
||||
data['is_valid'] = pattern.match(trigramme) and True or False
|
||||
try:
|
||||
account = Account.objects.get(trigramme=trigramme)
|
||||
except Account.DoesNotExist:
|
||||
data['is_free'] = True
|
||||
return data
|
||||
|
||||
def perms_to_perform_operation(self, amount):
|
||||
overdraft_duration_max = Settings.OVERDRAFT_DURATION()
|
||||
overdraft_amount_max = Settings.OVERDRAFT_AMOUNT()
|
||||
perms = set()
|
||||
stop_ope = False
|
||||
# Checking is cash account
|
||||
if self.is_cash:
|
||||
# Yes, so no perms and no stop
|
||||
return set(), False
|
||||
if self.need_comment:
|
||||
perms.add('kfet.perform_commented_operations')
|
||||
# Checking is frozen account
|
||||
if self.is_frozen:
|
||||
perms.add('kfet.override_frozen_protection')
|
||||
new_balance = self.balance + amount
|
||||
if new_balance < 0 and amount < 0:
|
||||
# Retrieving overdraft amount limit
|
||||
if (hasattr(self, 'negative')
|
||||
and self.negative.authz_overdraft_amount is not None):
|
||||
overdraft_amount = - self.negative.authz_overdraft_amount
|
||||
else:
|
||||
overdraft_amount = - overdraft_amount_max
|
||||
# Retrieving overdraft datetime limit
|
||||
if (hasattr(self, 'negative')
|
||||
and self.negative.authz_overdraft_until is not None):
|
||||
overdraft_until = self.negative.authz_overdraft_until
|
||||
elif hasattr(self, 'negative'):
|
||||
overdraft_until = \
|
||||
self.negative.start + overdraft_duration_max
|
||||
else:
|
||||
overdraft_until = timezone.now() + overdraft_duration_max
|
||||
# Checking it doesn't break 1 rule
|
||||
if new_balance < overdraft_amount or timezone.now() > overdraft_until:
|
||||
stop_ope = True
|
||||
perms.add('kfet.perform_negative_operations')
|
||||
return perms, stop_ope
|
||||
|
||||
# Surcharge Méthode save() avec gestions de User et CofProfile
|
||||
# Args:
|
||||
# - data : datas pour User et CofProfile
|
||||
# Action:
|
||||
# - Enregistre User, CofProfile à partir de "data"
|
||||
# - Enregistre Account
|
||||
def save(self, data = {}, *args, **kwargs):
|
||||
if self.pk and data:
|
||||
# Account update
|
||||
|
||||
# Updating User with data
|
||||
user = self.user
|
||||
user.first_name = data.get("first_name", user.first_name)
|
||||
user.last_name = data.get("last_name", user.last_name)
|
||||
user.email = data.get("email", user.email)
|
||||
user.save()
|
||||
# Updating CofProfile with data
|
||||
cof = self.cofprofile
|
||||
cof.departement = data.get("departement", cof.departement)
|
||||
cof.save()
|
||||
elif data:
|
||||
# New account
|
||||
|
||||
# Checking if user has already an account
|
||||
username = data.get("username")
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
if hasattr(user.profile, "account_kfet"):
|
||||
trigramme = user.profile.account_kfet.trigramme
|
||||
raise Account.UserHasAccount(trigramme)
|
||||
except User.DoesNotExist:
|
||||
pass
|
||||
|
||||
# Creating or updating User instance
|
||||
(user, _) = User.objects.get_or_create(username=username)
|
||||
if "first_name" in data:
|
||||
user.first_name = data['first_name']
|
||||
if "last_name" in data:
|
||||
user.last_name = data['last_name']
|
||||
if "email" in data:
|
||||
user.email = data['email']
|
||||
user.save()
|
||||
# Creating or updating CofProfile instance
|
||||
(cof, _) = CofProfile.objects.get_or_create(user=user)
|
||||
if "login_clipper" in data:
|
||||
cof.login_clipper = data['login_clipper']
|
||||
if "departement" in data:
|
||||
cof.departement = data['departement']
|
||||
cof.save()
|
||||
if data:
|
||||
self.cofprofile = cof
|
||||
super(Account, self).save(*args, **kwargs)
|
||||
|
||||
# Surcharge de delete
|
||||
# Pas de suppression possible
|
||||
# Cas à régler plus tard
|
||||
def delete(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
class UserHasAccount(Exception):
|
||||
def __init__(self, trigramme):
|
||||
self.trigramme = trigramme
|
||||
|
||||
class AccountNegative(models.Model):
|
||||
account = models.OneToOneField(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "negative")
|
||||
start = models.DateTimeField(
|
||||
blank = True, null = True, default = None)
|
||||
balance_offset = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
blank = True, null = True, default = None)
|
||||
authz_overdraft_amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
blank = True, null = True, default = None)
|
||||
authz_overdraft_until = models.DateTimeField(
|
||||
blank = True, null = True, default = None)
|
||||
comment = models.CharField(max_length = 255, blank = True)
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Checkout(models.Model):
|
||||
created_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+")
|
||||
name = models.CharField(max_length = 45)
|
||||
valid_from = models.DateTimeField()
|
||||
valid_to = models.DateTimeField()
|
||||
balance = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
is_protected = models.BooleanField(default = False)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('kfet.checkout.read', kwargs={'pk': self.pk})
|
||||
|
||||
class Meta:
|
||||
ordering = ['-valid_to']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class CheckoutTransfer(models.Model):
|
||||
from_checkout = models.ForeignKey(
|
||||
Checkout, on_delete = models.PROTECT,
|
||||
related_name = "transfers_from")
|
||||
to_checkout = models.ForeignKey(
|
||||
Checkout, on_delete = models.PROTECT,
|
||||
related_name = "transfers_to")
|
||||
amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2)
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class CheckoutStatement(models.Model):
|
||||
by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+")
|
||||
checkout = models.ForeignKey(
|
||||
Checkout, on_delete = models.PROTECT,
|
||||
related_name = "statements")
|
||||
balance_old = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
balance_new = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
amount_taken = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
amount_error = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
not_count = models.BooleanField(default=False)
|
||||
|
||||
taken_001 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_002 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_005 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_01 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_02 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_05 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_1 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_2 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_5 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_10 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_20 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_50 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_100 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_200 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_500 = models.PositiveSmallIntegerField(default=0)
|
||||
taken_cheque = models.DecimalField(default=0, max_digits=6, decimal_places=2)
|
||||
|
||||
def __str__(self):
|
||||
return '%s %s' % (self.checkout, self.at)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.pk:
|
||||
checkout_id = self.checkout_id
|
||||
self.balance_old = (Checkout.objects
|
||||
.values_list('balance', flat=True).get(pk=checkout_id))
|
||||
if self.not_count:
|
||||
self.balance_new = self.balance_old - self.amount_taken
|
||||
self.amount_error = (
|
||||
self.balance_new + self.amount_taken - self.balance_old)
|
||||
with transaction.atomic():
|
||||
Checkout.objects.filter(pk=checkout_id).update(balance=self.balance_new)
|
||||
super(CheckoutStatement, self).save(*args, **kwargs)
|
||||
else:
|
||||
self.amount_error = (
|
||||
self.balance_new + self.amount_taken - self.balance_old)
|
||||
# Si on modifie le dernier relevé d'une caisse et que la nouvelle
|
||||
# balance est modifiée alors on modifie la balance actuelle de la caisse
|
||||
last_statement = (CheckoutStatement.objects
|
||||
.filter(checkout=self.checkout)
|
||||
.order_by('at')
|
||||
.last())
|
||||
if (last_statement.pk == self.pk
|
||||
and last_statement.balance_new != self.balance_new):
|
||||
Checkout.objects.filter(pk=self.checkout_id).update(
|
||||
balance=F('balance') - last_statement.balance_new + self.balance_new)
|
||||
super(CheckoutStatement, self).save(*args, **kwargs)
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class ArticleCategory(models.Model):
|
||||
name = models.CharField(max_length = 45)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Article(models.Model):
|
||||
name = models.CharField(max_length = 45)
|
||||
is_sold = models.BooleanField(default = True)
|
||||
price = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
stock = models.IntegerField(default = 0)
|
||||
category = models.ForeignKey(
|
||||
ArticleCategory, on_delete = models.PROTECT,
|
||||
related_name = "articles")
|
||||
BOX_TYPE_CHOICES = (
|
||||
("caisse", "caisse"),
|
||||
("carton", "carton"),
|
||||
("palette", "palette"),
|
||||
("fût", "fût"),
|
||||
)
|
||||
box_type = models.CharField(
|
||||
choices = BOX_TYPE_CHOICES,
|
||||
max_length = choices_length(BOX_TYPE_CHOICES),
|
||||
blank = True, null = True, default = None)
|
||||
box_capacity = models.PositiveSmallIntegerField(
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
def __str__(self):
|
||||
return '%s - %s' % (self.category.name, self.name)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('kfet.article.read', kwargs={'pk': self.pk})
|
||||
|
||||
class ArticleRule(models.Model):
|
||||
article_on = models.OneToOneField(
|
||||
Article, on_delete = models.PROTECT,
|
||||
related_name = "rule_on")
|
||||
article_to = models.OneToOneField(
|
||||
Article, on_delete = models.PROTECT,
|
||||
related_name = "rule_to")
|
||||
ratio = models.PositiveSmallIntegerField()
|
||||
|
||||
class Inventory(models.Model):
|
||||
articles = models.ManyToManyField(
|
||||
Article,
|
||||
through = 'InventoryArticle',
|
||||
related_name = "inventories")
|
||||
by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+")
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
# Optional
|
||||
order = models.OneToOneField(
|
||||
'Order', on_delete = models.PROTECT,
|
||||
related_name = "inventory",
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-at']
|
||||
|
||||
class InventoryArticle(models.Model):
|
||||
inventory = models.ForeignKey(
|
||||
Inventory, on_delete = models.PROTECT)
|
||||
article = models.ForeignKey(
|
||||
Article, on_delete = models.PROTECT)
|
||||
stock_old = models.IntegerField()
|
||||
stock_new = models.IntegerField()
|
||||
stock_error = models.IntegerField(default = 0)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# S'il s'agit d'un inventaire provenant d'une livraison, il n'y a pas
|
||||
# d'erreur
|
||||
if not self.inventory.order:
|
||||
self.stock_error = self.stock_new - self.stock_old
|
||||
super(InventoryArticle, self).save(*args, **kwargs)
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Supplier(models.Model):
|
||||
articles = models.ManyToManyField(
|
||||
Article,
|
||||
through = 'SupplierArticle',
|
||||
related_name = "suppliers")
|
||||
name = models.CharField(max_length = 45)
|
||||
address = models.TextField()
|
||||
email = models.EmailField()
|
||||
phone = models.CharField(max_length = 10)
|
||||
comment = models.TextField()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class SupplierArticle(models.Model):
|
||||
supplier = models.ForeignKey(
|
||||
Supplier, on_delete = models.PROTECT)
|
||||
article = models.ForeignKey(
|
||||
Article, on_delete = models.PROTECT)
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
price_HT = models.DecimalField(
|
||||
max_digits = 7, decimal_places = 4,
|
||||
blank = True, null = True, default = None)
|
||||
TVA = models.DecimalField(
|
||||
max_digits = 4, decimal_places = 2,
|
||||
blank = True, null = True, default = None)
|
||||
rights = models.DecimalField(
|
||||
max_digits = 7, decimal_places = 4,
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
class Order(models.Model):
|
||||
supplier = models.ForeignKey(
|
||||
Supplier, on_delete = models.PROTECT,
|
||||
related_name = "orders")
|
||||
articles = models.ManyToManyField(
|
||||
Article,
|
||||
through = "OrderArticle",
|
||||
related_name = "orders")
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2, default = 0)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-at']
|
||||
|
||||
class OrderArticle(models.Model):
|
||||
order = models.ForeignKey(
|
||||
Order, on_delete = models.PROTECT)
|
||||
article = models.ForeignKey(
|
||||
Article, on_delete = models.PROTECT)
|
||||
quantity_ordered = models.IntegerField()
|
||||
quantity_received = models.IntegerField(default = 0)
|
||||
|
||||
class TransferGroup(models.Model):
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
# Optional
|
||||
comment = models.CharField(
|
||||
max_length = 255,
|
||||
blank = True, default = "")
|
||||
valid_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+",
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
class Transfer(models.Model):
|
||||
group = models.ForeignKey(
|
||||
TransferGroup, on_delete = models.PROTECT,
|
||||
related_name = "transfers")
|
||||
from_acc = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "transfers_from")
|
||||
to_acc = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "transfers_to")
|
||||
amount = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
# Optional
|
||||
canceled_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
null = True, blank = True, default = None,
|
||||
related_name = "+")
|
||||
canceled_at = models.DateTimeField(
|
||||
null = True, blank = True, default = None)
|
||||
|
||||
class OperationGroup(models.Model):
|
||||
on_acc = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "opesgroup")
|
||||
checkout = models.ForeignKey(
|
||||
Checkout, on_delete = models.PROTECT,
|
||||
related_name = "opesgroup")
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
is_cof = models.BooleanField(default = False)
|
||||
# Optional
|
||||
comment = models.CharField(
|
||||
max_length = 255,
|
||||
blank = True, default = "")
|
||||
valid_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+",
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
class Operation(models.Model):
|
||||
PURCHASE = 'purchase'
|
||||
DEPOSIT = 'deposit'
|
||||
WITHDRAW = 'withdraw'
|
||||
INITIAL = 'initial'
|
||||
|
||||
TYPE_ORDER_CHOICES = (
|
||||
(PURCHASE, 'Achat'),
|
||||
(DEPOSIT, 'Charge'),
|
||||
(WITHDRAW, 'Retrait'),
|
||||
(INITIAL, 'Initial'),
|
||||
)
|
||||
|
||||
group = models.ForeignKey(
|
||||
OperationGroup, on_delete = models.PROTECT,
|
||||
related_name = "opes")
|
||||
type = models.CharField(
|
||||
choices = TYPE_ORDER_CHOICES,
|
||||
max_length = choices_length(TYPE_ORDER_CHOICES))
|
||||
amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
blank = True, default = 0)
|
||||
is_checkout = models.BooleanField(default = True)
|
||||
# Optional
|
||||
article = models.ForeignKey(
|
||||
Article, on_delete = models.PROTECT,
|
||||
related_name = "operations",
|
||||
blank = True, null = True, default = None)
|
||||
article_nb = models.PositiveSmallIntegerField(
|
||||
blank = True, null = True, default = None)
|
||||
canceled_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+",
|
||||
blank = True, null = True, default = None)
|
||||
canceled_at = models.DateTimeField(
|
||||
blank = True, null = True, default = None)
|
||||
addcost_for = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "addcosts",
|
||||
blank = True, null = True, default = None)
|
||||
addcost_amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
class GlobalPermissions(models.Model):
|
||||
class Meta:
|
||||
managed = False
|
||||
permissions = (
|
||||
('is_team', 'Is part of the team'),
|
||||
('perform_deposit', 'Effectuer une charge'),
|
||||
('perform_negative_operations',
|
||||
'Enregistrer des commandes en négatif'),
|
||||
('override_frozen_protection', "Forcer le gel d'un compte"),
|
||||
('cancel_old_operations', 'Annuler des commandes non récentes'),
|
||||
('manage_perms', 'Gérer les permissions K-Fêt'),
|
||||
('manage_addcosts', 'Gérer les majorations'),
|
||||
('perform_commented_operations', 'Enregistrer des commandes avec commentaires'),
|
||||
('view_negs', 'Voir la liste des négatifs'),
|
||||
('order_to_inventory', "Générer un inventaire à partir d'une commande"),
|
||||
('edit_balance_account', "Modifier la balance d'un compte"),
|
||||
('change_account_password', "Modifier le mot de passe d'une personne de l'équipe"),
|
||||
('special_add_account', "Créer un compte avec une balance initiale")
|
||||
)
|
||||
|
||||
class Settings(models.Model):
|
||||
name = models.CharField(
|
||||
max_length = 45,
|
||||
unique = True,
|
||||
db_index = True)
|
||||
value_decimal = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
blank = True, null = True, default = None)
|
||||
value_account = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
blank = True, null = True, default = None)
|
||||
value_duration = models.DurationField(
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
@staticmethod
|
||||
def setting_inst(name):
|
||||
return Settings.objects.get(name=name)
|
||||
|
||||
@staticmethod
|
||||
def SUBVENTION_COF():
|
||||
subvention_cof = cache.get('SUBVENTION_COF')
|
||||
if subvention_cof:
|
||||
return subvention_cof
|
||||
try:
|
||||
subvention_cof = Settings.setting_inst("SUBVENTION_COF").value_decimal
|
||||
except Settings.DoesNotExist:
|
||||
subvention_cof = 0
|
||||
cache.set('SUBVENTION_COF', subvention_cof)
|
||||
return subvention_cof
|
||||
|
||||
@staticmethod
|
||||
def ADDCOST_AMOUNT():
|
||||
try:
|
||||
return Settings.setting_inst("ADDCOST_AMOUNT").value_decimal
|
||||
except Settings.DoesNotExist:
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def ADDCOST_FOR():
|
||||
try:
|
||||
return Settings.setting_inst("ADDCOST_FOR").value_account
|
||||
except Settings.DoesNotExist:
|
||||
return None;
|
||||
|
||||
@staticmethod
|
||||
def OVERDRAFT_DURATION():
|
||||
overdraft_duration = cache.get('OVERDRAFT_DURATION')
|
||||
if overdraft_duration:
|
||||
return overdraft_duration
|
||||
try:
|
||||
overdraft_duration = Settings.setting_inst("OVERDRAFT_DURATION").value_duration
|
||||
except Settings.DoesNotExist:
|
||||
overdraft_duration = timedelta()
|
||||
cache.set('OVERDRAFT_DURATION', overdraft_duration)
|
||||
return overdraft_duration
|
||||
|
||||
@staticmethod
|
||||
def OVERDRAFT_AMOUNT():
|
||||
overdraft_amount = cache.get('OVERDRAFT_AMOUNT')
|
||||
if overdraft_amount:
|
||||
return overdraft_amount
|
||||
try:
|
||||
overdraft_amount = Settings.setting_inst("OVERDRAFT_AMOUNT").value_decimal
|
||||
except Settings.DoesNotExist:
|
||||
overdraft_amount = 0
|
||||
cache.set('OVERDRAFT_AMOUNT', overdraft_amount)
|
||||
return overdraft_amount
|
||||
|
||||
@staticmethod
|
||||
def CANCEL_DURATION():
|
||||
cancel_duration = cache.get('CANCEL_DURATION')
|
||||
if cancel_duration:
|
||||
return cancel_duration
|
||||
try:
|
||||
cancel_duration = Settings.setting_inst("CANCEL_DURATION").value_duration
|
||||
except Settings.DoesNotExist:
|
||||
cancel_duration = timedelta()
|
||||
cache.set('CANCEL_DURATION', cancel_duration)
|
||||
return cancel_duration
|
||||
|
||||
@staticmethod
|
||||
def create_missing():
|
||||
s, created = Settings.objects.get_or_create(name='SUBVENTION_COF')
|
||||
if created:
|
||||
s.value_decimal = 25
|
||||
s.save()
|
||||
s, created = Settings.objects.get_or_create(name='ADDCOST_AMOUNT')
|
||||
if created:
|
||||
s.value_decimal = 0.5
|
||||
s.save()
|
||||
s, created = Settings.objects.get_or_create(name='ADDCOST_FOR')
|
||||
s, created = Settings.objects.get_or_create(name='OVERDRAFT_DURATION')
|
||||
if created:
|
||||
s.value_duration = timedelta(days=1) # 24h
|
||||
s.save()
|
||||
s, created = Settings.objects.get_or_create(name='OVERDRAFT_AMOUNT')
|
||||
if created:
|
||||
s.value_decimal = 20
|
||||
s.save()
|
||||
s, created = Settings.objects.get_or_create(name='CANCEL_DURATION')
|
||||
if created:
|
||||
s.value_duration = timedelta(minutes=5) # 5min
|
||||
s.save()
|
||||
|
||||
@staticmethod
|
||||
def empty_cache():
|
||||
cache.delete_many([
|
||||
'SUBVENTION_COF', 'OVERDRAFT_DURATION', 'OVERDRAFT_AMOUNT',
|
||||
'CANCEL_DURATION', 'ADDCOST_AMOUNT', 'ADDCOST_FOR',
|
||||
])
|
||||
|
||||
class GenericTeamToken(models.Model):
|
||||
token = models.CharField(max_length = 50, unique = True)
|
14
kfet/routing.py
Normal file
14
kfet/routing.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
|
||||
from channels.routing import route, route_class
|
||||
from kfet import consumers
|
||||
|
||||
channel_routing = [
|
||||
route_class(consumers.KPsul, path=r"^/ws/k-fet/k-psul/$"),
|
||||
#route("websocket.connect", ws_kpsul_history_connect),
|
||||
#route('websocket.receive', ws_message)
|
||||
]
|
5
kfet/static/kfet/css/bootstrap-datetimepicker.min.css
vendored
Normal file
5
kfet/static/kfet/css/bootstrap-datetimepicker.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
kfet/static/kfet/css/bootstrap.min.css
vendored
Normal file
6
kfet/static/kfet/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
106
kfet/static/kfet/css/history.css
Normal file
106
kfet/static/kfet/css/history.css
Normal file
|
@ -0,0 +1,106 @@
|
|||
#history {
|
||||
font-family:'Roboto Mono';
|
||||
}
|
||||
|
||||
#history span {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
#history .day {
|
||||
height:40px;
|
||||
line-height:40px;
|
||||
background-color:#c8102e;
|
||||
color:#fff;
|
||||
padding-left:20px;
|
||||
font-size:16px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#history .opegroup {
|
||||
height:30px;
|
||||
line-height:30px;
|
||||
background-color:rgba(200,16,46,0.85);
|
||||
color:#fff;
|
||||
font-weight:bold;
|
||||
padding-left:20px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
#history .opegroup .time {
|
||||
width:70px;
|
||||
}
|
||||
|
||||
#history .opegroup .trigramme {
|
||||
width:55px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
#history .opegroup .amount {
|
||||
text-align:right;
|
||||
width:90px;
|
||||
}
|
||||
|
||||
#history .opegroup .valid_by {
|
||||
padding-left:20px
|
||||
}
|
||||
|
||||
#history .opegroup .comment {
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
#history .ope {
|
||||
position:relative;
|
||||
height:25px;
|
||||
line-height:24px;
|
||||
font-size:12px;
|
||||
padding-left:15px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
#history .ope .amount {
|
||||
width:50px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
#history .ope .infos1 {
|
||||
width:80px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
#history .ope .infos2 {
|
||||
padding-left:15px;
|
||||
}
|
||||
|
||||
#history .ope .addcost {
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
#history .ope .canceled {
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
#history div.ope.ui-selected, #history div.ope.ui-selecting {
|
||||
background-color:rgba(200,16,46,0.6);
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
#history .ope.canceled, #history .transfer.canceled {
|
||||
color:#444;
|
||||
}
|
||||
|
||||
#history .ope.canceled::before, #history.transfer.canceled::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width:100%;
|
||||
left:0;
|
||||
top: 12px;
|
||||
border-top: 1px solid rgba(200,16,46,0.5);
|
||||
}
|
||||
|
||||
#history .transfer .amount {
|
||||
width:80px;
|
||||
}
|
||||
|
||||
#history .transfer .from_acc {
|
||||
padding-left:10px;
|
||||
}
|
265
kfet/static/kfet/css/index.css
Normal file
265
kfet/static/kfet/css/index.css
Normal file
|
@ -0,0 +1,265 @@
|
|||
@import url("nav.css");
|
||||
@import url("kpsul.css");
|
||||
@import url("jconfirm-kfet.css");
|
||||
@import url("history.css");
|
||||
|
||||
body {
|
||||
margin-top:50px;
|
||||
font-family:Roboto;
|
||||
background:#ddd;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-family:Oswald;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#333;
|
||||
}
|
||||
|
||||
a:focus, a:hover {
|
||||
color:#C8102E;
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline:none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
font-family:'Roboto Mono';
|
||||
border-radius:0 !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin-bottom:0;
|
||||
}
|
||||
|
||||
.table {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.table td {
|
||||
vertical-align:middle !important;
|
||||
}
|
||||
|
||||
.table td.no-padding {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.table thead {
|
||||
background:#c8102e;
|
||||
color:#fff;
|
||||
font-weight:bold;
|
||||
font-size:16px;
|
||||
}
|
||||
|
||||
.table thead td {
|
||||
padding:8px !important;
|
||||
}
|
||||
|
||||
.table tr.section {
|
||||
background:rgba(200,16,46,0.9);
|
||||
color:#fff;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.table tr.section td {
|
||||
border-top:0;
|
||||
font-size:16px;
|
||||
padding:8px 30px;
|
||||
}
|
||||
|
||||
.btn, .btn-lg, .btn-group-lg>.btn {
|
||||
border-radius:0;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
font-family:Oswald;
|
||||
background-color:rgba(200,16,46,0.9);
|
||||
color:#FFF;
|
||||
border:0;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary.focus, .btn-primary:focus {
|
||||
background-color:#000;
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
.row-page-header {
|
||||
background-color:rgba(200,16,46,1);
|
||||
color:#FFF;
|
||||
border-bottom:3px solid #000;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
border:0;
|
||||
padding:0;
|
||||
margin:15px 20px;
|
||||
text-transform:uppercase;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.col-content-left, .col-content-right {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.content-left-top {
|
||||
background:#fff;
|
||||
padding:10px 30px;
|
||||
}
|
||||
|
||||
.content-left .buttons {
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
.content-left .buttons .btn {
|
||||
display:block;
|
||||
}
|
||||
|
||||
.content-left-top.frozen-account {
|
||||
background:#000FBA;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.content-left .block {
|
||||
padding-top:25px;
|
||||
}
|
||||
|
||||
.content-left .block .line {
|
||||
font-size:16px;
|
||||
line-height:30px;
|
||||
}
|
||||
|
||||
.content-left .line.line-big {
|
||||
font-family:Oswald;
|
||||
font-size:60px;
|
||||
font-weight:bold;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.content-left .line.line-bigsub {
|
||||
font-size:25px;
|
||||
font-weight:bold;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.content-left .line.balance {
|
||||
font-size:45px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.content-right {
|
||||
margin:0 15px;
|
||||
}
|
||||
|
||||
.content-right-block {
|
||||
padding-bottom:5px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.content-right-block:last-child {
|
||||
padding-bottom:15px;
|
||||
}
|
||||
|
||||
.content-right-block > div:not(.buttons-title) {
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
.content-right-block .buttons-title {
|
||||
position:absolute;
|
||||
top:8px;
|
||||
right:20px;
|
||||
}
|
||||
|
||||
.content-right-block > div.row {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.content-right-block h2 {
|
||||
margin:20px 20px 15px;
|
||||
padding-bottom:5px;
|
||||
border-bottom:3px solid #c8102e;
|
||||
font-size:40px;
|
||||
}
|
||||
|
||||
.content-right-block h3 {
|
||||
border-bottom: 1px solid #c8102e;
|
||||
margin: 20px 15px 15px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
font-size:25px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pages formulaires seuls
|
||||
*/
|
||||
|
||||
.form-only .content-form {
|
||||
margin:15px;
|
||||
|
||||
background:#fff;
|
||||
|
||||
padding:15px;
|
||||
}
|
||||
|
||||
.form-only .account_create #id_trigramme {
|
||||
display:block;
|
||||
width:200px;
|
||||
height:80px;
|
||||
margin:0 auto 15px;
|
||||
border:1px solid #ccc;
|
||||
|
||||
font-size:70px;
|
||||
|
||||
text-align:center;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specific account create
|
||||
*/
|
||||
|
||||
.highlight_autocomplete {
|
||||
font-weight:bold;
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
#search_autocomplete {
|
||||
margin-bottom:15px;
|
||||
}
|
||||
|
||||
#search_results {
|
||||
top:-15px !important;
|
||||
left:0 !important;
|
||||
z-index:100;
|
||||
}
|
||||
|
||||
#search_results ul {
|
||||
list-style-type:none;
|
||||
padding:0;
|
||||
background:rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
#search_results ul li.user_category {
|
||||
font-weight:bold;
|
||||
background:#c8102e;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
#search_results ul li a {
|
||||
display:block;
|
||||
padding:5px 20px;
|
||||
height:100%;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
#search_results ul li a:hover {
|
||||
background:rgba(200,16,46,0.9);
|
||||
color:#fff;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
#search_results ul li span.text {
|
||||
display:block;
|
||||
padding:5px 20px;
|
||||
}
|
66
kfet/static/kfet/css/jconfirm-kfet.css
Normal file
66
kfet/static/kfet/css/jconfirm-kfet.css
Normal file
|
@ -0,0 +1,66 @@
|
|||
.jconfirm-bg.seen {
|
||||
opacity:1 !important;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box {
|
||||
padding:0;
|
||||
border-radius:0 !important;
|
||||
font-family:"Roboto Mono";
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box div.title-c .title {
|
||||
display: block;
|
||||
|
||||
padding:0 15px;
|
||||
height:40px;
|
||||
line-height:40px;
|
||||
|
||||
font-size:20px;
|
||||
font-weight:bold;
|
||||
|
||||
color:#FFF;
|
||||
background-color:#C8102E;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box .content-pane {
|
||||
margin:0 !important;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box .content {
|
||||
border-bottom:1px solid #ddd;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box input {
|
||||
width:100%;
|
||||
height:70px;
|
||||
|
||||
border:0;
|
||||
|
||||
font-size:40px;
|
||||
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box .buttons {
|
||||
margin-top:-5px; /* j'arrive pas à voir pk y'a un espace au dessus sinon... */
|
||||
padding:0;
|
||||
height:40px;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box .buttons button {
|
||||
height:100%;
|
||||
margin:0;
|
||||
margin:0 !important;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box .buttons button:first-child:focus,
|
||||
.jconfirm .jconfirm-box .buttons button:first-child:hover {
|
||||
color:#FFF !important;
|
||||
background:#009011 !important;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box .buttons button:nth-child(2):focus,
|
||||
.jconfirm .jconfirm-box .buttons button:nth-child(2):hover {
|
||||
color:#FFF !important;
|
||||
background:#C8102E !important;
|
||||
}
|
519
kfet/static/kfet/css/jquery-confirm.css
Normal file
519
kfet/static/kfet/css/jquery-confirm.css
Normal file
|
@ -0,0 +1,519 @@
|
|||
/*!
|
||||
* jquery-confirm v2.5.1 (http://craftpip.github.io/jquery-confirm/)
|
||||
* Author: boniface pereira
|
||||
* Website: www.craftpip.com
|
||||
* Contact: hey@craftpip.com
|
||||
*
|
||||
* Copyright 2013-2016 jquery-confirm
|
||||
* Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
|
||||
*/
|
||||
@-webkit-keyframes jconfirm-rotate {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes jconfirm-rotate {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
body.jconfirm-noscroll {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.jconfirm {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 99999999;
|
||||
font-family: inherit;
|
||||
overflow: hidden;
|
||||
}
|
||||
.jconfirm .jconfirm-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
-webkit-transition: all .4s;
|
||||
transition: all .4s;
|
||||
}
|
||||
.jconfirm .jconfirm-bg.seen {
|
||||
opacity: 1;
|
||||
}
|
||||
.jconfirm .jconfirm-scrollpane {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-perspective: 500px;
|
||||
perspective: 500px;
|
||||
-webkit-perspective-origin: center;
|
||||
perspective-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box {
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
outline: none;
|
||||
padding: 15px 15px 0;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.closeIcon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
cursor: pointer;
|
||||
opacity: .6;
|
||||
text-align: center;
|
||||
-webkit-transition: opacity 0.1s ease-in;
|
||||
transition: opacity 0.1s ease-in;
|
||||
display: none;
|
||||
font-size: 27px;
|
||||
line-height: 14px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.closeIcon .fa {
|
||||
font-size: 16px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.closeIcon .glyphicon {
|
||||
font-size: 16px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.closeIcon .zmdi {
|
||||
font-size: 16px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.closeIcon:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.title-c {
|
||||
display: block;
|
||||
font-size: 22px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.title-c .icon-c {
|
||||
font-size: inherit;
|
||||
padding-bottom: 15px;
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.title-c .icon-c i {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.title-c .icon-c:empty {
|
||||
display: none;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.title-c .title {
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.title-c .title:empty {
|
||||
display: none;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane {
|
||||
margin-bottom: 15px;
|
||||
height: auto;
|
||||
-webkit-transition: height 0.4s ease-in;
|
||||
transition: height 0.4s ease-in;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane .content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-transition: all 0.2s ease-in;
|
||||
transition: all 0.2s ease-in;
|
||||
right: 0;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane .content img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane .content:empty {
|
||||
display: none;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane .content:empty.loading {
|
||||
height: 40px;
|
||||
position: relative;
|
||||
opacity: 0.6;
|
||||
display: block;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane .content:empty.loading:before {
|
||||
content: '';
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border: solid 2px transparent;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: jconfirm-rotate 1s infinite linear;
|
||||
animation: jconfirm-rotate 1s infinite linear;
|
||||
border-bottom-color: #aaa;
|
||||
top: 50%;
|
||||
margin-top: -10px;
|
||||
}
|
||||
.jconfirm .jconfirm-box div.content-pane .content:empty.loading:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -15px;
|
||||
}
|
||||
.jconfirm .jconfirm-box .buttons {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
.jconfirm .jconfirm-box .buttons button + button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.jconfirm .jquery-clear {
|
||||
clear: both;
|
||||
}
|
||||
.jconfirm.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.jconfirm.rtl div.closeIcon {
|
||||
left: 12px;
|
||||
right: auto;
|
||||
}
|
||||
.jconfirm.jconfirm-white .jconfirm-bg {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.jconfirm.jconfirm-white .jconfirm-box {
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.jconfirm.jconfirm-white .jconfirm-box .buttons {
|
||||
float: right;
|
||||
}
|
||||
.jconfirm.jconfirm-white .jconfirm-box .buttons button {
|
||||
border: none;
|
||||
background-image: none;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-shadow: none;
|
||||
-webkit-transition: background .1s;
|
||||
transition: background .1s;
|
||||
color: white;
|
||||
}
|
||||
.jconfirm.jconfirm-white .jconfirm-box .buttons button.btn-default {
|
||||
box-shadow: none;
|
||||
color: #333;
|
||||
}
|
||||
.jconfirm.jconfirm-white .jconfirm-box .buttons button.btn-default:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
.jconfirm.jconfirm-black .jconfirm-bg {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.jconfirm.jconfirm-black .jconfirm-box {
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||
background: #444;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
}
|
||||
.jconfirm.jconfirm-black .jconfirm-box .buttons {
|
||||
float: right;
|
||||
}
|
||||
.jconfirm.jconfirm-black .jconfirm-box .buttons button {
|
||||
border: none;
|
||||
background-image: none;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-shadow: none;
|
||||
-webkit-transition: background .1s;
|
||||
transition: background .1s;
|
||||
color: white;
|
||||
}
|
||||
.jconfirm.jconfirm-black .jconfirm-box .buttons button.btn-default {
|
||||
box-shadow: none;
|
||||
color: #fff;
|
||||
background: none;
|
||||
}
|
||||
.jconfirm.jconfirm-black .jconfirm-box .buttons button.btn-default:hover {
|
||||
background: #666;
|
||||
}
|
||||
.jconfirm .jconfirm-box.hilight {
|
||||
-webkit-animation: hilight 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
|
||||
animation: hilight 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
@-webkit-keyframes hilight {
|
||||
10%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-2px, 0, 0);
|
||||
transform: translate3d(-2px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(4px, 0, 0);
|
||||
transform: translate3d(4px, 0, 0);
|
||||
}
|
||||
30%,
|
||||
50%,
|
||||
70% {
|
||||
-webkit-transform: translate3d(-8px, 0, 0);
|
||||
transform: translate3d(-8px, 0, 0);
|
||||
}
|
||||
40%,
|
||||
60% {
|
||||
-webkit-transform: translate3d(8px, 0, 0);
|
||||
transform: translate3d(8px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes hilight {
|
||||
10%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-2px, 0, 0);
|
||||
transform: translate3d(-2px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(4px, 0, 0);
|
||||
transform: translate3d(4px, 0, 0);
|
||||
}
|
||||
30%,
|
||||
50%,
|
||||
70% {
|
||||
-webkit-transform: translate3d(-8px, 0, 0);
|
||||
transform: translate3d(-8px, 0, 0);
|
||||
}
|
||||
40%,
|
||||
60% {
|
||||
-webkit-transform: translate3d(8px, 0, 0);
|
||||
transform: translate3d(8px, 0, 0);
|
||||
}
|
||||
}
|
||||
/*Transition rules*/
|
||||
.jconfirm {
|
||||
-webkit-perspective: 400px;
|
||||
perspective: 400px;
|
||||
}
|
||||
.jconfirm .jconfirm-box {
|
||||
opacity: 1;
|
||||
-webkit-transition-property: -webkit-transform, opacity, box-shadow;
|
||||
transition-property: transform, opacity, box-shadow;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-top,
|
||||
.jconfirm .jconfirm-box.anim-left,
|
||||
.jconfirm .jconfirm-box.anim-right,
|
||||
.jconfirm .jconfirm-box.anim-bottom,
|
||||
.jconfirm .jconfirm-box.anim-opacity,
|
||||
.jconfirm .jconfirm-box.anim-zoom,
|
||||
.jconfirm .jconfirm-box.anim-scale,
|
||||
.jconfirm .jconfirm-box.anim-none,
|
||||
.jconfirm .jconfirm-box.anim-rotate,
|
||||
.jconfirm .jconfirm-box.anim-rotatex,
|
||||
.jconfirm .jconfirm-box.anim-rotatey,
|
||||
.jconfirm .jconfirm-box.anim-scaley,
|
||||
.jconfirm .jconfirm-box.anim-scalex {
|
||||
opacity: 0;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-rotate {
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-rotatex {
|
||||
-webkit-transform: rotateX(90deg);
|
||||
transform: rotateX(90deg);
|
||||
-webkit-transform-origin: center;
|
||||
-ms-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-rotatexr {
|
||||
-webkit-transform: rotateX(-90deg);
|
||||
transform: rotateX(-90deg);
|
||||
-webkit-transform-origin: center;
|
||||
-ms-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-rotatey {
|
||||
-webkit-transform: rotatey(90deg);
|
||||
-ms-transform: rotatey(90deg);
|
||||
transform: rotatey(90deg);
|
||||
-webkit-transform-origin: center;
|
||||
-ms-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-rotateyr {
|
||||
-webkit-transform: rotatey(-90deg);
|
||||
-ms-transform: rotatey(-90deg);
|
||||
transform: rotatey(-90deg);
|
||||
-webkit-transform-origin: center;
|
||||
-ms-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-scaley {
|
||||
-webkit-transform: scaley(1.5);
|
||||
-ms-transform: scaley(1.5);
|
||||
transform: scaley(1.5);
|
||||
-webkit-transform-origin: center;
|
||||
-ms-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-scalex {
|
||||
-webkit-transform: scalex(1.5);
|
||||
-ms-transform: scalex(1.5);
|
||||
transform: scalex(1.5);
|
||||
-webkit-transform-origin: center;
|
||||
-ms-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-top {
|
||||
-webkit-transform: translate(0px, -100px);
|
||||
-ms-transform: translate(0px, -100px);
|
||||
transform: translate(0px, -100px);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-left {
|
||||
-webkit-transform: translate(-100px, 0px);
|
||||
-ms-transform: translate(-100px, 0px);
|
||||
transform: translate(-100px, 0px);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-right {
|
||||
-webkit-transform: translate(100px, 0px);
|
||||
-ms-transform: translate(100px, 0px);
|
||||
transform: translate(100px, 0px);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-bottom {
|
||||
-webkit-transform: translate(0px, 100px);
|
||||
-ms-transform: translate(0px, 100px);
|
||||
transform: translate(0px, 100px);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-zoom {
|
||||
-webkit-transform: scale(1.2);
|
||||
-ms-transform: scale(1.2);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-scale {
|
||||
-webkit-transform: scale(0.5);
|
||||
-ms-transform: scale(0.5);
|
||||
transform: scale(0.5);
|
||||
}
|
||||
.jconfirm .jconfirm-box.anim-none {
|
||||
display: none;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-bg {
|
||||
background-color: rgba(54, 70, 93, 0.95);
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box {
|
||||
background-color: transparent;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box div.closeIcon {
|
||||
color: white;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box div.title-c {
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-size: 28px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box div.title-c > * {
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box div.content-pane {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box div.content {
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box .buttons {
|
||||
text-align: center;
|
||||
}
|
||||
.jconfirm.jconfirm-supervan .jconfirm-box .buttons button {
|
||||
font-size: 16px;
|
||||
border-radius: 2px;
|
||||
background: #303f53;
|
||||
text-shadow: none;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
min-width: 100px;
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-bg {
|
||||
background-color: rgba(0, 0, 0, 0.67);
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-box {
|
||||
background-color: white;
|
||||
box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
|
||||
padding: 30px 25px 10px 25px;
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-box div.closeIcon {
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-box div.title-c {
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-box div.content {
|
||||
text-align: left;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-box .buttons {
|
||||
text-align: right;
|
||||
}
|
||||
.jconfirm.jconfirm-material .jconfirm-box .buttons button {
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-bg {
|
||||
background-color: rgba(0, 0, 0, 0.21);
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-box {
|
||||
background-color: white;
|
||||
box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
border: solid 1px rgba(0, 0, 0, 0.4);
|
||||
padding: 15px 0 0;
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-box div.closeIcon {
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-box div.title-c {
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-box div.content {
|
||||
text-align: left;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
padding: 0px 15px;
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-box .buttons {
|
||||
text-align: right;
|
||||
padding: 0px 0 0px;
|
||||
margin: -5px 0 0px;
|
||||
border-top: solid 1px #ddd;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
.jconfirm.jconfirm-bootstrap .jconfirm-box .buttons button {
|
||||
font-weight: 500;
|
||||
border-radius: 0px;
|
||||
margin: 0;
|
||||
border-left: solid 1px #ddd;
|
||||
}
|
6
kfet/static/kfet/css/jquery-ui.min.css
vendored
Normal file
6
kfet/static/kfet/css/jquery-ui.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*! jQuery UI - v1.12.0 - 2016-08-17
|
||||
* http://jqueryui.com
|
||||
* Includes: selectable.css
|
||||
* Copyright jQuery Foundation and other contributors; Licensed MIT */
|
||||
|
||||
.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}
|
385
kfet/static/kfet/css/kpsul.css
Normal file
385
kfet/static/kfet/css/kpsul.css
Normal file
|
@ -0,0 +1,385 @@
|
|||
input[type=number] {
|
||||
-moz-appearance:textfield;
|
||||
}
|
||||
|
||||
input[type=number]::-webkit-inner-spin-button,
|
||||
input[type=number]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#account, #checkout, input, #history, #basket, #basket_rel, #articles_data {
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
@keyframes colorchange {
|
||||
0% { background: yellow; }
|
||||
50% { background: #660066; }
|
||||
100% { background: yellow; }
|
||||
}
|
||||
|
||||
/*
|
||||
* Top row
|
||||
*/
|
||||
|
||||
.row.kpsul_top {
|
||||
padding:0 15px;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
.row.kpsul_top > div {
|
||||
margin-top:15px;
|
||||
}
|
||||
|
||||
/* Account */
|
||||
|
||||
#account {
|
||||
color:black;
|
||||
height:120px;
|
||||
}
|
||||
|
||||
#account[data-balance="ok"] #account_form input { background:#009011; color:#FFF;}
|
||||
#account[data-balance="low"] #account_form input { background:#EC6400; color:#FFF; }
|
||||
#account[data-balance="neg"] #account_form input { background:#C8102E; color:#FFF; }
|
||||
#account[data-balance="frozen"] #account_form input { background:#000FBA; color:#FFF; }
|
||||
|
||||
#account_form {
|
||||
padding:0;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
#account_form input {
|
||||
width:100%;
|
||||
height:100%;
|
||||
|
||||
padding:0;
|
||||
padding-bottom:10px;
|
||||
|
||||
border:0;
|
||||
border-radius:0;
|
||||
|
||||
background:#f3f3f3;
|
||||
|
||||
font-family:'Roboto Mono';
|
||||
font-size:50px;
|
||||
font-weight:bold;
|
||||
|
||||
text-align:center;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
|
||||
#account_data {
|
||||
height:100%;
|
||||
}
|
||||
|
||||
#account_data .data_line {
|
||||
line-height:16px;
|
||||
|
||||
font-family:'Roboto Mono';
|
||||
font-size:12px;
|
||||
}
|
||||
|
||||
#account_data #account-balance {
|
||||
height:40px;
|
||||
line-height:40px;
|
||||
|
||||
font-size:35px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#account-name {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#account .buttons {
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
right:0;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
#account_form input { font-size:60px; }
|
||||
|
||||
@media (min-width: 768px) {
|
||||
#account{ height:160px; }
|
||||
#account_form input { font-size: 70px; }
|
||||
#account_name { font-size:60px; }
|
||||
#account_data .data_line {
|
||||
font-size:14px;
|
||||
line-height:24px;
|
||||
}
|
||||
#account_data #account-balance {
|
||||
font-size:50px;
|
||||
line-height:60px;
|
||||
height:60px;
|
||||
}
|
||||
|
||||
#account { margin-right:0; }
|
||||
#account_form input { font-size:85px; }
|
||||
|
||||
@media (min-width: 992px) {
|
||||
#account_form input { font-size:100px; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Checkout */
|
||||
|
||||
#checkout {
|
||||
padding:0;
|
||||
height:160px;
|
||||
font-family:'Roboto Mono';
|
||||
}
|
||||
|
||||
#checkout_form select {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
cursor:pointer;
|
||||
outline:none;
|
||||
border:0;
|
||||
|
||||
width:100%;
|
||||
height:50px;
|
||||
padding:0 15px;
|
||||
|
||||
background:#c8102e;
|
||||
color:#fff;
|
||||
|
||||
font-weight:bold;
|
||||
font-size:18px;
|
||||
}
|
||||
|
||||
#checkout_form select option {
|
||||
height:25px;
|
||||
padding:0 15px;
|
||||
line-height:25px;
|
||||
font-weight:normal;
|
||||
font-size:14px;
|
||||
background-color:rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
#checkout_data {
|
||||
padding:0 15px;
|
||||
}
|
||||
|
||||
#checkout_data .buttons {
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
right:0;
|
||||
}
|
||||
|
||||
#addcost {
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
left:0;
|
||||
|
||||
height:32px;
|
||||
line-height:32px;
|
||||
padding:0 10px;
|
||||
|
||||
background:#c8102e;
|
||||
color:#fff;
|
||||
|
||||
font-weight:bold;
|
||||
|
||||
animation: blink 1.5s steps(1) infinite;
|
||||
}
|
||||
@keyframes blink { 50% { visibility: hidden; } }
|
||||
|
||||
/*
|
||||
* Second part
|
||||
*/
|
||||
|
||||
.row.kpsul_middle {
|
||||
margin:15px 0;
|
||||
font-family:'Roboto Mono';
|
||||
color:#000;
|
||||
}
|
||||
|
||||
.row.kpsul_middle > div {
|
||||
padding:0;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.row.kpsul_middle > div:first-child > div {
|
||||
margin-right:0;
|
||||
}
|
||||
|
||||
.row.kpsul_middle > div+div {
|
||||
margin-top:15px;
|
||||
}
|
||||
|
||||
@media (min-width:768px) {
|
||||
.row.kpsul_middle > div:first-child > div {
|
||||
margin-right:15px
|
||||
}
|
||||
|
||||
.row.kpsul_middle > div {
|
||||
margin-top:0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special operations */
|
||||
|
||||
#special_operations {
|
||||
height:40px;
|
||||
}
|
||||
|
||||
#special_operations button {
|
||||
height:100%;
|
||||
width:25%;
|
||||
|
||||
float:left;
|
||||
|
||||
background:#c8102e;
|
||||
color:#FFF;
|
||||
|
||||
font-size:18px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#special_operations button:focus, #special_operations button:hover {
|
||||
outline:none;
|
||||
background:#000;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
/* Article autocomplete */
|
||||
|
||||
#article_selection {
|
||||
height:40px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
#article_selection input {
|
||||
height:100%;
|
||||
float:left;
|
||||
border:0;
|
||||
border-right:1px solid #c8102e;
|
||||
border-bottom:1px solid #c8102e;
|
||||
border-radius:0;
|
||||
font-size:16px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#article_selection input+input {
|
||||
border-right:0;
|
||||
}
|
||||
|
||||
#article_autocomplete {
|
||||
width:90%;
|
||||
padding-left:10px;
|
||||
}
|
||||
|
||||
#article_number {
|
||||
width:10%;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
@media (min-width:1200px) {
|
||||
#article_autocomplete {
|
||||
width:92%
|
||||
}
|
||||
|
||||
#article_number {
|
||||
width:8%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Article data */
|
||||
|
||||
#articles_data {
|
||||
overflow:auto;
|
||||
max-height:500px;
|
||||
}
|
||||
|
||||
#articles_data table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#articles_data table tr.article {
|
||||
height:25px;
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
#articles_data table tr.article>td:first-child {
|
||||
padding-left:10px;
|
||||
}
|
||||
|
||||
#articles_data table tr.category {
|
||||
height:35px;
|
||||
background-color:#c8102e;
|
||||
font-size:16px;
|
||||
color:#FFF;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#articles_data table tr.category>td:first-child {
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
/* Second part - Left - bottom */
|
||||
|
||||
.kpsul_middle_left_bottom {
|
||||
margin:15px 0 0;
|
||||
}
|
||||
|
||||
.kpsul_middle_left_bottom > div {
|
||||
height:160px;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
#basket, #basket_rel {
|
||||
height:100%;
|
||||
}
|
||||
|
||||
#basket_rel {
|
||||
border-top:1px solid #C8102E;
|
||||
}
|
||||
|
||||
#basket {
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
@media (min-width:768px) {
|
||||
#basket {
|
||||
margin-right:7px;
|
||||
}
|
||||
#basket_rel {
|
||||
border-top:0;
|
||||
margin-left:7px;
|
||||
}
|
||||
}
|
||||
|
||||
#basket table {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
#basket table tr {
|
||||
height:25px;
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
#basket tr .amount {
|
||||
width:70px;
|
||||
padding-right:15px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
#basket tr .number {
|
||||
width:50px;
|
||||
padding-right:15px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
#basket tr.ui-selected, #basket tr.ui-selecting {
|
||||
background-color:rgba(200,16,46,0.6);
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
/* History */
|
||||
|
||||
.kpsul_middle_right_col {
|
||||
overflow:auto;
|
||||
}
|
9
kfet/static/kfet/css/kpsul_grid.css
Normal file
9
kfet/static/kfet/css/kpsul_grid.css
Normal file
|
@ -0,0 +1,9 @@
|
|||
@media (min-width:768px) {
|
||||
html { height:100%; }
|
||||
body { height:calc(100% - 50px); }
|
||||
.container-fluid { height:100%; }
|
||||
.kpsul_middle { height:calc(100% - 205px); }
|
||||
.kpsul_middle_left_top { height:calc(100% - 175px); min-height:80px; }
|
||||
.kpsul_middle_left { height:100%; }
|
||||
#articles_data { height: calc(100% - 80px); }
|
||||
}
|
191
kfet/static/kfet/css/multiple-select.css
Normal file
191
kfet/static/kfet/css/multiple-select.css
Normal file
|
@ -0,0 +1,191 @@
|
|||
/**
|
||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||
*/
|
||||
|
||||
.ms-parent {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ms-choice {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px solid #aaa;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
line-height: 26px;
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.ms-choice.disabled {
|
||||
background-color: #f4f4f4;
|
||||
background-image: none;
|
||||
border: 1px solid #ddd;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.ms-choice > span {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 20px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.ms-choice > span.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.ms-choice > div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 25px;
|
||||
background: url('../img/multiple-select.png') left top no-repeat;
|
||||
}
|
||||
|
||||
.ms-choice > div.open {
|
||||
background: url('../img/multiple-select.png') right top no-repeat;
|
||||
}
|
||||
|
||||
.ms-drop {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
margin-top: -1px;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #aaa;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ms-drop.bottom {
|
||||
top: 100%;
|
||||
-webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
|
||||
-moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
|
||||
box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.ms-drop.top {
|
||||
bottom: 100%;
|
||||
-webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
|
||||
-moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
|
||||
box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.ms-search {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
min-height: 26px;
|
||||
padding: 4px;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.ms-search input {
|
||||
width: 100%;
|
||||
height: auto !important;
|
||||
min-height: 24px;
|
||||
padding: 0 20px 0 5px;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
border: 1px solid #aaa;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
background: #fff url('../img/multiple-select.png') no-repeat 100% -22px;
|
||||
background: url('../img/multiple-select.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
|
||||
background: url('../img/multiple-select.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
|
||||
background: url('../img/multiple-select.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
|
||||
background: url('../img/multiple-select.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
|
||||
background: url('../img/multiple-select.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
|
||||
background: url('../img/multiple-select.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
|
||||
}
|
||||
|
||||
.ms-search, .ms-search input {
|
||||
-webkit-box-sizing: border-box;
|
||||
-khtml-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ms-drop ul {
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
.ms-drop ul > li {
|
||||
list-style: none;
|
||||
display: list-item;
|
||||
background-image: none;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.ms-drop ul > li .disabled {
|
||||
opacity: .35;
|
||||
filter: Alpha(Opacity=35);
|
||||
}
|
||||
|
||||
.ms-drop ul > li.multiple {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ms-drop ul > li.group {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.ms-drop ul > li.multiple label {
|
||||
width: 100%;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ms-drop ul > li label {
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ms-drop ul > li label.optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ms-drop input[type="checkbox"] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ms-drop .ms-no-results {
|
||||
display: none;
|
||||
}
|
67
kfet/static/kfet/css/nav.css
Normal file
67
kfet/static/kfet/css/nav.css
Normal file
|
@ -0,0 +1,67 @@
|
|||
nav {
|
||||
background:#000;
|
||||
color:#DDD;
|
||||
font-family:Oswald;
|
||||
}
|
||||
|
||||
.navbar-nav > li > .dropdown-menu {
|
||||
border:0;
|
||||
border-radius:0;
|
||||
}
|
||||
|
||||
.navbar-fixed-top {
|
||||
border:0;
|
||||
}
|
||||
|
||||
nav .navbar-brand {
|
||||
padding:3px 25px;
|
||||
}
|
||||
|
||||
nav .navbar-brand img {
|
||||
height:44px;
|
||||
}
|
||||
|
||||
nav .navbar-toggle .icon-bar {
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color:#DDD;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
font-weight:bold;
|
||||
font-size:14px;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
|
||||
.nav>li>a:focus, .nav>li>a:hover {
|
||||
background-color:#C8102E;
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
.nav .open>a, .nav .open>a:focus, .nav .open>a:hover {
|
||||
background-color:#C8102E;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.dropdown-menu>li>a {
|
||||
padding:8px 20px;
|
||||
}
|
||||
|
||||
.dropdown-menu .divider {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.navbar-nav .open .dropdown-menu {
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
margin:0 -15px;
|
||||
}
|
||||
}
|
73
kfet/static/kfet/css/transfers_form.css
Normal file
73
kfet/static/kfet/css/transfers_form.css
Normal file
|
@ -0,0 +1,73 @@
|
|||
.transfer_general {
|
||||
margin:15px 0;
|
||||
height:45px;
|
||||
}
|
||||
|
||||
.transfer_general input {
|
||||
height:100%;
|
||||
border:0;
|
||||
padding:0 5px;
|
||||
font-size:16px;
|
||||
}
|
||||
|
||||
.transfer_general button {
|
||||
height:100%;
|
||||
margin-top:-3px;
|
||||
}
|
||||
|
||||
.transfer_formset {
|
||||
background:#FFF;
|
||||
}
|
||||
|
||||
.transfer_formset thead {
|
||||
height:40px;
|
||||
background:#c8102e;
|
||||
color:#fff;
|
||||
font-size:20px;
|
||||
font-weight:bold;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.transfer_form td {
|
||||
height:50px;
|
||||
vertical-align:middle !important;
|
||||
padding:0 !important;
|
||||
}
|
||||
|
||||
.transfer_form input {
|
||||
border:0;
|
||||
border-radius:0;
|
||||
|
||||
width:100%;
|
||||
height:100%;
|
||||
|
||||
font-family:'Roboto Mono';
|
||||
font-size:25px;
|
||||
font-weight:bold;
|
||||
|
||||
text-align:center;
|
||||
vertical-align:middle;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
|
||||
.transfer_form .from_acc_data, .transfer_form .to_acc_data {
|
||||
width:30%;
|
||||
text-align:center;
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
.transfer_form .from_acc, .transfer_form .to_acc {
|
||||
width:15%;
|
||||
}
|
||||
|
||||
.transfer_form .from_acc {
|
||||
border-left:1px solid #ddd;
|
||||
}
|
||||
|
||||
.transfer_form .to_acc {
|
||||
border-right:1px solid #ddd;
|
||||
}
|
||||
|
||||
.transfer_form .amount {
|
||||
width:10%;
|
||||
}
|
BIN
kfet/static/kfet/img/logo3.png
Normal file
BIN
kfet/static/kfet/img/logo3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
kfet/static/kfet/img/multiple-select.png
Normal file
BIN
kfet/static/kfet/img/multiple-select.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
9
kfet/static/kfet/js/bootstrap-datetimepicker.min.js
vendored
Normal file
9
kfet/static/kfet/js/bootstrap-datetimepicker.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
139
kfet/static/kfet/js/history.js
Normal file
139
kfet/static/kfet/js/history.js
Normal file
|
@ -0,0 +1,139 @@
|
|||
function KHistory(options={}) {
|
||||
$.extend(this, KHistory.default_options, options);
|
||||
|
||||
this.$container = $(this.container);
|
||||
|
||||
this.reset = function() {
|
||||
this.$container.html('');
|
||||
};
|
||||
|
||||
this.addOpeGroup = function(opegroup) {
|
||||
var $day = this._getOrCreateDay(opegroup['at']);
|
||||
var $opegroup = this._opeGroupHtml(opegroup);
|
||||
|
||||
$day.after($opegroup);
|
||||
|
||||
var trigramme = opegroup['on_acc_trigramme'];
|
||||
var is_cof = opegroup['is_cof'];
|
||||
for (var i=0; i<opegroup['opes'].length; i++) {
|
||||
var $ope = this._opeHtml(opegroup['opes'][i], is_cof, trigramme);
|
||||
$ope.data('opegroup', opegroup['id']);
|
||||
$opegroup.after($ope);
|
||||
}
|
||||
}
|
||||
|
||||
this._opeHtml = function(ope, is_cof, trigramme) {
|
||||
var $ope_html = $(this.template_ope);
|
||||
var parsed_amount = parseFloat(ope['amount']);
|
||||
var amount = amountDisplay(parsed_amount, is_cof, trigramme);
|
||||
var infos1 = '', infos2 = '';
|
||||
|
||||
if (ope['type'] == 'purchase') {
|
||||
infos1 = ope['article_nb'];
|
||||
infos2 = ope['article__name'];
|
||||
} else if (ope['type'] == 'initial') {
|
||||
infos1 = parsed_amount.toFixed(2)+'€';
|
||||
infos2 = 'Initial';
|
||||
} else {
|
||||
infos1 = parsed_amount.toFixed(2)+'€';
|
||||
infos2 = (ope['type'] == 'deposit') ? 'Charge' : 'Retrait';
|
||||
infos2 = ope['is_checkout'] ? infos2 : 'Édition';
|
||||
}
|
||||
|
||||
$ope_html
|
||||
.data('ope', ope['id'])
|
||||
.find('.amount').text(amount).end()
|
||||
.find('.infos1').text(infos1).end()
|
||||
.find('.infos2').text(infos2).end();
|
||||
|
||||
var addcost_for = ope['addcost_for__trigramme'];
|
||||
if (addcost_for) {
|
||||
var addcost_amount = parseFloat(ope['addcost_amount']);
|
||||
$ope_html.find('.addcost').text('('+amountDisplay(addcost_amount, is_cof)+'UKF pour '+addcost_for+')');
|
||||
}
|
||||
|
||||
if (ope['canceled_at'])
|
||||
this.cancelOpe(ope, $ope_html);
|
||||
|
||||
return $ope_html;
|
||||
}
|
||||
|
||||
this.cancelOpe = function(ope, $ope = null) {
|
||||
if (!$ope)
|
||||
$ope = this.findOpe(ope['id']);
|
||||
|
||||
var cancel = 'Annulé';
|
||||
var canceled_at = dateUTCToParis(ope['canceled_at']);
|
||||
if (ope['canceled_by__trigramme'])
|
||||
cancel += ' par '+ope['canceled_by__trigramme'];
|
||||
cancel += ' le '+canceled_at.format('DD/MM/YY à HH:mm:ss');
|
||||
|
||||
$ope.addClass('canceled').find('.canceled').text(cancel);
|
||||
}
|
||||
|
||||
this._opeGroupHtml = function(opegroup) {
|
||||
var $opegroup_html = $(this.template_opegroup);
|
||||
|
||||
var at = dateUTCToParis(opegroup['at']).format('HH:mm:ss');
|
||||
var trigramme = opegroup['on_acc__trigramme'];
|
||||
var amount = amountDisplay(
|
||||
parseFloat(opegroup['amount']), opegroup['is_cof'], trigramme);
|
||||
var comment = opegroup['comment'] || '';
|
||||
|
||||
$opegroup_html
|
||||
.data('opegroup', opegroup['id'])
|
||||
.find('.time').text(at).end()
|
||||
.find('.amount').text(amount).end()
|
||||
.find('.comment').text(comment).end()
|
||||
.find('.trigramme').text(trigramme).end();
|
||||
|
||||
if (!this.display_trigramme)
|
||||
$opegroup_html.find('.trigramme').remove();
|
||||
|
||||
if (opegroup['valid_by__trigramme'])
|
||||
$opegroup_html.find('.valid_by').text('Par '+opegroup['valid_by__trigramme']);
|
||||
|
||||
return $opegroup_html;
|
||||
}
|
||||
|
||||
this._getOrCreateDay = function(date) {
|
||||
var at = dateUTCToParis(date);
|
||||
var at_ser = at.format('YYYY-MM-DD');
|
||||
var $day = this.$container.find('.day').filter(function() {
|
||||
return $(this).data('date') == at_ser
|
||||
});
|
||||
if ($day.length == 1)
|
||||
return $day;
|
||||
var $day = $(this.template_day).prependTo(this.$container);
|
||||
return $day.data('date', at_ser).text(at.format('D MMMM'));
|
||||
}
|
||||
|
||||
this.findOpeGroup = function(id) {
|
||||
return this.$container.find('.opegroup').filter(function() {
|
||||
return $(this).data('opegroup') == id
|
||||
});
|
||||
}
|
||||
|
||||
this.findOpe = function(id) {
|
||||
return this.$container.find('.ope').filter(function() {
|
||||
return $(this).data('ope') == id
|
||||
});
|
||||
}
|
||||
|
||||
this.cancelOpeGroup = function(opegroup) {
|
||||
var $opegroup = this.findOpeGroup(opegroup['id']);
|
||||
var trigramme = $opegroup.find('.trigramme').text();
|
||||
var amount = amountDisplay(
|
||||
parseFloat(opegroup['amount'], opegroup['is_cof'], trigramme));
|
||||
$opegroup.find('.amount').text(amount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
KHistory.default_options = {
|
||||
container: '#history',
|
||||
template_day: '<div class="day"></div>',
|
||||
template_opegroup: '<div class="opegroup"><span class="time"></span><span class="trigramme"></span><span class="amount"></span><span class="valid_by"></span><span class="comment"></span></div>',
|
||||
template_ope: '<div class="ope"><span class="amount"></span><span class="infos1"></span><span class="infos2"></span><span class="addcost"></span><span class="canceled"></span></div>',
|
||||
display_trigramme: true,
|
||||
}
|
607
kfet/static/kfet/js/jquery-confirm.js
vendored
Normal file
607
kfet/static/kfet/js/jquery-confirm.js
vendored
Normal file
|
@ -0,0 +1,607 @@
|
|||
/*!
|
||||
* jquery-confirm v2.5.1 (http://craftpip.github.io/jquery-confirm/)
|
||||
* Author: Boniface Pereira
|
||||
* Website: www.craftpip.com
|
||||
* Contact: hey@craftpip.com
|
||||
*
|
||||
* Copyright 2013-2015 jquery-confirm
|
||||
* Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
|
||||
*
|
||||
* Modifié par: Aurélien Delobelle
|
||||
* Contact: aure.delo@gmail.com
|
||||
* Contenu des modifications:
|
||||
* Cas où il y a un input avec autofocus dans 'content' -> Fix
|
||||
*/
|
||||
|
||||
if (typeof jQuery === 'undefined') {
|
||||
throw new Error('jquery-confirm requires jQuery');
|
||||
}
|
||||
|
||||
var jconfirm, Jconfirm;
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.fn.confirm = function (options, option2) {
|
||||
if (typeof options === 'undefined') options = {};
|
||||
if (typeof options === 'string')
|
||||
options = {
|
||||
content: options,
|
||||
title: (option2) ? option2 : false
|
||||
|
||||
};
|
||||
/*
|
||||
* Alias of $.confirm to emulate native confirm()
|
||||
*/
|
||||
$(this).each(function () {
|
||||
var $this = $(this);
|
||||
$this.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
var jcOption = $.extend({}, options);
|
||||
if ($this.attr('data-title'))
|
||||
jcOption['title'] = $this.attr('data-title');
|
||||
if ($this.attr('data-content'))
|
||||
jcOption['content'] = $this.attr('data-content');
|
||||
|
||||
jcOption['$target'] = $this;
|
||||
if ($this.attr('href') && !options['confirm'])
|
||||
jcOption['confirm'] = function () {
|
||||
location.href = $this.attr('href');
|
||||
};
|
||||
$.confirm(jcOption);
|
||||
});
|
||||
});
|
||||
return $(this);
|
||||
};
|
||||
$.confirm = function (options, option2) {
|
||||
if (typeof options === 'undefined') options = {};
|
||||
if (typeof options === 'string')
|
||||
options = {
|
||||
content: options,
|
||||
title: (option2) ? option2 : false
|
||||
};
|
||||
/*
|
||||
* Alias of jconfirm
|
||||
*/
|
||||
return jconfirm(options);
|
||||
};
|
||||
$.alert = function (options, option2) {
|
||||
if (typeof options === 'undefined') options = {};
|
||||
if (typeof options === 'string')
|
||||
options = {
|
||||
content: options,
|
||||
title: (option2) ? option2 : false
|
||||
};
|
||||
/*
|
||||
* Alias of jconfirm
|
||||
*/
|
||||
options.cancelButton = false;
|
||||
return jconfirm(options);
|
||||
};
|
||||
$.dialog = function (options, option2) {
|
||||
if (typeof options === 'undefined') options = {};
|
||||
if (typeof options === 'string')
|
||||
options = {
|
||||
content: options,
|
||||
title: (option2) ? option2 : false
|
||||
};
|
||||
/*
|
||||
* Alias of jconfirm
|
||||
*/
|
||||
options.cancelButton = false;
|
||||
options.confirmButton = false;
|
||||
options.confirmKeys = [13];
|
||||
return jconfirm(options);
|
||||
};
|
||||
jconfirm = function (options) {
|
||||
if (typeof options === 'undefined') options = {};
|
||||
/*
|
||||
* initial function for calling.
|
||||
*/
|
||||
if (jconfirm.defaults) {
|
||||
/*
|
||||
* Merge global defaults with plugin defaults
|
||||
*/
|
||||
$.extend(jconfirm.pluginDefaults, jconfirm.defaults);
|
||||
}
|
||||
/*
|
||||
* merge options with plugin defaults.
|
||||
*/
|
||||
var options = $.extend({}, jconfirm.pluginDefaults, options);
|
||||
return new Jconfirm(options);
|
||||
};
|
||||
Jconfirm = function (options) {
|
||||
/*
|
||||
* constructor function Jconfirm,
|
||||
* options = user options.
|
||||
*/
|
||||
$.extend(this, options);
|
||||
this._init();
|
||||
};
|
||||
Jconfirm.prototype = {
|
||||
_init: function () {
|
||||
var that = this;
|
||||
this._rand = Math.round(Math.random() * 99999);
|
||||
this._buildHTML();
|
||||
this._bindEvents();
|
||||
setTimeout(function () {
|
||||
that.open();
|
||||
that._watchContent();
|
||||
}, 0);
|
||||
},
|
||||
_buildHTML: function () {
|
||||
var that = this;
|
||||
/*
|
||||
* Prefixing animations.
|
||||
*/
|
||||
this.animation = 'anim-' + this.animation.toLowerCase();
|
||||
this.closeAnimation = 'anim-' + this.closeAnimation.toLowerCase();
|
||||
this.theme = 'jconfirm-' + this.theme.toLowerCase();
|
||||
if (this.animation == 'anim-none')
|
||||
this.animationSpeed = 0;
|
||||
|
||||
this._lastFocused = $('body').find(':focus');
|
||||
|
||||
/*
|
||||
* Append html.
|
||||
*/
|
||||
this.$el = $(this.template).appendTo(this.container).addClass(this.theme);
|
||||
this.$el.find('.jconfirm-box-container').addClass(this.columnClass);
|
||||
this.$el.find('.jconfirm-bg').css(this._getCSS(this.animationSpeed, 1));
|
||||
this.$el.find('.jconfirm-bg').css('opacity', this.opacity);
|
||||
this.$b = this.$el.find('.jconfirm-box').css(this._getCSS(this.animationSpeed, this.animationBounce)).addClass(this.animation);
|
||||
this.$body = this.$b; // alias
|
||||
|
||||
/*
|
||||
* Add rtl class if rtl option has selected
|
||||
*/
|
||||
if (this.rtl)
|
||||
this.$el.addClass("rtl");
|
||||
|
||||
this._contentReady = $.Deferred();
|
||||
this._modalReady = $.Deferred();
|
||||
|
||||
/*
|
||||
* Setup title contents
|
||||
*/
|
||||
this.$title = this.$el.find('.title');
|
||||
this.contentDiv = this.$el.find('div.content');
|
||||
this.$content = this.contentDiv; // alias
|
||||
this.$contentPane = this.$el.find('.content-pane');
|
||||
this.$icon = this.$el.find('.icon-c');
|
||||
this.$closeIcon = this.$el.find('.closeIcon');
|
||||
this.$contentPane.css(this._getCSS(this.animationSpeed, 1));
|
||||
this.setTitle();
|
||||
this.setIcon();
|
||||
this._setButtons();
|
||||
|
||||
if (this.closeIconClass)
|
||||
this.$closeIcon.html('<i class="' + this.closeIconClass + '"></i>');
|
||||
|
||||
that._contentHash = this._hash(that.$content.html());
|
||||
$.when(this._contentReady, this._modalReady).then(function () {
|
||||
that.setContent();
|
||||
that.setTitle();
|
||||
that.setIcon();
|
||||
});
|
||||
|
||||
this._getContent();
|
||||
this._imagesLoaded();
|
||||
|
||||
if (this.autoClose)
|
||||
this._startCountDown();
|
||||
},
|
||||
_unwatchContent: function () {
|
||||
clearInterval(this._timer);
|
||||
},
|
||||
_hash: function () {
|
||||
return btoa((encodeURIComponent(this.$content.html())));
|
||||
},
|
||||
_watchContent: function () {
|
||||
var that = this;
|
||||
this._timer = setInterval(function () {
|
||||
var now = that._hash(that.$content.html());
|
||||
if (that._contentHash != now) {
|
||||
that._contentHash = now;
|
||||
that.setDialogCenter();
|
||||
that._imagesLoaded();
|
||||
}
|
||||
}, this.watchInterval);
|
||||
},
|
||||
_bindEvents: function () {
|
||||
var that = this;
|
||||
var boxClicked = false;
|
||||
|
||||
this.$el.find('.jconfirm-scrollpane').click(function (e) {
|
||||
// ignore propagated clicks
|
||||
if (!boxClicked) {
|
||||
// background clicked
|
||||
if (that.backgroundDismiss) {
|
||||
that.cancel();
|
||||
that.close();
|
||||
} else {
|
||||
that.$b.addClass('hilight');
|
||||
setTimeout(function () {
|
||||
that.$b.removeClass('hilight');
|
||||
}, 800);
|
||||
}
|
||||
}
|
||||
boxClicked = false;
|
||||
});
|
||||
|
||||
this.$el.find('.jconfirm-box').click(function (e) {
|
||||
boxClicked = true;
|
||||
});
|
||||
|
||||
if (this.$confirmButton) {
|
||||
this.$confirmButton.click(function (e) {
|
||||
e.preventDefault();
|
||||
var r = that.confirm(that.$b);
|
||||
that._stopCountDown();
|
||||
that.onAction('confirm');
|
||||
if (typeof r === 'undefined' || r)
|
||||
that.close();
|
||||
});
|
||||
}
|
||||
if (this.$cancelButton) {
|
||||
this.$cancelButton.click(function (e) {
|
||||
e.preventDefault();
|
||||
var r = that.cancel(that.$b);
|
||||
that._stopCountDown();
|
||||
that.onAction('cancel');
|
||||
|
||||
if (typeof r === 'undefined' || r)
|
||||
that.close();
|
||||
});
|
||||
}
|
||||
if (this.$closeButton) {
|
||||
this.$closeButton.click(function (e) {
|
||||
e.preventDefault();
|
||||
that._stopCountDown();
|
||||
that.cancel();
|
||||
that.onAction('close');
|
||||
that.close();
|
||||
});
|
||||
}
|
||||
if (this.keyboardEnabled) {
|
||||
setTimeout(function () {
|
||||
$(window).on('keyup.' + this._rand, function (e) {
|
||||
that.reactOnKey(e);
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
$(window).on('resize.' + this._rand, function () {
|
||||
that.setDialogCenter(true);
|
||||
});
|
||||
},
|
||||
_getCSS: function (speed, bounce) {
|
||||
return {
|
||||
'-webkit-transition-duration': speed / 1000 + 's',
|
||||
'transition-duration': speed / 1000 + 's',
|
||||
'-webkit-transition-timing-function': 'cubic-bezier(.36,1.1,.2, ' + bounce + ')',
|
||||
'transition-timing-function': 'cubic-bezier(.36,1.1,.2, ' + bounce + ')'
|
||||
};
|
||||
},
|
||||
_imagesLoaded: function () {
|
||||
var that = this;
|
||||
$.each(this.$content.find('img:not(.loaded)'), function (i, a) {
|
||||
var interval = setInterval(function () {
|
||||
var h = $(a).css('height');
|
||||
if (h !== '0px') {
|
||||
$(a).addClass('loaded');
|
||||
that.setDialogCenter();
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 40);
|
||||
})
|
||||
},
|
||||
_setButtons: function () {
|
||||
/*
|
||||
* Settings up buttons
|
||||
*/
|
||||
this.$btnc = this.$el.find('.buttons');
|
||||
if (this.confirmButton && $.trim(this.confirmButton) !== '') {
|
||||
this.$confirmButton = $('<button type="button" class="btn">' + this.confirmButton + '</button>').appendTo(this.$btnc).addClass(this.confirmButtonClass);
|
||||
}
|
||||
if (this.cancelButton && $.trim(this.cancelButton) !== '') {
|
||||
this.$cancelButton = $('<button type="button" class="btn">' + this.cancelButton + '</button>').appendTo(this.$btnc).addClass(this.cancelButtonClass);
|
||||
}
|
||||
if (!this.confirmButton && !this.cancelButton) {
|
||||
this.$btnc.hide();
|
||||
}
|
||||
if (!this.confirmButton && !this.cancelButton && this.closeIcon === null) {
|
||||
this.$closeButton = this.$b.find('.closeIcon').show();
|
||||
}
|
||||
if (this.closeIcon === true) {
|
||||
this.$closeButton = this.$b.find('.closeIcon').show();
|
||||
}
|
||||
},
|
||||
setTitle: function (string) {
|
||||
this.title = (typeof string !== 'undefined') ? string : this.title;
|
||||
this.$title.html(this.title || '');
|
||||
},
|
||||
setIcon: function (iconClass) {
|
||||
this.title = (typeof string !== 'undefined') ? iconClass : this.title;
|
||||
this.$icon.html(this.icon ? '<i class="' + this.icon + '"></i>' : '');
|
||||
},
|
||||
setContent: function (string) {
|
||||
// only set the content on the modal.
|
||||
var that = this;
|
||||
this.content = (typeof string == 'undefined') ? this.content : string;
|
||||
|
||||
if (this.content == '') {
|
||||
this.$content.html(this.content);
|
||||
this.$contentPane.hide();
|
||||
} else {
|
||||
this.$content.html(this.content);
|
||||
this.$contentPane.show();
|
||||
}
|
||||
if (this.$content.hasClass('loading')) {
|
||||
this.$content.removeClass('loading');// it was loading via ajax.
|
||||
this.$btnc.find('button').prop('disabled', false);
|
||||
}
|
||||
},
|
||||
_getContent: function (string) {
|
||||
// get content from remote & stuff.
|
||||
var that = this;
|
||||
string = (string) ? string : this.content;
|
||||
this._isAjax = false;
|
||||
/*
|
||||
* Set content.
|
||||
*/
|
||||
if (!this.content) { // if the content is falsy
|
||||
this.content = '';
|
||||
this.setContent(this.content);
|
||||
this._contentReady.reject();
|
||||
} else if (typeof this.content === 'string') {
|
||||
if (this.content.substr(0, 4).toLowerCase() === 'url:') {
|
||||
this._isAjax = true;
|
||||
this.$content.addClass('loading');
|
||||
this.$btnc.find('button').prop('disabled', true);
|
||||
var url = this.content.substring(4, this.content.length);
|
||||
$.get(url).done(function (html) {
|
||||
that.content = html;
|
||||
that._contentReady.resolve();
|
||||
}).always(function (data, status, xhr) {
|
||||
if (typeof that.contentLoaded === 'function')
|
||||
that.contentLoaded(data, status, xhr);
|
||||
});
|
||||
} else {
|
||||
this.setContent(this.content);
|
||||
this._contentReady.reject();
|
||||
}
|
||||
} else if (typeof this.content === 'function') {
|
||||
this.$content.addClass('loading');
|
||||
this.$btnc.find('button').attr('disabled', 'disabled');
|
||||
var promise = this.content(this);
|
||||
if (typeof promise !== 'object') {
|
||||
console.error('The content function must return jquery promise.');
|
||||
} else if (typeof promise.always !== 'function') {
|
||||
console.error('The object returned is not a jquery promise.');
|
||||
} else {
|
||||
this._isAjax = true;
|
||||
promise.always(function (data, status) {
|
||||
that._contentReady.resolve();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error('Invalid option for property content, passed: ' + typeof this.content);
|
||||
}
|
||||
this.setDialogCenter();
|
||||
},
|
||||
_stopCountDown: function () {
|
||||
clearInterval(this.timerInterval);
|
||||
if (this.$cd)
|
||||
this.$cd.remove();
|
||||
},
|
||||
_startCountDown: function () {
|
||||
var opt = this.autoClose.split('|');
|
||||
if (/cancel/.test(opt[0]) && this.type === 'alert') {
|
||||
return false;
|
||||
} else if (/confirm|cancel/.test(opt[0])) {
|
||||
this.$cd = $('<span class="countdown">').appendTo(this['$' + opt[0] + 'Button']);
|
||||
var that = this;
|
||||
that.$cd.parent().click();
|
||||
var time = opt[1] / 1000;
|
||||
this.timerInterval = setInterval(function () {
|
||||
that.$cd.html(' (' + (time -= 1) + ')');
|
||||
if (time === 0) {
|
||||
that.$cd.html('');
|
||||
that.$cd.parent().trigger('click');
|
||||
clearInterval(that.timerInterval);
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
console.error('Invalid option ' + opt[0] + ', must be confirm/cancel');
|
||||
}
|
||||
},
|
||||
reactOnKey: function key(e) {
|
||||
|
||||
/*
|
||||
* prevent keyup event if the dialog is not last!
|
||||
*/
|
||||
var a = $('.jconfirm');
|
||||
if (a.eq(a.length - 1)[0] !== this.$el[0])
|
||||
return false;
|
||||
|
||||
var key = e.which;
|
||||
// Do not react if Enter/Space is pressed on input elements
|
||||
if (this.contentDiv.find(':input').is(':focus') && /13|32/.test(key))
|
||||
return false;
|
||||
|
||||
if ($.inArray(key, this.cancelKeys) !== -1) {
|
||||
/*
|
||||
* Cancel key pressed.
|
||||
*/
|
||||
if (this.$cancelButton) {
|
||||
this.$cancelButton.click();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}/*
|
||||
if ($.inArray(key, this.confirmKeys) !== -1) {
|
||||
*/
|
||||
/*
|
||||
* Confirm key pressed.
|
||||
*/
|
||||
/*
|
||||
if (this.$confirmButton) {
|
||||
this.$confirmButton.click();
|
||||
}
|
||||
}*/
|
||||
},
|
||||
setDialogCenter: function () {
|
||||
if (this.$contentPane.css('display') == 'none') {
|
||||
var contentHeight = 0;
|
||||
var paneHeight = 0;
|
||||
} else {
|
||||
var contentHeight = this.$content.outerHeight();
|
||||
var paneHeight = this.$contentPane.height();
|
||||
if (paneHeight == 0)
|
||||
paneHeight = contentHeight;
|
||||
}
|
||||
var off = 100;
|
||||
var w = this.$content.outerWidth();
|
||||
|
||||
//var s = '-clip-path: inset(0px 0px '+contentHeight+'px 0px);' +
|
||||
// 'clip-path: inset(0px 0px '+contentHeight+'px 0px)';
|
||||
|
||||
this.$content.css({
|
||||
'clip': 'rect(0px ' + (off + w) + 'px ' + contentHeight + 'px -' + off + 'px)'
|
||||
});
|
||||
|
||||
this.$contentPane.css({
|
||||
'height': contentHeight
|
||||
});
|
||||
|
||||
var windowHeight = $(window).height();
|
||||
var boxHeight = this.$b.outerHeight() - paneHeight + contentHeight;
|
||||
var topMargin = (windowHeight - boxHeight) / 2;
|
||||
var minMargin = 100;
|
||||
if (boxHeight > (windowHeight - minMargin)) {
|
||||
var style = {
|
||||
'margin-top': minMargin / 2,
|
||||
'margin-bottom': minMargin / 2
|
||||
}
|
||||
$('body').addClass('jconfirm-noscroll');
|
||||
} else {
|
||||
var style = {
|
||||
'margin-top': topMargin
|
||||
}
|
||||
$('body').removeClass('jconfirm-noscroll');
|
||||
}
|
||||
this.$b.css(style);
|
||||
},
|
||||
close: function () {
|
||||
var that = this;
|
||||
|
||||
if (this.isClosed())
|
||||
return false;
|
||||
|
||||
if (typeof this.onClose === 'function')
|
||||
this.onClose();
|
||||
|
||||
this._unwatchContent();
|
||||
that._lastFocused.focus();
|
||||
|
||||
//this.observer.disconnect();
|
||||
/*
|
||||
unbind the window resize & keyup event.
|
||||
*/
|
||||
$(window).unbind('resize.' + this._rand);
|
||||
if (this.keyboardEnabled)
|
||||
$(window).unbind('keyup.' + this._rand);
|
||||
|
||||
that.$el.find('.jconfirm-bg').removeClass('seen');
|
||||
$('body').removeClass('jconfirm-noscroll');
|
||||
|
||||
this.$b.addClass(this.closeAnimation);
|
||||
var closeTimer = (this.closeAnimation == 'anim-none') ? 0 : this.animationSpeed;
|
||||
setTimeout(function () {
|
||||
that.$el.remove();
|
||||
}, closeTimer * 25 / 100);
|
||||
|
||||
jconfirm.record.closed += 1;
|
||||
jconfirm.record.currentlyOpen -= 1;
|
||||
|
||||
return true;
|
||||
},
|
||||
open: function () {
|
||||
var that = this;
|
||||
if (this.isClosed())
|
||||
return false;
|
||||
|
||||
that.$el.find('.jconfirm-bg').addClass('seen');
|
||||
this.$b.removeClass(this.animation);
|
||||
jconfirm.record.opened += 1;
|
||||
jconfirm.record.currentlyOpen += 1;
|
||||
if (typeof this.onOpen === 'function')
|
||||
this.onOpen();
|
||||
|
||||
var jcr = 'jconfirm-box' + this._rand;
|
||||
this.$b.attr('aria-labelledby', jcr).attr('tabindex', -1).focus();
|
||||
this.$b.find('input[autofocus]:visible:first').focus();
|
||||
if (this.$title)
|
||||
this.$title.attr('id', jcr); else if (this.$content)
|
||||
this.$content.attr('id', jcr);
|
||||
|
||||
setTimeout(function () {
|
||||
that.$b.css({
|
||||
'transition-property': that.$b.css('transition-property') + ', margin'
|
||||
});
|
||||
that._modalReady.resolve();
|
||||
}, this.animationSpeed);
|
||||
|
||||
return true;
|
||||
},
|
||||
isClosed: function () {
|
||||
return this.$el.css('display') === '';
|
||||
}
|
||||
};
|
||||
|
||||
jconfirm.pluginDefaults = {
|
||||
template: '<div class="jconfirm"><div class="jconfirm-bg"></div><div class="jconfirm-scrollpane"><div class="container"><div class="row"><div class="jconfirm-box-container"><div class="jconfirm-box" role="dialog" aria-labelledby="labelled" tabindex="-1"><div class="closeIcon">×</div><div class="title-c"><span class="icon-c"></span><span class="title"></span></div><div class="content-pane"><div class="content"></div></div><div class="buttons"></div><div class="jquery-clear"></div></div></div></div></div></div></div>',
|
||||
title: 'Hello',
|
||||
content: 'Are you sure to continue?',
|
||||
contentLoaded: function () {
|
||||
},
|
||||
icon: '',
|
||||
opacity: 0.2,
|
||||
confirmButton: 'Okay',
|
||||
cancelButton: 'Close',
|
||||
confirmButtonClass: 'btn-default',
|
||||
cancelButtonClass: 'btn-default',
|
||||
theme: 'white',
|
||||
animation: 'zoom',
|
||||
closeAnimation: 'scale',
|
||||
animationSpeed: 500,
|
||||
animationBounce: 1.2,
|
||||
keyboardEnabled: false,
|
||||
rtl: false,
|
||||
confirmKeys: [13], // ENTER key
|
||||
cancelKeys: [27], // ESC key
|
||||
container: 'body',
|
||||
confirm: function () {
|
||||
},
|
||||
cancel: function () {
|
||||
},
|
||||
backgroundDismiss: false,
|
||||
autoClose: false,
|
||||
closeIcon: null,
|
||||
closeIconClass: false,
|
||||
watchInterval: 100,
|
||||
columnClass: 'col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3 col-xs-10 col-xs-offset-1',
|
||||
onOpen: function () {
|
||||
},
|
||||
onClose: function () {
|
||||
},
|
||||
onAction: function () {
|
||||
}
|
||||
};
|
||||
|
||||
jconfirm.record = {
|
||||
opened: 0,
|
||||
closed: 0,
|
||||
currentlyOpen: 0
|
||||
};
|
||||
})(jQuery);
|
6
kfet/static/kfet/js/jquery-ui.min.js
vendored
Normal file
6
kfet/static/kfet/js/jquery-ui.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
151
kfet/static/kfet/js/js.cookie.js
Normal file
151
kfet/static/kfet/js/js.cookie.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*!
|
||||
* JavaScript Cookie v2.1.2
|
||||
* https://github.com/js-cookie/js-cookie
|
||||
*
|
||||
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
|
||||
* Released under the MIT license
|
||||
*/
|
||||
;(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
var OldCookies = window.Cookies;
|
||||
var api = window.Cookies = factory();
|
||||
api.noConflict = function () {
|
||||
window.Cookies = OldCookies;
|
||||
return api;
|
||||
};
|
||||
}
|
||||
}(function () {
|
||||
function extend () {
|
||||
var i = 0;
|
||||
var result = {};
|
||||
for (; i < arguments.length; i++) {
|
||||
var attributes = arguments[ i ];
|
||||
for (var key in attributes) {
|
||||
result[key] = attributes[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function init (converter) {
|
||||
function api (key, value, attributes) {
|
||||
var result;
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write
|
||||
|
||||
if (arguments.length > 1) {
|
||||
attributes = extend({
|
||||
path: '/'
|
||||
}, api.defaults, attributes);
|
||||
|
||||
if (typeof attributes.expires === 'number') {
|
||||
var expires = new Date();
|
||||
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
|
||||
attributes.expires = expires;
|
||||
}
|
||||
|
||||
try {
|
||||
result = JSON.stringify(value);
|
||||
if (/^[\{\[]/.test(result)) {
|
||||
value = result;
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (!converter.write) {
|
||||
value = encodeURIComponent(String(value))
|
||||
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
|
||||
} else {
|
||||
value = converter.write(value, key);
|
||||
}
|
||||
|
||||
key = encodeURIComponent(String(key));
|
||||
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
|
||||
key = key.replace(/[\(\)]/g, escape);
|
||||
|
||||
return (document.cookie = [
|
||||
key, '=', value,
|
||||
attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
|
||||
attributes.path && '; path=' + attributes.path,
|
||||
attributes.domain && '; domain=' + attributes.domain,
|
||||
attributes.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// Read
|
||||
|
||||
if (!key) {
|
||||
result = {};
|
||||
}
|
||||
|
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all. Also prevents odd result when
|
||||
// calling "get()"
|
||||
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||
var rdecode = /(%[0-9A-Z]{2})+/g;
|
||||
var i = 0;
|
||||
|
||||
for (; i < cookies.length; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
var cookie = parts.slice(1).join('=');
|
||||
|
||||
if (cookie.charAt(0) === '"') {
|
||||
cookie = cookie.slice(1, -1);
|
||||
}
|
||||
|
||||
try {
|
||||
var name = parts[0].replace(rdecode, decodeURIComponent);
|
||||
cookie = converter.read ?
|
||||
converter.read(cookie, name) : converter(cookie, name) ||
|
||||
cookie.replace(rdecode, decodeURIComponent);
|
||||
|
||||
if (this.json) {
|
||||
try {
|
||||
cookie = JSON.parse(cookie);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (key === name) {
|
||||
result = cookie;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
result[name] = cookie;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
api.set = api;
|
||||
api.get = function (key) {
|
||||
return api(key);
|
||||
};
|
||||
api.getJSON = function () {
|
||||
return api.apply({
|
||||
json: true
|
||||
}, [].slice.call(arguments));
|
||||
};
|
||||
api.defaults = {};
|
||||
|
||||
api.remove = function (key, attributes) {
|
||||
api(key, '', extend(attributes, {
|
||||
expires: -1
|
||||
}));
|
||||
};
|
||||
|
||||
api.withConverter = init;
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
return init(function () {});
|
||||
}));
|
113
kfet/static/kfet/js/kfet.js
Normal file
113
kfet/static/kfet/js/kfet.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
$(document).ready(function() {
|
||||
$(window).scroll(function() {
|
||||
if ($(window).width() >= 768 && $(this).scrollTop() > 72.6) {
|
||||
$('.col-content-left').css({'position':'fixed', 'top':'50px'});
|
||||
$('.col-content-right').addClass('col-sm-offset-4 col-md-offset-3');
|
||||
} else {
|
||||
$('.col-content-left').css({'position':'relative', 'top':'0'});
|
||||
$('.col-content-right').removeClass('col-sm-offset-4 col-md-offset-3');
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof Cookies !== 'undefined') {
|
||||
// Retrieving csrf token
|
||||
csrftoken = Cookies.get('csrftoken');
|
||||
// Appending csrf token to ajax post requests
|
||||
function csrfSafeMethod(method) {
|
||||
// these HTTP methods do not require CSRF protection
|
||||
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||
}
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function dateUTCToParis(date) {
|
||||
return moment.tz(date, 'UTC').tz('Europe/Paris');
|
||||
}
|
||||
|
||||
function amountDisplay(amount, is_cof=false, tri='') {
|
||||
if (tri == 'LIQ')
|
||||
return (- amount).toFixed(2) +'€';
|
||||
return amountToUKF(amount, is_cof);
|
||||
}
|
||||
|
||||
function amountToUKF(amount, is_cof=false) {
|
||||
var coef_cof = is_cof ? 1 + settings['subvention_cof'] / 100 : 1;
|
||||
return Math.round(amount * coef_cof * 10);
|
||||
}
|
||||
|
||||
function isValidTrigramme(trigramme) {
|
||||
var pattern = /^[^a-z]{3}$/;
|
||||
return trigramme.match(pattern);
|
||||
}
|
||||
|
||||
function getErrorsHtml(data) {
|
||||
var content = '';
|
||||
if ('operation_group' in data['errors']) {
|
||||
content += 'Général';
|
||||
content += '<ul>';
|
||||
if (data['errors']['operation_group'].indexOf('on_acc') != -1)
|
||||
content += '<li>Pas de compte sélectionné</li>';
|
||||
if (data['errors']['operation_group'].indexOf('checkout') != -1)
|
||||
content += '<li>Pas de caisse sélectionnée</li>';
|
||||
content += '</ul>';
|
||||
}
|
||||
if ('missing_perms' in data['errors']) {
|
||||
content += 'Permissions manquantes';
|
||||
content += '<ul>';
|
||||
for (var i=0; i<data['errors']['missing_perms'].length; i++)
|
||||
content += '<li>'+data['errors']['missing_perms'][i]+'</li>';
|
||||
content += '</ul>';
|
||||
}
|
||||
if ('negative' in data['errors']) {
|
||||
var url_base = "{% url 'kfet.account.update' LIQ}";
|
||||
url_base = base_url(0, url_base.length-8);
|
||||
for (var i=0; i<data['errors']['negative'].length; i++) {
|
||||
content += '<a class="btn btn-primary" href="'+url_base+data['errors']['negative'][i]+'/edit" target="_blank" style="width:100%">Autorisation de négatif requise pour '+data['errors']['negative'][i]+'</a>';
|
||||
}
|
||||
}
|
||||
if ('addcost' in data['errors']) {
|
||||
content += '<ul>';
|
||||
if (data['errors']['addcost'].indexOf('__all__') != -1)
|
||||
content += '<li>Compte invalide</li>';
|
||||
if (data['errors']['addcost'].indexOf('amount') != -1)
|
||||
content += '<li>Montant invalide</li>';
|
||||
content += '</ul>';
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function requestAuth(data, callback, focus_next = null) {
|
||||
var content = getErrorsHtml(data);
|
||||
content += '<input type="password" name="password" autofocus>',
|
||||
$.confirm({
|
||||
title: 'Authentification requise',
|
||||
content: content,
|
||||
backgroundDismiss: true,
|
||||
animation:'top',
|
||||
closeAnimation:'bottom',
|
||||
keyboardEnabled: true,
|
||||
confirm: function() {
|
||||
var password = this.$content.find('input').val();
|
||||
callback(password);
|
||||
},
|
||||
onOpen: function() {
|
||||
var that = this;
|
||||
this.$content.find('input').on('keypress', function(e) {
|
||||
if (e.keyCode == 13)
|
||||
that.$confirmButton.click();
|
||||
});
|
||||
},
|
||||
onClose: function() {
|
||||
if (focus_next)
|
||||
this._lastFocused = focus_next;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
64
kfet/static/kfet/js/moment-fr.js
Normal file
64
kfet/static/kfet/js/moment-fr.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
//! moment.js locale configuration
|
||||
//! locale : French [fr]
|
||||
//! author : John Fischer : https://github.com/jfroffice
|
||||
|
||||
;(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined'
|
||||
&& typeof require === 'function' ? factory(require('../moment')) :
|
||||
typeof define === 'function' && define.amd ? define(['../moment'], factory) :
|
||||
factory(global.moment)
|
||||
}(this, function (moment) { 'use strict';
|
||||
|
||||
|
||||
var fr = moment.defineLocale('fr', {
|
||||
months : 'Janvier_Février_Mars_Avril_Mai_Juin_Juillet_Août_Septembre_Octobre_Novembre_Décembre'.split('_'),
|
||||
monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
|
||||
monthsParseExact : true,
|
||||
weekdays : 'Dimanche_Lundi_Mardi_Mercredi_Jeudi_Vendredi_Samedi'.split('_'),
|
||||
weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
|
||||
weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
|
||||
weekdaysParseExact : true,
|
||||
longDateFormat : {
|
||||
LT : 'HH:mm',
|
||||
LTS : 'HH:mm:ss',
|
||||
L : 'DD/MM/YYYY',
|
||||
LL : 'D MMMM YYYY',
|
||||
LLL : 'D MMMM YYYY HH:mm',
|
||||
LLLL : 'dddd D MMMM YYYY HH:mm'
|
||||
},
|
||||
calendar : {
|
||||
sameDay: '[Aujourd\'hui à] LT',
|
||||
nextDay: '[Demain à] LT',
|
||||
nextWeek: 'dddd [à] LT',
|
||||
lastDay: '[Hier à] LT',
|
||||
lastWeek: 'dddd [dernier à] LT',
|
||||
sameElse: 'L'
|
||||
},
|
||||
relativeTime : {
|
||||
future : 'dans %s',
|
||||
past : 'il y a %s',
|
||||
s : 'quelques secondes',
|
||||
m : 'une minute',
|
||||
mm : '%d minutes',
|
||||
h : 'une heure',
|
||||
hh : '%d heures',
|
||||
d : 'un jour',
|
||||
dd : '%d jours',
|
||||
M : 'un mois',
|
||||
MM : '%d mois',
|
||||
y : 'un an',
|
||||
yy : '%d ans'
|
||||
},
|
||||
ordinalParse: /\d{1,2}(er|)/,
|
||||
ordinal : function (number) {
|
||||
return number + (number === 1 ? 'er' : '');
|
||||
},
|
||||
week : {
|
||||
dow : 1, // Monday is the first day of the week.
|
||||
doy : 4 // The week that contains Jan 4th is the first week of the year.
|
||||
}
|
||||
});
|
||||
|
||||
return fr;
|
||||
|
||||
}));
|
1196
kfet/static/kfet/js/moment-timezone-with-data-2010-2020.js
Normal file
1196
kfet/static/kfet/js/moment-timezone-with-data-2010-2020.js
Normal file
File diff suppressed because it is too large
Load diff
4195
kfet/static/kfet/js/moment.js
Normal file
4195
kfet/static/kfet/js/moment.js
Normal file
File diff suppressed because it is too large
Load diff
782
kfet/static/kfet/js/multiple-select.js
Normal file
782
kfet/static/kfet/js/multiple-select.js
Normal file
|
@ -0,0 +1,782 @@
|
|||
/**
|
||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||
* @version 1.2.1
|
||||
*
|
||||
* http://wenzhixin.net.cn/p/multiple-select/
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// it only does '%s', and return '' when arguments are undefined
|
||||
var sprintf = function (str) {
|
||||
var args = arguments,
|
||||
flag = true,
|
||||
i = 1;
|
||||
|
||||
str = str.replace(/%s/g, function () {
|
||||
var arg = args[i++];
|
||||
|
||||
if (typeof arg === 'undefined') {
|
||||
flag = false;
|
||||
return '';
|
||||
}
|
||||
return arg;
|
||||
});
|
||||
return flag ? str : '';
|
||||
};
|
||||
|
||||
var removeDiacritics = function (str) {
|
||||
var defaultDiacriticsRemovalMap = [
|
||||
{'base':'A', 'letters':/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},
|
||||
{'base':'AA','letters':/[\uA732]/g},
|
||||
{'base':'AE','letters':/[\u00C6\u01FC\u01E2]/g},
|
||||
{'base':'AO','letters':/[\uA734]/g},
|
||||
{'base':'AU','letters':/[\uA736]/g},
|
||||
{'base':'AV','letters':/[\uA738\uA73A]/g},
|
||||
{'base':'AY','letters':/[\uA73C]/g},
|
||||
{'base':'B', 'letters':/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
|
||||
{'base':'C', 'letters':/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},
|
||||
{'base':'D', 'letters':/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},
|
||||
{'base':'DZ','letters':/[\u01F1\u01C4]/g},
|
||||
{'base':'Dz','letters':/[\u01F2\u01C5]/g},
|
||||
{'base':'E', 'letters':/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},
|
||||
{'base':'F', 'letters':/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
|
||||
{'base':'G', 'letters':/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},
|
||||
{'base':'H', 'letters':/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},
|
||||
{'base':'I', 'letters':/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},
|
||||
{'base':'J', 'letters':/[\u004A\u24BF\uFF2A\u0134\u0248]/g},
|
||||
{'base':'K', 'letters':/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},
|
||||
{'base':'L', 'letters':/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},
|
||||
{'base':'LJ','letters':/[\u01C7]/g},
|
||||
{'base':'Lj','letters':/[\u01C8]/g},
|
||||
{'base':'M', 'letters':/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
|
||||
{'base':'N', 'letters':/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},
|
||||
{'base':'NJ','letters':/[\u01CA]/g},
|
||||
{'base':'Nj','letters':/[\u01CB]/g},
|
||||
{'base':'O', 'letters':/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},
|
||||
{'base':'OI','letters':/[\u01A2]/g},
|
||||
{'base':'OO','letters':/[\uA74E]/g},
|
||||
{'base':'OU','letters':/[\u0222]/g},
|
||||
{'base':'P', 'letters':/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
|
||||
{'base':'Q', 'letters':/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
|
||||
{'base':'R', 'letters':/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},
|
||||
{'base':'S', 'letters':/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},
|
||||
{'base':'T', 'letters':/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},
|
||||
{'base':'TZ','letters':/[\uA728]/g},
|
||||
{'base':'U', 'letters':/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},
|
||||
{'base':'V', 'letters':/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
|
||||
{'base':'VY','letters':/[\uA760]/g},
|
||||
{'base':'W', 'letters':/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},
|
||||
{'base':'X', 'letters':/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
|
||||
{'base':'Y', 'letters':/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},
|
||||
{'base':'Z', 'letters':/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},
|
||||
{'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},
|
||||
{'base':'aa','letters':/[\uA733]/g},
|
||||
{'base':'ae','letters':/[\u00E6\u01FD\u01E3]/g},
|
||||
{'base':'ao','letters':/[\uA735]/g},
|
||||
{'base':'au','letters':/[\uA737]/g},
|
||||
{'base':'av','letters':/[\uA739\uA73B]/g},
|
||||
{'base':'ay','letters':/[\uA73D]/g},
|
||||
{'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},
|
||||
{'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},
|
||||
{'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},
|
||||
{'base':'dz','letters':/[\u01F3\u01C6]/g},
|
||||
{'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},
|
||||
{'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},
|
||||
{'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},
|
||||
{'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},
|
||||
{'base':'hv','letters':/[\u0195]/g},
|
||||
{'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},
|
||||
{'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},
|
||||
{'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},
|
||||
{'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},
|
||||
{'base':'lj','letters':/[\u01C9]/g},
|
||||
{'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},
|
||||
{'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},
|
||||
{'base':'nj','letters':/[\u01CC]/g},
|
||||
{'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},
|
||||
{'base':'oi','letters':/[\u01A3]/g},
|
||||
{'base':'ou','letters':/[\u0223]/g},
|
||||
{'base':'oo','letters':/[\uA74F]/g},
|
||||
{'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},
|
||||
{'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},
|
||||
{'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},
|
||||
{'base':'s','letters':/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},
|
||||
{'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},
|
||||
{'base':'tz','letters':/[\uA729]/g},
|
||||
{'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},
|
||||
{'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},
|
||||
{'base':'vy','letters':/[\uA761]/g},
|
||||
{'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},
|
||||
{'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},
|
||||
{'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},
|
||||
{'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}
|
||||
];
|
||||
|
||||
for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
|
||||
str = str.replace(defaultDiacriticsRemovalMap[i].letters, defaultDiacriticsRemovalMap[i].base);
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
};
|
||||
|
||||
function MultipleSelect($el, options) {
|
||||
var that = this,
|
||||
name = $el.attr('name') || options.name || '';
|
||||
|
||||
this.options = options;
|
||||
|
||||
// hide select element
|
||||
this.$el = $el.hide();
|
||||
|
||||
// label element
|
||||
this.$label = this.$el.closest('label');
|
||||
if (this.$label.length === 0 && this.$el.attr('id')) {
|
||||
this.$label = $(sprintf('label[for="%s"]', this.$el.attr('id').replace(/:/g, '\\:')));
|
||||
}
|
||||
|
||||
// restore class and title from select element
|
||||
this.$parent = $(sprintf(
|
||||
'<div class="ms-parent %s" %s/>',
|
||||
$el.attr('class') || '',
|
||||
sprintf('title="%s"', $el.attr('title'))));
|
||||
|
||||
// add placeholder to choice button
|
||||
this.$choice = $(sprintf([
|
||||
'<button type="button" class="ms-choice">',
|
||||
'<span class="placeholder">%s</span>',
|
||||
'<div></div>',
|
||||
'</button>'
|
||||
].join(''),
|
||||
this.options.placeholder));
|
||||
|
||||
// default position is bottom
|
||||
this.$drop = $(sprintf('<div class="ms-drop %s"%s></div>',
|
||||
this.options.position,
|
||||
sprintf(' style="width: %s"', this.options.dropWidth)));
|
||||
|
||||
this.$el.after(this.$parent);
|
||||
this.$parent.append(this.$choice);
|
||||
this.$parent.append(this.$drop);
|
||||
|
||||
if (this.$el.prop('disabled')) {
|
||||
this.$choice.addClass('disabled');
|
||||
}
|
||||
this.$parent.css('width',
|
||||
this.options.width ||
|
||||
this.$el.css('width') ||
|
||||
this.$el.outerWidth() + 20);
|
||||
|
||||
this.selectAllName = 'data-name="selectAll' + name + '"';
|
||||
this.selectGroupName = 'data-name="selectGroup' + name + '"';
|
||||
this.selectItemName = 'data-name="selectItem' + name + '"';
|
||||
|
||||
if (!this.options.keepOpen) {
|
||||
$(document).click(function (e) {
|
||||
if ($(e.target)[0] === that.$choice[0] ||
|
||||
$(e.target).parents('.ms-choice')[0] === that.$choice[0]) {
|
||||
return;
|
||||
}
|
||||
if (($(e.target)[0] === that.$drop[0] ||
|
||||
$(e.target).parents('.ms-drop')[0] !== that.$drop[0] && e.target !== $el[0]) &&
|
||||
that.options.isOpen) {
|
||||
that.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
MultipleSelect.prototype = {
|
||||
constructor: MultipleSelect,
|
||||
|
||||
init: function () {
|
||||
var that = this,
|
||||
$ul = $('<ul></ul>');
|
||||
|
||||
this.$drop.html('');
|
||||
|
||||
if (this.options.filter) {
|
||||
this.$drop.append([
|
||||
'<div class="ms-search">',
|
||||
'<input type="text" autocomplete="off" autocorrect="off" autocapitilize="off" spellcheck="false">',
|
||||
'</div>'].join('')
|
||||
);
|
||||
}
|
||||
|
||||
if (this.options.selectAll && !this.options.single) {
|
||||
$ul.append([
|
||||
'<li class="ms-select-all">',
|
||||
'<label>',
|
||||
sprintf('<input type="checkbox" %s /> ', this.selectAllName),
|
||||
this.options.selectAllDelimiter[0],
|
||||
this.options.selectAllText,
|
||||
this.options.selectAllDelimiter[1],
|
||||
'</label>',
|
||||
'</li>'
|
||||
].join(''));
|
||||
}
|
||||
|
||||
$.each(this.$el.children(), function (i, elm) {
|
||||
$ul.append(that.optionToHtml(i, elm));
|
||||
});
|
||||
$ul.append(sprintf('<li class="ms-no-results">%s</li>', this.options.noMatchesFound));
|
||||
this.$drop.append($ul);
|
||||
|
||||
this.$drop.find('ul').css('max-height', this.options.maxHeight + 'px');
|
||||
this.$drop.find('.multiple').css('width', this.options.multipleWidth + 'px');
|
||||
|
||||
this.$searchInput = this.$drop.find('.ms-search input');
|
||||
this.$selectAll = this.$drop.find('input[' + this.selectAllName + ']');
|
||||
this.$selectGroups = this.$drop.find('input[' + this.selectGroupName + ']');
|
||||
this.$selectItems = this.$drop.find('input[' + this.selectItemName + ']:enabled');
|
||||
this.$disableItems = this.$drop.find('input[' + this.selectItemName + ']:disabled');
|
||||
this.$noResults = this.$drop.find('.ms-no-results');
|
||||
|
||||
this.events();
|
||||
this.updateSelectAll(true);
|
||||
this.update(true);
|
||||
|
||||
if (this.options.isOpen) {
|
||||
this.open();
|
||||
}
|
||||
},
|
||||
|
||||
optionToHtml: function (i, elm, group, groupDisabled) {
|
||||
var that = this,
|
||||
$elm = $(elm),
|
||||
classes = $elm.attr('class') || '',
|
||||
title = sprintf('title="%s"', $elm.attr('title')),
|
||||
multiple = this.options.multiple ? 'multiple' : '',
|
||||
disabled,
|
||||
type = this.options.single ? 'radio' : 'checkbox';
|
||||
|
||||
if ($elm.is('option')) {
|
||||
var value = $elm.val(),
|
||||
text = that.options.textTemplate($elm),
|
||||
selected = $elm.prop('selected'),
|
||||
style = sprintf('style="%s"', this.options.styler(value)),
|
||||
$el;
|
||||
|
||||
disabled = groupDisabled || $elm.prop('disabled');
|
||||
|
||||
$el = $([
|
||||
sprintf('<li class="%s %s" %s %s>', multiple, classes, title, style),
|
||||
sprintf('<label class="%s">', disabled ? 'disabled' : ''),
|
||||
sprintf('<input type="%s" %s%s%s%s>',
|
||||
type, this.selectItemName,
|
||||
selected ? ' checked="checked"' : '',
|
||||
disabled ? ' disabled="disabled"' : '',
|
||||
sprintf(' data-group="%s"', group)),
|
||||
sprintf('<span>%s</span>', text),
|
||||
'</label>',
|
||||
'</li>'
|
||||
].join(''));
|
||||
$el.find('input').val(value);
|
||||
return $el;
|
||||
}
|
||||
if ($elm.is('optgroup')) {
|
||||
var label = that.options.labelTemplate($elm),
|
||||
$group = $('<div/>');
|
||||
|
||||
group = 'group_' + i;
|
||||
disabled = $elm.prop('disabled');
|
||||
|
||||
$group.append([
|
||||
'<li class="group">',
|
||||
sprintf('<label class="optgroup %s" data-group="%s">', disabled ? 'disabled' : '', group),
|
||||
this.options.hideOptgroupCheckboxes || this.options.single ? '' :
|
||||
sprintf('<input type="checkbox" %s %s>',
|
||||
this.selectGroupName, disabled ? 'disabled="disabled"' : ''),
|
||||
label,
|
||||
'</label>',
|
||||
'</li>'
|
||||
].join(''));
|
||||
|
||||
$.each($elm.children(), function (i, elm) {
|
||||
$group.append(that.optionToHtml(i, elm, group, disabled));
|
||||
});
|
||||
return $group.html();
|
||||
}
|
||||
},
|
||||
|
||||
events: function () {
|
||||
var that = this,
|
||||
toggleOpen = function (e) {
|
||||
e.preventDefault();
|
||||
that[that.options.isOpen ? 'close' : 'open']();
|
||||
};
|
||||
|
||||
if (this.$label) {
|
||||
this.$label.off('click').on('click', function (e) {
|
||||
if (e.target.nodeName.toLowerCase() !== 'label' || e.target !== this) {
|
||||
return;
|
||||
}
|
||||
toggleOpen(e);
|
||||
if (!that.options.filter || !that.options.isOpen) {
|
||||
that.focus();
|
||||
}
|
||||
e.stopPropagation(); // Causes lost focus otherwise
|
||||
});
|
||||
}
|
||||
|
||||
this.$choice.off('click').on('click', toggleOpen)
|
||||
.off('focus').on('focus', this.options.onFocus)
|
||||
.off('blur').on('blur', this.options.onBlur);
|
||||
|
||||
this.$parent.off('keydown').on('keydown', function (e) {
|
||||
switch (e.which) {
|
||||
case 27: // esc key
|
||||
that.close();
|
||||
that.$choice.focus();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
this.$searchInput.off('keydown').on('keydown',function (e) {
|
||||
// Ensure shift-tab causes lost focus from filter as with clicking away
|
||||
if (e.keyCode === 9 && e.shiftKey) {
|
||||
that.close();
|
||||
}
|
||||
}).off('keyup').on('keyup', function (e) {
|
||||
// enter or space
|
||||
// Avoid selecting/deselecting if no choices made
|
||||
if (that.options.filterAcceptOnEnter && (e.which === 13 || e.which == 32) && that.$searchInput.val()) {
|
||||
that.$selectAll.click();
|
||||
that.close();
|
||||
that.focus();
|
||||
return;
|
||||
}
|
||||
that.filter();
|
||||
});
|
||||
|
||||
this.$selectAll.off('click').on('click', function () {
|
||||
var checked = $(this).prop('checked'),
|
||||
$items = that.$selectItems.filter(':visible');
|
||||
|
||||
if ($items.length === that.$selectItems.length) {
|
||||
that[checked ? 'checkAll' : 'uncheckAll']();
|
||||
} else { // when the filter option is true
|
||||
that.$selectGroups.prop('checked', checked);
|
||||
$items.prop('checked', checked);
|
||||
that.options[checked ? 'onCheckAll' : 'onUncheckAll']();
|
||||
that.update();
|
||||
}
|
||||
});
|
||||
this.$selectGroups.off('click').on('click', function () {
|
||||
var group = $(this).parent().attr('data-group'),
|
||||
$items = that.$selectItems.filter(':visible'),
|
||||
$children = $items.filter(sprintf('[data-group="%s"]', group)),
|
||||
checked = $children.length !== $children.filter(':checked').length;
|
||||
|
||||
$children.prop('checked', checked);
|
||||
that.updateSelectAll();
|
||||
that.update();
|
||||
that.options.onOptgroupClick({
|
||||
label: $(this).parent().text(),
|
||||
checked: checked,
|
||||
children: $children.get(),
|
||||
instance: that
|
||||
});
|
||||
});
|
||||
this.$selectItems.off('click').on('click', function () {
|
||||
that.updateSelectAll();
|
||||
that.update();
|
||||
that.updateOptGroupSelect();
|
||||
that.options.onClick({
|
||||
label: $(this).parent().text(),
|
||||
value: $(this).val(),
|
||||
checked: $(this).prop('checked'),
|
||||
instance: that
|
||||
});
|
||||
|
||||
if (that.options.single && that.options.isOpen && !that.options.keepOpen) {
|
||||
that.close();
|
||||
}
|
||||
|
||||
if (that.options.single) {
|
||||
var clickedVal = $(this).val();
|
||||
that.$selectItems.filter(function() {
|
||||
return $(this).val() !== clickedVal;
|
||||
}).each(function() {
|
||||
$(this).prop('checked', false);
|
||||
});
|
||||
that.update();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
open: function () {
|
||||
if (this.$choice.hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
this.options.isOpen = true;
|
||||
this.$choice.find('>div').addClass('open');
|
||||
this.$drop[this.animateMethod('show')]();
|
||||
|
||||
// fix filter bug: no results show
|
||||
this.$selectAll.parent().show();
|
||||
this.$noResults.hide();
|
||||
|
||||
// Fix #77: 'All selected' when no options
|
||||
if (!this.$el.children().length) {
|
||||
this.$selectAll.parent().hide();
|
||||
this.$noResults.show();
|
||||
}
|
||||
|
||||
if (this.options.container) {
|
||||
var offset = this.$drop.offset();
|
||||
this.$drop.appendTo($(this.options.container));
|
||||
this.$drop.offset({
|
||||
top: offset.top,
|
||||
left: offset.left
|
||||
});
|
||||
}
|
||||
|
||||
if (this.options.filter) {
|
||||
this.$searchInput.val('');
|
||||
this.$searchInput.focus();
|
||||
this.filter();
|
||||
}
|
||||
this.options.onOpen();
|
||||
},
|
||||
|
||||
close: function () {
|
||||
this.options.isOpen = false;
|
||||
this.$choice.find('>div').removeClass('open');
|
||||
this.$drop[this.animateMethod('hide')]();
|
||||
if (this.options.container) {
|
||||
this.$parent.append(this.$drop);
|
||||
this.$drop.css({
|
||||
'top': 'auto',
|
||||
'left': 'auto'
|
||||
});
|
||||
}
|
||||
this.options.onClose();
|
||||
},
|
||||
|
||||
animateMethod: function (method) {
|
||||
var methods = {
|
||||
show: {
|
||||
fade: 'fadeIn',
|
||||
slide: 'slideDown'
|
||||
},
|
||||
hide: {
|
||||
fade: 'fadeOut',
|
||||
slide: 'slideUp'
|
||||
}
|
||||
};
|
||||
|
||||
return methods[method][this.options.animate] || method;
|
||||
},
|
||||
|
||||
update: function (isInit) {
|
||||
var selects = this.options.displayValues ? this.getSelects() : this.getSelects('text'),
|
||||
$span = this.$choice.find('>span'),
|
||||
sl = selects.length;
|
||||
|
||||
if (sl === 0) {
|
||||
$span.addClass('placeholder').html(this.options.placeholder);
|
||||
} else if (this.options.allSelected && sl === this.$selectItems.length + this.$disableItems.length) {
|
||||
$span.removeClass('placeholder').html(this.options.allSelected);
|
||||
} else if (this.options.ellipsis && sl > this.options.minimumCountSelected) {
|
||||
$span.removeClass('placeholder').text(selects.slice(0, this.options.minimumCountSelected)
|
||||
.join(this.options.delimiter) + '...');
|
||||
} else if (this.options.countSelected && sl > this.options.minimumCountSelected) {
|
||||
$span.removeClass('placeholder').html(this.options.countSelected
|
||||
.replace('#', selects.length)
|
||||
.replace('%', this.$selectItems.length + this.$disableItems.length));
|
||||
} else {
|
||||
$span.removeClass('placeholder').text(selects.join(this.options.delimiter));
|
||||
}
|
||||
|
||||
if (this.options.addTitle) {
|
||||
$span.prop('title', this.getSelects('text'));
|
||||
}
|
||||
|
||||
// set selects to select
|
||||
this.$el.val(this.getSelects()).trigger('change');
|
||||
|
||||
// add selected class to selected li
|
||||
this.$drop.find('li').removeClass('selected');
|
||||
this.$drop.find('input:checked').each(function () {
|
||||
$(this).parents('li').first().addClass('selected');
|
||||
});
|
||||
|
||||
// trigger <select> change event
|
||||
if (!isInit) {
|
||||
this.$el.trigger('change');
|
||||
}
|
||||
},
|
||||
|
||||
updateSelectAll: function (isInit) {
|
||||
var $items = this.$selectItems;
|
||||
|
||||
if (!isInit) {
|
||||
$items = $items.filter(':visible');
|
||||
}
|
||||
this.$selectAll.prop('checked', $items.length &&
|
||||
$items.length === $items.filter(':checked').length);
|
||||
if (!isInit && this.$selectAll.prop('checked')) {
|
||||
this.options.onCheckAll();
|
||||
}
|
||||
},
|
||||
|
||||
updateOptGroupSelect: function () {
|
||||
var $items = this.$selectItems.filter(':visible');
|
||||
$.each(this.$selectGroups, function (i, val) {
|
||||
var group = $(val).parent().attr('data-group'),
|
||||
$children = $items.filter(sprintf('[data-group="%s"]', group));
|
||||
$(val).prop('checked', $children.length &&
|
||||
$children.length === $children.filter(':checked').length);
|
||||
});
|
||||
},
|
||||
|
||||
//value or text, default: 'value'
|
||||
getSelects: function (type) {
|
||||
var that = this,
|
||||
texts = [],
|
||||
values = [];
|
||||
this.$drop.find(sprintf('input[%s]:checked', this.selectItemName)).each(function () {
|
||||
texts.push($(this).parents('li').first().text());
|
||||
values.push($(this).val());
|
||||
});
|
||||
|
||||
if (type === 'text' && this.$selectGroups.length) {
|
||||
texts = [];
|
||||
this.$selectGroups.each(function () {
|
||||
var html = [],
|
||||
text = $.trim($(this).parent().text()),
|
||||
group = $(this).parent().data('group'),
|
||||
$children = that.$drop.find(sprintf('[%s][data-group="%s"]', that.selectItemName, group)),
|
||||
$selected = $children.filter(':checked');
|
||||
|
||||
if (!$selected.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
html.push('[');
|
||||
html.push(text);
|
||||
if ($children.length > $selected.length) {
|
||||
var list = [];
|
||||
$selected.each(function () {
|
||||
list.push($(this).parent().text());
|
||||
});
|
||||
html.push(': ' + list.join(', '));
|
||||
}
|
||||
html.push(']');
|
||||
texts.push(html.join(''));
|
||||
});
|
||||
}
|
||||
return type === 'text' ? texts : values;
|
||||
},
|
||||
|
||||
setSelects: function (values) {
|
||||
var that = this;
|
||||
this.$selectItems.prop('checked', false);
|
||||
this.$disableItems.prop('checked', false);
|
||||
$.each(values, function (i, value) {
|
||||
that.$selectItems.filter(sprintf('[value="%s"]', value)).prop('checked', true);
|
||||
that.$disableItems.filter(sprintf('[value="%s"]', value)).prop('checked', true);
|
||||
});
|
||||
this.$selectAll.prop('checked', this.$selectItems.length ===
|
||||
this.$selectItems.filter(':checked').length + this.$disableItems.filter(':checked').length);
|
||||
|
||||
$.each(that.$selectGroups, function (i, val) {
|
||||
var group = $(val).parent().attr('data-group'),
|
||||
$children = that.$selectItems.filter('[data-group="' + group + '"]');
|
||||
$(val).prop('checked', $children.length &&
|
||||
$children.length === $children.filter(':checked').length);
|
||||
});
|
||||
|
||||
this.update();
|
||||
},
|
||||
|
||||
enable: function () {
|
||||
this.$choice.removeClass('disabled');
|
||||
},
|
||||
|
||||
disable: function () {
|
||||
this.$choice.addClass('disabled');
|
||||
},
|
||||
|
||||
checkAll: function () {
|
||||
this.$selectItems.prop('checked', true);
|
||||
this.$selectGroups.prop('checked', true);
|
||||
this.$selectAll.prop('checked', true);
|
||||
this.update();
|
||||
this.options.onCheckAll();
|
||||
},
|
||||
|
||||
uncheckAll: function () {
|
||||
this.$selectItems.prop('checked', false);
|
||||
this.$selectGroups.prop('checked', false);
|
||||
this.$selectAll.prop('checked', false);
|
||||
this.update();
|
||||
this.options.onUncheckAll();
|
||||
},
|
||||
|
||||
focus: function () {
|
||||
this.$choice.focus();
|
||||
this.options.onFocus();
|
||||
},
|
||||
|
||||
blur: function () {
|
||||
this.$choice.blur();
|
||||
this.options.onBlur();
|
||||
},
|
||||
|
||||
refresh: function () {
|
||||
this.init();
|
||||
},
|
||||
|
||||
filter: function () {
|
||||
var that = this,
|
||||
text = $.trim(this.$searchInput.val()).toLowerCase();
|
||||
|
||||
if (text.length === 0) {
|
||||
this.$selectAll.parent().show();
|
||||
this.$selectItems.parent().show();
|
||||
this.$disableItems.parent().show();
|
||||
this.$selectGroups.parent().show();
|
||||
this.$noResults.hide();
|
||||
} else {
|
||||
this.$selectItems.each(function () {
|
||||
var $parent = $(this).parent();
|
||||
$parent[removeDiacritics($parent.text().toLowerCase()).indexOf(removeDiacritics(text)) < 0 ? 'hide' : 'show']();
|
||||
});
|
||||
this.$disableItems.parent().hide();
|
||||
this.$selectGroups.each(function () {
|
||||
var $parent = $(this).parent();
|
||||
var group = $parent.attr('data-group'),
|
||||
$items = that.$selectItems.filter(':visible');
|
||||
$parent[$items.filter(sprintf('[data-group="%s"]', group)).length ? 'show' : 'hide']();
|
||||
});
|
||||
|
||||
//Check if no matches found
|
||||
if (this.$selectItems.parent().filter(':visible').length) {
|
||||
this.$selectAll.parent().show();
|
||||
this.$noResults.hide();
|
||||
} else {
|
||||
this.$selectAll.parent().hide();
|
||||
this.$noResults.show();
|
||||
}
|
||||
}
|
||||
this.updateOptGroupSelect();
|
||||
this.updateSelectAll();
|
||||
this.options.onFilter(text);
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.multipleSelect = function () {
|
||||
var option = arguments[0],
|
||||
args = arguments,
|
||||
|
||||
value,
|
||||
allowedMethods = [
|
||||
'getSelects', 'setSelects',
|
||||
'enable', 'disable',
|
||||
'open', 'close',
|
||||
'checkAll', 'uncheckAll',
|
||||
'focus', 'blur',
|
||||
'refresh', 'close'
|
||||
];
|
||||
|
||||
this.each(function () {
|
||||
var $this = $(this),
|
||||
data = $this.data('multipleSelect'),
|
||||
options = $.extend({}, $.fn.multipleSelect.defaults,
|
||||
$this.data(), typeof option === 'object' && option);
|
||||
|
||||
if (!data) {
|
||||
data = new MultipleSelect($this, options);
|
||||
$this.data('multipleSelect', data);
|
||||
}
|
||||
|
||||
if (typeof option === 'string') {
|
||||
if ($.inArray(option, allowedMethods) < 0) {
|
||||
throw 'Unknown method: ' + option;
|
||||
}
|
||||
value = data[option](args[1]);
|
||||
} else {
|
||||
data.init();
|
||||
if (args[1]) {
|
||||
value = data[args[1]].apply(data, [].slice.call(args, 2));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeof value !== 'undefined' ? value : this;
|
||||
};
|
||||
|
||||
$.fn.multipleSelect.defaults = {
|
||||
name: '',
|
||||
isOpen: false,
|
||||
placeholder: '',
|
||||
selectAll: true,
|
||||
selectAllDelimiter: ['[', ']'],
|
||||
minimumCountSelected: 3,
|
||||
ellipsis: false,
|
||||
multiple: false,
|
||||
multipleWidth: 80,
|
||||
single: false,
|
||||
filter: false,
|
||||
width: undefined,
|
||||
dropWidth: undefined,
|
||||
maxHeight: 250,
|
||||
container: null,
|
||||
position: 'bottom',
|
||||
keepOpen: false,
|
||||
animate: 'none', // 'none', 'fade', 'slide'
|
||||
displayValues: false,
|
||||
delimiter: ', ',
|
||||
addTitle: false,
|
||||
filterAcceptOnEnter: false,
|
||||
hideOptgroupCheckboxes: false,
|
||||
|
||||
selectAllText: 'Select all',
|
||||
allSelected: 'All selected',
|
||||
countSelected: '# of % selected',
|
||||
noMatchesFound: 'No matches found',
|
||||
|
||||
styler: function () {
|
||||
return false;
|
||||
},
|
||||
textTemplate: function ($elm) {
|
||||
return $elm.html();
|
||||
},
|
||||
labelTemplate: function ($elm) {
|
||||
return $elm.attr('label');
|
||||
},
|
||||
|
||||
onOpen: function () {
|
||||
return false;
|
||||
},
|
||||
onClose: function () {
|
||||
return false;
|
||||
},
|
||||
onCheckAll: function () {
|
||||
return false;
|
||||
},
|
||||
onUncheckAll: function () {
|
||||
return false;
|
||||
},
|
||||
onFocus: function () {
|
||||
return false;
|
||||
},
|
||||
onBlur: function () {
|
||||
return false;
|
||||
},
|
||||
onOptgroupClick: function () {
|
||||
return false;
|
||||
},
|
||||
onClick: function () {
|
||||
return false;
|
||||
},
|
||||
onFilter: function () {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
365
kfet/static/kfet/js/reconnecting-websocket.js
Normal file
365
kfet/static/kfet/js/reconnecting-websocket.js
Normal file
|
@ -0,0 +1,365 @@
|
|||
// MIT License:
|
||||
//
|
||||
// Copyright (c) 2010-2012, Joe Walnes
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/**
|
||||
* This behaves like a WebSocket in every way, except if it fails to connect,
|
||||
* or it gets disconnected, it will repeatedly poll until it successfully connects
|
||||
* again.
|
||||
*
|
||||
* It is API compatible, so when you have:
|
||||
* ws = new WebSocket('ws://....');
|
||||
* you can replace with:
|
||||
* ws = new ReconnectingWebSocket('ws://....');
|
||||
*
|
||||
* The event stream will typically look like:
|
||||
* onconnecting
|
||||
* onopen
|
||||
* onmessage
|
||||
* onmessage
|
||||
* onclose // lost connection
|
||||
* onconnecting
|
||||
* onopen // sometime later...
|
||||
* onmessage
|
||||
* onmessage
|
||||
* etc...
|
||||
*
|
||||
* It is API compatible with the standard WebSocket API, apart from the following members:
|
||||
*
|
||||
* - `bufferedAmount`
|
||||
* - `extensions`
|
||||
* - `binaryType`
|
||||
*
|
||||
* Latest version: https://github.com/joewalnes/reconnecting-websocket/
|
||||
* - Joe Walnes
|
||||
*
|
||||
* Syntax
|
||||
* ======
|
||||
* var socket = new ReconnectingWebSocket(url, protocols, options);
|
||||
*
|
||||
* Parameters
|
||||
* ==========
|
||||
* url - The url you are connecting to.
|
||||
* protocols - Optional string or array of protocols.
|
||||
* options - See below
|
||||
*
|
||||
* Options
|
||||
* =======
|
||||
* Options can either be passed upon instantiation or set after instantiation:
|
||||
*
|
||||
* var socket = new ReconnectingWebSocket(url, null, { debug: true, reconnectInterval: 4000 });
|
||||
*
|
||||
* or
|
||||
*
|
||||
* var socket = new ReconnectingWebSocket(url);
|
||||
* socket.debug = true;
|
||||
* socket.reconnectInterval = 4000;
|
||||
*
|
||||
* debug
|
||||
* - Whether this instance should log debug messages. Accepts true or false. Default: false.
|
||||
*
|
||||
* automaticOpen
|
||||
* - Whether or not the websocket should attempt to connect immediately upon instantiation. The socket can be manually opened or closed at any time using ws.open() and ws.close().
|
||||
*
|
||||
* reconnectInterval
|
||||
* - The number of milliseconds to delay before attempting to reconnect. Accepts integer. Default: 1000.
|
||||
*
|
||||
* maxReconnectInterval
|
||||
* - The maximum number of milliseconds to delay a reconnection attempt. Accepts integer. Default: 30000.
|
||||
*
|
||||
* reconnectDecay
|
||||
* - The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. Accepts integer or float. Default: 1.5.
|
||||
*
|
||||
* timeoutInterval
|
||||
* - The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. Accepts integer. Default: 2000.
|
||||
*
|
||||
*/
|
||||
(function (global, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], factory);
|
||||
} else if (typeof module !== 'undefined' && module.exports){
|
||||
module.exports = factory();
|
||||
} else {
|
||||
global.ReconnectingWebSocket = factory();
|
||||
}
|
||||
})(this, function () {
|
||||
|
||||
if (!('WebSocket' in window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
function ReconnectingWebSocket(url, protocols, options) {
|
||||
|
||||
// Default settings
|
||||
var settings = {
|
||||
|
||||
/** Whether this instance should log debug messages. */
|
||||
debug: false,
|
||||
|
||||
/** Whether or not the websocket should attempt to connect immediately upon instantiation. */
|
||||
automaticOpen: true,
|
||||
|
||||
/** The number of milliseconds to delay before attempting to reconnect. */
|
||||
reconnectInterval: 1000,
|
||||
/** The maximum number of milliseconds to delay a reconnection attempt. */
|
||||
maxReconnectInterval: 30000,
|
||||
/** The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. */
|
||||
reconnectDecay: 1.5,
|
||||
|
||||
/** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. */
|
||||
timeoutInterval: 2000,
|
||||
|
||||
/** The maximum number of reconnection attempts to make. Unlimited if null. */
|
||||
maxReconnectAttempts: null,
|
||||
|
||||
/** The binary type, possible values 'blob' or 'arraybuffer', default 'blob'. */
|
||||
binaryType: 'blob'
|
||||
}
|
||||
if (!options) { options = {}; }
|
||||
|
||||
// Overwrite and define settings with options if they exist.
|
||||
for (var key in settings) {
|
||||
if (typeof options[key] !== 'undefined') {
|
||||
this[key] = options[key];
|
||||
} else {
|
||||
this[key] = settings[key];
|
||||
}
|
||||
}
|
||||
|
||||
// These should be treated as read-only properties
|
||||
|
||||
/** The URL as resolved by the constructor. This is always an absolute URL. Read only. */
|
||||
this.url = url;
|
||||
|
||||
/** The number of attempted reconnects since starting, or the last successful connection. Read only. */
|
||||
this.reconnectAttempts = 0;
|
||||
|
||||
/**
|
||||
* The current state of the connection.
|
||||
* Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
|
||||
* Read only.
|
||||
*/
|
||||
this.readyState = WebSocket.CONNECTING;
|
||||
|
||||
/**
|
||||
* A string indicating the name of the sub-protocol the server selected; this will be one of
|
||||
* the strings specified in the protocols parameter when creating the WebSocket object.
|
||||
* Read only.
|
||||
*/
|
||||
this.protocol = null;
|
||||
|
||||
// Private state variables
|
||||
|
||||
var self = this;
|
||||
var ws;
|
||||
var forcedClose = false;
|
||||
var timedOut = false;
|
||||
var eventTarget = document.createElement('div');
|
||||
|
||||
// Wire up "on*" properties as event handlers
|
||||
|
||||
eventTarget.addEventListener('open', function(event) { self.onopen(event); });
|
||||
eventTarget.addEventListener('close', function(event) { self.onclose(event); });
|
||||
eventTarget.addEventListener('connecting', function(event) { self.onconnecting(event); });
|
||||
eventTarget.addEventListener('message', function(event) { self.onmessage(event); });
|
||||
eventTarget.addEventListener('error', function(event) { self.onerror(event); });
|
||||
|
||||
// Expose the API required by EventTarget
|
||||
|
||||
this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
|
||||
this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
|
||||
this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
|
||||
|
||||
/**
|
||||
* This function generates an event that is compatible with standard
|
||||
* compliant browsers and IE9 - IE11
|
||||
*
|
||||
* This will prevent the error:
|
||||
* Object doesn't support this action
|
||||
*
|
||||
* http://stackoverflow.com/questions/19345392/why-arent-my-parameters-getting-passed-through-to-a-dispatched-event/19345563#19345563
|
||||
* @param s String The name that the event should use
|
||||
* @param args Object an optional object that the event will use
|
||||
*/
|
||||
function generateEvent(s, args) {
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(s, false, false, args);
|
||||
return evt;
|
||||
};
|
||||
|
||||
this.open = function (reconnectAttempt) {
|
||||
ws = new WebSocket(self.url, protocols || []);
|
||||
ws.binaryType = this.binaryType;
|
||||
|
||||
if (reconnectAttempt) {
|
||||
if (this.maxReconnectAttempts && this.reconnectAttempts > this.maxReconnectAttempts) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
eventTarget.dispatchEvent(generateEvent('connecting'));
|
||||
this.reconnectAttempts = 0;
|
||||
}
|
||||
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'attempt-connect', self.url);
|
||||
}
|
||||
|
||||
var localWs = ws;
|
||||
var timeout = setTimeout(function() {
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'connection-timeout', self.url);
|
||||
}
|
||||
timedOut = true;
|
||||
localWs.close();
|
||||
timedOut = false;
|
||||
}, self.timeoutInterval);
|
||||
|
||||
ws.onopen = function(event) {
|
||||
clearTimeout(timeout);
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'onopen', self.url);
|
||||
}
|
||||
self.protocol = ws.protocol;
|
||||
self.readyState = WebSocket.OPEN;
|
||||
self.reconnectAttempts = 0;
|
||||
var e = generateEvent('open');
|
||||
e.isReconnect = reconnectAttempt;
|
||||
reconnectAttempt = false;
|
||||
eventTarget.dispatchEvent(e);
|
||||
};
|
||||
|
||||
ws.onclose = function(event) {
|
||||
clearTimeout(timeout);
|
||||
ws = null;
|
||||
if (forcedClose) {
|
||||
self.readyState = WebSocket.CLOSED;
|
||||
eventTarget.dispatchEvent(generateEvent('close'));
|
||||
} else {
|
||||
self.readyState = WebSocket.CONNECTING;
|
||||
var e = generateEvent('connecting');
|
||||
e.code = event.code;
|
||||
e.reason = event.reason;
|
||||
e.wasClean = event.wasClean;
|
||||
eventTarget.dispatchEvent(e);
|
||||
if (!reconnectAttempt && !timedOut) {
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'onclose', self.url);
|
||||
}
|
||||
eventTarget.dispatchEvent(generateEvent('close'));
|
||||
}
|
||||
|
||||
var timeout = self.reconnectInterval * Math.pow(self.reconnectDecay, self.reconnectAttempts);
|
||||
setTimeout(function() {
|
||||
self.reconnectAttempts++;
|
||||
self.open(true);
|
||||
}, timeout > self.maxReconnectInterval ? self.maxReconnectInterval : timeout);
|
||||
}
|
||||
};
|
||||
ws.onmessage = function(event) {
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'onmessage', self.url, event.data);
|
||||
}
|
||||
var e = generateEvent('message');
|
||||
e.data = event.data;
|
||||
eventTarget.dispatchEvent(e);
|
||||
};
|
||||
ws.onerror = function(event) {
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'onerror', self.url, event);
|
||||
}
|
||||
eventTarget.dispatchEvent(generateEvent('error'));
|
||||
};
|
||||
}
|
||||
|
||||
// Whether or not to create a websocket upon instantiation
|
||||
if (this.automaticOpen == true) {
|
||||
this.open(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmits data to the server over the WebSocket connection.
|
||||
*
|
||||
* @param data a text string, ArrayBuffer or Blob to send to the server.
|
||||
*/
|
||||
this.send = function(data) {
|
||||
if (ws) {
|
||||
if (self.debug || ReconnectingWebSocket.debugAll) {
|
||||
console.debug('ReconnectingWebSocket', 'send', self.url, data);
|
||||
}
|
||||
return ws.send(data);
|
||||
} else {
|
||||
throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the WebSocket connection or connection attempt, if any.
|
||||
* If the connection is already CLOSED, this method does nothing.
|
||||
*/
|
||||
this.close = function(code, reason) {
|
||||
// Default CLOSE_NORMAL code
|
||||
if (typeof code == 'undefined') {
|
||||
code = 1000;
|
||||
}
|
||||
forcedClose = true;
|
||||
if (ws) {
|
||||
ws.close(code, reason);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Additional public API method to refresh the connection if still open (close, re-open).
|
||||
* For example, if the app suspects bad data / missed heart beats, it can try to refresh.
|
||||
*/
|
||||
this.refresh = function() {
|
||||
if (ws) {
|
||||
ws.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* An event listener to be called when the WebSocket connection's readyState changes to OPEN;
|
||||
* this indicates that the connection is ready to send and receive data.
|
||||
*/
|
||||
ReconnectingWebSocket.prototype.onopen = function(event) {};
|
||||
/** An event listener to be called when the WebSocket connection's readyState changes to CLOSED. */
|
||||
ReconnectingWebSocket.prototype.onclose = function(event) {};
|
||||
/** An event listener to be called when a connection begins being attempted. */
|
||||
ReconnectingWebSocket.prototype.onconnecting = function(event) {};
|
||||
/** An event listener to be called when a message is received from the server. */
|
||||
ReconnectingWebSocket.prototype.onmessage = function(event) {};
|
||||
/** An event listener to be called when an error occurs. */
|
||||
ReconnectingWebSocket.prototype.onerror = function(event) {};
|
||||
|
||||
/**
|
||||
* Whether all instances of ReconnectingWebSocket should log debug messages.
|
||||
* Setting this to true is the equivalent of setting all instances of ReconnectingWebSocket.debug to true.
|
||||
*/
|
||||
ReconnectingWebSocket.debugAll = false;
|
||||
|
||||
ReconnectingWebSocket.CONNECTING = WebSocket.CONNECTING;
|
||||
ReconnectingWebSocket.OPEN = WebSocket.OPEN;
|
||||
ReconnectingWebSocket.CLOSING = WebSocket.CLOSING;
|
||||
ReconnectingWebSocket.CLOSED = WebSocket.CLOSED;
|
||||
|
||||
return ReconnectingWebSocket;
|
||||
});
|
68
kfet/templates/kfet/account.html
Normal file
68
kfet/templates/kfet/account.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
{% extends "kfet/base.html" %}
|
||||
|
||||
{% block title %}Liste des comptes{% endblock %}
|
||||
{% block content-header-title %}Comptes{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-content-left">
|
||||
<div class="content-left">
|
||||
<div class="content-left-top">
|
||||
<div class="line line-big">{{ accounts|length|add:-1 }}</div>
|
||||
<div class="line line-bigsub">compte{{ accounts|length|add:-1|pluralize }}</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-primary btn-lg" href="{% url 'kfet.account.create' %}">Créer un compte</a>
|
||||
{% if perms.kfet.manage_perms %}
|
||||
<a class="btn btn-primary btn-lg" href="{% url 'kfet.account.group' %}">Permissions</a>
|
||||
{% endif %}
|
||||
{% if perms.kfet.view_negs %}
|
||||
<a class="btn btn-primary btn-lg" href="{% url 'kfet.account.negative' %}">Négatifs</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-9 col-content-right">
|
||||
{% include 'kfet/base_messages.html' %}
|
||||
<div class="content-right">
|
||||
<div class="content-right-block">
|
||||
<h2>Liste des comptes</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Trigramme</td>
|
||||
<td>Nom</td>
|
||||
<td>Balance</td>
|
||||
<td>COF</td>
|
||||
<td>Dpt</td>
|
||||
<td>Promo</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for account in accounts %}
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'kfet.account.read' account.trigramme %}">
|
||||
<span class="glyphicon glyphicon-cog"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ account.trigramme }}</td>
|
||||
<td>{{ account.name }}</td>
|
||||
<td class="text-right">{{ account.balance }}€</td>
|
||||
<td>{{ account.is_cof }}</td>
|
||||
<td>{{ account.departement }}</td>
|
||||
<td>{{ account.promo|default_if_none:'' }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
95
kfet/templates/kfet/account_create.html
Normal file
95
kfet/templates/kfet/account_create.html
Normal file
|
@ -0,0 +1,95 @@
|
|||
{% extends "kfet/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Nouveau compte{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script src="{% static "autocomplete_light/autocomplete.js" %}" type="text/javascript"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content-header-title %}Création d'un compte{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include 'kfet/base_messages.html' %}
|
||||
|
||||
<div class="row form-only">
|
||||
<div class="col-sm-12 col-md-8 col-md-offset-2">
|
||||
<div class="content-form">
|
||||
<form action="{% url "kfet.account.create" %}" method="post" class="account_create">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
{{ trigramme_form.trigramme.errors }}
|
||||
{{ trigramme_form.trigramme }}
|
||||
</div>
|
||||
<div id="trigramme_valid"></div>
|
||||
<input type="text" name="q" id="search_autocomplete" spellcheck="false" placeholder="Chercher un utilisateur par nom, prénom ou identifiant clipper" class="form-control">
|
||||
<div style="position:relative;">
|
||||
<div id="search_results"></div>
|
||||
</div>
|
||||
<div class="form-horizontal">
|
||||
<div id="form-placeholder">
|
||||
{% include 'kfet/account_create_form.html' %}
|
||||
</div>
|
||||
{% if not perms.kfet.add_account %}
|
||||
{% include 'kfet/form_authentication_snippet.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
// Affichage des résultats d'autocomplétion
|
||||
$('input#search_autocomplete').yourlabsAutocomplete({
|
||||
url: '{% url "kfet.account.create.autocomplete" %}',
|
||||
minimumCharacters: 0,
|
||||
id: 'search_autocomplete',
|
||||
choiceSelector: 'li:has(a)',
|
||||
container: $("#search_results"),
|
||||
box: $("#search_results"),
|
||||
});
|
||||
|
||||
// Chargement du formulaire adapté au choix sélectionné
|
||||
$('input#search_autocomplete').bind(
|
||||
'selectChoice',
|
||||
function(e, choice, autocomplete) {
|
||||
autocomplete.hide();
|
||||
link = choice.find('a:first');
|
||||
if (link.length && link.attr('href') != undefined) {
|
||||
$('#form-placeholder').html("").load(link.attr('href'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Vérification client de la validité
|
||||
// et de ladisponibilité du trigramme choisi
|
||||
$('#id_trigramme').on('input', function() {
|
||||
var trigramme = $('#id_trigramme').val().toUpperCase();
|
||||
var container = '#trigramme_valid';
|
||||
|
||||
var pattern = /^[^a-z]{3}$/;
|
||||
if (!(trigramme.match(pattern))) {
|
||||
$('#id_trigramme')
|
||||
.css('background', '#fff')
|
||||
.css('color', '#000');
|
||||
} else {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: "{% url "kfet.account.is_validandfree.ajax" %}",
|
||||
data: { trigramme: trigramme },
|
||||
}).done(function(data) {
|
||||
if (data['is_free']) {
|
||||
$('#id_trigramme').css('background', '#009011');
|
||||
} else {
|
||||
$('#id_trigramme').css('background', '#C8102E');
|
||||
}
|
||||
$('#id_trigramme').css('color', '#fff');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
49
kfet/templates/kfet/account_create_autocomplete.html
Normal file
49
kfet/templates/kfet/account_create_autocomplete.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
{% load kfet_tags %}
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.empty" %}">
|
||||
Créer un compte
|
||||
</a>
|
||||
</li>
|
||||
{% if kfet %}
|
||||
<li class="user_category"><span class="text">Comptes existant</span></li>
|
||||
{% for account, user in kfet %}
|
||||
<li><span class="text">{{ account }} [{{ user|highlight_user:q }}]</span></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if users_cof %}
|
||||
<li class="user_category"><span class="text">Membres du COF</span></li>
|
||||
{% for user in users_cof %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromuser" user.username %}">
|
||||
{{ user|highlight_user:q }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if users_notcof %}
|
||||
<li class="user_category"><span class="text">Non-membres du COF</span></li>
|
||||
{% for user in users_notcof %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromuser" user.username %}">
|
||||
{{ user|highlight_user:q }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if clippers %}
|
||||
<li class="user_category"><span class="text">Utilisateurs clipper</span></li>
|
||||
{% for clipper in clippers %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromclipper" clipper.username %}">
|
||||
{{ clipper|highlight_clipper:q }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if not q %}
|
||||
<li class="user_category"><span class="text">Pas de recherche, pas de résultats !</span></li>
|
||||
{% elif not options %}
|
||||
<li class="user_category"><span class="text">Aucune correspondance trouvée :-(</span></li>
|
||||
{% endif %}
|
||||
</ul>
|
9
kfet/templates/kfet/account_create_form.html
Normal file
9
kfet/templates/kfet/account_create_form.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
{% load widget_tweaks %}
|
||||
|
||||
{% include 'kfet/form_snippet.html' with form=user_form %}
|
||||
{% include 'kfet/form_snippet.html' with form=cof_form %}
|
||||
{% include 'kfet/form_snippet.html' with form=account_form %}
|
||||
|
||||
{% if user_form %}
|
||||
{% include 'kfet/form_submit_snippet.html' with value="Enregistrer" %}
|
||||
{% endif %}
|
96
kfet/templates/kfet/account_create_special.html
Normal file
96
kfet/templates/kfet/account_create_special.html
Normal file
|
@ -0,0 +1,96 @@
|
|||
{% extends "kfet/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Nouveau compte{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script src="{% static "autocomplete_light/autocomplete.js" %}" type="text/javascript"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content-header-title %}Création d'un compte{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include 'kfet/base_messages.html' %}
|
||||
|
||||
<div class="row form-only">
|
||||
<div class="col-sm-12 col-md-8 col-md-offset-2">
|
||||
<div class="content-form">
|
||||
<form action="{% url "kfet.account.create_special" %}" method="post" class="account_create">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
{{ trigramme_form.trigramme.errors }}
|
||||
{{ trigramme_form.trigramme }}
|
||||
{{ balance_form }}
|
||||
</div>
|
||||
<div id="trigramme_valid"></div>
|
||||
<input type="text" name="q" id="search_autocomplete" spellcheck="false" placeholder="Chercher un utilisateur par nom, prénom ou identifiant clipper" class="form-control">
|
||||
<div style="position:relative;">
|
||||
<div id="search_results"></div>
|
||||
</div>
|
||||
<div class="form-horizontal">
|
||||
<div id="form-placeholder">
|
||||
{% include 'kfet/account_create_form.html' %}
|
||||
</div>
|
||||
{% if not perms.kfet.add_account %}
|
||||
{% include 'kfet/form_authentication_snippet.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
// Affichage des résultats d'autocomplétion
|
||||
$('input#search_autocomplete').yourlabsAutocomplete({
|
||||
url: '{% url "kfet.account.create.autocomplete" %}',
|
||||
minimumCharacters: 0,
|
||||
id: 'search_autocomplete',
|
||||
choiceSelector: 'li:has(a)',
|
||||
container: $("#search_results"),
|
||||
box: $("#search_results"),
|
||||
});
|
||||
|
||||
// Chargement du formulaire adapté au choix sélectionné
|
||||
$('input#search_autocomplete').bind(
|
||||
'selectChoice',
|
||||
function(e, choice, autocomplete) {
|
||||
autocomplete.hide();
|
||||
link = choice.find('a:first');
|
||||
if (link.length && link.attr('href') != undefined) {
|
||||
$('#form-placeholder').html("").load(link.attr('href'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Vérification client de la validité
|
||||
// et de ladisponibilité du trigramme choisi
|
||||
$('#id_trigramme').on('input', function() {
|
||||
var trigramme = $('#id_trigramme').val().toUpperCase();
|
||||
var container = '#trigramme_valid';
|
||||
|
||||
var pattern = /^[^a-z]{3}$/;
|
||||
if (!(trigramme.match(pattern))) {
|
||||
$('#id_trigramme')
|
||||
.css('background', '#fff')
|
||||
.css('color', '#000');
|
||||
} else {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: "{% url "kfet.account.is_validandfree.ajax" %}",
|
||||
data: { trigramme: trigramme },
|
||||
}).done(function(data) {
|
||||
if (data['is_free']) {
|
||||
$('#id_trigramme').css('background', '#009011');
|
||||
} else {
|
||||
$('#id_trigramme').css('background', '#C8102E');
|
||||
}
|
||||
$('#id_trigramme').css('color', '#fff');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
54
kfet/templates/kfet/account_group.html
Normal file
54
kfet/templates/kfet/account_group.html
Normal file
|
@ -0,0 +1,54 @@
|
|||
{% extends 'kfet/base.html' %}
|
||||
|
||||
{% block title %}Groupes de comptes{% endblock %}
|
||||
{% block content-header-title %}Groupes de comptes{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-content-left">
|
||||
<div class="content-left">
|
||||
<div class="content-left-top text-center">
|
||||
<div class="line"></div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-primary btn-lg" href="{% url 'kfet.account.group.create' %}">Créer un groupe</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-9 col-content-right">
|
||||
{% include 'kfet/base_messages.html' %}
|
||||
<div class="content-right">
|
||||
{% for group in groups %}
|
||||
<div class="content-right-block">
|
||||
<div class="buttons-title">
|
||||
<a class="btn btn-primary" href="{% url 'kfet.account.group.update' group.pk %}">
|
||||
<span class="glyphicon glyphicon-cog"></span>
|
||||
</a>
|
||||
</div>
|
||||
<h2>{{ group.name }}</h2>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h3>Permissions</h3>
|
||||
<ul>
|
||||
{% for perm in group.permissions.all %}
|
||||
<li>{{ perm.name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<h3>Comptes</h3>
|
||||
<ul>
|
||||
{% for user in group.user_set.all %}
|
||||
<li>{{ user.profile.account_kfet }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue