8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-24 04:13:12 +00:00

feat: Add statistics for deposits app

This commit is contained in:
Jean-Romain Garnier 2021-08-07 23:19:14 +02:00
parent 1861baeb12
commit 8138aa9af1
6 changed files with 254 additions and 21 deletions

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-07 18:27+0200\n" "POT-Creation-Date: 2021-08-07 23:10+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -32,10 +32,12 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: deposits/forms.py:44 deposits/templates/deposits/aff_deposit_item.html:31 #: deposits/forms.py:44 deposits/templates/deposits/aff_deposit_item.html:31
#: deposits/views.py:301
msgid "Deposit item" msgid "Deposit item"
msgstr "Article (caution)" msgstr "Article (caution)"
#: deposits/forms.py:45 deposits/templates/deposits/aff_deposits.html:48 #: deposits/forms.py:45 deposits/templates/deposits/aff_deposits.html:48
#: deposits/views.py:272
msgid "Payment method" msgid "Payment method"
msgstr "Moyen de paiement" msgstr "Moyen de paiement"
@ -59,7 +61,7 @@ msgstr "rendue"
msgid "deposit amount" msgid "deposit amount"
msgstr "montant de la caution" msgstr "montant de la caution"
#: deposits/models.py:60 deposits/views.py:114 #: deposits/models.py:60 deposits/views.py:116
msgid "deposit" msgid "deposit"
msgstr "caution" msgstr "caution"
@ -98,7 +100,8 @@ msgid "deposit items"
msgstr "articles (cautions)" msgstr "articles (cautions)"
#: deposits/templates/deposits/aff_deposit_item.html:32 #: deposits/templates/deposits/aff_deposit_item.html:32
#: deposits/templates/deposits/aff_deposits.html:44 #: deposits/templates/deposits/aff_deposits.html:44 deposits/views.py:276
#: deposits/views.py:305 deposits/views.py:338
msgid "Amount" msgid "Amount"
msgstr "Montant" msgstr "Montant"
@ -144,7 +147,7 @@ msgstr ""
"Attention: voulez-vous vraiment supprimer cet objet %(objet_name)s " "Attention: voulez-vous vraiment supprimer cet objet %(objet_name)s "
"( %(objet)s ) ?" "( %(objet)s ) ?"
#: deposits/templates/deposits/delete.html:36 deposits/views.py:70 #: deposits/templates/deposits/delete.html:36 deposits/views.py:72
msgid "Confirm" msgid "Confirm"
msgstr "Confirmer" msgstr "Confirmer"
@ -152,7 +155,7 @@ msgstr "Confirmer"
msgid "Create or edit deposit" msgid "Create or edit deposit"
msgstr "Créer ou modifier une caution" msgstr "Créer ou modifier une caution"
#: deposits/templates/deposits/deposit.html:35 deposits/views.py:173 #: deposits/templates/deposits/deposit.html:35 deposits/views.py:179
msgid "Add" msgid "Add"
msgstr "Ajouter" msgstr "Ajouter"
@ -189,66 +192,102 @@ msgid_plural "Unreturned deposits"
msgstr[0] "Caution non rendue" msgstr[0] "Caution non rendue"
msgstr[1] "Cautions non rendues" msgstr[1] "Cautions non rendues"
#: deposits/templates/deposits/index_deposits.html:46 #: deposits/templates/deposits/index_deposits.html:45 deposits/views.py:274
#: deposits/views.py:303
msgid "Unreturned deposits" msgid "Unreturned deposits"
msgstr "Cautions non rendues" msgstr "Cautions non rendues"
#: deposits/templates/deposits/index_deposits.html:57 #: deposits/templates/deposits/index_deposits.html:56 deposits/views.py:273
#: deposits/views.py:302
msgid "Returned deposits" msgid "Returned deposits"
msgstr "Cautions rendues" msgstr "Cautions rendues"
#: deposits/templates/deposits/index_stats.html:28
#: deposits/templates/deposits/index_stats.html:31
#: deposits/templates/deposits/navbar.html:36
msgid "Deposits statistics"
msgstr "Statistiques sur les cautions"
#: deposits/templates/deposits/navbar.html:30 #: deposits/templates/deposits/navbar.html:30
msgid "View deposits" msgid "View deposits"
msgstr "Voir les cautions" msgstr "Voir les cautions"
#: deposits/views.py:64 #: deposits/views.py:66
msgid "The deposit was created." msgid "The deposit was created."
msgstr "La caution a été créée." msgstr "La caution a été créée."
#: deposits/views.py:71 #: deposits/views.py:73
msgid "New deposit" msgid "New deposit"
msgstr "Nouvelle caution" msgstr "Nouvelle caution"
#: deposits/views.py:89 #: deposits/views.py:91
msgid "The deposit was edited." msgid "The deposit was edited."
msgstr "La caution a été modifiée." msgstr "La caution a été modifiée."
#: deposits/views.py:95 deposits/views.py:196 #: deposits/views.py:97 deposits/views.py:202
msgid "Edit" msgid "Edit"
msgstr "Modifier" msgstr "Modifier"
#: deposits/views.py:96 #: deposits/views.py:98
msgid "Edit deposit" msgid "Edit deposit"
msgstr "Modifier la caution" msgstr "Modifier la caution"
#: deposits/views.py:111 #: deposits/views.py:113
msgid "The deposit was deleted." msgid "The deposit was deleted."
msgstr "La caution a été supprimée." msgstr "La caution a été supprimée."
#: deposits/views.py:168 #: deposits/views.py:174
msgid "The item was created." msgid "The item was created."
msgstr "L'article a été créé." msgstr "L'article a été créé."
#: deposits/views.py:174 #: deposits/views.py:180
msgid "New deposit item" msgid "New deposit item"
msgstr "Nouvel article (caution)" msgstr "Nouvel article (caution)"
#: deposits/views.py:191 #: deposits/views.py:197
msgid "The item was edited." msgid "The item was edited."
msgstr "L'article a été modifié." msgstr "L'article a été modifié."
#: deposits/views.py:197 #: deposits/views.py:203
msgid "Edit deposit item" msgid "Edit deposit item"
msgstr "Modifier l'article" msgstr "Modifier l'article"
#: deposits/views.py:214 #: deposits/views.py:220
msgid "The items were deleted." msgid "The items were deleted."
msgstr "Les articles ont été supprimés." msgstr "Les articles ont été supprimés."
#: deposits/views.py:219 #: deposits/views.py:225
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: deposits/views.py:220 #: deposits/views.py:226
msgid "Delete deposit item" msgid "Delete deposit item"
msgstr "Supprimer l'article" msgstr "Supprimer l'article"
#: deposits/views.py:270
msgid "Deposits by payment method"
msgstr "Cautions par moyen de paiement"
#: deposits/views.py:275 deposits/views.py:304 deposits/views.py:337
msgid "Total"
msgstr "Total"
#: deposits/views.py:299
msgid "Deposits by item type"
msgstr "Cautions par type d'article"
#: deposits/views.py:321
msgid "Not yet returned"
msgstr "Pas encore rendues"
#: deposits/views.py:326
msgid "Already returned"
msgstr "Déjà rendues"
#: deposits/views.py:334
msgid "Deposits amounts"
msgstr "Montants de cautions"
#: deposits/views.py:336
msgid "Category"
msgstr "Catégorie"

View file

@ -0,0 +1,40 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2021 Jean-Romain Garnier
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
<h3>{{ stats_dict.title }}</h3>
<table class="table table-striped">
<thead>
<tr>
{% for header in stats_dict.headers %}
<th>{{ header }}</th>
{% endfor %}
</tr>
</thead>
{% for stats in stats_dict.data %}
<tr>
{% for item in stats %}
<td>{{ item }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,36 @@
{% extends 'deposits/sidebar.html' %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2021 Jean-Romain Garnier
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load i18n %}
{% block title %}{% trans "Deposits statistics" %}{% endblock %}
{% block content %}
<h2>{% trans "Deposits statistics" %}</h2>
{% for stats_dict in stats_list %}
{% include 'deposits/aff_stats.html' with stats_dict=stats_dict %}
<br/>
{% endfor %}
{% endblock %}

View file

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% endcomment %} {% endcomment %}
{% load i18n %} {% load i18n %}
<li><a class="dropdown-item" href="#"><i class="fa fa-balance-scale"></i> <li><a class="dropdown-item" href="#"><i class="fa fa-balance-scale"></i>
{% trans "Deposits" %} {% trans "Deposits" %}
&raquo </a> &raquo </a>
@ -31,5 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<li><a class="dropdown-item" href="{% url 'deposits:index-deposit-item' %}"><i <li><a class="dropdown-item" href="{% url 'deposits:index-deposit-item' %}"><i
class="fa fa-barcode"></i> class="fa fa-barcode"></i>
{% trans "Deposit items" %}</a></li> {% trans "Deposit items" %}</a></li>
<li><a class="dropdown-item" href="{% url 'deposits:index-stats' %}"><i
class="fa fa-area-chart"></i>
{% trans "Deposits statistics" %}</a></li>
</ul> </ul>
</li> </li>

View file

@ -41,4 +41,5 @@ urlpatterns = [
), ),
path("del_deposit_item", views.del_deposit_item, name="del-deposit-item"), path("del_deposit_item", views.del_deposit_item, name="del-deposit-item"),
path("index_deposit_item", views.index_deposit_item, name="index-deposit-item"), path("index_deposit_item", views.index_deposit_item, name="index-deposit-item"),
path("index_stats", views.index_stats, name="index-stats"),
] ]

View file

@ -28,6 +28,7 @@ from django.shortcuts import redirect, render
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.db.models import Sum
from preferences.models import GeneralOption from preferences.models import GeneralOption
from re2o.acl import ( from re2o.acl import (
@ -40,6 +41,7 @@ from re2o.acl import (
from re2o.base import re2o_paginator from re2o.base import re2o_paginator
from re2o.views import form from re2o.views import form
from users.models import User from users.models import User
from cotisations.models import Paiement
from .forms import DepositForm, DepositItemForm, DelDepositItemForm from .forms import DepositForm, DepositItemForm, DelDepositItemForm
from .models import Deposit, DepositItem from .models import Deposit, DepositItem
@ -118,7 +120,7 @@ def del_deposit(request, deposit, **_kwargs):
@login_required @login_required
@can_view_all(Deposit) @can_view_all(Deposit, DepositItem, Paiement, User)
def index_deposits(request): def index_deposits(request):
""" """
View used to display the list of all deposits. View used to display the list of all deposits.
@ -239,6 +241,117 @@ def index_deposit_item(request):
return render(request, "deposits/index_deposit_item.html", {"item_list": item_list}) return render(request, "deposits/index_deposit_item.html", {"item_list": item_list})
@login_required
@can_view_all(Deposit, DepositItem, Paiement, User)
def index_stats(request):
"""
View used to display general statistics about deposits
"""
# We want to build a list of tables for statistics
stats = []
# Statistics for payment methods
payment_data = []
for method in Paiement.objects.order_by("moyen"):
deposits = Deposit.objects.filter(payment_method=method)
amount = deposits.aggregate(Sum("deposit_amount")).get(
"deposit_amount__sum", None
)
payment_data.append(
(
method.moyen,
deposits.filter(returned=False).count(),
deposits.filter(returned=True).count(),
deposits.count(),
"{}".format(amount or 0),
)
)
stats.append(
{
"title": _("Deposits by payment method"),
"headers": [
_("Payment method"),
_("Returned deposits"),
_("Unreturned deposits"),
_("Total"),
_("Amount"),
],
"data": payment_data,
}
)
# Statistics for deposit items
items_data = []
for item in DepositItem.objects.order_by("name"):
deposits = Deposit.objects.filter(item=item)
amount = deposits.aggregate(Sum("deposit_amount")).get(
"deposit_amount__sum", None
)
items_data.append(
(
item.name,
deposits.filter(returned=False).count(),
deposits.filter(returned=True).count(),
deposits.count(),
"{}".format(amount or 0),
)
)
stats.append(
{
"title": _("Deposits by item type"),
"headers": [
_("Deposit item"),
_("Returned deposits"),
_("Unreturned deposits"),
_("Total"),
_("Amount"),
],
"data": items_data,
}
)
# Statistics for amounts
pending_amount = (
Deposit.objects.filter(returned=False)
.aggregate(Sum("deposit_amount"))
.get("deposit_amount__sum", None)
)
reimbursed_amount = (
Deposit.objects.filter(returned=True)
.aggregate(Sum("deposit_amount"))
.get("deposit_amount__sum", None)
)
amounts_data = [
(
_("Not yet returned"),
Deposit.objects.filter(returned=False).count(),
"{}".format(pending_amount or 0),
),
(
_("Already returned"),
Deposit.objects.filter(returned=True).count(),
"{}".format(reimbursed_amount or 0),
),
]
stats.append(
{
"title": _("Deposits amounts"),
"headers": [
_("Category"),
_("Total"),
_("Amount"),
],
"data": amounts_data,
}
)
return render(request, "deposits/index_stats.html", {"stats_list": stats})
# Canonic views for optional apps # Canonic views for optional apps
def aff_profil(request, user): def aff_profil(request, user):
"""View used to display the deposits on a user's profile.""" """View used to display the deposits on a user's profile."""