Merge branch 'k-fet' into qwann/k-fet/home

This commit is contained in:
Qwann 2017-03-05 19:21:20 +01:00
commit f52aba8ca6
15 changed files with 511 additions and 557 deletions

View file

@ -1,37 +1,49 @@
# -*- coding: utf-8 -*-
from django.shortcuts import render, get_object_or_404, redirect
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.exceptions import PermissionDenied
from django.core.cache import cache
from django.views.generic import ListView, DetailView, TemplateView
from django.views.generic.list import BaseListView, MultipleObjectTemplateResponseMixin
from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
from django.core.urlresolvers import reverse_lazy
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.models import User, Permission, Group
from django.http import HttpResponse, JsonResponse, Http404
from django.forms import modelformset_factory, formset_factory
from django.db import IntegrityError, transaction
from django.db.models import F, Sum, Prefetch, Count, Func
from django.http import JsonResponse, Http404
from django.forms import formset_factory
from django.db import transaction
from django.db.models import F, Sum, Prefetch, Count
from django.db.models.functions import Coalesce
from django.utils import timezone
from django.utils.crypto import get_random_string
from django.utils.decorators import method_decorator
from gestioncof.models import CofProfile, Clipper
from kfet.decorators import teamkfet_required
from kfet.models import (Account, Checkout, Article, Settings, AccountNegative,
from kfet.models import (
Account, Checkout, Article, Settings, AccountNegative,
CheckoutStatement, GenericTeamToken, Supplier, SupplierArticle, Inventory,
InventoryArticle, Order, OrderArticle, Operation, OperationGroup, Transfer)
from kfet.forms import *
InventoryArticle, Order, OrderArticle, Operation, OperationGroup,
TransferGroup, Transfer)
from kfet.forms import (
AccountTriForm, AccountBalanceForm, AccountNoTriForm, UserForm, CofForm,
UserRestrictTeamForm, UserGroupForm, AccountForm, CofRestrictForm,
AccountPwdForm, AccountNegativeForm, UserRestrictForm, AccountRestrictForm,
GroupForm, CheckoutForm, CheckoutRestrictForm, CheckoutStatementCreateForm,
CheckoutStatementUpdateForm, ArticleForm, ArticleRestrictForm,
KPsulOperationGroupForm, KPsulAccountForm, KPsulCheckoutForm,
KPsulOperationFormSet, AddcostForm, FilterHistoryForm, SettingsForm,
TransferFormSet, InventoryArticleForm, OrderArticleForm,
OrderArticleToInventoryForm
)
from collections import defaultdict
from kfet import consumers
from datetime import timedelta
from decimal import Decimal
import django_cas_ng
import hashlib
import heapq
import statistics
from .statistic import daynames, monthnames, weeknames, \
@ -54,6 +66,7 @@ class Home(TemplateView):
def dispatch(self, *args, **kwargs):
return super(TemplateView, self).dispatch(*args, **kwargs)
@teamkfet_required
def login_genericteam(request):
# Check si besoin de déconnecter l'utilisateur de CAS
@ -359,6 +372,7 @@ def account_read(request, trigramme):
# Account - Update
@login_required
def account_update(request, trigramme):
account = get_object_or_404(Account, trigramme=trigramme)
@ -369,39 +383,43 @@ def account_update(request, trigramme):
raise PermissionDenied
if request.user.has_perm('kfet.is_team'):
user_form = UserRestrictTeamForm(instance=account.user)
group_form = UserGroupForm(instance=account.user)
user_form = UserRestrictTeamForm(instance=account.user)
group_form = UserGroupForm(instance=account.user)
account_form = AccountForm(instance=account)
cof_form = CofRestrictForm(instance=account.cofprofile)
pwd_form = AccountPwdForm()
cof_form = CofRestrictForm(instance=account.cofprofile)
pwd_form = AccountPwdForm()
if account.balance < 0 and not hasattr(account, 'negative'):
AccountNegative.objects.create(account=account, start=timezone.now())
AccountNegative.objects.create(account=account,
start=timezone.now())
account.refresh_from_db()
if hasattr(account, 'negative'):
negative_form = AccountNegativeForm(instance=account.negative)
else:
negative_form = None
else:
user_form = UserRestrictForm(instance=account.user)
user_form = UserRestrictForm(instance=account.user)
account_form = AccountRestrictForm(instance=account)
cof_form = None
group_form = None
cof_form = None
group_form = None
negative_form = None
pwd_form = None
pwd_form = None
if request.method == "POST":
# Update attempt
success = False
success = False
missing_perm = True
if request.user.has_perm('kfet.is_team'):
account_form = AccountForm(request.POST, instance=account)
cof_form = CofRestrictForm(request.POST, instance=account.cofprofile)
user_form = UserRestrictTeamForm(request.POST, instance=account.user)
group_form = UserGroupForm(request.POST, instance=account.user)
pwd_form = AccountPwdForm(request.POST)
cof_form = CofRestrictForm(request.POST,
instance=account.cofprofile)
user_form = UserRestrictTeamForm(request.POST,
instance=account.user)
group_form = UserGroupForm(request.POST, instance=account.user)
pwd_form = AccountPwdForm(request.POST)
if hasattr(account, 'negative'):
negative_form = AccountNegativeForm(request.POST, instance=account.negative)
negative_form = AccountNegativeForm(request.POST,
instance=account.negative)
if (request.user.has_perm('kfet.change_account')
and account_form.is_valid() and cof_form.is_valid()
@ -413,15 +431,14 @@ def account_update(request, trigramme):
put_cleaned_data_in_dict(data, cof_form)
# Updating
account_form.save(data = data)
account_form.save(data=data)
# Checking perm to update password
if (request.user.has_perm('kfet.change_account_password')
and pwd_form.is_valid()):
pwd = pwd_form.cleaned_data['pwd1']
pwd_sha256 = hashlib.sha256(pwd.encode('utf-8')).hexdigest()
Account.objects.filter(pk=account.pk).update(
password = pwd_sha256)
account.change_pwd(pwd)
account.save()
messages.success(request, 'Mot de passe mis à jour')
# Checking perm to manage perms
@ -435,49 +452,66 @@ def account_update(request, trigramme):
if account.negative.balance_offset:
balance_offset_old = account.negative.balance_offset
if (hasattr(account, 'negative')
and request.user.has_perm('kfet.change_accountnegative')
and request.user.has_perm('kfet.change_accountnegative')
and negative_form.is_valid()):
balance_offset_new = negative_form.cleaned_data['balance_offset']
balance_offset_new = \
negative_form.cleaned_data['balance_offset']
if not balance_offset_new:
balance_offset_new = 0
balance_offset_diff = balance_offset_new - balance_offset_old
balance_offset_diff = (balance_offset_new
- balance_offset_old)
Account.objects.filter(pk=account.pk).update(
balance = F('balance') + balance_offset_diff)
balance=F('balance') + balance_offset_diff)
negative_form.save()
if not balance_offset_new and Account.objects.get(pk=account.pk).balance >= 0:
if Account.objects.get(pk=account.pk).balance >= 0 \
and not balance_offset_new:
AccountNegative.objects.get(account=account).delete()
success = True
messages.success(request,
'Informations du compte %s mises à jour' % account.trigramme)
messages.success(
request,
'Informations du compte %s mises à jour'
% account.trigramme)
# Modification de ses propres informations
if request.user == account.user:
missing_perm = False
account.refresh_from_db()
user_form = UserRestrictForm(request.POST, instance=account.user)
account_form = AccountRestrictForm(request.POST, instance=account)
pwd_form = AccountPwdForm(request.POST)
if user_form.is_valid() and account_form.is_valid():
user_form.save()
account_form.save()
success = True
messages.success(request, 'Vos informations ont été mises à jour')
messages.success(request,
'Vos informations ont été mises à jour')
if request.user.has_perm('kfet.is_team') \
and pwd_form.is_valid():
pwd = pwd_form.cleaned_data['pwd1']
account.change_pwd(pwd)
account.save()
messages.success(
request, 'Votre mot de passe a été mis à jour')
if missing_perm:
messages.error(request, 'Permission refusée')
if success:
return redirect('kfet.account.read', account.trigramme)
else:
messages.error(request, 'Informations non mises à jour. Corrigez les erreurs')
messages.error(
request, 'Informations non mises à jour. Corrigez les erreurs')
return render(request, "kfet/account_update.html", {
'account' : account,
'account_form' : account_form,
'cof_form' : cof_form,
'user_form' : user_form,
'group_form' : group_form,
'account': account,
'account_form': account_form,
'cof_form': cof_form,
'user_form': user_form,
'group_form': group_form,
'negative_form': negative_form,
'pwd_form' : pwd_form,
'pwd_form': pwd_form,
})
@permission_required('kfet.manage_perms')
@ -1703,6 +1737,7 @@ def order_create(request, pk):
articles = (Article.objects
.filter(suppliers=supplier.pk)
.distinct()
.select_related('category')
.order_by('category__name', 'name'))
@ -1993,6 +2028,14 @@ class JSONResponseMixin(object):
return context
class JSONDetailView(JSONResponseMixin,
BaseDetailView):
"""
Returns a DetailView that renders a JSON
"""
def render_to_response(self, context):
return self.render_to_json_response(context)
class HybridDetailView(JSONResponseMixin,
SingleObjectTemplateResponseMixin,
BaseDetailView):
@ -2023,14 +2066,13 @@ class HybridListView(JSONResponseMixin,
return super(HybridListView, self).render_to_response(context)
class ObjectResumeStat(DetailView):
class ObjectResumeStat(JSONDetailView):
"""
Summarize all the stats of an object
DOES NOT RETURN A JSON RESPONSE
Handles JSONResponse
"""
template_name = 'kfet/object_stat_resume.html'
context_object_name = ''
id_prefix = 'id_a_definir'
id_prefix = ''
# nombre de vues à résumer
nb_stat = 2
# Le combienième est celui par defaut ?
@ -2059,7 +2101,7 @@ class ObjectResumeStat(DetailView):
'btn': "btn_%s_%d_%d" % (self.id_prefix,
object_id,
i),
'url': reverse_lazy(self.stat_urls[i],
'url': reverse(self.stat_urls[i],
kwargs=dict(
self.get_object_url_kwargs(),
**url_kwargs[i]
@ -2082,7 +2124,7 @@ ID_PREFIX_ACC_BALANCE = "balance_acc"
# Un résumé de toutes les vues ArticleStatBalance
# NE REND PAS DE JSON
# REND DU JSON
class AccountStatBalanceAll(ObjectResumeStat):
model = Account
context_object_name = 'account'
@ -2115,9 +2157,9 @@ class AccountStatBalanceAll(ObjectResumeStat):
return super(AccountStatBalanceAll, self).dispatch(*args, **kwargs)
class AccountStatBalance(HybridDetailView):
class AccountStatBalance(JSONDetailView):
"""
Returns a graph (or a JSON Response) of the evolution a the personnal
Returns a JSON containing the evolution a the personnal
balance of a trigramme between timezone.now() and `nb_days`
ago (specified to the view as an argument)
takes into account the Operations and the Transfers
@ -2126,7 +2168,6 @@ class AccountStatBalance(HybridDetailView):
model = Account
trigramme_url_kwarg = 'trigramme'
nb_date_url_kwargs = 'nb_date'
template_name = 'kfet/account_stat_balance.html'
context_object_name = 'account'
id_prefix = ""
@ -2233,10 +2274,10 @@ class AccountStatBalance(HybridDetailView):
nb_days_string = 'anytime'
else:
nb_days_string = str(int(nb_days))
context['changes'] = changes
context['chart_id'] = "%s_%s_%s_days" % (self.id_prefix,
self.object.id,
nb_days_string)
context['charts'] = [ { "color": "rgb(255, 99, 132)",
"label": "Balance",
"values": changes } ]
context['is_time_chart'] = True
context['min_date'] = changes[len(changes)-1]['at']
context['max_date'] = changes[0]['at']
# TODO: offset
@ -2282,14 +2323,13 @@ class AccountStatLastAll(ObjectResumeStat):
return super(AccountStatLastAll, self).dispatch(*args, **kwargs)
class AccountStatLast(HybridDetailView):
class AccountStatLast(JSONDetailView):
"""
Returns a graph (or a JSON Response) of the evolution a the personnal
Returns a JSON containing the evolution a the personnal
consommation of a trigramme at the diffent dates specified
"""
model = Account
trigramme_url_kwarg = 'trigramme'
template_name = 'kfet/account_stat_last.html'
context_object_name = 'account'
end_date = timezone.now()
id_prefix = ""
@ -2341,10 +2381,9 @@ class AccountStatLast(HybridDetailView):
operations = self.sort_operations()
for i in operations:
nb_ventes[i] = tot_ventes(operations[i])
context['nb_ventes'] = nb_ventes
# ID unique
context['chart_id'] = "%s_%d" % (self.id_prefix,
self.object.id)
context['charts'] = [ { "color": "rgb(255, 99, 132)",
"label": "NB items achetés",
"values": nb_ventes } ]
return context
@method_decorator(login_required)
@ -2421,13 +2460,12 @@ class ArticleStatLastAll(ObjectResumeStat):
return super(ArticleStatLastAll, self).dispatch(*args, **kwargs)
class ArticleStatLast(HybridDetailView):
class ArticleStatLast(JSONDetailView):
"""
Returns a graph (or a JSON Response) of the consommation
Returns a JSON containing the consommation
of an article at the diffent dates precised
"""
model = Article
template_name = 'kfet/article_stat_last.html'
context_object_name = 'article'
end_date = timezone.now()
id_prefix = ""
@ -2488,12 +2526,15 @@ class ArticleStatLast(HybridDetailView):
operations[i]
.exclude(group__on_acc__trigramme='LIQ')
)
context['nb_ventes'] = nb_ventes
context['nb_accounts'] = nb_accounts
context['nb_liq'] = nb_liq
# ID unique
context['chart_id'] = "%s_%d" % (self.id_prefix,
self.object.id)
context['charts'] = [ { "color": "rgb(255, 99, 132)",
"label": "Toutes consommations",
"values": nb_ventes },
{ "color": "rgb(54, 162, 235)",
"label": "LIQ",
"values": nb_liq },
{ "color": "rgb(255, 205, 86)",
"label": "Comptes K-Fêt",
"values": nb_accounts } ]
return context
@method_decorator(login_required)