From 73e7697a3c6e50e9093d2c8ff21413b1d105cb40 Mon Sep 17 00:00:00 2001 From: nanoy Date: Thu, 12 Sep 2019 09:40:43 +0200 Subject: [PATCH 01/13] Improvements --- coopeV3/settings.py | 4 +- preferences/admin.py | 14 +++- preferences/forms.py | 10 ++- preferences/migrations/0019_improvement.py | 31 ++++++++ .../migrations/0020_auto_20190908_1217.py | 39 ++++++++++ preferences/models.py | 28 +++++++ .../preferences/improvement_profile.html | 21 ++++++ .../preferences/improvements_index.html | 68 +++++++++++++++++ preferences/urls.py | 9 ++- preferences/views.py | 75 ++++++++++++++++++- templates/nav.html | 8 ++ 11 files changed, 299 insertions(+), 8 deletions(-) create mode 100644 preferences/migrations/0019_improvement.py create mode 100644 preferences/migrations/0020_auto_20190908_1217.py create mode 100644 preferences/templates/preferences/improvement_profile.html create mode 100644 preferences/templates/preferences/improvements_index.html 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

+
+
+ + + + + + + + + + + + {% for improvement in todo_improvements %} + + + + + + + + {% endfor %} + +
TitreTypeVu ?DateAdministration
{{improvement.title}}{{improvement.get_mode_display}}{{improvement.seen|yesno:"Oui,Non"}}{{improvement.date}} Voir Passer en fait Supprimer
+
+
+
+
+

Liste des améliorations faîtes

+
+
+ + + + + + + + + + + + {% for improvement in done_improvements %} + + + + + + + + {% endfor %} + +
TitreTypeVu ?DateAdministration
{{improvement.title}}{{improvement.get_mode_display}}{{improvement.seen|yesno:"Oui,Non"}}{{improvement.date}} Voir Passer en non fait Supprimer
+
+
+{% 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 From ed60e5800254d8d7f47269e05395bc0c74cf57d7 Mon Sep 17 00:00:00 2001 From: nanoy Date: Fri, 20 Sep 2019 22:01:51 +0200 Subject: [PATCH 02/13] Improvements --- gestion/forms.py | 5 ++- gestion/migrations/0014_auto_20190912_0951.py | 33 +++++++++++++++++++ gestion/models.py | 1 + gestion/views.py | 24 +++++++++++++- preferences/views.py | 4 +-- 5 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 gestion/migrations/0014_auto_20190912_0951.py diff --git a/gestion/forms.py b/gestion/forms.py index 20822bc..cb75c03 100644 --- a/gestion/forms.py +++ b/gestion/forms.py @@ -49,11 +49,10 @@ class CreateKegForm(forms.ModelForm): class Meta: model = Keg - fields = ["name", "stockHold", "amount", "capacity"] + fields = ["name", "stockHold", "amount", "capacity", "deg"] widgets = {'amount': forms.TextInput} category = forms.ModelChoiceField(queryset=Category.objects.all(), label="Catégorie", help_text="Catégorie dans laquelle placer les produits pinte, demi (et galopin si besoin).") - deg = forms.DecimalField(max_digits=5, decimal_places=2, label="Degré", validators=[MinValueValidator(0)]) create_galopin = forms.BooleanField(required=False, label="Créer le produit galopin ?") def clean(self): @@ -68,7 +67,7 @@ class EditKegForm(forms.ModelForm): class Meta: model = Keg - fields = ["name", "stockHold", "amount", "capacity", "pinte", "demi", "galopin"] + fields = ["name", "stockHold", "amount", "capacity", "pinte", "demi", "galopin", "deg"] widgets = {'amount': forms.TextInput} def clean(self): diff --git a/gestion/migrations/0014_auto_20190912_0951.py b/gestion/migrations/0014_auto_20190912_0951.py new file mode 100644 index 0000000..e1f5dba --- /dev/null +++ b/gestion/migrations/0014_auto_20190912_0951.py @@ -0,0 +1,33 @@ +# Generated by Django 2.1 on 2019-09-12 07:51 + +import django.core.validators +from django.db import migrations, models + +def update(apps, schema_editor): + Keg = apps.get_model('gestion', 'Keg') + for keg in Keg.objects.all(): + keg.deg = keg.pinte.deg + keg.save() + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('gestion', '0013_auto_20190829_1219'), + ] + + operations = [ + migrations.AddField( + model_name='historicalkeg', + name='deg', + field=models.DecimalField(decimal_places=2, default=0, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Degré'), + ), + migrations.AddField( + model_name='keg', + name='deg', + field=models.DecimalField(decimal_places=2, default=0, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Degré'), + ), + migrations.RunPython(update, reverse) + ] diff --git a/gestion/models.py b/gestion/models.py index 627cebf..f736d66 100644 --- a/gestion/models.py +++ b/gestion/models.py @@ -194,6 +194,7 @@ class Keg(models.Model): """ If True, will be displayed on :func:`~gestion.views.manage` view """ + deg = models.DecimalField(default=0,max_digits=5, decimal_places=2, verbose_name="Degré", validators=[MinValueValidator(0)]) history = HistoricalRecords() def __str__(self): diff --git a/gestion/views.py b/gestion/views.py index fc45a4b..54266df 100644 --- a/gestion/views.py +++ b/gestion/views.py @@ -592,7 +592,29 @@ def editKeg(request, pk): keg = get_object_or_404(Keg, pk=pk) form = EditKegForm(request.POST or None, instance=keg) if(form.is_valid()): - form.save() + try: + price_profile = PriceProfile.objects.get(use_for_draft=True) + except: + messages.error(request, "Il n'y a pas de profil de prix pour les pressions") + return redirect(reverse('preferences:priceProfilesIndex')) + keg = form.save() + # Update produtcs + name = form.cleaned_data["name"][4:] + pinte_price = compute_price(keg.amount/(2*keg.capacity), price_profile.a, price_profile.b, price_profile.c, price_profile.alpha) + pinte_price = ceil(10*pinte_price)/10 + keg.pinte.deg = keg.deg + keg.pinte.amount = pinte_price + keg.pinte.name = "Pinte " + name + keg.pinte.save() + keg.demi.deg = keg.deg + keg.demi.amount = ceil(5*pinte_price)/10 + keg.demi.name = "Demi " + name + keg.demi.save() + if(keg.galopin): + keg.galopin.deg = deg + keg.galopin.amount = ceil(2.5 * pinte_price)/10 + keg.galopin.name = "Galopin " + name + keg.galopin.save() messages.success(request, "Le fût a bien été modifié") return redirect(reverse('gestion:kegsList')) return render(request, "form.html", {"form": form, "form_title": "Modification d'un fût", "form_button": "Modifier", "form_button_icon": "pencil-alt"}) diff --git a/preferences/views.py b/preferences/views.py index 12fe461..d8bc7b9 100644 --- a/preferences/views.py +++ b/preferences/views.py @@ -274,8 +274,8 @@ def improvements_index(request): """ Display all improvements """ - todo_improvements = Improvement.objects.filter(done=False) - done_improvements = Improvement.objects.filter(done=True) + todo_improvements = Improvement.objects.filter(done=False).order_by('-date') + done_improvements = Improvement.objects.filter(done=True).order_by('-date') return render(request, "preferences/improvements_index.html", {"todo_improvements": todo_improvements, "done_improvements": done_improvements}) From 42736920056dbdd32724f5b56b68dbd0271dbf31 Mon Sep 17 00:00:00 2001 From: nanoy Date: Sun, 22 Sep 2019 15:32:40 +0200 Subject: [PATCH 03/13] Direct reloads --- gestion/templates/gestion/manage.html | 22 +++++++++++-- gestion/views.py | 45 +++++++++++++++++++++++++++ staticfiles/dropdown.css | 28 +++++++++++++++++ staticfiles/dropdown.js | 27 ++++++++++++++++ staticfiles/manage.js | 40 ++++++++++++++++++++++-- templates/base.html | 2 ++ 6 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 staticfiles/dropdown.css create mode 100644 staticfiles/dropdown.js diff --git a/gestion/templates/gestion/manage.html b/gestion/templates/gestion/manage.html index d4f49f6..e64335f 100644 --- a/gestion/templates/gestion/manage.html +++ b/gestion/templates/gestion/manage.html @@ -61,7 +61,6 @@
- Annuler

{{gestion_form}}
@@ -84,7 +83,7 @@ 0€ 0€ 0€ - {% for pm in pay_buttons %} {% endfor %} + {% for pm in pay_buttons %} {% endfor %} Annuler @@ -127,6 +126,25 @@ {% if not cotisations|divisibleby:3 %} {% endif %} + + Rechargements + + + + + + + Bières pression {% for product in bieresPression %} {% if forloop.counter0|divisibleby:3 %} diff --git a/gestion/views.py b/gestion/views.py index 54266df..4faf317 100644 --- a/gestion/views.py +++ b/gestion/views.py @@ -87,9 +87,18 @@ def order(request): menus = json.loads(request.POST["menus"]) listPintes = json.loads(request.POST["listPintes"]) cotisations = json.loads(request.POST['cotisations']) + reloads = json.loads(request.POST['reloads']) gp,_ = GeneralPreferences.objects.get_or_create(pk=1) if (not order) and (not menus) and (not cotisations): raise Exception("Pas de commande.") + if(reloads): + for reload in reloads: + reload_payment_method = get_object_or_404(PaymentMethod, pk=reload["payment_method"]) + reload_amount = Decimal(reload["value"])*Decimal(reload["quantity"]) + reload_entry = Reload(customer=user, amount=reload_amount, PaymentMethod=reload_payment_method, coopeman=request.user) + reload_entry.save() + user.profile.credit += reload_amount + user.save() if(cotisations): for co in cotisations: cotisation = Cotisation.objects.get(pk=co['pk']) @@ -639,6 +648,15 @@ def openKeg(request): keg.stockHold -= 1 keg.is_active = True keg.save() + if keg.pinte: + keg.pinte.is_active = True + keg.pinte.save() + if keg.demi: + keg.demi.is_active = True + keg.demi.save() + if keg.galopin: + keg.galopin.is_active = True + keg.galopin.save() messages.success(request, "Le fut a bien été percuté") return redirect(reverse('gestion:kegsList')) return render(request, "form.html", {"form": form, "form_title":"Percutage d'un fût", "form_button":"Percuter", "form_button_icon": "fill-drip"}) @@ -665,6 +683,15 @@ def openDirectKeg(request, pk): keg.stockHold -= 1 keg.is_active = True keg.save() + if keg.pinte: + keg.pinte.is_active = True + keg.pinte.save() + if keg.demi: + keg.demi.is_active = True + keg.demi.save() + if keg.galopin: + keg.galopin.is_active = True + keg.galopin.save() messages.success(request, "Le fût a bien été percuté") else: messages.error(request, "Il n'y a pas de fût en stock") @@ -686,6 +713,15 @@ def closeKeg(request): kegHistory.save() keg.is_active = False keg.save() + if keg.pinte: + keg.pinte.is_active = False + keg.pinte.save() + if keg.demi: + keg.demi.is_active = False + keg.demi.save() + if keg.galopin: + keg.galopin.is_active = False + keg.galopin.save() messages.success(request, "Le fût a bien été fermé") return redirect(reverse('gestion:kegsList')) return render(request, "form.html", {"form": form, "form_title":"Fermeture d'un fût", "form_button":"Fermer le fût", "form_button_icon": "fill"}) @@ -708,6 +744,15 @@ def closeDirectKeg(request, pk): kegHistory.save() keg.is_active = False keg.save() + if keg.pinte: + keg.pinte.is_active = False + keg.pinte.save() + if keg.demi: + keg.demi.is_active = False + keg.demi.save() + if keg.galopin: + keg.galopin.is_active = False + keg.galopin.save() messages.success(request, "Le fût a bien été fermé") else: messages.error(request, "Le fût n'est pas ouvert") diff --git a/staticfiles/dropdown.css b/staticfiles/dropdown.css new file mode 100644 index 0000000..97b8a3d --- /dev/null +++ b/staticfiles/dropdown.css @@ -0,0 +1,28 @@ +/* The container
- needed to position the dropdown content */ +.dropdown { + position: relative; + display: inline-block; +} + +/* Dropdown Content (Hidden by Default) */ +.dropdown-content { + display: none; + position: absolute; + background-color: #f1f1f1; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; +} + +/* Links inside the dropdown */ +.dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; + cursor: pointer; +} +/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ +.show { + display:block; +} \ No newline at end of file diff --git a/staticfiles/dropdown.js b/staticfiles/dropdown.js new file mode 100644 index 0000000..93f4671 --- /dev/null +++ b/staticfiles/dropdown.js @@ -0,0 +1,27 @@ +/* When the user clicks on the button, +toggle between hiding and showing the dropdown content */ +function dropdown(target) { + var dropdowns = document.getElementsByClassName("dropdown-content"); + var i; + for (i = 0; i < dropdowns.length; i++) { + var openDropdown = dropdowns[i]; + if (openDropdown.classList.contains('show')) { + openDropdown.classList.remove('show'); + } + } + document.getElementById(target).classList.toggle("show"); +} + +// Close the dropdown menu if the user clicks outside of it +window.onclick = function(event) { + if (!event.target.matches('.dropbtn')) { + var dropdowns = document.getElementsByClassName("dropdown-content"); + var i; + for (i = 0; i < dropdowns.length; i++) { + var openDropdown = dropdowns[i]; + if (openDropdown.classList.contains('show')) { + openDropdown.classList.remove('show'); + } + } + } +} \ No newline at end of file diff --git a/staticfiles/manage.js b/staticfiles/manage.js index 0efcd3c..aa0a629 100644 --- a/staticfiles/manage.js +++ b/staticfiles/manage.js @@ -2,6 +2,7 @@ total = 0 products = [] menus = [] cotisations = [] +reloads = [] paymentMethod = null balance = 0 username = "" @@ -95,12 +96,33 @@ function add_cotisation(pk, duration, amount){ generate_html(); } +function add_reload(value, payment_method, payment_method_name){ + exist = false; + index = -1; + for(k=0; k < reloads.length; k++){ + if(reloads[k].value == value && reloads[k].payment_method == payment_method){ + exist = true; + index = k; + } + } + if(exist){ + reloads[index].quantity += 1; + }else{ + reloads.push({"value": value, "quantity": 1, "payment_method": payment_method, "payment_method_name": payment_method_name}); + } + generate_html(); +} + function generate_html(){ html = ""; for(k=0;k' + String(cotisation.amount) + ' €' + String(Number((cotisation.quantity * cotisation.amount).toFixed(2))) + ' €'; } + for(k=0;k-' + String(reload.value) + ' €-' + String(Number((reload.quantity * reload.value).toFixed(2))) + ' €'; + } for(k=0;k' + String(product.amount) + ' €' + String(Number((product.quantity * product.amount).toFixed(2))) + ' €'; @@ -109,7 +131,7 @@ function generate_html(){ menu = menus[k] html += '' + menu.name + '' + String(menu.amount) + ' €' + String(Number((menu.quantity * menu.amount).toFixed(2))) + ' €'; } - $("#items").html(html) + $("#items").html(html); updateTotal(); } @@ -124,6 +146,9 @@ function updateTotal(){ for(k=0; k