diff --git a/coopeV3/settings.py b/coopeV3/settings.py
index 7b3448b..4a75236 100644
--- a/coopeV3/settings.py
+++ b/coopeV3/settings.py
@@ -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"]
\ No newline at end of file
+INTERNAL_IPS = ["127.0.0.1"]
+
+EMAIL_SUBJECT_PREFIX = "[Coope Admin] "
\ No newline at end of file
diff --git a/preferences/admin.py b/preferences/admin.py
index 626fa75..239dc61 100644
--- a/preferences/admin.py
+++ b/preferences/admin.py
@@ -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)
\ No newline at end of file
+admin.site.register(DivideHistory, DivideHistoryAdmin)
+admin.site.register(Improvement, ImprovementAdmin)
\ No newline at end of file
diff --git a/preferences/forms.py b/preferences/forms.py
index 1ccd939..089269f 100644
--- a/preferences/forms.py
+++ b/preferences/forms.py
@@ -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"]
diff --git a/preferences/migrations/0019_improvement.py b/preferences/migrations/0019_improvement.py
new file mode 100644
index 0000000..6e24176
--- /dev/null
+++ b/preferences/migrations/0019_improvement.py
@@ -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',
+ },
+ ),
+ ]
diff --git a/preferences/migrations/0020_auto_20190908_1217.py b/preferences/migrations/0020_auto_20190908_1217.py
new file mode 100644
index 0000000..f246c11
--- /dev/null
+++ b/preferences/migrations/0020_auto_20190908_1217.py
@@ -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'),
+ ),
+ ]
diff --git a/preferences/models.py b/preferences/models.py
index 161b079..4ffc74e 100644
--- a/preferences/models.py
+++ b/preferences/models.py
@@ -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)
+
+
\ No newline at end of file
diff --git a/preferences/templates/preferences/improvement_profile.html b/preferences/templates/preferences/improvement_profile.html
new file mode 100644
index 0000000..ff2af09
--- /dev/null
+++ b/preferences/templates/preferences/improvement_profile.html
@@ -0,0 +1,21 @@
+{% extends "base.html" %}
+{% block entete %}Amélioration {{improvement.title}}{% endblock %}
+{% block navbar %}
+
+{% endblock %}
+{% block content %}
+
+
+ {{improvement.title}}
+
+ Retour à la liste des améliorations
+ Titre : {{improvement.title}}
+ Type : {{improvement.get_mode_display}}
+ Date : {{improvement.date}}
+ Fait : {{improvement.done|yesno:"Oui,Non"}}
+ Coopeman : {{improvement.coopeman}}
+ Description : {{improvement.description}}
+
+{% endblock %}
diff --git a/preferences/templates/preferences/improvements_index.html b/preferences/templates/preferences/improvements_index.html
new file mode 100644
index 0000000..930b158
--- /dev/null
+++ b/preferences/templates/preferences/improvements_index.html
@@ -0,0 +1,68 @@
+{% extends "base.html" %}
+{% block entete %}Améliorations{% endblock %}
+{% block navbar %}
+
+{% endblock %}
+{% block content %}
+
+
+ Liste des améliorations à faire
+
+
+
+
+
+ Titre |
+ Type |
+ Vu ? |
+ Date |
+ Administration |
+
+
+
+ {% for improvement in todo_improvements %}
+
+ {{improvement.title}} |
+ {{improvement.get_mode_display}} |
+ {{improvement.seen|yesno:"Oui,Non"}} |
+ {{improvement.date}} |
+ Voir Passer en fait Supprimer |
+
+ {% endfor %}
+
+
+
+
+
+
+ Liste des améliorations faîtes
+
+
+
+
+
+ Titre |
+ Type |
+ Vu ? |
+ Date |
+ Administration |
+
+
+
+ {% for improvement in done_improvements %}
+
+ {{improvement.title}} |
+ {{improvement.get_mode_display}} |
+ {{improvement.seen|yesno:"Oui,Non"}} |
+ {{improvement.date}} |
+ Voir Passer en non fait Supprimer |
+
+ {% endfor %}
+
+
+
+
+{% endblock %}
diff --git a/preferences/urls.py b/preferences/urls.py
index fa31467..ddf0878 100644
--- a/preferences/urls.py
+++ b/preferences/urls.py
@@ -19,5 +19,10 @@ urlpatterns = [
path('deletePriceProfile/', views.delete_price_profile, name="deletePriceProfile"),
path('inactive', views.inactive, name="inactive"),
path('getConfig', views.get_config, name="getConfig"),
- path('getCotisation/', views.get_cotisation, name="getCotisation")
-,]
+ path('getCotisation/', views.get_cotisation, name="getCotisation"),
+ path('addImprovement', views.add_improvement, name="addImprovement"),
+ path('improvementsIndex', views.improvements_index, name="improvementsIndex"),
+ path('improvementProfile/', views.improvement_profile, name="improvementProfile"),
+ path('deleteImprovement/', views.delete_improvement, name="deleteImprovement"),
+ path('changeImprovementState/', views.change_improvement_state, name="changeImprovementState"),
+]
diff --git a/preferences/views.py b/preferences/views.py
index ffeda09..12fe461 100644
--- a/preferences/views.py
+++ b/preferences/views.py
@@ -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'))
\ No newline at end of file
diff --git a/templates/nav.html b/templates/nav.html
index c8583bd..1443214 100644
--- a/templates/nav.html
+++ b/templates/nav.html
@@ -70,6 +70,14 @@
Calcul de prix
{% endif %}
+
+ Proposition d'amélioration
+
+{% if perms.preferences.view_improvement %}
+
+ Améliorations
+
+{% endif %}
Deconnexion