3
0
Fork 0
mirror of https://github.com/nanoy42/coope synced 2024-12-23 15:33:45 +00:00

Merge branch 'inscription' into dev

This commit is contained in:
Yoann Pétri 2019-02-26 23:19:34 +01:00
commit eabf4cdb2b
13 changed files with 182 additions and 56 deletions

View file

@ -16,7 +16,7 @@ def run_tex(source):
with open(filename, 'x', encoding='utf-8') as f:
f.write(source)
latex_interpreter = getattr(settings, 'LATEX_INTERPRETER', DEFAULT_INTERPRETER)
latex_command = f'cd "{tempdir}" && {latex_interpreter} -interaction=batchmode {os.path.basename(filename)}'
latex_command = 'cd "{tempdir}" && {latex_interpreter} -interaction=batchmode {path}'.format(tempdir=tempdir, latex_interpreter=latex_interpreter, path=os.path.basename(filename))
process = run(latex_command, shell=True, stdout=PIPE, stderr=PIPE)
try:
if process.returncode == 1:

View file

@ -47,12 +47,11 @@ class Product(models.Model):
def user_ranking(self, pk):
user = User.objects.get(pk=pk)
consumptions = ConsumptionHistory.objects.filter(customer=user).filter(product=self)
# add menu
nb = 0
for consumption in consumptions:
nb += consumption.quantity
return (user, nb)
consumptions = Consumption.objects.filter(customer=user).filter(product=self)
if consumptions:
return (user, consumptions[0].quantity)
else:
return (user, 0)
@property
def ranking(self):

View file

@ -6,6 +6,7 @@ from django.urls import reverse
from django.contrib.auth.decorators import login_required, permission_required
from django.http import HttpResponse
from django.forms.models import model_to_dict
from django.http import Http404
from coopeV3.acl import active_required
@ -263,7 +264,11 @@ def get_config(request):
"""
Load the config and return it in a json format
"""
gp,_ = GeneralPreferences.objects.get_or_create(pk=1)
data = json.dumps(model_to_dict(gp))
gp, _ = GeneralPreferences.objects.defer("statutes", "rules", "menu").get_or_create(pk=1)
gp_dict = model_to_dict(gp)
del gp_dict["statutes"]
del gp_dict["rules"]
del gp_dict["menu"]
data = json.dumps(gp_dict)
return HttpResponse(data, content_type='application/json')

View file

@ -16,6 +16,7 @@
{% csrf_token %}
{{ form }}
<br>
{{ extra_html | safe }}<br><br>
<button type="submit"><i class="fa fa-{{form_button_icon}}"></i> {{form_button}}</button>
</form>
</section>

View file

@ -0,0 +1,23 @@
# Generated by Django 2.1 on 2019-02-18 21:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='historicalprofile',
name='date_verified',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='profile',
name='date_verified',
field=models.DateTimeField(blank=True, null=True),
),
]

View file

@ -0,0 +1,21 @@
# Generated by Django 2.1 on 2019-02-19 18:21
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0002_auto_20190218_2231'),
]
operations = [
migrations.RemoveField(
model_name='historicalprofile',
name='date_verified',
),
migrations.RemoveField(
model_name='profile',
name='date_verified',
),
]

View file

@ -0,0 +1,25 @@
# Generated by Django 2.1 on 2019-02-26 22:13
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0003_auto_20190219_1921'),
]
operations = [
migrations.AlterModelOptions(
name='cotisationhistory',
options={'verbose_name': 'Historique cotisation'},
),
migrations.RemoveField(
model_name='cotisationhistory',
name='valid',
),
migrations.RemoveField(
model_name='historicalcotisationhistory',
name='valid',
),
]

View file

@ -26,18 +26,6 @@ class CotisationHistory(models.Model):
"""
class Meta:
verbose_name = "Historique cotisation"
permissions = (
("validate_cotisationhistory", "Peut (in)valider les cotisations"),
)
WAITING = 0
VALID = 1
INVALID = 2
VALIDATION_CHOICES = (
(WAITING, 'En attente de validation'),
(VALID, 'Validée'),
(INVALID, 'Invalidée'),
)
user = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name="Client")
amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant")
duration = models.PositiveIntegerField(verbose_name="Durée")
@ -46,7 +34,6 @@ class CotisationHistory(models.Model):
paymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT, verbose_name="Moyen de paiement")
cotisation = models.ForeignKey(Cotisation, on_delete=models.PROTECT, verbose_name="Type de cotisation")
coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="cotisation_made")
valid = models.IntegerField(choices=VALIDATION_CHOICES, default=WAITING)
history = HistoricalRecords()
class WhiteListHistory(models.Model):

View file

@ -0,0 +1,70 @@
\documentclass[a4paper, 12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage{eurosym}
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
\usepackage{tabularx}
\usepackage{longtable}
\usepackage{tabu}
\usepackage{fancyhdr}
\usepackage{natbib}
\usepackage{graphicx}
\setlength{\parindent}{0pt}
\pagestyle{fancy}
\renewcommand{\headrulewidth}{0pt}
\fancyhead[C]{\includegraphics[scale=0.3]{ {{- path -}} }}
\begin{document}
\vspace*{0.3\baselineskip}
\begin{center}
\huge{Bulletin d'adhésion à l'association Coopé Technopôle Metz}
\end{center}
\vspace*{\baselineskip}
Je soussigné(e), {{user.first_name}} {{user.last_name}},
\begin{itemize}
\item atteste sur l'honneur que les informations fournies à l'association Coopé Technopôle Metz sont correctes et que je n'ai jamais été enregistré dans l'association sous un autre nom / pseudonyme
\item joins l'association de mon plein gré
\item m'engage à respecter les statuts et le réglement intérieur de l'association
\item reconnais le but de l'assocation Coopé Technopôle Metz et atteste avoir pris conaissances des droits et des devoirs des membres de l'association
\item consent à ce que les données fournies à l'association, ainsi que mes autres données de compte (débit, crédit, solde et historique des transactions) soient stockées dans le logiciel de gestion et accessibles par tous les membres actifs de l'association, en particulier par le comité de direction
\end{itemize}
\begin{flushright}
Fait à Metz, le {{user.date_joined.strftime('%d/%m/%Y')}}
\end{flushright}
Ce bulletin a été validé électroniquement par {{user.first_name}} {{user.last_name}} le {{user.date_joined.strftime('%d/%m/%Y %H:%M:%S')}}, heure de Paris.
\newpage
\begin{center}
\huge{Historique des cotisations à l'association}
\end{center}
\vspace*{\baselineskip}
\begin{longtabu}{|c|X|X|X|X|X|}
\hline
\# & Date & Montant & Durée & Moyen de paiement & Date de fin\\
\hline
{% for cotisation in cotisations %}
{{cotisation.pk}} & {{cotisation.paymentDate.strftime('%d/%M/%Y %H:%M')}} & {{cotisation.amount}} \euro{} & {{cotisation.duration}} jour(s)& {{cotisation.paymentMethod}} & {{cotisation.endDate.strftime('%d/%M/%Y %H:%M')}} \\
\hline
{% endfor %}
\end{longtabu}
\newpage
\begin{center}
\huge{Attestation d'adhésion}
\end{center}
\vspace*{\baselineskip}
Le comité de direction de la Coopé Technopôle Metz atteste avoir reçu les cotisations de la part de {{user.first_name}} {{user.last_name}}. {% if user.profile.is_adherent %}Le comité atteste aussi que {{user.first_name}} {{user.last_name}} est membre adhérent de l'association au {{now.strftime('%d/%m/%Y')}}.{% endif %}
{% if user.is_staff %}
\vspace*{\baselineskip}
Le membre est jugé comme membre actif par le comité de direction.
{% endif %}
\vspace*{\baselineskip}
Cette attestation est délivrée pour jouir des droits qui lui sont dus.
\end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

View file

@ -51,7 +51,7 @@
<div class="12u">
<ul class="alt">
<li>
{% if self or perms.users.can_change_user %}
{% if self or perms.users.change_user %}
<span><a href="{% url 'users:editUser' user.pk %}"><i class="fa fa-pencil-alt"></i> Modifier {{self | yesno:"mes,les"}} informations</a></span>
{% endif %}
{% if self %}
@ -66,6 +66,9 @@
{% if perms.auth.change_user %}
<span class="tabulation"><a href="{% url 'users:switchActivateUser' user.pk %}"><i class="fa fa-check-circle"></i> {{ user.is_active | yesno:"Désa,A"}}ctiver</a></span>
{% endif %}
{% if perms.users.view_user %}
<span class="tabulation"><a href="{% url 'users:genUserInfos' user.pk %}"><i class="fa fa-id-card"></i> Générer les informations</a></span>
{% endif %}
</li>
</ul>
</div>
@ -227,7 +230,6 @@
<th>Date de paiement</th>
<th>Moyen de paiement</th>
<th>Date de fin</th>
<th>État</th>
<th>Modération</th>
</tr>
</thead>
@ -239,8 +241,7 @@
<td>{{cotisation.paymentDate}}</td>
<td>{{cotisation.paymentMethod}}</td>
<td>{{cotisation.endDate}}</td>
<td>{{cotisation.valid}}</td>
<td>{% if perms.users.validate_cotisationHistory %}<a class="button small" href="{% url 'users:validateCotisationHistory' cotisation.pk %}"><i class="fa fa-check-circle"></i> Valider</a> <a class="button small" href="{% url 'users:invalidateCotisationHistory' cotisation.pk %}"><i class="fa fa-times-circle"></i> Invalider</a>{% endif %}</td>
<td>{% if perms.users.delete_cotisationhistory %}<a class="button small" href="{% url 'users:deleteCotisationHistory' cotisation.pk %}"><i class="fa fa-trash"></i> Supprimer</a>{% endif %}</td>
</tr>
{% endfor %}
</tbody>

View file

@ -33,8 +33,7 @@ urlpatterns = [
path('non-admin-users-autocomplete', views.NonAdminUserAutocomplete.as_view(), name="non-admin-users-autocomplete"),
path('getUser/<int:pk>', views.getUser, name="getUser"),
path('addCotisationHistory/<int:pk>', views.addCotisationHistory, name="addCotisationHistory"),
path('validateCotisationHistory/<int:pk>', views.validateCotisationHistory, name="validateCotisationHistory"),
path('invalidateCotisationHistory/<int:pk>', views.invalidateCotisationHistory, name="invalidateCotisationHistory"),
path('deleteCotisationHistory/<int:pk>', views.deleteCotisationHistory, name="deleteCotisationHistory"),
path('addWhiteListHistory/<int:pk>', views.addWhiteListHistory, name="addWhiteListHistory"),
path('schoolsIndex', views.schoolsIndex, name="schoolsIndex"),
path('createSchool', views.createSchool, name="createSchool"),
@ -45,4 +44,5 @@ urlpatterns = [
path('allMenus/<int:pk>/<int:page>', views.all_menus, name="allMenus"),
path('exportCSV', views.export_csv, name="exportCSV"),
path('switchActivateUser/<int:pk>', views.switch_activate_user, name="switchActivateUser"),
path('genUserInfos/<int:pk>', views.gen_user_infos, name="genUserInfos"),
]

View file

@ -9,12 +9,16 @@ from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.contrib.auth.decorators import login_required, permission_required
from django.forms.models import model_to_dict
from django.utils import timezone
from django.conf import settings
import simplejson as json
from datetime import datetime, timedelta
from dal import autocomplete
import csv
import os
from django_tex.views import render_to_pdf
from coopeV3.acl import admin_required, superuser_required, self_or_has_perm, active_required
from .models import CotisationHistory, WhiteListHistory, School
from .forms import CreateUserForm, LoginForm, CreateGroupForm, EditGroupForm, SelectUserForm, GroupsEditForm, EditPasswordForm, addCotisationHistoryForm, addCotisationHistoryForm, addWhiteListHistoryForm, SelectNonAdminUserForm, SelectNonSuperUserForm, SchoolForm, ExportForm
@ -156,7 +160,7 @@ def profile(request, pk):
"""
user = get_object_or_404(User, pk=pk)
self = request.user == user
cotisations = CotisationHistory.objects.filter(user=user)
cotisations = CotisationHistory.objects.filter(user=user).order_by('-paymentDate')
whitelists = WhiteListHistory.objects.filter(user=user)
reloads = Reload.objects.filter(customer=user).order_by('-date')[:5]
consumptionsChart = Consumption.objects.filter(customer=user)
@ -177,8 +181,6 @@ def profile(request, pk):
if quantities_pre[k]/totQ >= 0.01:
products.append(products_pre[k])
quantities.append(quantities_pre[k])
print(products)
print(quantities)
lastConsumptions = ConsumptionHistory.objects.filter(customer=user).order_by('-date')[:10]
lastMenus = MenuHistory.objects.filter(customer=user).order_by('-date')[:10]
return render(request, "users/profile.html",
@ -219,13 +221,12 @@ def createUser(request):
form = CreateUserForm(request.POST or None)
if(form.is_valid()):
user = form.save(commit=False)
user.set_password(user.username)
user.save()
user.profile.school = form.cleaned_data['school']
user.save()
messages.success(request, "L'utilisateur a bien été créé")
return redirect(reverse('users:profile', kwargs={'pk':user.pk}))
return render(request, "form.html", {"form_entete": "Gestion des utilisateurs", "form":form, "form_title":"Création d'un nouvel utilisateur", "form_button":"Créer l'utilisateur", "form_button_icon": "user-plus"})
return render(request, "form.html", {"form_entete": "Gestion des utilisateurs", "form":form, "form_title":"Création d'un nouvel utilisateur", "form_button":"Créer mon compte", "form_button_icon": "user-plus", 'extra_html': '<strong>En cliquant sur le bouton "Créer mon compte", vous :<ul><li>attestez sur l\'honneur que les informations fournies à l\'association Coopé Technopôle Metz sont correctes et que vous n\'avez jamais été enregistré dans l\'association sous un autre nom / pseudonyme</li><li>joignez l\'association de votre plein gré</li><li>vous engagez à respecter les statuts et le réglement intérieur de l\'association (envoyés par mail)</li><li>reconnaissez le but de l\'assocation Coopé Technopôle Metz et vous attestez avoir pris conaissances des droits et des devoirs des membres de l\'association</li><li>consentez à ce que les données fournies à l\'association, ainsi que vos autres données de compte (débit, crédit, solde et historique des transactions) soient stockées dans le logiciel de gestion et accessibles par tous les membres actifs de l\'association, en particulier par le comité de direction</li></ul></strong>'})
@active_required
@login_required
@ -512,7 +513,17 @@ def switch_activate_user(request, pk):
user.save()
messages.success(request, "Le statut de l'utilisateur a bien été changé")
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
@active_required
@login_required
@permission_required('auth.view_user')
def gen_user_infos(request, pk):
user= get_object_or_404(User, pk=pk)
cotisations = CotisationHistory.objects.filter(user=user).order_by('-paymentDate')
now = datetime.now()
path = os.path.join(settings.BASE_DIR, "users/templates/users/coope.png")
return render_to_pdf(request, 'users/bulletin.tex', {"user": user, "now": now, "cotisations": cotisations, "path":path}, filename="bulletin_" + user.first_name + "_" + user.last_name + ".pdf")
########## Groups ##########
@active_required
@ -892,39 +903,22 @@ def addCotisationHistory(request, pk):
@active_required
@login_required
@permission_required('users.validate_cotisationhistory')
def validateCotisationHistory(request, pk):
@permission_required('users.delete_cotisationhistory')
def deleteCotisationHistory(request, pk):
"""
Validate the requested :model:`users.CotisationHistory`
Delete the requested :model:`users.CotisationHistory`
``pk``
The primary key of the :model:`users.CotisationHistory`
"""
cotisationHistory = get_object_or_404(CotisationHistory, pk=pk)
cotisationHistory.valid = CotisationHistory.VALID
cotisationHistory.save()
messages.success(request, "La cotisation a bien été validée")
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
@active_required
@login_required
@permission_required('users.validate_cotisationhistory')
def invalidateCotisationHistory(request, pk):
"""
Invalidate the requested :model:`users.CotisationHistory`
``pk``
The primary key of the :model:`users.CotisationHistory`
"""
cotisationHistory = get_object_or_404(CotisationHistory, pk=pk)
cotisationHistory.valid = CotisationHistory.INVALID
cotisationHistory.save()
user = cotisationHistory.user
user.profile.cotisationEnd = user.profile.cotisationEnd - timedelta(days=cotisationHistory.duration)
if(cotisationHistory.paymentMethod.affect_balance):
user.profile.debit -= cotisationHistory.cotisation.amount
user.save()
messages.success(request, "La cotisation a bien été invalidée")
cotisationHistory.delete()
messages.success(request, "La cotisation a bien été supprimée")
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
########## Whitelist ##########