mirror of
https://github.com/nanoy42/coope
synced 2024-11-22 03:13:12 +00:00
Comptabilité
This commit is contained in:
parent
44db06a604
commit
84b7e5281c
9 changed files with 186 additions and 30 deletions
|
@ -38,6 +38,7 @@ INSTALLED_APPS = [
|
||||||
'dal',
|
'dal',
|
||||||
'dal_select2',
|
'dal_select2',
|
||||||
'simple_history',
|
'simple_history',
|
||||||
|
'django_tex',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -68,6 +69,14 @@ TEMPLATES = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'tex',
|
||||||
|
'BACKEND': 'django_tex.engine.TeXEngine',
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'environment': 'gestion.environment.my_environment',
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'coopeV3.wsgi.application'
|
WSGI_APPLICATION = 'coopeV3.wsgi.application'
|
||||||
|
|
12
gestion/environment.py
Normal file
12
gestion/environment.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from django_tex.environment import environment
|
||||||
|
|
||||||
|
def latex_safe(value):
|
||||||
|
return str(value).replace('_', '\_').replace('$', '\$').replace('&', '\&').replace('#', '\#').replace('{', '\{').replace('}','\}')
|
||||||
|
|
||||||
|
|
||||||
|
def my_environment(**options):
|
||||||
|
env = environment(**options)
|
||||||
|
env.filters.update({
|
||||||
|
'latex_safe': latex_safe
|
||||||
|
})
|
||||||
|
return env
|
|
@ -66,4 +66,8 @@ class SelectActiveKegForm(forms.Form):
|
||||||
class PinteForm(forms.Form):
|
class PinteForm(forms.Form):
|
||||||
ids = forms.CharField(widget=forms.Textarea, label="Numéros", help_text="Numéros séparés par un espace. Laissez vide pour utiliser le range.", required=False)
|
ids = forms.CharField(widget=forms.Textarea, label="Numéros", help_text="Numéros séparés par un espace. Laissez vide pour utiliser le range.", required=False)
|
||||||
begin = forms.IntegerField(label="Début", help_text="Début du range", required=False)
|
begin = forms.IntegerField(label="Début", help_text="Début du range", required=False)
|
||||||
end = forms.IntegerField(label="Fin", help_text="Fin du range", required=False)
|
end = forms.IntegerField(label="Fin", help_text="Fin du range", required=False)
|
||||||
|
|
||||||
|
class GenerateReleveForm(forms.Form):
|
||||||
|
begin = forms.DateTimeField(label="Date de début")
|
||||||
|
end = forms.DateTimeField(label="Date de fin")
|
71
gestion/templates/gestion/releve.tex
Normal file
71
gestion/templates/gestion/releve.tex
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
\documentclass[11pt,a4paper]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[french]{babel}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amsfonts}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{eurosym}
|
||||||
|
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
|
||||||
|
\usepackage{tabularx}
|
||||||
|
\usepackage{longtable}
|
||||||
|
\usepackage{tabu}
|
||||||
|
\author{Généré par CoopeV3}
|
||||||
|
\title{Relevé Coopé Technopôle Metz}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Informations générales}
|
||||||
|
\begin{longtabu}{|X|X|X|}
|
||||||
|
\hline
|
||||||
|
\multicolumn{2}{|c|}{Généré le } & \textbf{ {{- now | date('d/m/Y H:i:s') -}} }\\
|
||||||
|
\hline
|
||||||
|
Infos & De & \textbf{ {{- begin | date('d/m/Y H:i:s')-}} } \\
|
||||||
|
\cline{2-3} & À & \textbf{ {{- end | date('d/m/Y H:i:s') -}} }\\
|
||||||
|
\hline
|
||||||
|
Estimations & Espèces & \textbf{ {{- value_especes | latex_safe -}} \euro{}} \\
|
||||||
|
\cline{2-3} & Lydia & \textbf{ {{- value_lydia | latex_safe -}} \euro{}} \\
|
||||||
|
\cline{2-3} & Chèques & \textbf{ {{- value_cheque | latex_safe -}} \euro{}} \\
|
||||||
|
\hline
|
||||||
|
\end{longtabu}
|
||||||
|
\section{Transactions}
|
||||||
|
\begin{longtabu}{|c|X|X|X|X|X|}
|
||||||
|
\hline
|
||||||
|
\# & Date & Client & Montant & Moyen de paiement & Produit (Qté) \\
|
||||||
|
\hline
|
||||||
|
{% for consumption in consumptions %}
|
||||||
|
{{consumption.pk}} & {{consumption.date | date('d/m/Y H:i:s')}} & {{consumption.customer.first_name|latex_safe}} {{consumption.customer.last_name|latex_safe}} & {{consumption.amount}} \euro{} & {{consumption.paymentMethod}} & {{consumption.product}} (x{{consumption.quantity}})\\
|
||||||
|
\hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtabu}
|
||||||
|
\section{Rechargements}
|
||||||
|
\begin{longtabu}{|c|X|X|X|X|}
|
||||||
|
\hline
|
||||||
|
\# & Date & Client & Montant & Moyen de paiement \\
|
||||||
|
\hline
|
||||||
|
{% for reload in reloads %}
|
||||||
|
{{reload.pk}} & {{ reload.date | date('d/m/Y H:i:s')}} & {{reload.customer.first_name | latex_safe}} {{reload.customer.last_name | latex_safe}} & {{ reload.amount }} \euro{} & {{reload.PaymentMethod}} \\
|
||||||
|
\hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtabu}
|
||||||
|
\section{Remboursement}
|
||||||
|
\begin{longtabu}{|c|X|X|X|}
|
||||||
|
\hline
|
||||||
|
\# & Date & Client & Montant\\
|
||||||
|
\hline
|
||||||
|
{% for refund in refunds %}
|
||||||
|
{{refund.pk}} & {{ refund.date | date('d/m/Y H:i:s')}} & {{refund.customer.first_name|latex_safe}} {{refund.customer.last_name|latex_safe}} & {{ refund.amount }} \euro{}\\
|
||||||
|
\hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtabu}
|
||||||
|
\section{Cotisations}
|
||||||
|
\begin{longtabu}{|c|X|X|X|X|X|}
|
||||||
|
\hline
|
||||||
|
\# & Date & Client & Montant & Durée & Moyen de paiement \\
|
||||||
|
\hline
|
||||||
|
{% for cot in cotisations %}
|
||||||
|
{{cot.pk}} & {{ cot.paymentDate | date('d/m/Y H:i:s')}} & {{cot.user.first_name|latex_safe}} {{cot.user.last_name|latex_safe}} & {{cot.amount}} \euro{} & {{cot.duration}} jours & {{cot.paymentMethod}} \\
|
||||||
|
\hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtabu}
|
||||||
|
\end{document}
|
|
@ -44,4 +44,5 @@ urlpatterns = [
|
||||||
path('kegs-active-autocomplete', views.KegActiveAutocomplete.as_view(), name="kegs-active-autocomplete"),
|
path('kegs-active-autocomplete', views.KegActiveAutocomplete.as_view(), name="kegs-active-autocomplete"),
|
||||||
path('menus-autcomplete', views.MenusAutocomplete.as_view(), name="menus-autocomplete"),
|
path('menus-autcomplete', views.MenusAutocomplete.as_view(), name="menus-autocomplete"),
|
||||||
path('cancelReload/<int:pk>', views.cancel_reload, name="cancelReload"),
|
path('cancelReload/<int:pk>', views.cancel_reload, name="cancelReload"),
|
||||||
|
path('gen_releve', views.gen_releve, name="gen_releve"),
|
||||||
]
|
]
|
106
gestion/views.py
106
gestion/views.py
|
@ -8,15 +8,19 @@ from django.contrib.auth.decorators import login_required, permission_required
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
|
||||||
from coopeV3.acl import active_required, acl_or
|
from django_tex.views import render_to_pdf
|
||||||
|
|
||||||
|
from coopeV3.acl import active_required, acl_or, admin_required
|
||||||
|
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
from decimal import *
|
from decimal import *
|
||||||
|
import datetime
|
||||||
|
|
||||||
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm
|
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm, GenerateReleveForm
|
||||||
from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte, Reload
|
from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte, Reload, Refund
|
||||||
from preferences.models import PaymentMethod, GeneralPreferences
|
from preferences.models import PaymentMethod, GeneralPreferences
|
||||||
|
from users.models import CotisationHistory
|
||||||
|
|
||||||
@active_required
|
@active_required
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -26,10 +30,10 @@ def manage(request):
|
||||||
Display the manage page
|
Display the manage page
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``gestion_form``
|
``gestion_form``
|
||||||
The manage form
|
The manage form
|
||||||
|
|
||||||
``reload_form``
|
``reload_form``
|
||||||
The :model:`gestion.Reload` form
|
The :model:`gestion.Reload` form
|
||||||
|
|
||||||
|
@ -44,13 +48,13 @@ def manage(request):
|
||||||
|
|
||||||
``panini``
|
``panini``
|
||||||
A list of active :model:`gestion.Product` corresponding to panini items
|
A list of active :model:`gestion.Product` corresponding to panini items
|
||||||
|
|
||||||
``food``
|
``food``
|
||||||
A list of active :model:`gestion.Product` corresponding to non-panini items
|
A list of active :model:`gestion.Product` corresponding to non-panini items
|
||||||
|
|
||||||
``soft``
|
``soft``
|
||||||
A list of active :model:`gestion.Product` correspond to non alcoholic beverage
|
A list of active :model:`gestion.Product` correspond to non alcoholic beverage
|
||||||
|
|
||||||
``menus``
|
``menus``
|
||||||
The list of active :model:`gestion.Menu`
|
The list of active :model:`gestion.Menu`
|
||||||
|
|
||||||
|
@ -288,7 +292,7 @@ def cancel_menu(request, pk):
|
||||||
for product in manu_history.menu.articles:
|
for product in manu_history.menu.articles:
|
||||||
consumptionT = Consumption.objects.get(customer=user, product=product)
|
consumptionT = Consumption.objects.get(customer=user, product=product)
|
||||||
consumptionT -= menu_history.quantity
|
consumptionT -= menu_history.quantity
|
||||||
consumptionT.save()
|
consumptionT.save()
|
||||||
menu_history.delete()
|
menu_history.delete()
|
||||||
messages.success(request, "La consommation du menu a bien été annulée")
|
messages.success(request, "La consommation du menu a bien été annulée")
|
||||||
return redirect(reverse('users:profile', kwargs={'pk': user.pk}))
|
return redirect(reverse('users:profile', kwargs={'pk': user.pk}))
|
||||||
|
@ -318,7 +322,7 @@ def addProduct(request):
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The ProductForm instance
|
The ProductForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the form template
|
The title for the form template
|
||||||
|
|
||||||
|
@ -350,7 +354,7 @@ def editProduct(request, pk):
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The ProductForm instance
|
The ProductForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the form template
|
The title for the form template
|
||||||
|
|
||||||
|
@ -399,7 +403,7 @@ def searchProduct(request):
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The SearchProductForm instance
|
The SearchProductForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the form template
|
The title for the form template
|
||||||
|
|
||||||
|
@ -426,7 +430,7 @@ def productProfile(request, pk):
|
||||||
The primary key of the requested :model:`gestion.Product`
|
The primary key of the requested :model:`gestion.Product`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``product``
|
``product``
|
||||||
The :model:`gestion.Product` instance
|
The :model:`gestion.Product` instance
|
||||||
|
|
||||||
|
@ -500,10 +504,10 @@ def addKeg(request):
|
||||||
Display a form to add a :model:`gestion.Keg`
|
Display a form to add a :model:`gestion.Keg`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The KegForm instance
|
The KegForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the :template:`form.html` template
|
The title for the :template:`form.html` template
|
||||||
|
|
||||||
|
@ -532,10 +536,10 @@ def editKeg(request, pk):
|
||||||
The primary key of the requested :model:`gestion.Keg`
|
The primary key of the requested :model:`gestion.Keg`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The KegForm instance
|
The KegForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the :template:`form.html` template
|
The title for the :template:`form.html` template
|
||||||
|
|
||||||
|
@ -562,10 +566,10 @@ def openKeg(request):
|
||||||
Display a form to open a :model:`gestion.Keg`
|
Display a form to open a :model:`gestion.Keg`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The SelectPositiveKegForm instance
|
The SelectPositiveKegForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the :template:`form.html` template
|
The title for the :template:`form.html` template
|
||||||
|
|
||||||
|
@ -628,10 +632,10 @@ def closeKeg(request):
|
||||||
Display a form to close a :model:`gestion.Keg`
|
Display a form to close a :model:`gestion.Keg`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The SelectActiveKegForm instance
|
The SelectActiveKegForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the :template:`form.html` template
|
The title for the :template:`form.html` template
|
||||||
|
|
||||||
|
@ -716,7 +720,7 @@ def kegH(request, pk):
|
||||||
|
|
||||||
``keg``
|
``keg``
|
||||||
The :model:`gestion.Keg` instance
|
The :model:`gestion.Keg` instance
|
||||||
|
|
||||||
``kegHistory``
|
``kegHistory``
|
||||||
List of :model:`gestion.KegHistory` attached to keg
|
List of :model:`gestion.KegHistory` attached to keg
|
||||||
|
|
||||||
|
@ -758,10 +762,10 @@ def addMenu(request):
|
||||||
Display a form to add a :model:`gestion.Menu`
|
Display a form to add a :model:`gestion.Menu`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The MenuForm instance
|
The MenuForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the :template:`form.html` template
|
The title for the :template:`form.html` template
|
||||||
|
|
||||||
|
@ -791,10 +795,10 @@ def edit_menu(request, pk):
|
||||||
The primary key of requested :model:`gestion.Menu`
|
The primary key of requested :model:`gestion.Menu`
|
||||||
|
|
||||||
**Context**
|
**Context**
|
||||||
|
|
||||||
``form``
|
``form``
|
||||||
The MenuForm instance
|
The MenuForm instance
|
||||||
|
|
||||||
``form_title``
|
``form_title``
|
||||||
The title for the :template:`form.html` template
|
The title for the :template:`form.html` template
|
||||||
|
|
||||||
|
@ -962,7 +966,7 @@ def release(request, pinte_pk):
|
||||||
else:
|
else:
|
||||||
messages.error(request, "Impossible de libérer la pinte")
|
messages.error(request, "Impossible de libérer la pinte")
|
||||||
return redirect(reverse('gestion:pintesList'))
|
return redirect(reverse('gestion:pintesList'))
|
||||||
|
|
||||||
@active_required
|
@active_required
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('gestion.add_pinte')
|
@permission_required('gestion.add_pinte')
|
||||||
|
@ -1017,4 +1021,52 @@ def pintes_list(request):
|
||||||
def pintes_user_list(request):
|
def pintes_user_list(request):
|
||||||
pks = [x.pk for x in User.objects.all() if x.profile.nb_pintes > 0]
|
pks = [x.pk for x in User.objects.all() if x.profile.nb_pintes > 0]
|
||||||
users = User.objects.filter(pk__in=pks)
|
users = User.objects.filter(pk__in=pks)
|
||||||
return render(request, "gestion/pintes_user_list.html", {"users": users})
|
return render(request, "gestion/pintes_user_list.html", {"users": users})
|
||||||
|
|
||||||
|
@active_required
|
||||||
|
@login_required
|
||||||
|
@admin_required
|
||||||
|
def gen_releve(request):
|
||||||
|
form = GenerateReleveForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
begin, end = form.cleaned_data['begin'], form.cleaned_data['end']
|
||||||
|
consumptions = ConsumptionHistory.objects.filter(date__gte=begin).filter(date__lte=end).order_by('-date')
|
||||||
|
reloads = Reload.objects.filter(date__gt=begin).filter(date__lt=end).order_by('-date')
|
||||||
|
refunds = Refund.objects.filter(date__gt=begin).filter(date__lt=end).order_by('-date')
|
||||||
|
cotisations = CotisationHistory.objects.filter(paymentDate__gt=begin).filter(paymentDate__lt=end).order_by('-paymentDate')
|
||||||
|
especes = PaymentMethod.objects.get(name="Espèces")
|
||||||
|
lydia = PaymentMethod.objects.get(name="Lydia")
|
||||||
|
cheque = PaymentMethod.objects.get(name="Chèque")
|
||||||
|
value_especes = 0
|
||||||
|
value_lydia = 0
|
||||||
|
value_cheque = 0
|
||||||
|
for consumption in consumptions:
|
||||||
|
pm = consumption.paymentMethod
|
||||||
|
if pm == especes:
|
||||||
|
value_especes += consumption.amount
|
||||||
|
elif pm == lydia:
|
||||||
|
value_lydia += consumption.amount
|
||||||
|
elif pm == cheque:
|
||||||
|
value_cheque += consumption.amount
|
||||||
|
for reload in reloads:
|
||||||
|
pm = reload.PaymentMethod
|
||||||
|
if pm == especes:
|
||||||
|
value_especes += reload.amount
|
||||||
|
elif pm == lydia:
|
||||||
|
value_lydia += reload.amount
|
||||||
|
elif pm == cheque:
|
||||||
|
value_cheque += reload.amount
|
||||||
|
for refund in refunds:
|
||||||
|
value_especes -= refund.amount
|
||||||
|
for cot in cotisations:
|
||||||
|
pm = cot.paymentMethod
|
||||||
|
if pm == especes:
|
||||||
|
value_especes += cot.amount
|
||||||
|
elif pm == lydia:
|
||||||
|
value_lydia += cot.amount
|
||||||
|
elif pm == cheque:
|
||||||
|
value_cheque += cot.amount
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return render_to_pdf(request, 'gestion/releve.tex', {"consumptions": consumptions, "reloads": reloads, "refunds": refunds, "cotisations": cotisations, "begin": begin, "end": end, "now": now, "value_especes": value_especes, "value_lydia": value_lydia, "value_cheque": value_cheque}, filename="releve.pdf")
|
||||||
|
else:
|
||||||
|
return render(request, "form.html", {"form": form, "form_title": "Génération d'un relevé", "form_button": "Générer"})
|
||||||
|
|
|
@ -3,4 +3,5 @@ django-autocomplete-light==3.3.2
|
||||||
pytz==2018.5
|
pytz==2018.5
|
||||||
simplejson==3.16.0
|
simplejson==3.16.0
|
||||||
docutils==0.14
|
docutils==0.14
|
||||||
django-simple-history==2.5.1
|
django-simple-history==2.5.1
|
||||||
|
jinja2==2.10
|
|
@ -25,6 +25,11 @@
|
||||||
<a href="{% url 'preferences:generalPreferences' %}">Admin</a>
|
<a href="{% url 'preferences:generalPreferences' %}">Admin</a>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if request.user.is_staff %}
|
||||||
|
<span class="tabulation2">
|
||||||
|
<a href="{% url 'gestion:gen_releve' %}">Comptabilité</a>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
{% if perms.preferences.view_cotisation %}
|
{% if perms.preferences.view_cotisation %}
|
||||||
<span class="tabulation2">
|
<span class="tabulation2">
|
||||||
<a href="{% url 'preferences:cotisationsIndex' %}">Cotisations</a>
|
<a href="{% url 'preferences:cotisationsIndex' %}">Cotisations</a>
|
||||||
|
|
|
@ -169,4 +169,5 @@ def str_user(self):
|
||||||
fin = "Non adhérent"
|
fin = "Non adhérent"
|
||||||
return self.username + " (" + self.first_name + " " + self.last_name + ", " + str(self.profile.balance) + "€, " + fin + ")"
|
return self.username + " (" + self.first_name + " " + self.last_name + ", " + str(self.profile.balance) + "€, " + fin + ")"
|
||||||
|
|
||||||
User.add_to_class("__str__", str_user)
|
|
||||||
|
User.add_to_class("__str__", str_user)
|
Loading…
Reference in a new issue