diff --git a/apps/food/forms.py b/apps/food/forms.py
index 59226a52..e8601306 100644
--- a/apps/food/forms.py
+++ b/apps/food/forms.py
@@ -11,7 +11,7 @@ from note_kfet.inputs import Autocomplete, DateTimePickerInput
from note_kfet.middlewares import get_current_request
from permission.backends import PermissionBackend
-from .models import BasicFood, QRCode, TransformedFood
+from .models import BasicFood, QRCode, TransformedFood, Food
class AddIngredientForms(forms.ModelForm):
@@ -20,7 +20,7 @@ class AddIngredientForms(forms.ModelForm):
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.fields['ingredient'].queryset = self.fields['ingredient'].queryset.filter(is_ready=False)
+ self.fields['ingredient'].queryset = self.fields['ingredient'].queryset.filter(is_ready=False, is_active=True, was_eaten=False)
class Meta:
model = TransformedFood
@@ -45,7 +45,7 @@ class BasicFoodForms(forms.ModelForm):
class Meta:
model = BasicFood
- fields = ('name', 'owner', 'date_type', 'expiry_date', 'allergens')
+ fields = ('name', 'owner', 'date_type', 'expiry_date', 'is_active', 'was_eaten', 'allergens',)
widgets = {
"owner": Autocomplete(
model=Club,
@@ -80,6 +80,8 @@ class TransformedFoodForms(forms.ModelForm):
self.fields['creation_date'].required = True
self.fields['creation_date'].initial = timezone.now
self.fields['is_active'].initial = True
+ self.fields['is_ready'].initial = False
+ self.fields['was_eaten'].initial = False
# Some example
self.fields['name'].widget.attrs.update({"placeholder": _("lasagna")})
@@ -89,7 +91,7 @@ class TransformedFoodForms(forms.ModelForm):
class Meta:
model = TransformedFood
- fields = ('name', 'creation_date', 'owner', 'is_active', 'shelf_life')
+ fields = ('name', 'creation_date', 'owner', 'is_active', 'is_ready', 'was_eaten', 'shelf_life')
widgets = {
"owner": Autocomplete(
model=Club,
@@ -97,3 +99,13 @@ class TransformedFoodForms(forms.ModelForm):
),
'creation_date': DateTimePickerInput(),
}
+
+class FoodForms(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.fields['was_eaten'].initial = True
+
+ class Meta:
+ model = Food
+ fields = ('was_eaten',)
+
diff --git a/apps/food/migrations/0004_auto_20240813_2358.py b/apps/food/migrations/0004_auto_20240813_2358.py
new file mode 100644
index 00000000..d7fdf200
--- /dev/null
+++ b/apps/food/migrations/0004_auto_20240813_2358.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.2.28 on 2024-08-13 21:58
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('food', '0003_create_14_allergens_mandatory'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='transformedfood',
+ name='is_active',
+ ),
+ migrations.AddField(
+ model_name='food',
+ name='is_active',
+ field=models.BooleanField(default=True, verbose_name='is active'),
+ ),
+ migrations.AlterField(
+ model_name='qrcode',
+ name='food_container',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='QR_code', to='food.Food', verbose_name='food container'),
+ ),
+ ]
diff --git a/apps/food/models.py b/apps/food/models.py
index 50db24f3..48974e00 100644
--- a/apps/food/models.py
+++ b/apps/food/models.py
@@ -19,9 +19,9 @@ class QRCode(models.Model):
unique=True,
)
- food_container = models.OneToOneField(
+ food_container = models.ForeignKey(
'Food',
- on_delete=models.PROTECT,
+ on_delete=models.CASCADE,
related_name='QR_code',
verbose_name=_('food container'),
)
@@ -80,11 +80,21 @@ class Food(PolymorphicModel):
verbose_name=_('was eaten'),
)
+ # is_ready != is_active : is_ready signifie que la nourriture est prête à être manger,
+ # is_active signifie que la nourriture n'est pas encore archivé
+ # il sert dans les cas où il est plus intéressant que de l'open soit conservé (confiture par ex)
+
is_ready = models.BooleanField(
default=False,
verbose_name=_('is ready'),
)
+ is_active = models.BooleanField(
+ default=True,
+ verbose_name=_('is active'),
+ )
+
+
def __str__(self):
return self.name
@@ -160,11 +170,6 @@ class TransformedFood(Food):
verbose_name=_('transformed ingredient'),
)
- is_active = models.BooleanField(
- default=True,
- verbose_name=_('is active'),
- )
-
# Without microbiological analyzes, the storage time is 3 days
shelf_life = models.DurationField(
verbose_name=_("shelf life"),
diff --git a/apps/food/templates/food/add_ingredient_form.html b/apps/food/templates/food/add_ingredient_form.html
index 86e3b03e..395928e4 100644
--- a/apps/food/templates/food/add_ingredient_form.html
+++ b/apps/food/templates/food/add_ingredient_form.html
@@ -7,7 +7,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %}
diff --git a/apps/food/templates/food/basic_food_form.html b/apps/food/templates/food/basicfood_form.html
similarity index 89%
rename from apps/food/templates/food/basic_food_form.html
rename to apps/food/templates/food/basicfood_form.html
index dbfb49e3..6fe6f06f 100644
--- a/apps/food/templates/food/basic_food_form.html
+++ b/apps/food/templates/food/basicfood_form.html
@@ -7,13 +7,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %}
diff --git a/apps/food/templates/food/qrcode_detail.html b/apps/food/templates/food/qrcode_detail.html
index def3a028..4c6b1118 100644
--- a/apps/food/templates/food/qrcode_detail.html
+++ b/apps/food/templates/food/qrcode_detail.html
@@ -7,18 +7,28 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %}
{% endblock %}
diff --git a/apps/food/urls.py b/apps/food/urls.py
index 59640bae..09bb8ebe 100644
--- a/apps/food/urls.py
+++ b/apps/food/urls.py
@@ -13,12 +13,9 @@ urlpatterns = [
path('detail/
', views.FoodView.as_view(), name='food_view'),
path('/create_qrcode', views.QRCodeCreateView.as_view(), name='qrcode_create'),
- path('create', views.FoodCreateView.as_view(), name='food_create'),
path('/create_qrcode/basic', views.QRCodeBasicFoodCreateView.as_view(), name='qrcode_basic_create'),
path('create/transformed', views.TransformedFoodCreateView.as_view(), name='transformed_create'),
-
path('update/basic/', views.BasicFoodUpdateView.as_view(), name='basic_update'),
path('update/transformed/', views.TransformedFoodUpdateView.as_view(), name='transformed_update'),
-
path('add/', views.AddIngredientView.as_view(), name='add_ingredient'),
]
diff --git a/apps/food/views.py b/apps/food/views.py
index 10f296f7..cddb19f6 100644
--- a/apps/food/views.py
+++ b/apps/food/views.py
@@ -10,12 +10,13 @@ from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.views.generic import DetailView, UpdateView, TemplateView
from django.views.generic.list import ListView
+from django.forms import HiddenInput
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from member.models import Club
from note_kfet.middlewares import get_current_request
-from .forms import AddIngredientForms, BasicFoodForms, QRCodeForms, TransformedFoodForms
+from .forms import AddIngredientForms, BasicFoodForms, QRCodeForms, TransformedFoodForms, FoodForms
from .models import BasicFood, Food, QRCode, TransformedFood
from .tables import TransformedFoodTable
@@ -24,6 +25,7 @@ class AddIngredientView(ProtectQuerysetMixin, UpdateView):
"""
A view to add an ingredient
"""
+ # TO DO : ajouter un champ fully_used dans le form et changer was_eaten en conséquence + mieux filtrer les plat dispo avec des perms
model = Food
template_name = 'food/add_ingredient_form.html'
extra_context = {"title": _("Add the ingredient")}
@@ -39,8 +41,9 @@ class AddIngredientView(ProtectQuerysetMixin, UpdateView):
form.instance.creater = self.request.user
food = Food.objects.get(pk=self.kwargs['pk'])
add_ingredient_form = AddIngredientForms(data=self.request.POST)
- if not food.is_ready:
- form.add_error(None, _("The product isn't ready"))
+ food_form = FoodForms(data=self.request.POST)
+ if food.is_ready:
+ form.add_error(None, _("The product is already prepared"))
return self.form_invalid(form)
if not add_ingredient_form.is_valid():
return self.form_invalid(form)
@@ -59,11 +62,11 @@ class AddIngredientView(ProtectQuerysetMixin, UpdateView):
class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
- A view to add a basic food
+ A view to update a basic food
"""
model = BasicFood
form_class = BasicFoodForms
- template_name = 'food/basic_food_form.html'
+ template_name = 'food/basicfood_form.html'
extra_context = {"title": _("Add a new aliment")}
@transaction.atomic
@@ -81,6 +84,18 @@ class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk})
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ form = context['form']
+ # TO DO : Add perms here
+ if 1==0:
+ form.fields['is_active'].widget = HiddenInput()
+ if 1==0:
+ form.fields['was_eaten'].widget = HiddenInput()
+ form.fields['is_active'].help_text = _("Uncheck if the food doesn't exist anymore")
+ form.fields['was_eaten'].help_text = _("Check if the food has been entirely eaten")
+
+ return context
class FoodCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView):
"""
@@ -98,7 +113,6 @@ class FoodView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
extra_context = {"title": _("Details")}
context_object_name = "food"
-
class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
#####################################################################
# TO DO
@@ -110,7 +124,7 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
"""
model = BasicFood
form_class = BasicFoodForms
- template_name = 'food/basic_food_form.html'
+ template_name = 'food/basicfood_form.html'
extra_context = {"title": _("Add a new basic food with QRCode")}
@transaction.atomic
@@ -124,7 +138,9 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
basic_food = form.save(commit=False)
# We assume the date of labeling and the same as the date of arrival
basic_food.arrival_date = timezone.now()
- basic_food.is_ready = True
+ basic_food.is_ready = False
+ basic_food.is_active = True
+ basic_food.was_eaten = False
basic_food._force_save = True
basic_food.save()
basic_food.refresh_from_db()
@@ -146,6 +162,16 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
expiry_date=timezone.now(),
)
+ def get_context_data(self, **kwargs):
+ # Some field are hidden on create
+ context = super().get_context_data(**kwargs)
+
+ form = context['form']
+ form.fields['is_active'].widget = HiddenInput()
+ form.fields['was_eaten'].widget = HiddenInput()
+
+ return context
+
class QRCodeCreateView(ProtectQuerysetMixin, ProtectedCreateView):
"""
@@ -160,6 +186,8 @@ class QRCodeCreateView(ProtectQuerysetMixin, ProtectedCreateView):
qrcode = kwargs["slug"]
if self.model.objects.filter(qr_code_number=qrcode).count() > 0:
return HttpResponseRedirect(reverse("food:qrcode_view", kwargs=kwargs))
+ elif not TransformedFood.objects.filter(is_ready=False, was_eaten=False, is_active=True).count() > 0:
+ return HttpResponseRedirect(reverse("food:qrcode_basic_create", kwargs=kwargs))
else:
return super().get(*args, **kwargs)
@@ -213,11 +241,21 @@ class QRCodeView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
else:
return HttpResponseRedirect(reverse("food:qrcode_create", kwargs=kwargs))
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ # TO DO : Add perms here
+ context["can_update_basic"]=True
+ context["can_update_transformed"]=True
+ context["can_add_ingredient"] = True
-class TransformedFoodFormView(ProtectQuerysetMixin):
+ return context
+
+
+class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
"""
A view to add a tranformed food
"""
+ # TO DO : fix the "NotImplementedError" (╯°□°)╯︵ ┻━┻ ...
model = TransformedFood
template_name = 'food/transformed_food_form.html'
form_class = TransformedFoodForms
@@ -233,6 +271,9 @@ class TransformedFoodFormView(ProtectQuerysetMixin):
# Save the aliment and allergens associated
transformed_food = form.save(commit=False)
transformed_food.expiry_date = transformed_food.creation_date
+ transformed_food.is_active = True
+ transformed_food.is_ready = False
+ transformed_food.was_eaten = False
transformed_food._force_save = True
transformed_food.save()
transformed_food.refresh_from_db()
@@ -244,18 +285,58 @@ class TransformedFoodFormView(ProtectQuerysetMixin):
self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk})
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+
+ # Some field are hidden on create
+ form = context['form']
+ form.fields['is_active'].widget = HiddenInput()
+ form.fields['is_ready'].widget = HiddenInput()
+ form.fields['was_eaten'].widget = HiddenInput()
-class TransformedFoodUpdateView(TransformedFoodFormView, LoginRequiredMixin, UpdateView):
- pass
+ # Field shelf life is only display for authorized user
+ # TO DO : Add permission here
+ if not True:
+ form.fields['shelf_life'].widget = HiddenInput()
+
+ return context
-class TransformedFoodCreateView(TransformedFoodFormView, ProtectedCreateView):
- def get_sample_object(self):
- return TransformedFood(
- name="",
- creation_date=timezone.now(),
- )
+class TransformedFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
+ """
+ A view to update transformed product
+ """
+ model = TransformedFood
+ template_name = 'food/transformed_food_form.html'
+ form_class = TransformedFoodForms
+ extra_context = {'title' : _('Update meal')}
+ @transaction.atomic
+ def form_valid(self, form):
+ form.instance.creater = self.request.user
+ transformedfood_form = TransformedFoodForms(data=self.request.POST)
+ if not transformedfood_form.is_valid():
+ return self.form_invalid(form)
+
+ ans = super().form_valid(form)
+ form.instance.update()
+ return ans
+
+ def get_success_url(self, **kwargs):
+ self.object.refresh_from_db()
+ return reverse('food:food_view', kwargs={"pk": self.object.pk})
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+
+ form = context['form']
+
+ fields = ['is_active','is_ready','was_eaten','shelf_life']
+ # TO DO : Add permissions here
+ permissions = [True]*len(fields)
+ for i in range(len(fields)):
+ if not permissions[i] : form[fields[i]].widget = HiddenInput()
+ return context
class TransformedListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, ListView):
"""
diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json
index 92ab6340..a4c5ecad 100644
--- a/apps/permission/fixtures/initial.json
+++ b/apps/permission/fixtures/initial.json
@@ -3119,7 +3119,7 @@
"food",
"transformedfood"
],
- "query": "",
+ "query": "[]",
"type": "view",
"mask": 3,
"field": "",
@@ -3135,7 +3135,7 @@
"food",
"transformedfood"
],
- "query": "{\"owner\": \"club\"}",
+ "query": "{\"owner\": [\"club\"]}",
"type": "view",
"mask": 3,
"field": "",
@@ -3145,7 +3145,7 @@
},
{
"model": "permission.permission",
- "pk": 200,
+ "pk": 201,
"fields": {
"model": [
"food",
@@ -3239,7 +3239,7 @@
158,
159,
160,
- 200
+ 201
]
}
},
@@ -3266,7 +3266,7 @@
50,
141,
169,
- 199
+ 200
]
}
},
@@ -3441,7 +3441,7 @@
167,
168,
182,
- 199
+ 200
]
}
},