diff --git a/apps/food/admin.py b/apps/food/admin.py index 820036c3..7579aff5 100644 --- a/apps/food/admin.py +++ b/apps/food/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from note_kfet.admin import admin_site -from .models import QR_code, Basic_food, Transformed_food, Allergen +from .models import QR_code, BasicFood, TransformedFood, Allergen @admin.register(QR_code, site = admin_site) @@ -10,13 +10,13 @@ class QR_codeAdmin(admin.ModelAdmin): TEMPORARY """ -@admin.register(Basic_food, site = admin_site) +@admin.register(BasicFood, site = admin_site) class Basic_foodAdmin(admin.ModelAdmin): """ TEMPORARY """ -@admin.register(Transformed_food, site = admin_site) +@admin.register(TransformedFood, site = admin_site) class Transformed_foodAdmin(admin.ModelAdmin): """ TEMPORARY diff --git a/apps/food/forms.py b/apps/food/forms.py index 92887c32..5855c936 100644 --- a/apps/food/forms.py +++ b/apps/food/forms.py @@ -7,14 +7,14 @@ from django import forms from django.utils.translation import gettext_lazy as _ from django.utils import timezone from member.models import Club -from note_kfet.inputs import Autocomplete, DatePickerInput +from note_kfet.inputs import Autocomplete, DatePickerInput, DateTimePickerInput from note_kfet.middlewares import get_current_request from permission.backends import PermissionBackend -from .models import QR_code, Allergen, Basic_food, Transformed_food +from .models import QR_code, Allergen, BasicFood, TransformedFood -class Basic_foodForms(forms.ModelForm): +class BasicFoodForms(forms.ModelForm): """ Form for add non-transformed food """ @@ -38,7 +38,7 @@ class Basic_foodForms(forms.ModelForm): return is_ddm class Meta: - model = Basic_food + model = BasicFood fields = ('name', 'owner', 'is_DLC', 'is_DDM', 'expiry_date', 'label') widgets = { "owner": Autocomplete( @@ -50,7 +50,7 @@ class Basic_foodForms(forms.ModelForm): -class Transformed_foodForms(forms.ModelForm): +class TransformedFoodForms(forms.ModelForm): """ Form for add transformed food """ @@ -71,14 +71,14 @@ class Transformed_foodForms(forms.ModelForm): class Meta: - model = Transformed_food + model = TransformedFood fields = ('name', 'creation_date', 'owner', 'is_active',) - widget = { + widgets = { "owner": Autocomplete( model = Club, attrs = {"api_url": "/api/members/club/"}, ), - 'creation_date': DatePickerInput(), + 'creation_date': DateTimePickerInput(), } class AllergenForms(forms.ModelForm): """ diff --git a/apps/food/migrations/0003_auto_20240525_1350.py b/apps/food/migrations/0003_auto_20240525_1350.py new file mode 100644 index 00000000..23321d64 --- /dev/null +++ b/apps/food/migrations/0003_auto_20240525_1350.py @@ -0,0 +1,55 @@ +# Generated by Django 2.2.28 on 2024-05-25 11:50 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('member', '0011_profile_vss_charter_read'), + ('food', '0002_auto_20240524_2139'), + ] + + operations = [ + migrations.CreateModel( + name='BasicFood', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='name')), + ('is_DLC', models.BooleanField(default=False, verbose_name='is DLC')), + ('is_DDM', models.BooleanField(default=False, verbose_name='is DDM')), + ('expiry_date', models.DateTimeField(blank=True, default=django.utils.timezone.now, null=True, verbose_name='expiry date')), + ('label', models.ImageField(default='pic/default.png', max_length=255, upload_to='label/', verbose_name='food label')), + ('was_eaten', models.BooleanField(default=False, verbose_name='was eaten')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')), + ], + options={ + 'verbose_name': 'Basic food', + 'verbose_name_plural': 'Basic foods', + }, + ), + migrations.AlterField( + model_name='allergen', + name='basic_food', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='Allergen', to='food.BasicFood', verbose_name='basic food'), + ), + migrations.AlterField( + model_name='qr_code', + name='basic_food', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.BasicFood', verbose_name='basic food'), + ), + migrations.RenameModel( + old_name='Transformed_food', + new_name='TransformedFood', + ), + migrations.DeleteModel( + name='Basic_food', + ), + migrations.AddField( + model_name='basicfood', + name='transformed_food', + field=models.ManyToManyField(blank=True, null=True, related_name='BasicFood', to='food.TransformedFood', verbose_name='transformed food'), + ), + ] diff --git a/apps/food/migrations/0004_auto_20240525_1352.py b/apps/food/migrations/0004_auto_20240525_1352.py new file mode 100644 index 00000000..5c7932c4 --- /dev/null +++ b/apps/food/migrations/0004_auto_20240525_1352.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.28 on 2024-05-25 11:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('food', '0003_auto_20240525_1350'), + ] + + operations = [ + migrations.AlterField( + model_name='basicfood', + name='transformed_food', + field=models.ManyToManyField(blank=True, related_name='BasicFood', to='food.TransformedFood', verbose_name='transformed food'), + ), + ] diff --git a/apps/food/models.py b/apps/food/models.py index e957ae99..b0a222f4 100644 --- a/apps/food/models.py +++ b/apps/food/models.py @@ -7,7 +7,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.core.validators import MinValueValidator -from django.db import models +from django.db import models, transaction from django.db.models import Q from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -23,7 +23,7 @@ class QR_code(models.Model): ) transformed_food_container = models.ForeignKey( - 'Transformed_food', + 'TransformedFood', on_delete = models.PROTECT, related_name = 'QR_code', null = True, @@ -32,7 +32,7 @@ class QR_code(models.Model): ) basic_food = models.ForeignKey( - 'Basic_food', + 'BasicFood', on_delete = models.PROTECT, related_name = 'QR_code', null = True, @@ -128,7 +128,7 @@ class Allergen(models.Model): ) transformed_food = models.ForeignKey( - 'Transformed_food', + 'TransformedFood', on_delete = models.CASCADE, related_name = 'Allergen', blank = True, @@ -137,7 +137,7 @@ class Allergen(models.Model): ) basic_food = models.ForeignKey( - 'Basic_food', + 'BasicFood', on_delete = models.CASCADE, related_name = 'Allergen', blank = True, @@ -150,10 +150,12 @@ class Allergen(models.Model): verbose_name_plural = _('Allergens') def __str__(self): - return _('Allergens of #{id}').format(id=self.id) + return _('Allergens of #{id}').format(id=self.id) + + -class Basic_food(models.Model): +class BasicFood(models.Model): """ Food which has been directly buy on supermarket """ @@ -201,8 +203,8 @@ class Basic_food(models.Model): ) transformed_food = models.ManyToManyField( - 'Transformed_food', - related_name= 'Basic_food', + 'TransformedFood', + related_name= 'BasicFood', blank = True, verbose_name = _('transformed food'), ) @@ -215,7 +217,15 @@ class Basic_food(models.Model): def __str__(self): return self.name -class Transformed_food(models.Model): + @transaction.atomic + def save(self, force_insert=False, force_update=False, using= None, update_fields=None): + # Check if is_DLC and is DDM are not both True + if self.is_DLC and self.is_DDM: + raise ValidationError("The product cannot be a DLC and a DDM") + return super().save(force_insert, force_update, using, update_fields) + + +class TransformedFood(models.Model): """ Transformed food are a mix between basic food and meal """ @@ -265,4 +275,6 @@ class Transformed_food(models.Model): def __str__(self): return self.name - + @transaction.atomic + def save(self, force_insert=False, force_update=False, using= None, update_fields=None): + return super().save(force_insert, force_update, using, update_fields) diff --git a/apps/food/templates/food/basic_food_form.html b/apps/food/templates/food/basic_food_form.html index a56aa063..abce7e9b 100644 --- a/apps/food/templates/food/basic_food_form.html +++ b/apps/food/templates/food/basic_food_form.html @@ -13,6 +13,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% csrf_token %} {{ form|crispy }} + {{ allergenform|crispy }}
diff --git a/apps/food/templates/food/transformed_food_form.html b/apps/food/templates/food/transformed_food_form.html new file mode 100644 index 00000000..917654db --- /dev/null +++ b/apps/food/templates/food/transformed_food_form.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} +
+

+ {{ title }} +

+
+
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+{% endblock %} diff --git a/apps/food/urls.py b/apps/food/urls.py index aff8b8b5..b81bc8fa 100644 --- a/apps/food/urls.py +++ b/apps/food/urls.py @@ -11,6 +11,7 @@ urlpatterns = [ path('test_basic_food_form',views.test_basic_foodform), path('test_transformed_food_form', views.test_transformed_foodform), path('test_allergen_form', views.test_allergenform), - path('0', views.Basic_foodCreateView.as_view(), name = 'basic_food'), + path('0', views.BasicFoodCreateView.as_view(), name = 'basic_food'), + path('1', views.TransformedFoodCreateView.as_view(), name = 'transformed_food'), ] diff --git a/apps/food/views.py b/apps/food/views.py index 43161b0d..1768fd38 100644 --- a/apps/food/views.py +++ b/apps/food/views.py @@ -13,6 +13,7 @@ from django.urls import reverse_lazy from django.db import transaction from django.utils.translation import gettext_lazy as _ from django.utils import timezone +from datetime import timedelta ''' from django.views.generic import UpdateView, DetailView from django.views.generic.base import View, TemplateView @@ -23,41 +24,96 @@ from permission.views import ProtectQuerysetMixin, ProtectedCreateView from django.shortcuts import render -from .forms import Basic_foodForms, Transformed_foodForms, AllergenForms -from .models import Basic_food +from .forms import BasicFoodForms, TransformedFoodForms, AllergenForms +from .models import BasicFood, TransformedFood, Allergen def test_basic_foodform(request): - return render(request,'food/test.html', {"form": Basic_foodForms()}) + return render(request,'food/test.html', {"form": BasicFoodForms()}) def test_transformed_foodform(request): - return render(request,'food/test.html', {"form": Transformed_foodForms()}) + return render(request,'food/transformed_food_form.html', {"form": TransformedFoodForms()}) def test_allergenform(request): return render(request,'food/test.html', {"form": AllergenForms()}) -class Basic_foodCreateView(ProtectQuerysetMixin, ProtectedCreateView): +class BasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView): """ A view to add a basic food """ - model = Basic_food - form_class = Basic_foodForms + model = BasicFood + form_class = BasicFoodForms + template_name = 'food/basic_food_form.html' + second_form = AllergenForms extra_context = {"title": _("Add a new aliment")} def get_sample_object(self): - return Basic_food( + return Allergen( + groundnut = "False", + ) + ''' + return BasicFood( name="", is_DLC=False, is_DDM=False, expiry_date=timezone.now(), label='pic/default.png', ) + ''' @transaction.atomic def form_valid(self, form): form.instance.creater = self.request.user + basic_food_form = BasicFoodForms(data=self.request.POST) + allergen_form = AllergenForms(data=self.request.POST) + if not basic_food_form.is_valid() or not allergen_form.is_valid(): + return self.form_invalid(form) + + # Save the aliment and the allergens associed + basic_food = form.save(commit=False) + basic_food._force_save = True + basic_food.save() + basic_food.refresh_from_db() return super().form_valid(form) def get_success_url(self, **kwargs): - self.objects.refresh_from_db() - return reverse_lazy('food:basic_food', kwargs={"pk": self.object.pk}) + self.object.refresh_from_db() + # return reverse_lazy('food:basicfood', kwargs={"pk": self.object.pk}) + return '0' + +class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView): + """ + A view to add a tranformed food + """ + model = TransformedFood + template_name = 'food/transformed_food_form.html' + form_class = TransformedFoodForms + extra_context = {"title": _("Add a new meal")} + + def get_sample_object(self): + return TransformedFood( + name="", + creation_date=timezone.now(), + ) + + @transaction.atomic + def form_valid(self, form): + form.instance.creater = self.request.user + transformed_food_form = TransformedFoodForms(data=self.request.POST) + if not transformed_food_form.is_valid(): + return self.form_invalid(form) + + # Save the aliment and allergens associated + transformed_food = form.save(commit=False) + # Without microbiologic analysis, the time of conservation is 3 days + transformed_food.expiry_date = transformed_food.creation_date + timedelta(days = 3) + transformed_food._force_save = True + transformed_food.save() + transformed_food.refresh_from_db() + return super().form_valid(form) + + + def get_success_url(self, **kwargs): + self.object.refresh_from_db() + # return reverse_lazy('food:tranformed_food', kwargs={"pk": self.object.pk}) + return '1'