Edit forms, views, template to improve/modify view. Edit urls to remove some path. Few changes in models.

This commit is contained in:
quark 2024-08-14 01:32:55 +02:00
parent 196df1e775
commit 6d7076b03e
9 changed files with 179 additions and 48 deletions

View File

@ -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',)

View File

@ -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'),
),
]

View File

@ -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"),

View File

@ -7,7 +7,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %}
<div class="card bg-white mb-3">
<h3 class="card-header text-center">
HTML not finished <br>
{{ title }}
</h3>
<div class="card-body" id="form">

View File

@ -7,13 +7,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %}
<div class="card bg-white mb-3">
<h3 class="card-header text-center">
HTML not finished <br>
{{ title }}
</h3>
<div class="card-body" id="form">
<form method="post">
{% csrf_token %}
{{ form|crispy }}
{{ form | crispy }}
<button class="btn btn-primary" type="submit">{% trans "Submit"%}</button>
</form>
</div>

View File

@ -7,18 +7,28 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %}
<div class="card bg-white mb-3">
<h3 class="card-header text-center">
HTML not finished <br>
HTML finished <br>
{{ title }}
</h3>
<div class="card-body">
<p>{% trans 'QR-code' %} : {{ qrcode.qr_code_number }}</p>
<p>{% trans 'QR-code number' %} : {{ qrcode.qr_code_number }}</p>
<p>{% trans 'Name' %} : {{ qrcode.food_container.name }}</p>
{% if qrcode.food_container.polymorphic_ctype.name == 'Basic food' %}
<a href="{% url "food:basic_update" pk=qrcode.food_container.pk %}">{% trans 'Update' %}</a>
{% else %}
<a href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">{% trans 'Update' %}</a>
<p>{% trans 'Owner' %} : {{ qrcode.food_container.owner }}</p>
<p>{% trans 'Expiry date' %} : {{ qrcode.food_container.expiry_date }}</p>
{% if qrcode.food_container.polymorphic_ctype.model == 'basicfood' and can_update_basic %}
<a class="btn btn-sm btn-warning" href="{% url "food:basic_update" pk=qrcode.food_container.pk %}" data-turbolinks="false">
{% trans 'Update' %}
</a>
{% elif can_update_transformed %}
<a class="btn btn-sm btn-warning" href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">
{% trans 'Update' %}
</a>
{% endif %}
<a href="{% url "food:add_ingredient" pk=qrcode.food_container.pk %}">{% trans 'Add the ingredient' %}</a>
</div>
{% if can_add_ingredient %}
<a class="btn btn-sm btn-success" href="{% url "food:add_ingredient" pk=qrcode.food_container.pk %}">
{% trans 'Add the ingredient' %}
</a>
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -13,12 +13,9 @@ urlpatterns = [
path('detail/<int:pk>', views.FoodView.as_view(), name='food_view'),
path('<int:slug>/create_qrcode', views.QRCodeCreateView.as_view(), name='qrcode_create'),
path('create', views.FoodCreateView.as_view(), name='food_create'),
path('<int:slug>/create_qrcode/basic', views.QRCodeBasicFoodCreateView.as_view(), name='qrcode_basic_create'),
path('create/transformed', views.TransformedFoodCreateView.as_view(), name='transformed_create'),
path('update/basic/<int:pk>', views.BasicFoodUpdateView.as_view(), name='basic_update'),
path('update/transformed/<int:pk>', views.TransformedFoodUpdateView.as_view(), name='transformed_update'),
path('add/<int:pk>', views.AddIngredientView.as_view(), name='add_ingredient'),
]

View File

@ -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):
"""

View File

@ -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
]
}
},