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:
parent
1861baeb12
commit
8138aa9af1
6 changed files with 254 additions and 21 deletions
|
@ -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"
|
||||||
|
|
40
deposits/templates/deposits/aff_stats.html
Normal file
40
deposits/templates/deposits/aff_stats.html
Normal 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>
|
36
deposits/templates/deposits/index_stats.html
Normal file
36
deposits/templates/deposits/index_stats.html
Normal 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 %}
|
|
@ -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" %}
|
||||||
» </a>
|
» </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>
|
||||||
|
|
|
@ -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"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
Loading…
Reference in a new issue