From 6aad16445e5fbfc9b32b73b69e81648db8bf603d Mon Sep 17 00:00:00 2001 From: nanoy Date: Tue, 27 Nov 2018 09:07:12 +0100 Subject: [PATCH] Fix de bugs, menus --- coopeV3/settings.py | 4 +- gestion/admin.py | 19 +- gestion/forms.py | 16 -- ...keg_historicalkeghistory_historicalmenu.py | 266 ++++++++++++++++++ gestion/migrations/0006_auto_20181126_1408.py | 84 ++++++ gestion/migrations/0007_auto_20181127_0902.py | 23 ++ gestion/models.py | 39 ++- gestion/templates/gestion/manage.html | 12 +- gestion/urls.py | 1 + gestion/views.py | 33 ++- preferences/admin.py | 9 +- preferences/forms.py | 8 - ...eralpreferences_historicalpaymentmethod.py | 84 ++++++ .../migrations/0004_auto_20181126_1408.py | 24 ++ preferences/models.py | 8 +- requirements.txt | 3 +- staticfiles/manage.js | 60 +++- users/admin.py | 9 +- ...oricalschool_historicalwhitelisthistory.py | 106 +++++++ users/models.py | 12 +- users/views.py | 4 +- 21 files changed, 748 insertions(+), 76 deletions(-) create mode 100644 gestion/migrations/0005_historicalconsumption_historicalconsumptionhistory_historicalkeg_historicalkeghistory_historicalmenu.py create mode 100644 gestion/migrations/0006_auto_20181126_1408.py create mode 100644 gestion/migrations/0007_auto_20181127_0902.py create mode 100644 preferences/migrations/0003_historicalcotisation_historicalgeneralpreferences_historicalpaymentmethod.py create mode 100644 preferences/migrations/0004_auto_20181126_1408.py create mode 100644 users/migrations/0004_historicalcotisationhistory_historicalprofile_historicalschool_historicalwhitelisthistory.py diff --git a/coopeV3/settings.py b/coopeV3/settings.py index 0cb6d72..62250b1 100644 --- a/coopeV3/settings.py +++ b/coopeV3/settings.py @@ -43,7 +43,8 @@ INSTALLED_APPS = [ 'preferences', 'coopeV3', 'dal', - 'dal_select2', + 'dal_select2', + 'simple_history', ] MIDDLEWARE = [ @@ -54,6 +55,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'simple_history.middleware.HistoryRequestMiddleware', ] ROOT_URLCONF = 'coopeV3.urls' diff --git a/gestion/admin.py b/gestion/admin.py index 1fa3040..253981b 100644 --- a/gestion/admin.py +++ b/gestion/admin.py @@ -1,11 +1,14 @@ from django.contrib import admin +from simple_history.admin import SimpleHistoryAdmin -from .models import Reload, Refund, Product, Keg, ConsumptionHistory, KegHistory, Consumption +from .models import Reload, Refund, Product, Keg, ConsumptionHistory, KegHistory, Consumption, Menu, MenuHistory -admin.site.register(Reload) -admin.site.register(Refund) -admin.site.register(Product) -admin.site.register(Keg) -admin.site.register(ConsumptionHistory) -admin.site.register(KegHistory) -admin.site.register(Consumption) \ No newline at end of file +admin.site.register(Reload, SimpleHistoryAdmin) +admin.site.register(Refund, SimpleHistoryAdmin) +admin.site.register(Product, SimpleHistoryAdmin) +admin.site.register(Keg, SimpleHistoryAdmin) +admin.site.register(ConsumptionHistory, SimpleHistoryAdmin) +admin.site.register(KegHistory, SimpleHistoryAdmin) +admin.site.register(Consumption, SimpleHistoryAdmin) +admin.site.register(Menu, SimpleHistoryAdmin) +admin.site.register(MenuHistory, SimpleHistoryAdmin) \ No newline at end of file diff --git a/gestion/forms.py b/gestion/forms.py index 89a694f..6c364b7 100644 --- a/gestion/forms.py +++ b/gestion/forms.py @@ -18,14 +18,6 @@ class ReloadForm(forms.ModelForm): fields = ("customer", "amount", "PaymentMethod") widgets = {'customer': autocomplete.ModelSelect2(url='users:active-users-autocomplete', attrs={'data-minimum-input-length':2})} - def clean_amount(self): - if self.cleaned_data['amount'] <= 0: - raise ValidationError( - "Le montant doit être strictement positif" - ) - else: - return self.cleaned_data['amount'] - class RefundForm(forms.ModelForm): class Meta: @@ -33,14 +25,6 @@ class RefundForm(forms.ModelForm): fields = ("customer", "amount") widgets = {'customer': autocomplete.ModelSelect2(url='users:active-users-autocomplete', attrs={'data-minimum-input-length':2})} - def clean_amount(self): - if self.cleaned_data['amount'] <= 0: - raise ValidationError( - "Le montant doit être strictement positif" - ) - else: - return self.cleaned_data['amount'] - class ProductForm(forms.ModelForm): class Meta: diff --git a/gestion/migrations/0005_historicalconsumption_historicalconsumptionhistory_historicalkeg_historicalkeghistory_historicalmenu.py b/gestion/migrations/0005_historicalconsumption_historicalconsumptionhistory_historicalkeg_historicalkeghistory_historicalmenu.py new file mode 100644 index 0000000..ae67db9 --- /dev/null +++ b/gestion/migrations/0005_historicalconsumption_historicalconsumptionhistory_historicalkeg_historicalkeghistory_historicalmenu.py @@ -0,0 +1,266 @@ +# Generated by Django 2.1 on 2018-11-26 07:57 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import simple_history.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0003_historicalcotisation_historicalgeneralpreferences_historicalpaymentmethod'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('gestion', '0004_consumption'), + ] + + operations = [ + migrations.CreateModel( + name='HistoricalConsumption', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('quantity', models.PositiveIntegerField(default=0)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('customer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('product', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Product')), + ], + options={ + 'verbose_name': 'historical consumption', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalConsumptionHistory', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('quantity', models.PositiveIntegerField(default=0)), + ('date', models.DateTimeField(blank=True, editable=False)), + ('amount', models.DecimalField(decimal_places=2, default=0, max_digits=7)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('coopeman', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('customer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('menu', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.MenuHistory')), + ('paymentMethod', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='preferences.PaymentMethod')), + ('product', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Product')), + ], + options={ + 'verbose_name': 'historical consumption history', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalKeg', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=20, verbose_name='Nom')), + ('stockHold', models.IntegerField(default=0, verbose_name='Stock en soute')), + ('barcode', models.CharField(db_index=True, max_length=20, verbose_name='Code barre')), + ('amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Prix du fût')), + ('capacity', models.IntegerField(default=30, verbose_name='Capacité (L)')), + ('is_active', models.BooleanField(default=False, verbose_name='Actif')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('demi', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Product')), + ('galopin', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Product')), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('pinte', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Product')), + ], + options={ + 'verbose_name': 'historical keg', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalKegHistory', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('openingDate', models.DateTimeField(blank=True, editable=False)), + ('quantitySold', models.DecimalField(decimal_places=2, default=0, max_digits=5)), + ('amountSold', models.DecimalField(decimal_places=2, default=0, max_digits=5)), + ('closingDate', models.DateTimeField(blank=True, null=True)), + ('isCurrentKegHistory', models.BooleanField(default=True)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('keg', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Keg')), + ], + options={ + 'verbose_name': 'historical keg history', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalMenu', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Nom')), + ('amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Montant')), + ('barcode', models.CharField(db_index=True, max_length=20, verbose_name='Code barre')), + ('is_active', models.BooleanField(default=False, verbose_name='Actif')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical menu', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalMenuHistory', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('quantity', models.PositiveIntegerField(default=0)), + ('date', models.DateTimeField(blank=True, editable=False)), + ('amount', models.DecimalField(decimal_places=2, default=0, max_digits=5)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('PaymentMethod', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='preferences.PaymentMethod')), + ('coopeman', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('customer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('menu', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Menu')), + ], + options={ + 'verbose_name': 'historical menu history', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalProduct', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=40, verbose_name='Nom')), + ('amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Prix de vente')), + ('stockHold', models.IntegerField(default=0, verbose_name='Stock en soute')), + ('stockBar', models.IntegerField(default=0, verbose_name='Stock en bar')), + ('barcode', models.CharField(db_index=True, max_length=20, verbose_name='Code barre')), + ('category', models.CharField(choices=[('PP', 'Pinte Pression'), ('DP', 'Demi Pression'), ('GP', 'Galopin pression'), ('BT', 'Bouteille'), ('SO', 'Soft'), ('FO', 'Bouffe autre que panini'), ('PA', 'Bouffe pour panini')], default='FO', max_length=2, verbose_name='Catégorie')), + ('needQuantityButton', models.BooleanField(default=False, verbose_name='Bouton quantité')), + ('is_active', models.BooleanField(default=True, verbose_name='Actif')), + ('volume', models.IntegerField(default=0)), + ('deg', models.DecimalField(decimal_places=2, default=0, max_digits=5, verbose_name='Degré')), + ('adherentRequired', models.BooleanField(default=True)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical product', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalRaming', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('date', models.DateTimeField(blank=True, editable=False)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('coopeman', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('keg', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='gestion.Keg')), + ], + options={ + 'verbose_name': 'historical raming', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalRefund', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('date', models.DateTimeField(blank=True, editable=False)), + ('amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Montant')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('coopeman', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('customer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical refund', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalReload', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('amount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Montant')), + ('date', models.DateTimeField(blank=True, editable=False)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('PaymentMethod', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='preferences.PaymentMethod')), + ('coopeman', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('customer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical reload', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalStocking', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('date', models.DateTimeField(blank=True, editable=False)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical stocking', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + ] diff --git a/gestion/migrations/0006_auto_20181126_1408.py b/gestion/migrations/0006_auto_20181126_1408.py new file mode 100644 index 0000000..adf6b47 --- /dev/null +++ b/gestion/migrations/0006_auto_20181126_1408.py @@ -0,0 +1,84 @@ +# Generated by Django 2.1 on 2018-11-26 13:08 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('gestion', '0005_historicalconsumption_historicalconsumptionhistory_historicalkeg_historicalkeghistory_historicalmenu'), + ] + + operations = [ + migrations.AlterField( + model_name='historicalkeg', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Prix du fût'), + ), + migrations.AlterField( + model_name='historicalmenu', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + migrations.AlterField( + model_name='historicalproduct', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Prix de vente'), + ), + migrations.AlterField( + model_name='historicalproduct', + name='deg', + field=models.DecimalField(decimal_places=2, default=0, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Degré'), + ), + migrations.AlterField( + model_name='historicalproduct', + name='volume', + field=models.PositiveIntegerField(default=0), + ), + migrations.AlterField( + model_name='historicalrefund', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + migrations.AlterField( + model_name='historicalreload', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + migrations.AlterField( + model_name='keg', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Prix du fût'), + ), + migrations.AlterField( + model_name='menu', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + migrations.AlterField( + model_name='product', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Prix de vente'), + ), + migrations.AlterField( + model_name='product', + name='deg', + field=models.DecimalField(decimal_places=2, default=0, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Degré'), + ), + migrations.AlterField( + model_name='product', + name='volume', + field=models.PositiveIntegerField(default=0), + ), + migrations.AlterField( + model_name='refund', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + migrations.AlterField( + model_name='reload', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + ] diff --git a/gestion/migrations/0007_auto_20181127_0902.py b/gestion/migrations/0007_auto_20181127_0902.py new file mode 100644 index 0000000..b4c58bb --- /dev/null +++ b/gestion/migrations/0007_auto_20181127_0902.py @@ -0,0 +1,23 @@ +# Generated by Django 2.1 on 2018-11-27 08:02 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('gestion', '0006_auto_20181126_1408'), + ] + + operations = [ + migrations.RenameField( + model_name='historicalmenuhistory', + old_name='PaymentMethod', + new_name='paymentMethod', + ), + migrations.RenameField( + model_name='menuhistory', + old_name='PaymentMethod', + new_name='paymentMethod', + ), + ] diff --git a/gestion/models.py b/gestion/models.py index 0e019bf..8a5a21a 100644 --- a/gestion/models.py +++ b/gestion/models.py @@ -2,6 +2,9 @@ from django.db import models from django.contrib.auth.models import User from preferences.models import PaymentMethod from django.core.exceptions import ValidationError +from simple_history.models import HistoricalRecords +from django.core.validators import MinValueValidator + class Product(models.Model): P_PRESSION = 'PP' @@ -21,16 +24,17 @@ class Product(models.Model): (PANINI, "Bouffe pour panini"), ) name = models.CharField(max_length=40, verbose_name="Nom", unique=True) - amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Prix de vente") + amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Prix de vente", validators=[MinValueValidator(0)]) stockHold = models.IntegerField(default=0, verbose_name="Stock en soute") stockBar = models.IntegerField(default=0, verbose_name="Stock en bar") - barcode= models.CharField(max_length=20, unique=True, verbose_name="Code barre") + barcode = models.CharField(max_length=20, unique=True, verbose_name="Code barre") category = models.CharField(max_length=2, choices=TYPEINPUT_CHOICES_CATEGORIE, default=FOOD, verbose_name="Catégorie") needQuantityButton = models.BooleanField(default=False, verbose_name="Bouton quantité") is_active = models.BooleanField(default=True, verbose_name="Actif") - volume = models.IntegerField(default=0) - deg = models.DecimalField(default=0,max_digits=5, decimal_places=2, verbose_name="Degré") + volume = models.PositiveIntegerField(default=0) + deg = models.DecimalField(default=0,max_digits=5, decimal_places=2, verbose_name="Degré", validators=[MinValueValidator(0)]) adherentRequired = models.BooleanField(default=True) + history = HistoricalRecords() def __str__(self): return self.name @@ -71,12 +75,13 @@ class Keg(models.Model): name = models.CharField(max_length=20, unique=True, verbose_name="Nom") stockHold = models.IntegerField(default=0, verbose_name="Stock en soute") barcode = models.CharField(max_length=20, unique=True, verbose_name="Code barre") - amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Prix du fût") + amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Prix du fût", validators=[MinValueValidator(0)]) capacity = models.IntegerField(default=30, verbose_name="Capacité (L)") pinte = models.ForeignKey(Product, on_delete=models.PROTECT, related_name="futp", validators=[isPinte]) demi = models.ForeignKey(Product, on_delete=models.PROTECT, related_name="futd", validators=[isDemi]) galopin = models.ForeignKey(Product, on_delete=models.PROTECT, related_name="futg", validators=[isGalopin],null=True, blank=True) is_active = models.BooleanField(default=False, verbose_name="Actif") + history = HistoricalRecords() def __str__(self): return self.name @@ -88,6 +93,7 @@ class KegHistory(models.Model): amountSold = models.DecimalField(decimal_places=2, max_digits=5, default=0) closingDate = models.DateTimeField(null=True, blank=True) isCurrentKegHistory = models.BooleanField(default=True) + history = HistoricalRecords() def __str__(self): res = "Fût de " + str(self.keg) + " (" + str(self.openingDate) + " - " @@ -99,10 +105,11 @@ class KegHistory(models.Model): class Reload(models.Model): customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="reload_taken", verbose_name="Client") - amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant") + amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant", validators=[MinValueValidator(0)]) PaymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT, verbose_name="Moyen de paiement") coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="reload_realized") date = models.DateTimeField(auto_now_add=True) + history = HistoricalRecords() def __str__(self): return "Rechargement effectue par {0} le {1} ({2} euros, coopeman : {3})".format(self.customer, self.date, self.amount, self.coopeman) @@ -112,12 +119,14 @@ class Raming(models.Model): keg = models.ForeignKey(Keg, on_delete=models.PROTECT) coopeman = models.ForeignKey(User, on_delete=models.PROTECT) date = models.DateTimeField(auto_now_add=True) + history = HistoricalRecords() def __str__(self): return "Percussion d'un {0} effectué par {1} le {2}".format(self.keg, self.coopeman, self.date) class Stocking(models.Model): date = models.DateTimeField(auto_now_add=True) + history = HistoricalRecords() def __str__(self): return "Inventaire fait le {0}".format(self.date) @@ -126,8 +135,9 @@ class Stocking(models.Model): class Refund(models.Model): date = models.DateTimeField(auto_now_add=True) customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="refund_taken", verbose_name="Client") - amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant") + amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant", validators=[MinValueValidator(0)]) coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="refund_realized") + history = HistoricalRecords() def __str__(self): return "{0} remboursé de {1} le {2} (effectué par {3})".format(self.customer, self.amount, self.date, self.coopeman) @@ -135,22 +145,31 @@ class Refund(models.Model): class Menu(models.Model): name = models.CharField(max_length=255, verbose_name="Nom") - amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant") + amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant", validators=[MinValueValidator(0)]) barcode = models.CharField(max_length=20, unique=True, verbose_name="Code barre") articles = models.ManyToManyField(Product, verbose_name="Produits") is_active = models.BooleanField(default=False, verbose_name="Actif") + history = HistoricalRecords() def __str__(self): return self.name + @property + def adherent_required(self): + res = False + for article in self.articles.all(): + res = res or article.adherentRequired + return res + class MenuHistory(models.Model): customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="menu_taken") quantity = models.PositiveIntegerField(default=0) - PaymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT) + paymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT) date = models.DateTimeField(auto_now_add=True) menu = models.ForeignKey(Menu, on_delete=models.PROTECT) amount = models.DecimalField(max_digits=5, decimal_places=2, default=0) coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="menu_selled") + history = HistoricalRecords() def __str__(self): return "{2} a consommé {0} {1}".format(self.quantity, self.menu, self.customer) @@ -164,6 +183,7 @@ class ConsumptionHistory(models.Model): menu = models.ForeignKey(MenuHistory, on_delete=models.CASCADE, null=True, blank=True) amount = models.DecimalField(max_digits=7, decimal_places=2, default=0) coopeman = models.ForeignKey(User, on_delete=models.PROTECT, related_name="consumption_selled") + history = HistoricalRecords() def __str__(self): return "{0} {1} consommé par {2} le {3} (encaissé par {4})".format(self.quantity, self.product, self.customer, self.date, self.coopeman) @@ -172,6 +192,7 @@ class Consumption(models.Model): customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="consumption_global_taken") product = models.ForeignKey(Product, on_delete=models.PROTECT) quantity = models.PositiveIntegerField(default=0) + history = HistoricalRecords() def __str__(self): return "Consommation de " + str(self.customer) + " concernant le produit " + str(self.product) diff --git a/gestion/templates/gestion/manage.html b/gestion/templates/gestion/manage.html index 7113482..3b107d6 100644 --- a/gestion/templates/gestion/manage.html +++ b/gestion/templates/gestion/manage.html @@ -97,7 +97,7 @@ {% if forloop.counter0|divisibleby:4 %} {% endif %} - + {% if forloop.counter|divisibleby:4 %} {% endif %} @@ -110,7 +110,7 @@ {% if forloop.counter0|divisibleby:4 %} {% endif %} - + {% if forloop.counter|divisibleby:4 %} {% endif %} @@ -123,7 +123,7 @@ {% if forloop.counter0|divisibleby:4 %} {% endif %} - + {% if forloop.counter|divisibleby:4 %} {% endif %} @@ -136,7 +136,7 @@ {% if forloop.counter0|divisibleby:4 %} {% endif %} - + {% if forloop.counter|divisibleby:4 %} {% endif %} @@ -150,7 +150,7 @@ {% if forloop.counter0|divisibleby:4 %} {% endif %} - + {% if forloop.counter|divisibleby:4 %} {% endif %} @@ -164,7 +164,7 @@ {% if forloop.counter0|divisibleby:4 %} {% endif %} - + {% if forloop.counter|divisibleby:4 %} {% endif %} diff --git a/gestion/urls.py b/gestion/urls.py index bdd3ef1..41b0cda 100644 --- a/gestion/urls.py +++ b/gestion/urls.py @@ -24,6 +24,7 @@ urlpatterns = [ path('searchMenu', views.searchMenu, name="searchMenu"), path('editMenu/', views.edit_menu, name="editMenu"), path('menusList', views.menus_list, name="menusList"), + path('getMenu/', views.get_menu, name="getMenu"), path('swicthActivateMenu/', views.switch_activate_menu, name="switchActivateMenu"), path('getProduct/', views.getProduct, name="getProduct"), path('order', views.order, name="order"), diff --git a/gestion/views.py b/gestion/views.py index ab200a2..ac59eeb 100644 --- a/gestion/views.py +++ b/gestion/views.py @@ -14,7 +14,7 @@ from dal import autocomplete from decimal import * from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm -from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption +from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory from preferences.models import PaymentMethod @active_required @@ -52,12 +52,16 @@ def order(request): paymentMethod = get_object_or_404(PaymentMethod, pk=request.POST['paymentMethod']) amount = Decimal(request.POST['amount']) order = json.loads(request.POST["order"]) - if(len(order) == 0 or amount == 0): + menus = json.loads(request.POST["menus"]) + if (not order) and (not menus): return HttpResponse("Pas de commande") adherentRequired = False for o in order: product = get_object_or_404(Product, pk=o["pk"]) adherentRequired = adherentRequired or product.adherentRequired + for m in menus: + menu = get_object_or_404(Menu, pk=m["pk"]) + adherentRequired = adherentRequired or menu.adherent_required if(adherentRequired and not user.profile.is_adherent): return HttpResponse("N'est pas adhérent et devrait l'être") if(paymentMethod.affect_balance): @@ -72,7 +76,7 @@ def order(request): if(product.category == Product.P_PRESSION): keg = get_object_or_404(Keg, pinte=product) if(not keg.is_active): - return HttpResponse("Une erreur inconnue s'est produite") + return HttpResponse("Une erreur inconnue s'est produite. Veuillez contacter le trésorier ou le président") kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True) kegHistory.quantitySold += Decimal(quantity * 0.5) kegHistory.amountSold += Decimal(quantity * product.amount) @@ -80,7 +84,7 @@ def order(request): elif(product.category == Product.D_PRESSION): keg = get_object_or_404(Keg, demi=product) if(not keg.is_active): - return HttpResponse("Une erreur inconnue s'est produite") + return HttpResponse("Une erreur inconnue s'est produite. Veuillez contacter le trésorier ou le président") kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True) kegHistory.quantitySold += Decimal(quantity * 0.25) kegHistory.amountSold += Decimal(quantity * product.amount) @@ -88,7 +92,7 @@ def order(request): elif(product.category == Product.G_PRESSION): keg = get_object_or_404(Keg, galopin=product) if(not keg.is_active): - return HttpResponse("Une erreur inconnue s'est produite") + return HttpResponse("Une erreur inconnue s'est produite. Veuillez contacter le trésorier ou le président") kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True) kegHistory.quantitySold += Decimal(quantity * 0.125) kegHistory.amountSold += Decimal(quantity * product.amount) @@ -100,8 +104,19 @@ def order(request): consumption, _ = Consumption.objects.get_or_create(customer=user, product=product) consumption.quantity += quantity consumption.save() - ch = ConsumptionHistory(customer = user, quantity = quantity, paymentMethod=paymentMethod, product=product, amount=int(o["quantity"])*product.amount, coopeman=request.user) + ch = ConsumptionHistory(customer = user, quantity = quantity, paymentMethod=paymentMethod, product=product, amount=int(quantity*product.amount), coopeman=request.user) ch.save() + for m in menus: + menu = get_object_or_404(Menu, pk=m["pk"]) + quantity = int(m["quantity"]) + mh = MenuHistory(customer=user, quantity=quantity, paymentMethod=paymentMethod, menu=menu, amount=int(quantity*menu.amount), coopeman=request.user) + mh.save() + for article in menu.articles.all(): + consumption, _ = Consumption.objects.get_or_create(customer=user, product=article) + consumption.quantity += quantity + consumption.save() + ch = ConsumptionHistory(customer=user, quantity=quantity, paymentMethod=paymentMethod, product=article, amount=int(quantity*article.amount), coopeman=request.user, menu=mh) + ch.save() return HttpResponse("La commande a bien été effectuée") @login_required @@ -410,6 +425,12 @@ def switch_activate_menu(request, pk): messages.success(request, "La disponibilité du menu a bien été changée") return redirect(reverse('gestion:menusList')) +@login_required +def get_menu(request, barcode): + menu = get_object_or_404(Menu, barcode=barcode) + data = json.dumps({"pk": menu.pk, "barcode" : menu.barcode, "name": menu.name, "amount" : menu.amount}) + return HttpResponse(data, content_type='application/json') + class MenusAutocomplete(autocomplete.Select2QuerySetView): def get_queryset(self): qs = Menu.objects.all() diff --git a/preferences/admin.py b/preferences/admin.py index 773c1f0..f90378e 100644 --- a/preferences/admin.py +++ b/preferences/admin.py @@ -1,8 +1,7 @@ from django.contrib import admin - +from simple_history.admin import SimpleHistoryAdmin from .models import PaymentMethod, GeneralPreferences, Cotisation -admin.site.register(PaymentMethod) -admin.site.register(GeneralPreferences) -admin.site.register(Cotisation) -# Register your models here. +admin.site.register(PaymentMethod, SimpleHistoryAdmin) +admin.site.register(GeneralPreferences, SimpleHistoryAdmin) +admin.site.register(Cotisation, SimpleHistoryAdmin) \ No newline at end of file diff --git a/preferences/forms.py b/preferences/forms.py index 52a197e..bfcb2f0 100644 --- a/preferences/forms.py +++ b/preferences/forms.py @@ -7,14 +7,6 @@ class CotisationForm(forms.ModelForm): class Meta: model = Cotisation fields = "__all__" - - def clean_amount(self): - if self.cleaned_data['amount'] <= 0: - raise ValidationError( - "Le montant doit être strictement positif" - ) - else: - return self.cleaned_data['amount'] class PaymentMethodForm(forms.ModelForm): class Meta: diff --git a/preferences/migrations/0003_historicalcotisation_historicalgeneralpreferences_historicalpaymentmethod.py b/preferences/migrations/0003_historicalcotisation_historicalgeneralpreferences_historicalpaymentmethod.py new file mode 100644 index 0000000..6fe6bbb --- /dev/null +++ b/preferences/migrations/0003_historicalcotisation_historicalgeneralpreferences_historicalpaymentmethod.py @@ -0,0 +1,84 @@ +# Generated by Django 2.1 on 2018-11-26 07:57 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import simple_history.models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('preferences', '0002_auto_20181009_1119'), + ] + + operations = [ + migrations.CreateModel( + name='HistoricalCotisation', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('amount', models.DecimalField(decimal_places=2, max_digits=5, null=True, verbose_name='Montant')), + ('duration', models.PositiveIntegerField(verbose_name='Durée de la cotisation (jours)')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical cotisation', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalGeneralPreferences', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('is_active', models.BooleanField(default=True)), + ('active_message', models.TextField(blank=True)), + ('global_message', models.TextField(blank=True)), + ('president', models.CharField(blank=True, max_length=255)), + ('vice_president', models.CharField(blank=True, max_length=255)), + ('treasurer', models.CharField(blank=True, max_length=255)), + ('secretary', models.CharField(blank=True, max_length=255)), + ('brewer', models.CharField(blank=True, max_length=255)), + ('grocer', models.CharField(blank=True, max_length=255)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical general preferences', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalPaymentMethod', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Nom')), + ('is_active', models.BooleanField(default=True, verbose_name='Actif')), + ('is_usable_in_cotisation', models.BooleanField(default=True, verbose_name='Cotisations ?')), + ('is_usable_in_reload', models.BooleanField(default=True, verbose_name='Rechargements ?')), + ('affect_balance', models.BooleanField(default=False, verbose_name='Affecte le solde')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_date', models.DateTimeField()), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical payment method', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + ] diff --git a/preferences/migrations/0004_auto_20181126_1408.py b/preferences/migrations/0004_auto_20181126_1408.py new file mode 100644 index 0000000..0a32328 --- /dev/null +++ b/preferences/migrations/0004_auto_20181126_1408.py @@ -0,0 +1,24 @@ +# Generated by Django 2.1 on 2018-11-26 13:08 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0003_historicalcotisation_historicalgeneralpreferences_historicalpaymentmethod'), + ] + + operations = [ + migrations.AlterField( + model_name='cotisation', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + migrations.AlterField( + model_name='historicalcotisation', + name='amount', + field=models.DecimalField(decimal_places=2, max_digits=5, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Montant'), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index 4502f93..13781b1 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -1,4 +1,7 @@ from django.db import models +from simple_history.models import HistoricalRecords +from django.core.validators import MinValueValidator + class PaymentMethod(models.Model): name = models.CharField(max_length=255, verbose_name="Nom") @@ -6,6 +9,7 @@ class PaymentMethod(models.Model): is_usable_in_cotisation = models.BooleanField(default=True, verbose_name="Cotisations ?") is_usable_in_reload = models.BooleanField(default=True, verbose_name="Rechargements ?") affect_balance = models.BooleanField(default=False, verbose_name="Affecte le solde") + history = HistoricalRecords() def __str__(self): return self.name @@ -20,10 +24,12 @@ class GeneralPreferences(models.Model): secretary = models.CharField(max_length=255, blank=True) brewer = models.CharField(max_length=255, blank=True) grocer = models.CharField(max_length=255, blank=True) + history = HistoricalRecords() class Cotisation(models.Model): - amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant") + amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant", validators=[MinValueValidator(0)]) duration = models.PositiveIntegerField(verbose_name="Durée de la cotisation (jours)") + history = HistoricalRecords() def __str__(self): return "Cotisation de " + str(self.duration) + " jours pour le prix de " + str(self.amount) + "€" diff --git a/requirements.txt b/requirements.txt index 46ba27e..543b013 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ Django==2.1 django-autocomplete-light==3.3.2 pytz==2018.5 simplejson==3.16.0 -docutils==0.14 \ No newline at end of file +docutils==0.14 +django-simple-history==2.5.1 \ No newline at end of file diff --git a/staticfiles/manage.js b/staticfiles/manage.js index f37b4af..7577025 100644 --- a/staticfiles/manage.js +++ b/staticfiles/manage.js @@ -1,5 +1,6 @@ total = 0 products = [] +menus = [] paymentMethod = null balance = 0 username = "" @@ -11,6 +12,12 @@ function get_product(barcode){ }); } +function get_menu(barcode){ + res = $.get("getMenu/" + barcode, function(data){ + add_menu(data.pk, data.barcode, data.name, data.amount); + }); +} + function add_product(pk, barcode, name, amount){ exist = false index = -1 @@ -28,30 +35,71 @@ function add_product(pk, barcode, name, amount){ generate_html() } +function add_menu(pk, barcode, name, amount){ + exist = false; + index = -1; + for(k=0; k < menus.length; k++){ + if(menus[k].pk == pk){ + exist = true; + index = k; + } + } + if(exist){ + menus[index].quantity += 1; + }else{ + menus.push({"pk": pk, "barcode": barcode, "name": name, "amount": amount, "quantity":1}); + } + generate_html(); +} + function generate_html(){ html ="" for(k=0;k" + product.name + "" + String(product.amount) + "" + String(product.quantity) + "" + String(product.quantity * product.amount) + "" + html += '' + product.barcode + '' + product.name + '' + String(product.amount) + '' + String(product.quantity * product.amount) + ''; + } + for(k=0; k' + menu.name + '' + String(menu.amount) + '' + String(menu.quantity * menu.amount) + ''; } $("#items").html(html) - updateTotal() + updateTotal(); } function updateTotal(){ total = 0 for(k=0;k= cotisation.cotisation.amount): user.profile.debit += cotisation.cotisation.amount else: - cotisation.delete() messages.error(request, "Solde insuffisant") + return redirect(reverse('users:profile',kwargs={'pk':user.pk})) cotisation.user = user cotisation.coopeman = request.user cotisation.amount = cotisation.cotisation.amount @@ -708,7 +708,7 @@ def addWhiteListHistory(request, pk): if(user.profile.cotisationEnd): whiteList.endDate = user.profile.cotisationEnd + timedelta(days=whiteList.duration) else: - whiteList = datetime.now() + timedelta(days=whiteList.duration) + whiteList.endDate = datetime.now() + timedelta(days=whiteList.duration) user.profile.cotisationEnd = whiteList.endDate user.save() whiteList.save()