mirror of
https://github.com/nanoy42/coope
synced 2024-12-23 07:23:47 +00:00
Improvements
This commit is contained in:
parent
192696d026
commit
73e7697a3c
11 changed files with 299 additions and 8 deletions
|
@ -129,4 +129,6 @@ LOGIN_URL = '/users/login'
|
|||
MEDIA_ROOT = os.path.join(BASE_DIR, 'mediafiles')
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
INTERNAL_IPS = ["127.0.0.1"]
|
||||
INTERNAL_IPS = ["127.0.0.1"]
|
||||
|
||||
EMAIL_SUBJECT_PREFIX = "[Coope Admin] "
|
|
@ -1,6 +1,6 @@
|
|||
from django.contrib import admin
|
||||
from simple_history.admin import SimpleHistoryAdmin
|
||||
from .models import PaymentMethod, GeneralPreferences, Cotisation, DivideHistory, PriceProfile
|
||||
from .models import PaymentMethod, GeneralPreferences, Cotisation, DivideHistory, PriceProfile, Improvement
|
||||
|
||||
class CotisationAdmin(SimpleHistoryAdmin):
|
||||
"""
|
||||
|
@ -40,8 +40,18 @@ class DivideHistoryAdmin(SimpleHistoryAdmin):
|
|||
list_display = ('date', 'total_cotisations', 'total_cotisations_amount', 'total_ptm_amount', 'coopeman')
|
||||
ordering = ('-date',)
|
||||
|
||||
class ImprovementAdmin(SimpleHistoryAdmin):
|
||||
"""
|
||||
The admin class for Improvement.
|
||||
"""
|
||||
list_display = ('title', 'mode', 'seen', 'done', 'date')
|
||||
ordering = ('-date',)
|
||||
search_fields = ('title', 'description')
|
||||
list_filter = ('mode', 'seen', 'done')
|
||||
|
||||
admin.site.register(PaymentMethod, PaymentMethodAdmin)
|
||||
admin.site.register(GeneralPreferences, GeneralPreferencesAdmin)
|
||||
admin.site.register(Cotisation, CotisationAdmin)
|
||||
admin.site.register(PriceProfile, PriceProfileAdmin)
|
||||
admin.site.register(DivideHistory, DivideHistoryAdmin)
|
||||
admin.site.register(DivideHistory, DivideHistoryAdmin)
|
||||
admin.site.register(Improvement, ImprovementAdmin)
|
|
@ -1,7 +1,7 @@
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from .models import Cotisation, PaymentMethod, GeneralPreferences, PriceProfile
|
||||
from .models import Cotisation, PaymentMethod, GeneralPreferences, PriceProfile, Improvement
|
||||
|
||||
class CotisationForm(forms.ModelForm):
|
||||
"""
|
||||
|
@ -50,3 +50,11 @@ class GeneralPreferencesForm(forms.ModelForm):
|
|||
'home_text': forms.Textarea(attrs={'placeholder': 'Ce message sera affiché sur la page d\'accueil'})
|
||||
}
|
||||
|
||||
|
||||
class ImprovementForm(forms.ModelForm):
|
||||
"""
|
||||
Form to create an improvement
|
||||
"""
|
||||
class Meta:
|
||||
model = Improvement
|
||||
fields = ["title", "mode", "description"]
|
||||
|
|
31
preferences/migrations/0019_improvement.py
Normal file
31
preferences/migrations/0019_improvement.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 2.1 on 2019-09-08 09:59
|
||||
|
||||
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', '0018_auto_20190627_2302'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Improvement',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=255)),
|
||||
('mode', models.IntegerField(choices=[(0, 'Bug'), (1, 'Amélioration'), (2, 'Nouvelle fonctionnalité')])),
|
||||
('description', models.TextField()),
|
||||
('seen', models.BooleanField(default=False)),
|
||||
('done', models.BooleanField(default=False)),
|
||||
('coopeman', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='improvement_submitted', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Amélioration',
|
||||
},
|
||||
),
|
||||
]
|
39
preferences/migrations/0020_auto_20190908_1217.py
Normal file
39
preferences/migrations/0020_auto_20190908_1217.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Generated by Django 2.1 on 2019-09-08 10:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('preferences', '0019_improvement'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='improvement',
|
||||
name='date',
|
||||
field=models.DateTimeField(auto_now_add=True, default='2019-09-08 00:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='improvement',
|
||||
name='done',
|
||||
field=models.BooleanField(default=False, verbose_name='Fait ?'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='improvement',
|
||||
name='mode',
|
||||
field=models.IntegerField(choices=[(0, 'Bug'), (1, 'Amélioration'), (2, 'Nouvelle fonctionnalité')], verbose_name='Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='improvement',
|
||||
name='seen',
|
||||
field=models.BooleanField(default=False, verbose_name='Vu ?'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='improvement',
|
||||
name='title',
|
||||
field=models.CharField(max_length=255, verbose_name='Titre'),
|
||||
),
|
||||
]
|
|
@ -202,3 +202,31 @@ class PriceProfile(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Improvement(models.Model):
|
||||
"""
|
||||
Stores bugs and amelioration proposals.
|
||||
"""
|
||||
|
||||
BUG = 0
|
||||
AMELIORATION = 1
|
||||
NEWFEATURE = 2
|
||||
|
||||
MODES = (
|
||||
(BUG, "Bug"),
|
||||
(AMELIORATION, "Amélioration"),
|
||||
(NEWFEATURE, "Nouvelle fonctionnalité")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Amélioration"
|
||||
|
||||
title = models.CharField(max_length=255, verbose_name="Titre")
|
||||
mode = models.IntegerField(choices=MODES, verbose_name="Type")
|
||||
description = models.TextField()
|
||||
seen = models.BooleanField(default=False, verbose_name="Vu ?")
|
||||
done = models.BooleanField(default=False, verbose_name="Fait ?")
|
||||
coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="improvement_submitted")
|
||||
date = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
21
preferences/templates/preferences/improvement_profile.html
Normal file
21
preferences/templates/preferences/improvement_profile.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% extends "base.html" %}
|
||||
{% block entete %}Amélioration {{improvement.title}}{% endblock %}
|
||||
{% block navbar %}
|
||||
<ul>
|
||||
<li><a href="#first">{{improvement.title}}</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<section id="first" class="main">
|
||||
<header class="major">
|
||||
<h2>{{improvement.title}}</h2>
|
||||
</header>
|
||||
<a href="{% url 'preferences:improvementsIndex' %}" class="button">Retour à la liste des améliorations</a><br><br>
|
||||
<strong>Titre : </strong> {{improvement.title}}<br>
|
||||
<strong>Type : </strong> {{improvement.get_mode_display}}<br>
|
||||
<strong>Date : </strong> {{improvement.date}}<br>
|
||||
<strong>Fait : </strong> {{improvement.done|yesno:"Oui,Non"}}<br>
|
||||
<strong>Coopeman : </strong> {{improvement.coopeman}}<br>
|
||||
<strong>Description : </strong> {{improvement.description}}<br>
|
||||
</section>
|
||||
{% endblock %}
|
68
preferences/templates/preferences/improvements_index.html
Normal file
68
preferences/templates/preferences/improvements_index.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
{% extends "base.html" %}
|
||||
{% block entete %}Améliorations{% endblock %}
|
||||
{% block navbar %}
|
||||
<ul>
|
||||
<li><a href="#first">Liste des améliorations à faire</a></li>
|
||||
<li><a href="#seconde">Liste des améliorations faîtes</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<section id="first" class="main">
|
||||
<header class="major">
|
||||
<h2>Liste des améliorations à faire</h2>
|
||||
</header>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Titre</th>
|
||||
<th>Type</th>
|
||||
<th>Vu ?</th>
|
||||
<th>Date</th>
|
||||
<th>Administration</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for improvement in todo_improvements %}
|
||||
<tr>
|
||||
<td>{{improvement.title}}</td>
|
||||
<td>{{improvement.get_mode_display}}</td>
|
||||
<td>{{improvement.seen|yesno:"Oui,Non"}}</td>
|
||||
<td>{{improvement.date}}</td>
|
||||
<td><a href="{% url 'preferences:improvementProfile' improvement.pk %}" class="button small"><i class="fa fa-eye"></i> Voir</a> <a href="{% url 'preferences:changeImprovementState' improvement.pk %}" class="button small"><i class="fa fa-check"></i> Passer en fait</a> <a href="{% url 'preferences:deleteImprovement' improvement.pk %}" class="button small"><i class="fa fa-trash"></i> Supprimer</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<section id="second" class="main">
|
||||
<header class="major">
|
||||
<h2>Liste des améliorations faîtes</h2>
|
||||
</header>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Titre</th>
|
||||
<th>Type</th>
|
||||
<th>Vu ?</th>
|
||||
<th>Date</th>
|
||||
<th>Administration</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for improvement in done_improvements %}
|
||||
<tr>
|
||||
<td>{{improvement.title}}</td>
|
||||
<td>{{improvement.get_mode_display}}</td>
|
||||
<td>{{improvement.seen|yesno:"Oui,Non"}}</td>
|
||||
<td>{{improvement.date}}</td>
|
||||
<td><a href="{% url 'preferences:improvementProfile' improvement.pk %}" class="button small"><i class="fa fa-eye"></i> Voir</a> <a href="{% url 'preferences:changeImprovementState' improvement.pk %}" class="button small"><i class="fa fa-check"></i> Passer en non fait</a> <a href="{% url 'preferences:deleteImprovement' improvement.pk %}" class="button small"><i class="fa fa-trash"></i> Supprimer</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -19,5 +19,10 @@ urlpatterns = [
|
|||
path('deletePriceProfile/<int:pk>', views.delete_price_profile, name="deletePriceProfile"),
|
||||
path('inactive', views.inactive, name="inactive"),
|
||||
path('getConfig', views.get_config, name="getConfig"),
|
||||
path('getCotisation/<int:pk>', views.get_cotisation, name="getCotisation")
|
||||
,]
|
||||
path('getCotisation/<int:pk>', views.get_cotisation, name="getCotisation"),
|
||||
path('addImprovement', views.add_improvement, name="addImprovement"),
|
||||
path('improvementsIndex', views.improvements_index, name="improvementsIndex"),
|
||||
path('improvementProfile/<int:pk>', views.improvement_profile, name="improvementProfile"),
|
||||
path('deleteImprovement/<int:pk>', views.delete_improvement, name="deleteImprovement"),
|
||||
path('changeImprovementState/<int:pk>', views.change_improvement_state, name="changeImprovementState"),
|
||||
]
|
||||
|
|
|
@ -7,12 +7,13 @@ 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 django.core.mail import mail_admins
|
||||
|
||||
from coopeV3.acl import active_required
|
||||
|
||||
from .models import GeneralPreferences, Cotisation, PaymentMethod, PriceProfile
|
||||
from .models import GeneralPreferences, Cotisation, PaymentMethod, PriceProfile, Improvement
|
||||
|
||||
from .forms import CotisationForm, PaymentMethodForm, GeneralPreferencesForm, PriceProfileForm
|
||||
from .forms import CotisationForm, PaymentMethodForm, GeneralPreferencesForm, PriceProfileForm, ImprovementForm
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
|
@ -245,3 +246,73 @@ def delete_price_profile(request,pk):
|
|||
price_profile.delete()
|
||||
messages.success(request, message)
|
||||
return redirect(reverse('preferences:priceProfilesIndex'))
|
||||
|
||||
|
||||
########## Improvements ##########
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
def add_improvement(request):
|
||||
"""
|
||||
Display a form to create an improvement. Any logged user can access it
|
||||
"""
|
||||
form = ImprovementForm(request.POST or None)
|
||||
if form.is_valid():
|
||||
improvement = form.save(commit=False)
|
||||
improvement.coopeman = request.user
|
||||
improvement.save()
|
||||
mail_admins("Nouvelle proposition d'amélioration", "Une nouvelle proposition d'amélioration a été postée (" + improvement.title + ", " + improvement.get_mode_display() + "). Le corps est le suivant : " + improvement.description)
|
||||
messages.success(request, "Votre proposition a bien été envoyée")
|
||||
return redirect(reverse('home'))
|
||||
return render(request, "form.html", {"form": form, "form_title": "Proposition d'amélioration", "form_button": "Envoyer", "form_button_icon": "bug"})
|
||||
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('preferences.view_improvement')
|
||||
def improvements_index(request):
|
||||
"""
|
||||
Display all improvements
|
||||
"""
|
||||
todo_improvements = Improvement.objects.filter(done=False)
|
||||
done_improvements = Improvement.objects.filter(done=True)
|
||||
return render(request, "preferences/improvements_index.html", {"todo_improvements": todo_improvements, "done_improvements": done_improvements})
|
||||
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('preferences.view_improvement')
|
||||
@permission_required('preferences.change_improvement')
|
||||
def improvement_profile(request, pk):
|
||||
"""
|
||||
Display an improvement
|
||||
"""
|
||||
improvement = get_object_or_404(Improvement, pk=pk)
|
||||
improvement.seen = 1
|
||||
improvement.save()
|
||||
return render(request, "preferences/improvement_profile.html", {"improvement": improvement})
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('preferences.change_improvement')
|
||||
def change_improvement_state(request, pk):
|
||||
"""
|
||||
Change done state of an improvement
|
||||
"""
|
||||
improvement = get_object_or_404(Improvement, pk=pk)
|
||||
improvement.done = 1 - improvement.done
|
||||
improvement.save()
|
||||
messages.success(request, "L'état a bien été changé")
|
||||
return redirect(reverse('preferences:improvementsIndex'))
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('preferences.delete_improvement')
|
||||
def delete_improvement(request, pk):
|
||||
"""
|
||||
Delete an improvement
|
||||
"""
|
||||
improvement = get_object_or_404(Improvement, pk=pk)
|
||||
improvement.delete()
|
||||
messages.success(request, "L'amélioration a bien été supprimée.")
|
||||
return redirect(reverse('preferences:improvementsIndex'))
|
|
@ -70,6 +70,14 @@
|
|||
<i class="fa fa-search-dollar"></i> <a href="{% url 'gestion:compute-price' %}">Calcul de prix</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
<span class="tabulation2">
|
||||
<i class="fa fa-bug"></i> <a href="{% url 'preferences:addImprovement' %}">Proposition d'amélioration</a>
|
||||
</span>
|
||||
{% if perms.preferences.view_improvement %}
|
||||
<span class="tabulation2">
|
||||
<i class="fa fa-bug"></i> <a href="{% url 'preferences:improvementsIndex' %}">Améliorations</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
<span class="tabulation2">
|
||||
<i class="fa fa-bed"></i> <a href="{% url 'users:logout' %}">Deconnexion</a>
|
||||
</span>
|
||||
|
|
Loading…
Reference in a new issue