3
0
Fork 0
mirror of https://github.com/nanoy42/coope synced 2024-11-25 22:22:27 +00:00

Add divide vie and DivideHisotry model

This commit is contained in:
Yoann Pétri 2019-06-23 10:54:21 +02:00
parent 88561613fb
commit 0fd8f2d419
14 changed files with 297 additions and 6 deletions

View file

@ -0,0 +1,77 @@
{% extends 'base.html' %}
{% block entete %}Répartition des cotisations{% endblock %}
{% block navbar %}
<ul>
<li><a href="#first">Répartition des cotisations</a></li>
<li><a href="#second">Historique des répartitions</a></li>
</ul>
{% endblock %}
{% block content %}
<section id="first" class="main">
<header class="major">
<h2>Répartition des cotisations</h2>
</header>
<section>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Champ</th>
<th>Valeur</th>
</tr>
</thead>
<tbody>
<tr>
<td>Nombre de cotisations non réparties</td>
<td>{{total_cotisations}}</td>
</tr>
<tr>
<td>Valeur totale des cotisations non réparties</td>
<td>{{total_amount}} €</td>
</tr>
<tr>
<td>Valeur à donner au Club Phœnix Technopôle Metz</td>
<td>{{total_amount_ptm}} €</td>
</tr>
</tbody>
</table>
</div>
<form action="" method="post">
{% csrf_token %}
<button type="submit"><i class="fa fa-hand-holding-usd"></i> Répartir</button>
</form>
<p>Attention, cliquer sur ce bouton marquera toutes les cotisations actuellement non réparties comme réparties. L'historique de cette action n'est pas simple à obtenir et l'action peut être considérée comme irreversible.</p>
</section>
</section>
<section id="second" class="main">
<header class="major">
<h2>Historique des répartitions</h2>
</header>
<section>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Date</th>
<th>Nombre de cotisations</th>
<th>Montant des cotisations</th>
<th>Montant des cotisations pourle Phœnix</th>
<th>Coopeman</th>
</tr>
</thead>
<tbody>
{% for divide_history in divide_histories %}
<tr>
<td>{{ divide_history.date }}</td>
<td>{{ divide_history.total_cotisations }}</td>
<td>{{ divide_history.total_cotisations_amount }} €</td>
<td>{{ divide_history.total_ptm_amount }} €</td>
<td>{{ divide_history.coopeman }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
</section>
{% endblock %}

View file

@ -53,4 +53,5 @@ urlpatterns = [
path('categoriesList', views.categoriesList, name="categoriesList"), path('categoriesList', views.categoriesList, name="categoriesList"),
path('categories-autocomplete', views.CategoriesAutocomplete.as_view(), name="categories-autocomplete"), path('categories-autocomplete', views.CategoriesAutocomplete.as_view(), name="categories-autocomplete"),
path('stats', views.stats, name="stats"), path('stats', views.stats, name="stats"),
path('divide', views.divide, name="divide"),
] ]

View file

@ -21,7 +21,7 @@ from decimal import *
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm, GenerateReleveForm, CategoryForm, SearchCategoryForm from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm, GenerateReleveForm, CategoryForm, SearchCategoryForm
from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte, Reload, Refund, Category from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte, Reload, Refund, Category
from users.models import School from users.models import School
from preferences.models import PaymentMethod, GeneralPreferences, Cotisation from preferences.models import PaymentMethod, GeneralPreferences, Cotisation, DivideHistory
from users.models import CotisationHistory from users.models import CotisationHistory
@active_required @active_required
@ -877,7 +877,39 @@ def gen_releve(request):
else: else:
return render(request, "form.html", {"form": form, "form_title": "Génération d'un relevé", "form_button": "Générer", "form_button_icon": "file-pdf"}) return render(request, "form.html", {"form": form, "form_title": "Génération d'un relevé", "form_button": "Générer", "form_button_icon": "file-pdf"})
@active_required
@login_required
@permission_required('preferences.can_divide')
def divide(request):
"""
Divide all non-divided cotisation
"""
if request.POST:
non_divided_cotisations = CotisationHistory.objects.filter(divided=False)
for cotisation_history in non_divided_cotisations:
cotisation_history.divided = True
cotisation_history.save()
divide_history = DivideHistory(
total_cotisations = non_divided_cotisations.count(),
total_cotisations_amount = sum([x.amount for x in non_divided_cotisations]),
total_ptm_amount = sum([x.amount_ptm for x in non_divided_cotisations]),
coopeman = request.user
)
divide_history.save()
non_divided_cotisations = CotisationHistory.objects.filter(divided=False)
total_amount = sum([x.amount for x in non_divided_cotisations])
total_amount_ptm = sum([x.amount_ptm for x in non_divided_cotisations])
divide_histories = DivideHistory.objects.all().order_by('-date')
return render(
request,
"gestion/divide.html",
{
"total_cotisations": non_divided_cotisations.count(),
"total_amount": total_amount,
"total_amount_ptm": total_amount_ptm,
"divide_histories": divide_histories,
}
)
########## categories ########## ########## categories ##########
@active_required @active_required
@login_required @login_required

View file

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin from simple_history.admin import SimpleHistoryAdmin
from .models import PaymentMethod, GeneralPreferences, Cotisation from .models import PaymentMethod, GeneralPreferences, Cotisation, DivideHistory
class CotisationAdmin(SimpleHistoryAdmin): class CotisationAdmin(SimpleHistoryAdmin):
""" """
@ -24,6 +24,14 @@ class PaymentMethodAdmin(SimpleHistoryAdmin):
search_fields = ('name',) search_fields = ('name',)
list_filter = ('is_active', 'is_usable_in_cotisation', 'is_usable_in_reload', 'affect_balance') list_filter = ('is_active', 'is_usable_in_cotisation', 'is_usable_in_reload', 'affect_balance')
class DivideHistoryAdmin(SimpleHistoryAdmin):
"""
The admin class for Divide histories
"""
list_display = ('date', 'total_cotisations', 'total_cotisations_amount', 'total_ptm_amount', 'coopeman')
ordering = ('-date',)
admin.site.register(PaymentMethod, PaymentMethodAdmin) admin.site.register(PaymentMethod, PaymentMethodAdmin)
admin.site.register(GeneralPreferences, GeneralPreferencesAdmin) admin.site.register(GeneralPreferences, GeneralPreferencesAdmin)
admin.site.register(Cotisation, CotisationAdmin) admin.site.register(Cotisation, CotisationAdmin)
admin.site.register(DivideHistory, DivideHistoryAdmin)

View file

@ -11,6 +11,12 @@ class CotisationForm(forms.ModelForm):
model = Cotisation model = Cotisation
fields = "__all__" fields = "__all__"
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get("amount_ptm") > cleaned_data.get("amount"):
raise ValidationError("La quantité d'argent donnée au club doit être inférieure à\
la quantité d'argent totale")
class PaymentMethodForm(forms.ModelForm): class PaymentMethodForm(forms.ModelForm):
""" """
Form to add and edit :class:`~preferences.models.PaymentMethod`. Form to add and edit :class:`~preferences.models.PaymentMethod`.

View file

@ -0,0 +1,23 @@
# Generated by Django 2.1 on 2019-06-22 21:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0012_auto_20190428_1327'),
]
operations = [
migrations.AddField(
model_name='cotisation',
name='amount_ptm',
field=models.DecimalField(decimal_places=2, max_digits=5, null=True, verbose_name='Montant pour le club Phœnix Technopôle Metz'),
),
migrations.AddField(
model_name='historicalcotisation',
name='amount_ptm',
field=models.DecimalField(decimal_places=2, max_digits=5, null=True, verbose_name='Montant pour le club Phœnix Technopôle Metz'),
),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 2.1 on 2019-06-23 07:57
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('preferences', '0013_auto_20190622_2334'),
]
operations = [
migrations.AlterModelOptions(
name='cotisation',
options={'permissions': (('can_divide', 'Can divide money for cotisation'),)},
),
]

View file

@ -0,0 +1,30 @@
# Generated by Django 2.1 on 2019-06-23 08:49
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('preferences', '0014_auto_20190623_0957'),
]
operations = [
migrations.CreateModel(
name='DivideHistory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now_add=True)),
('total_cotisations', models.IntegerField(verbose_name='Nombre de cotisations')),
('total_cotisations_amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Montant total des cotisations')),
('total_ptm_amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Montant donné au Phœnix Technopôle Metz')),
('coopeman', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='divide_realized', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Historique répartition',
},
),
]

View file

@ -1,6 +1,7 @@
from django.db import models from django.db import models
from simple_history.models import HistoricalRecords from simple_history.models import HistoricalRecords
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
class PaymentMethod(models.Model): class PaymentMethod(models.Model):
@ -118,6 +119,8 @@ class Cotisation(models.Model):
""" """
Stores cotisations. Stores cotisations.
""" """
class Meta:
permissions = (("can_divide", "Can divide money for cotisation"),)
amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant", validators=[MinValueValidator(0)]) amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant", validators=[MinValueValidator(0)])
""" """
Price of the cotisation. Price of the cotisation.
@ -126,6 +129,10 @@ class Cotisation(models.Model):
""" """
Duration (in days) of the cotisation Duration (in days) of the cotisation
""" """
amount_ptm = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant pour le club Phœnix Technopôle Metz")
"""
Amount of money given to the PTM club
"""
history = HistoricalRecords() history = HistoricalRecords()
def __str__(self): def __str__(self):
@ -134,3 +141,35 @@ class Cotisation(models.Model):
else: else:
jour = "jours" jour = "jours"
return "Cotisation de " + str(self.duration) + " " + jour + " pour le prix de " + str(self.amount) + "" return "Cotisation de " + str(self.duration) + " " + jour + " pour le prix de " + str(self.amount) + ""
class DivideHistory(models.Model):
"""
Stores divide history
"""
class Meta:
verbose_name = "Historique répartition"
date = models.DateTimeField(auto_now_add=True)
"""
Date of the divide
"""
total_cotisations = models.IntegerField(verbose_name="Nombre de cotisations")
"""
Number of non-divided cotisations (before the divide)
"""
total_cotisations_amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant total des cotisations")
"""
Amount of non-divided cotisations (before the divide)
"""
total_ptm_amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant donné au Phœnix Technopôle Metz")
"""
Amount given to the PTM
"""
coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="divide_realized")
"""
Coopeman (:class:`django.contrib.auth.models.User`) who collected the reload.
"""
def __str__(self):
return "Répartition du " + str(self.date)

View file

@ -19,6 +19,7 @@
<tr> <tr>
<th>Durée de cotisation</th> <th>Durée de cotisation</th>
<th>Prix</th> <th>Prix</th>
<th>Pour PhœnixTM</th>
<th>Administration</th> <th>Administration</th>
</tr> </tr>
</thead> </thead>
@ -27,6 +28,7 @@
<tr> <tr>
<td>{{ cotisation.duration }} jour{{ cotisation.duration|pluralize }}</td> <td>{{ cotisation.duration }} jour{{ cotisation.duration|pluralize }}</td>
<td>{{ cotisation.amount }} €</td> <td>{{ cotisation.amount }} €</td>
<td>{{ cotisation.amount_ptm | default:0}} €</td>
<td>{% if perms.preferences.change_cotisation %}<a class="button small" href="{% url 'preferences:editCotisation' cotisation.pk %}"><i class="fa fa-pencil-alt"></i> Modifier</a> {% endif %}{% if perms.preferences.delete_cotisation %}<a class="button small" href="{% url 'preferences:deleteCotisation' cotisation.pk %}"><i class="fa fa-trash"></i> Supprimer</a>{% endif %}</td> <td>{% if perms.preferences.change_cotisation %}<a class="button small" href="{% url 'preferences:editCotisation' cotisation.pk %}"><i class="fa fa-pencil-alt"></i> Modifier</a> {% endif %}{% if perms.preferences.delete_cotisation %}<a class="button small" href="{% url 'preferences:deleteCotisation' cotisation.pk %}"><i class="fa fa-trash"></i> Supprimer</a>{% endif %}</td>
</tr> </tr>
{% endfor %} {% endfor %}

View file

@ -32,9 +32,14 @@
{% if request.user.is_staff %} {% if request.user.is_staff %}
<span class="tabulation2"> <span class="tabulation2">
<i class="fa fa-chart-bar"></i> <a href="{% url 'gestion:stats' %}">Stats</a> <i class="fa fa-chart-bar"></i> <a href="{% url 'gestion:stats' %}">Stats</a>
</span> </span>
<span class="tabulation2"> <span class="tabulation2">
<i class="fa fa-business-time"></i> <a href="{% url 'gestion:gen_releve' %}">Comptabilité</a> <i class="fa fa-business-time"></i> <a href="{% url 'gestion:gen_releve' %}">Relevé</a>
</span>
{% endif %}
{% if perms.preferences.can_divide %}
<span class="tabulation2">
<i class="fa fa-hand-holding-usd"></i> <a href="{% url 'gestion:divide' %}">Répartition</a>
</span> </span>
{% endif %} {% endif %}
{% if perms.preferences.view_cotisation %} {% if perms.preferences.view_cotisation %}

View file

@ -0,0 +1,42 @@
# Generated by Django 2.1 on 2019-06-23 07:57
from django.db import migrations, models
def update(apps, schema_editor):
CotisationHistory = apps.get_model('users', 'CotisationHistory')
for cotisation_history in CotisationHistory.objects.all():
cotisation_history.amount_ptm = cotisation_history.cotisation.amount_ptm
cotisation_history.save()
def reverse_update(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('users', '0006_auto_20190611_0105'),
]
operations = [
migrations.AddField(
model_name='cotisationhistory',
name='amount_ptm',
field=models.DecimalField(decimal_places=2, max_digits=5, null=True, verbose_name='Montant pour le club Phœnix Technopôle Metz'),
),
migrations.AddField(
model_name='cotisationhistory',
name='divided',
field=models.BooleanField(default=False, verbose_name='Répartition'),
),
migrations.AddField(
model_name='historicalcotisationhistory',
name='amount_ptm',
field=models.DecimalField(decimal_places=2, max_digits=5, null=True, verbose_name='Montant pour le club Phœnix Technopôle Metz'),
),
migrations.AddField(
model_name='historicalcotisationhistory',
name='divided',
field=models.BooleanField(default=False, verbose_name='Répartition'),
),
migrations.RunPython(update, reverse_update)
]

View file

@ -61,6 +61,14 @@ class CotisationHistory(models.Model):
""" """
User (:class:`django.contrib.auth.models.User`) who registered the cotisation. User (:class:`django.contrib.auth.models.User`) who registered the cotisation.
""" """
divided = models.BooleanField(default=False, verbose_name="Répartition")
"""
True if money of cotisation have been divided between CTM and PTM
"""
amount_ptm = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant pour le club Phœnix Technopôle Metz")
"""
Amount of money given to the PTM club
"""
history = HistoricalRecords() history = HistoricalRecords()
class WhiteListHistory(models.Model): class WhiteListHistory(models.Model):

View file

@ -583,6 +583,7 @@ def addCotisationHistory(request, pk):
cotisation.coopeman = request.user cotisation.coopeman = request.user
cotisation.amount = cotisation.cotisation.amount cotisation.amount = cotisation.cotisation.amount
cotisation.duration = cotisation.cotisation.duration cotisation.duration = cotisation.cotisation.duration
cotisation.amount_ptm = cotisation.cotisation.amount_ptm
if(user.profile.cotisationEnd and user.profile.cotisationEnd > timezone.now()): if(user.profile.cotisationEnd and user.profile.cotisationEnd > timezone.now()):
cotisation.endDate = user.profile.cotisationEnd + timedelta(days=cotisation.cotisation.duration) cotisation.endDate = user.profile.cotisationEnd + timedelta(days=cotisation.cotisation.duration)
else: else: