Merge branch 'k-fet' of git.eleves.ens.fr:cof-geek/gestioCOF
This commit is contained in:
commit
bb6c3fdd20
140 changed files with 17827 additions and 2 deletions
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',
|
'django_cas_ng',
|
||||||
'debug_toolbar',
|
'debug_toolbar',
|
||||||
'bootstrapform',
|
'bootstrapform',
|
||||||
|
'kfet',
|
||||||
|
'channels',
|
||||||
|
'widget_tweaks',
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE_CLASSES = (
|
||||||
|
@ -58,6 +61,7 @@ MIDDLEWARE_CLASSES = (
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||||
|
'kfet.middleware.KFetAuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
@ -80,6 +84,7 @@ TEMPLATES = [
|
||||||
'django.core.context_processors.media',
|
'django.core.context_processors.media',
|
||||||
'django.core.context_processors.static',
|
'django.core.context_processors.static',
|
||||||
'gestioncof.shared.context_processor',
|
'gestioncof.shared.context_processor',
|
||||||
|
'kfet.context_processors.auth',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -87,7 +92,6 @@ TEMPLATES = [
|
||||||
|
|
||||||
# WSGI_APPLICATION = 'cof.wsgi.application'
|
# WSGI_APPLICATION = 'cof.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||||
|
|
||||||
|
@ -120,6 +124,10 @@ USE_TZ = True
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
STATICFILES_DIRS = (
|
||||||
|
os.path.join(BASE_DIR, 'static/'),
|
||||||
|
)
|
||||||
|
|
||||||
# Media upload (through ImageField, SiteField)
|
# Media upload (through ImageField, SiteField)
|
||||||
# https://docs.djangoproject.com/en/1.9/ref/models/fields/
|
# https://docs.djangoproject.com/en/1.9/ref/models/fields/
|
||||||
|
|
||||||
|
@ -161,6 +169,17 @@ RECAPTCHA_PUBLIC_KEY = "DUMMY"
|
||||||
RECAPTCHA_PRIVATE_KEY = "DUMMY"
|
RECAPTCHA_PRIVATE_KEY = "DUMMY"
|
||||||
RECAPTCHA_USE_SSL = True
|
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):
|
def show_toolbar(request):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -81,6 +81,7 @@ urlpatterns = [
|
||||||
url(r'^utile_bda/bda_diff$', gestioncof_views.liste_bdadiff),
|
url(r'^utile_bda/bda_diff$', gestioncof_views.liste_bdadiff),
|
||||||
url(r'^utile_cof/diff_cof$', gestioncof_views.liste_diffcof),
|
url(r'^utile_cof/diff_cof$', gestioncof_views.liste_diffcof),
|
||||||
url(r'^utile_bda/bda_revente$', gestioncof_views.liste_bdarevente),
|
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)
|
(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
if settings.DEBUG
|
if settings.DEBUG
|
||||||
|
|
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 %}
|
38
kfet/templates/kfet/account_group_form.html
Normal file
38
kfet/templates/kfet/account_group_form.html
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{% extends 'kfet/base.html' %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
<link rel="stylesheet" text="text/css" href="{% static 'kfet/css/multiple-select.css' %}">
|
||||||
|
<script src="{% static 'kfet/js/multiple-select.js' %}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div>
|
||||||
|
{{ form.name.errors }}
|
||||||
|
{{ form.name.label_tag }}
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon">K-Fêt</span>
|
||||||
|
{{ form.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ form.permissions.errors }}
|
||||||
|
{{ form.permissions.label_tag }}
|
||||||
|
{{ form.permissions }}
|
||||||
|
</div>
|
||||||
|
<input type="submit" value="Enregistrer">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$("select").multipleSelect({
|
||||||
|
width: 500,
|
||||||
|
filter: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
80
kfet/templates/kfet/account_negative.html
Normal file
80
kfet/templates/kfet/account_negative.html
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
{% extends 'kfet/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Comptes en négatifs{% endblock %}
|
||||||
|
{% block content-header-title %}Comptes - Négatifs{% 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">{{ negatives|length }}</div>
|
||||||
|
<div class="line line-bigsub">compte{{ negatives|length|pluralize }} en négatif</div>
|
||||||
|
<div class="block">
|
||||||
|
<div class="line"><b>Total:</b> {{ negatives_sum|floatformat:2 }}€</div>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<div class="line"><b>Découvert autorisé par défaut</b></div>
|
||||||
|
<div class="line">Montant: {{ settings.overdraft_amount }}€</div>
|
||||||
|
<div class="line">Pendant: {{ settings.overdraft_duration }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if perms.kfet.change_settings %}
|
||||||
|
<div class="buttons">
|
||||||
|
<a class="btn btn-primary btn-lg" href="{% url 'kfet.settings' %}">Modifier les valeurs par défaut</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</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 en négatifs</h2>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>Tri</td>
|
||||||
|
<td>Nom</td>
|
||||||
|
<td>Balance</td>
|
||||||
|
<td>Réelle</td>
|
||||||
|
<td>Début</td>
|
||||||
|
<td>Découvert autorisé</td>
|
||||||
|
<td>Jusqu'au</td>
|
||||||
|
<td>Balance offset</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for neg in negatives %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="{% url 'kfet.account.update' neg.account.trigramme %}">
|
||||||
|
<span class="glyphicon glyphicon-cog"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ neg.account.trigramme }}</td>
|
||||||
|
<td>{{ neg.account.name }}</td>
|
||||||
|
<td class="text-right">{{ neg.account.balance|floatformat:2 }}€</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{% if neg.account.balance_offset %}
|
||||||
|
{{ neg.account.real_balance|floatformat:2 }}€
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{ neg.start|date:'d/m/Y H:i:s'}}</td>
|
||||||
|
<td>{{ neg.authz_overdraft_amount|default_if_none:'' }}</td>
|
||||||
|
<td>{{ neg.authz_overdrafy_until|default_if_none:'' }}</td>
|
||||||
|
<td>{{ neg.balance_offset|default_if_none:'' }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
95
kfet/templates/kfet/account_read.html
Normal file
95
kfet/templates/kfet/account_read.html
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
{% extends "kfet/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load kfet_tags %}
|
||||||
|
{% load l10n %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/js.cookie.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/moment.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/moment-fr.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/moment-timezone-with-data-2010-2020.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/kfet.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/history.js' %}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% if account.user == request.user %}
|
||||||
|
Mon compte
|
||||||
|
{% else %}
|
||||||
|
Informations du compte {{ account.trigramme }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content-header-title %}
|
||||||
|
{% if account.user == request.user %}
|
||||||
|
Mon compte
|
||||||
|
{% else %}
|
||||||
|
Compte - {{ account.trigramme }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4 col-md-3 col-content-left">
|
||||||
|
<div class="content-left">
|
||||||
|
{% include 'kfet/left_account.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8 col-md-9 col-content-right">
|
||||||
|
{% include "kfet/base_messages.html" %}
|
||||||
|
<div class="content-right">
|
||||||
|
{% if addcosts %}
|
||||||
|
<div class="content-right-block">
|
||||||
|
<h2>Gagné des majorations</h2>
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
{% for addcost in addcosts %}
|
||||||
|
<li>{{ addcost.date|date:'l j F' }}: +{{ addcost.sum_addcosts }}€</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="content-right-block">
|
||||||
|
<h2>Historique</h2>
|
||||||
|
<div id="history">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
settings = { 'subvention_cof': parseFloat({{ settings.subvention_cof|unlocalize }})}
|
||||||
|
|
||||||
|
khistory = new KHistory({
|
||||||
|
display_trigramme: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
function getHistory() {
|
||||||
|
var data = {
|
||||||
|
'accounts': [{{ account.pk }}],
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
dataType: "json",
|
||||||
|
url : "{% url 'kfet.history.json' %}",
|
||||||
|
method : "POST",
|
||||||
|
data : data,
|
||||||
|
})
|
||||||
|
.done(function(data) {
|
||||||
|
for (var i=0; i<data['opegroups'].length; i++) {
|
||||||
|
khistory.addOpeGroup(data['opegroups'][i]);
|
||||||
|
}
|
||||||
|
var nb_opes = khistory.$container.find('.ope:not(.canceled)').length;
|
||||||
|
$('#nb_opes').text(nb_opes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getHistory();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
5
kfet/templates/kfet/account_read_title.html
Normal file
5
kfet/templates/kfet/account_read_title.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% if account.user == request.user %}
|
||||||
|
Mon compte
|
||||||
|
{% else %}
|
||||||
|
Informations du compte {{ account.trigramme }}
|
||||||
|
{% endif %}
|
61
kfet/templates/kfet/account_update.html
Normal file
61
kfet/templates/kfet/account_update.html
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
{% extends "kfet/base.html" %}
|
||||||
|
{% load widget_tweaks %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
{{ negative_form.media }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% if account.user == request.user %}
|
||||||
|
Modification de mes informations
|
||||||
|
{% else %}
|
||||||
|
{{ account.trigramme }} - Édition
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content-header-title %}
|
||||||
|
{% if account.user == request.user %}
|
||||||
|
Modification de mes informations
|
||||||
|
{% else %}
|
||||||
|
Édition du compte {{ account.trigramme }}
|
||||||
|
{% endif %}
|
||||||
|
{% 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.update' account.trigramme %}" method="post" class="form-horizontal">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% 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 %}
|
||||||
|
{% include 'kfet/form_snippet.html' with form=group_form %}
|
||||||
|
{% include 'kfet/form_snippet.html' with form=pwd_form %}
|
||||||
|
{% include 'kfet/form_snippet.html' with form=negative_form %}
|
||||||
|
{% if perms.kfet.is_team %}
|
||||||
|
{% include 'kfet/form_authentication_snippet.html' %}
|
||||||
|
{% endif %}
|
||||||
|
{% include 'kfet/form_submit_snippet.html' with value="Mettre à jour" %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#id_authz_overdraft_until').datetimepicker({
|
||||||
|
format: 'YYYY-MM-DD HH:mm',
|
||||||
|
stepping: 5,
|
||||||
|
locale: 'fr',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
67
kfet/templates/kfet/article.html
Normal file
67
kfet/templates/kfet/article.html
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
{% extends 'kfet/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Articles{% endblock %}
|
||||||
|
{% block content-header-title %}Articles{% 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">{{ articles|length }}</div>
|
||||||
|
<div class="line line-bigsub">article{{ articles|length|pluralize }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
|
<a class="btn btn-primary btn-lg" href="{% url 'kfet.article.create' %}">
|
||||||
|
Nouvel article
|
||||||
|
</a>
|
||||||
|
</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 articles</h2>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>Nom</td>
|
||||||
|
<td class="text-right">Prix</td>
|
||||||
|
<td class="text-right">Stock</td>
|
||||||
|
<td class="text-right">En vente</td>
|
||||||
|
<td class="text-right">Dernier inventaire</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for article in articles %}
|
||||||
|
{% ifchanged article.category %}
|
||||||
|
<tr class="section">
|
||||||
|
<td colspan="6">{{ article.category.name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endifchanged %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="{% url 'kfet.article.read' article.pk %}">
|
||||||
|
<span class="glyphicon glyphicon-cog"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ article.name }}</td>
|
||||||
|
<td class="text-right">{{ article.price }}€</td>
|
||||||
|
<td class="text-right">{{ article.stock }}</td>
|
||||||
|
<td class="text-right">{{ article.is_sold }}</td>
|
||||||
|
<td class="text-right">{{ article.inventory.0.at }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
17
kfet/templates/kfet/article_create.html
Normal file
17
kfet/templates/kfet/article_create.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends 'kfet/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Nouvel article{% endblock %}
|
||||||
|
{% block content-header-title %}Création d'un article{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form submit="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
{% if not perms.kfet.add_article %}
|
||||||
|
<input type="password" name="KFETPASSWORD">
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" value="Enregistrer">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
85
kfet/templates/kfet/article_read.html
Normal file
85
kfet/templates/kfet/article_read.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
{% extends 'kfet/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Informations sur l'article {{ article }}{% endblock %}
|
||||||
|
{% block content-header-title %}Article - {{ article.name }}{% 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">{{ article.name }}</div>
|
||||||
|
<div class="line line-bigsub">{{ article.category }}</div>
|
||||||
|
<div class="block">
|
||||||
|
<div class="line">Prix (hors réduc.): {{ article.price }}€</div>
|
||||||
|
<div class="line">Stock: {{ article.stock }}</div>
|
||||||
|
<div class="line">En vente: {{ article.is_sold }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
|
<a class="btn btn-primary btn-lg" href="{% url 'kfet.article.update' article.pk %}">
|
||||||
|
Modifier
|
||||||
|
</a>
|
||||||
|
</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>Historique</h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h3>Inventaires</h3>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Stock</td>
|
||||||
|
<td>Erreur</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for inventoryart in inventoryarts %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ inventoryart.inventory.at }}</td>
|
||||||
|
<td>{{ inventoryart.stock_new }}</td>
|
||||||
|
<td>{{ inventoryart.stock_error }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h3>Prix fournisseurs</h3>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Fournisseur</td>
|
||||||
|
<td>HT</td>
|
||||||
|
<td>TVA</td>
|
||||||
|
<td>Droits</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for supplierart in supplierarts %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ supplierart.at }}</td>
|
||||||
|
<td>{{ supplierart.supplier.name }}</td>
|
||||||
|
<td>{{ supplierart.price_HT }}</td>
|
||||||
|
<td>{{ supplierart.TVA }}</td>
|
||||||
|
<td>{{ supplierart.rights }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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