Browse Source

Add divide vie and DivideHisotry model

pull/1/head
Yoann Piétri 7 years ago
parent
commit
0fd8f2d419
  1. 77
      gestion/templates/gestion/divide.html
  2. 1
      gestion/urls.py
  3. 36
      gestion/views.py
  4. 12
      preferences/admin.py
  5. 6
      preferences/forms.py
  6. 23
      preferences/migrations/0013_auto_20190622_2334.py
  7. 17
      preferences/migrations/0014_auto_20190623_0957.py
  8. 30
      preferences/migrations/0015_dividehistory.py
  9. 39
      preferences/models.py
  10. 2
      preferences/templates/preferences/cotisations_index.html
  11. 9
      templates/nav.html
  12. 42
      users/migrations/0007_auto_20190623_0957.py
  13. 8
      users/models.py
  14. 1
      users/views.py

77
gestion/templates/gestion/divide.html

@ -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 %}

1
gestion/urls.py

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

36
gestion/views.py

@ -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 .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte, Reload, Refund, Category
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
@active_required
@ -877,7 +877,39 @@ def gen_releve(request):
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"})
@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 ##########
@active_required
@login_required

12
preferences/admin.py

@ -1,6 +1,6 @@
from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin
from .models import PaymentMethod, GeneralPreferences, Cotisation
from .models import PaymentMethod, GeneralPreferences, Cotisation, DivideHistory
class CotisationAdmin(SimpleHistoryAdmin):
"""
@ -24,6 +24,14 @@ class PaymentMethodAdmin(SimpleHistoryAdmin):
search_fields = ('name',)
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(GeneralPreferences, GeneralPreferencesAdmin)
admin.site.register(Cotisation, CotisationAdmin)
admin.site.register(Cotisation, CotisationAdmin)
admin.site.register(DivideHistory, DivideHistoryAdmin)

6
preferences/forms.py

@ -11,6 +11,12 @@ class CotisationForm(forms.ModelForm):
model = Cotisation
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):
"""
Form to add and edit :class:`~preferences.models.PaymentMethod`.

23
preferences/migrations/0013_auto_20190622_2334.py

@ -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'),
),
]

17
preferences/migrations/0014_auto_20190623_0957.py

@ -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'),)},
),
]

30
preferences/migrations/0015_dividehistory.py

@ -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',
},
),
]

39
preferences/models.py

@ -1,6 +1,7 @@
from django.db import models
from simple_history.models import HistoricalRecords
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
class PaymentMethod(models.Model):
@ -118,6 +119,8 @@ class Cotisation(models.Model):
"""
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)])
"""
Price of the cotisation.
@ -126,6 +129,10 @@ class Cotisation(models.Model):
"""
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()
def __str__(self):
@ -134,3 +141,35 @@ class Cotisation(models.Model):
else:
jour = "jours"
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)

2
preferences/templates/preferences/cotisations_index.html

@ -19,6 +19,7 @@
<tr>
<th>Durée de cotisation</th>
<th>Prix</th>
<th>Pour PhœnixTM</th>
<th>Administration</th>
</tr>
</thead>
@ -27,6 +28,7 @@
<tr>
<td>{{ cotisation.duration }} jour{{ cotisation.duration|pluralize }}</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>
</tr>
{% endfor %}

9
templates/nav.html

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

42
users/migrations/0007_auto_20190623_0957.py

@ -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)
]

8
users/models.py

@ -61,6 +61,14 @@ class CotisationHistory(models.Model):
"""
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()
class WhiteListHistory(models.Model):

1
users/views.py

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

Loading…
Cancel
Save