Adding ingredients to a preparation

This commit is contained in:
korenstin 2024-07-05 11:57:44 +02:00
parent 7051294d76
commit fda9df3d6b
16 changed files with 335 additions and 170 deletions

View File

@ -11,7 +11,20 @@ from note_kfet.inputs import Autocomplete, DateTimePickerInput
from note_kfet.middlewares import get_current_request from note_kfet.middlewares import get_current_request
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from .models import BasicFood, TransformedFood from .models import BasicFood, QRCode, TransformedFood
class AddIngredientForms(forms.ModelForm):
"""
Form for add an ingredient
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['ingredient'].queryset = self.fields['ingredient'].queryset.filter(is_ready=False)
class Meta:
model = TransformedFood
fields = ('ingredient',)
class BasicFoodForms(forms.ModelForm): class BasicFoodForms(forms.ModelForm):
@ -42,6 +55,19 @@ class BasicFoodForms(forms.ModelForm):
} }
class QRCodeForms(forms.ModelForm):
"""
Form for create QRCode
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['food_container'].queryset = self.fields['food_container'].queryset.filter(is_ready=False)
class Meta:
model = QRCode
fields = ('food_container',)
class TransformedFoodForms(forms.ModelForm): class TransformedFoodForms(forms.ModelForm):
""" """
Form for add transformed food Form for add transformed food

View File

@ -1,4 +1,4 @@
# Generated by Django 2.2.28 on 2024-07-03 07:40 # Generated by Django 2.2.28 on 2024-07-05 08:57
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
@ -10,8 +10,8 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('member', '0011_profile_vss_charter_read'),
('contenttypes', '0002_remove_content_type_name'), ('contenttypes', '0002_remove_content_type_name'),
('member', '0011_profile_vss_charter_read'),
] ]
operations = [ operations = [
@ -19,7 +19,7 @@ class Migration(migrations.Migration):
name='Allergen', name='Allergen',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, null=True, verbose_name='name')), ('name', models.CharField(max_length=255, verbose_name='name')),
], ],
options={ options={
'verbose_name': 'Allergen', 'verbose_name': 'Allergen',
@ -33,7 +33,7 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=255, verbose_name='name')), ('name', models.CharField(max_length=255, verbose_name='name')),
('expiry_date', models.DateTimeField(verbose_name='expiry date')), ('expiry_date', models.DateTimeField(verbose_name='expiry date')),
('was_eaten', models.BooleanField(default=False, verbose_name='was eaten')), ('was_eaten', models.BooleanField(default=False, verbose_name='was eaten')),
('code', models.IntegerField(unique=True, verbose_name='code')), ('is_ready', models.BooleanField(default=False, verbose_name='is ready')),
('allergens', models.ManyToManyField(blank=True, to='food.Allergen', verbose_name='allergen')), ('allergens', models.ManyToManyField(blank=True, to='food.Allergen', verbose_name='allergen')),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')), ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_food.food_set+', to='contenttypes.ContentType')), ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_food.food_set+', to='contenttypes.ContentType')),
@ -47,7 +47,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('food_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='food.Food')), ('food_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='food.Food')),
('date_type', models.CharField(choices=[('DLC', 'DLC'), ('DDM', 'DDM')], max_length=255)), ('date_type', models.CharField(choices=[('DLC', 'DLC'), ('DDM', 'DDM')], max_length=255)),
('arrival_date', models.DateTimeField(blank=True, default=django.utils.timezone.now, verbose_name='arrival date')), ('arrival_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='arrival date')),
], ],
options={ options={
'verbose_name': 'Basic food', 'verbose_name': 'Basic food',
@ -55,6 +55,18 @@ class Migration(migrations.Migration):
}, },
bases=('food.food',), bases=('food.food',),
), ),
migrations.CreateModel(
name='QRCode',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('qr_code_number', models.PositiveIntegerField(unique=True, verbose_name='QR-code number')),
('food_container', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.Food', verbose_name='food container')),
],
options={
'verbose_name': 'QR-code',
'verbose_name_plural': 'QR-codes',
},
),
migrations.CreateModel( migrations.CreateModel(
name='TransformedFood', name='TransformedFood',
fields=[ fields=[

View File

@ -1,30 +0,0 @@
# Generated by Django 2.2.28 on 2024-07-03 13:49
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('food', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='food',
name='code',
),
migrations.CreateModel(
name='QRCode',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('qr_code_number', models.PositiveIntegerField(verbose_name='QR-code number')),
('food_container', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.Food', unique=True, verbose_name='food container')),
],
options={
'verbose_name': 'QR-code',
'verbose_name_plural': 'QR-codes',
},
),
]

View File

@ -7,13 +7,6 @@ from django.utils.translation import gettext_lazy as _
from member.models import Club from member.models import Club
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
#################################################################
# TO DO
# - link allergen with one food (basic or transformed) with check
# - check on basic food
# - check on transformed food
#################################################################
class QRCode(models.Model): class QRCode(models.Model):
""" """
@ -21,13 +14,13 @@ class QRCode(models.Model):
""" """
qr_code_number = models.PositiveIntegerField( qr_code_number = models.PositiveIntegerField(
verbose_name=_("QR-code number"), verbose_name=_("QR-code number"),
unique=True,
) )
food_container = models.ForeignKey( food_container = models.OneToOneField(
'Food', 'Food',
on_delete=models.PROTECT, on_delete=models.PROTECT,
related_name='QR_code', related_name='QR_code',
unique=True,
verbose_name=_('food container'), verbose_name=_('food container'),
) )
@ -77,6 +70,7 @@ class Food(PolymorphicModel):
expiry_date = models.DateTimeField( expiry_date = models.DateTimeField(
verbose_name=_('expiry date'), verbose_name=_('expiry date'),
null=False,
) )
was_eaten = models.BooleanField( was_eaten = models.BooleanField(
@ -84,6 +78,11 @@ class Food(PolymorphicModel):
verbose_name=_('was eaten'), verbose_name=_('was eaten'),
) )
is_ready = models.BooleanField(
default=False,
verbose_name=_('is ready'),
)
def __str__(self): def __str__(self):
return self.name return self.name
@ -111,7 +110,6 @@ class BasicFood(Food):
arrival_date = models.DateTimeField( arrival_date = models.DateTimeField(
verbose_name=_('arrival date'), verbose_name=_('arrival date'),
default=timezone.now, default=timezone.now,
blank=True, # TEMPORARY
) )
# label = models.ImageField( # label = models.ImageField(

19
apps/food/tables.py Normal file
View File

@ -0,0 +1,19 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
import django_tables2 as tables
from django_tables2 import A
from .models import TransformedFood
class TransformedFoodTable(tables.Table):
name = tables.LinkColumn(
'food:food_view',
args=[A('pk'), ],
)
class Meta:
model = TransformedFood
template_name = 'django_tables2/bootstrap4.html'
fields = ('name', )

View File

@ -0,0 +1,21 @@
{% extends "base.html" %}
{% comment %}
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n crispy_forms_tags %}
{% 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 }}
<button class="btn btn-primary" type="submit">{% trans "Submit"%}</button>
</form>
</div>
</div>
{% endblock %}

View File

@ -11,8 +11,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
{{ title }} {{ title }}
</h3> </h3>
<div class="card-body"> <div class="card-body">
<p>name : {{ food.name }}</p> <p>name : {{ food.name }}</p>
<a href="{% url "food:basic_update" pk=food.pk %}">Update</a> <a href="{% url "food:basic_update" pk=food.pk %}">Update</a>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -10,12 +10,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
{{ title }} {{ title }}
</h3> </h3>
<div class="row"> <div class="row">
<div class="col-xl-12"> <div class="col-xl-12">
<div class="btn-group btn-block"> <div class="btn-group btn-block">
<a href="{% url "food:basic_create" %}" class="btn btn-sm btn-outline-primary">Basic</a> <a href="{% url "food:basic_create" %}" class="btn btn-sm btn-outline-primary">Basic</a>
<a href="{% url "food:transformed_create" %}" class="btn btn-sm btn-outline-primary">Transformed</a> <a href="{% url "food:transformed_create" %}" class="btn btn-sm btn-outline-primary">Transformed</a>
</div>
</div> </div>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -2,6 +2,7 @@
{% comment %} {% comment %}
SPDX-License-Identifier: GPL-3.0-or-later SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %} {% endcomment %}
{% load i18n crispy_forms_tags %}
{% block content %} {% block content %}
<div class="card bg-white mb-3"> <div class="card bg-white mb-3">
@ -9,13 +10,20 @@ SPDX-License-Identifier: GPL-3.0-or-later
HTML not finished <br> HTML not finished <br>
{{ title }} {{ title }}
</h3> </h3>
<div class="row"> <div class="row">
<div class="col-xl-12"> <div class="col-xl-12">
<div class="btn-group btn-block"> <div class="btn-group btn-block">
<a href="{% url "food:qrcode_basic_create" slug=slug %}" class="btn btn-sm btn-outline-primary">Basic</a> <a href="{% url "food:qrcode_basic_create" slug=slug %}" class="btn btn-sm btn-outline-primary">Basic</a>
<a href="{% url "food:qrcode_transformed_create" slug=slug %}" class="btn btn-sm btn-outline-primary">Transformed</a> <a href="{% url "food:qrcode_transformed_create" slug=slug %}" class="btn btn-sm btn-outline-primary">Transformed</a>
</div>
</div> </div>
</div> </div>
</div>
<div class="card-body" id="form">
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit">{% trans "Submit"%}</button>
</form>
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -11,13 +11,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
{{ title }} {{ title }}
</h3> </h3>
<div class="card-body"> <div class="card-body">
<p>qrcode : {{ qrcode.qr_code_number }}</p> <p>qrcode : {{ qrcode.qr_code_number }}</p>
<p>name : {{ qrcode.food_container.name }}</p> <p>name : {{ qrcode.food_container.name }}</p>
{% if qrcode.food_container.polymorphic_ctype.name == 'Basic food' %} {% if qrcode.food_container.polymorphic_ctype.name == 'Basic food' %}
<a href="{% url "food:basic_update" pk=qrcode.food_container.pk %}">Update</a> <a href="{% url "food:basic_update" pk=qrcode.food_container.pk %}">Update</a>
{% else %} {% else %}
<a href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">Update</a> <a href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">Update</a>
{% endif %} {% endif %}
<a href="{% url "food:add_ingredient" pk=qrcode.food_container.pk %}">Add the ingrdient</a>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -13,6 +13,18 @@ SPDX-License-Identifier: GPL-3.0-or-later
<div class="card-body"> <div class="card-body">
<p>name : {{ food.name }}</p> <p>name : {{ food.name }}</p>
<p>owner : {{ food.owner }}</p> <p>owner : {{ food.owner }}</p>
<p>allergens :</p>
<ul>
{% for allergen in food.allergens.iterator %}
<li>{{ allergen.name }}</li>
{% endfor %}
</ul>
<p>ingredients :</p>
<ul>
{% for ingredient in food.ingredient.iterator %}
<li><a href="{% url "food:food_view" pk=ingredient.pk %}">{{ ingredient.name }}</a></li>
{% endfor %}
</ul>
<a href="{% url "food:transformed_update" pk=food.pk %}">Update</a> <a href="{% url "food:transformed_update" pk=food.pk %}">Update</a>
</div> </div>
</div> </div>

View File

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% comment %}
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load render_table from django_tables2 %}
{% load i18n %}
{% block content %}
<div class="card bg-light mb-3">
<h3 class="card-header text-center">
Transformed food
</h3>
<div class="card-footer">
<a class="btn btn-sm btn-success" href="{% url 'food:transformed_create' %}" data-turbolinks="false">
New transformed food
</a>
</div>
{% render_table table %}
</div>
{% endblock %}

View File

@ -8,6 +8,7 @@ from . import views
app_name = 'food' app_name = 'food'
urlpatterns = [ urlpatterns = [
path('', views.TransfomedListView.as_view(), name='food_list'),
path('<int:slug>', views.QRCodeView.as_view(), name='qrcode_view'), path('<int:slug>', views.QRCodeView.as_view(), name='qrcode_view'),
path('detail/<int:pk>', views.FoodView.as_view(), name='food_view'), path('detail/<int:pk>', views.FoodView.as_view(), name='food_view'),
@ -15,9 +16,10 @@ urlpatterns = [
path('create', views.FoodCreateView.as_view(), name='food_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('<int:slug>/create_qrcode/basic', views.QRCodeBasicFoodCreateView.as_view(), name='qrcode_basic_create'),
path('<int:slug>/create_qrcode/transformed', views.QRCodeTransformedFoodCreateView.as_view(), name='qrcode_transformed_create'), path('<int:slug>/create_qrcode/transformed', views.QRCodeTransformedFoodCreateView.as_view(), name='qrcode_transformed_create'),
path('create/basic', views.BasicFoodCreateView.as_view(), name='basic_create'),
path('create/transformed', views.TransformedFoodCreateView.as_view(), name='transformed_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/basic/<int:pk>', views.BasicFoodUpdateView.as_view(), name='basic_update'),
path('update/transformed/<int:pk>', views.TransformedFoodUpdateView.as_view(), name='transformed_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

@ -6,69 +6,62 @@ from datetime import timedelta
from django.db import transaction from django.db import transaction
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django_tables2.views import SingleTableView
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils import timezone from django.utils import timezone
from django.views.generic import DetailView, UpdateView, TemplateView from django.views.generic import DetailView, UpdateView, TemplateView
from django.views.generic.edit import FormView
from permission.views import ProtectQuerysetMixin, ProtectedCreateView from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import BasicFoodForms, TransformedFoodForms from .forms import AddIngredientForms, BasicFoodForms, QRCodeForms, TransformedFoodForms
from .models import BasicFood, Food, QRCode, TransformedFood from .models import BasicFood, Food, QRCode, TransformedFood
from .tables import TransformedFoodTable
class QRCodeView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): class AddIngredientView(ProtectQuerysetMixin, FormView):
""" """
A view to add a basic food A view to see a qrcode
""" """
model = QRCode model = Food
extra_context = {"title": _("Add a new meal")} template_name = 'food/add_ingredient_form.html'
context_object_name = "qrcode" extra_context = {"title": _("Add the ingredient")}
slug_field = "qr_code_number" form_class = AddIngredientForms
def get(self, *args, **kwargs):
qrcode = kwargs["slug"]
if self.model.objects.filter(qr_code_number=qrcode).count() > 0:
return super().get(*args, **kwargs)
else:
return HttpResponseRedirect(reverse("food:qrcode_create", kwargs=kwargs))
class QRCodeCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView):
"""
A view to add a basic food
"""
template_name = 'food/create_qrcode_form.html'
extra_context = {"title": _("Add a new aliment")}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["slug"] = kwargs["slug"] context["pk"] = self.kwargs["pk"]
return context return context
@transaction.atomic
def form_valid(self, form):
form.instance.creater = self.request.user
add_ingredient_form = AddIngredientForms(data=self.request.POST)
if not add_ingredient_form.is_valid():
return self.form_invalid(form)
class FoodView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): food = Food.objects.get(pk=self.kwargs['pk'])
""" # Save the aliment and the allergens associed
A view to add a basic food for transformed_pk in self.request.POST.getlist('ingredient'):
""" transformed = TransformedFood.objects.get(pk=transformed_pk)
model = Food transformed.ingredient.add(food)
extra_context = {"title": _("Add a new meal")} transformed._force_save = True
context_object_name = "food" transformed.save()
transformed.refresh_from_db()
return super().form_valid(form)
def get_success_url(self, **kwargs):
return reverse('food:food_list')
def get_sample_object(self):
return TransformedFood(
name="",
creation_date=timezone.now(),
)
class FoodCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView): class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
A view to add a basic food
"""
template_name = 'food/create_food_form.html'
extra_context = {"title": _("Add a new aliment")}
class BasicFoodFormView(ProtectQuerysetMixin):
#####################################################################
# TO DO
# - fix picture save
# - implement solution crop and convert image (reuse or recode ImageForm from members apps)
#####################################################################
""" """
A view to add a basic food A view to add a basic food
""" """
@ -98,16 +91,21 @@ class BasicFoodFormView(ProtectQuerysetMixin):
return reverse('food:food_view', kwargs={"pk": self.object.pk}) return reverse('food:food_view', kwargs={"pk": self.object.pk})
class BasicFoodUpdateView(BasicFoodFormView, LoginRequiredMixin, UpdateView): class FoodCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView):
pass """
A view to add a new aliment
"""
template_name = 'food/create_food_form.html'
extra_context = {"title": _("Add a new aliment")}
class BasicFoodCreateView(BasicFoodFormView, ProtectedCreateView): class FoodView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
def get_sample_object(self): """
return BasicFood( A view to see a food
name="", """
expiry_date=timezone.now(), model = Food
) extra_context = {"title": _("Details")}
context_object_name = "food"
class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView): class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
@ -117,12 +115,12 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
# - implement solution crop and convert image (reuse or recode ImageForm from members apps) # - implement solution crop and convert image (reuse or recode ImageForm from members apps)
##################################################################### #####################################################################
""" """
A view to add a basic food A view to add a basic food with a qrcode
""" """
model = BasicFood model = BasicFood
form_class = BasicFoodForms form_class = BasicFoodForms
template_name = 'food/basic_food_form.html' template_name = 'food/basic_food_form.html'
extra_context = {"title": _("Add a new aliment")} extra_context = {"title": _("Add a new basic food with QRCode")}
@transaction.atomic @transaction.atomic
def form_valid(self, form): def form_valid(self, form):
@ -135,6 +133,7 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
basic_food = form.save(commit=False) basic_food = form.save(commit=False)
# We assume the date of labeling and the same as the date of arrival # We assume the date of labeling and the same as the date of arrival
basic_food.arrival_date = timezone.now() basic_food.arrival_date = timezone.now()
basic_food.is_ready = True
basic_food._force_save = True basic_food._force_save = True
basic_food.save() basic_food.save()
basic_food.refresh_from_db() basic_food.refresh_from_db()
@ -148,7 +147,7 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
self.object.refresh_from_db() self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk}) return reverse('food:qrcode_view', kwargs={"slug": self.kwargs['slug']})
def get_sample_object(self): def get_sample_object(self):
return BasicFood( return BasicFood(
@ -157,12 +156,117 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
) )
class QRCodeCreateView(ProtectQuerysetMixin, ProtectedCreateView):
"""
A view to add a new qrcode
"""
model = QRCode
template_name = 'food/create_qrcode_form.html'
form_class = QRCodeForms
extra_context = {"title": _("Add a new QRCode")}
def get(self, *args, **kwargs):
qrcode = kwargs["slug"]
if self.model.objects.filter(qr_code_number=qrcode).count() > 0:
return HttpResponseRedirect(reverse("food:qrcode_view", kwargs=kwargs))
else:
return super().get(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["slug"] = self.kwargs["slug"]
return context
@transaction.atomic
def form_valid(self, form):
form.instance.creater = self.request.user
qrcode_food_form = QRCodeForms(data=self.request.POST)
if not qrcode_food_form.is_valid():
return self.form_invalid(form)
# Save the qrcode
qrcode = form.save(commit=False)
qrcode.qr_code_number = self.kwargs["slug"]
qrcode._force_save = True
qrcode.save()
qrcode.refresh_from_db()
qrcode.food_container.is_ready = True
qrcode.food_container.save()
return super().form_valid(form)
def get_success_url(self, **kwargs):
self.object.refresh_from_db()
return reverse('food:qrcode_view', kwargs={"slug": self.kwargs['slug']})
def get_sample_object(self):
return QRCode(
qr_code_number=self.kwargs["slug"],
)
class QRCodeTransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
"""
A view to add a transformed food with a qrcode
"""
model = TransformedFood
template_name = 'food/transformed_food_form.html'
form_class = TransformedFoodForms
extra_context = {"title": _("Add a new transformed food with QRCode")}
@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 microbiological analyzes, the storage time is 3 days
transformed_food.expiry_date = transformed_food.creation_date + timedelta(days=3)
transformed_food.is_ready = True
transformed_food._force_save = True
transformed_food.save()
transformed_food.refresh_from_db()
qrcode = QRCode()
qrcode.qr_code_number = self.kwargs['slug']
qrcode.food_container = transformed_food
qrcode.save()
return super().form_valid(form)
def get_success_url(self, **kwargs):
self.object.refresh_from_db()
return reverse('food:qrcode_view', kwargs={"slug": self.kwargs['slug']})
def get_sample_object(self):
return TransformedFood(
name="",
creation_date=timezone.now(),
)
class QRCodeView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
A view to see a qrcode
"""
model = QRCode
extra_context = {"title": _("QRCode")}
context_object_name = "qrcode"
slug_field = "qr_code_number"
def get(self, *args, **kwargs):
qrcode = kwargs["slug"]
if self.model.objects.filter(qr_code_number=qrcode).count() > 0:
return super().get(*args, **kwargs)
else:
return HttpResponseRedirect(reverse("food:qrcode_create", kwargs=kwargs))
class TransformedFoodFormView(ProtectQuerysetMixin): class TransformedFoodFormView(ProtectQuerysetMixin):
#####################################################################
# TO DO
# - fix picture save
# - implement solution crop and convert image (reuse or recode ImageForm from members apps)
#####################################################################
""" """
A view to add a tranformed food A view to add a tranformed food
""" """
@ -204,48 +308,16 @@ class TransformedFoodCreateView(TransformedFoodFormView, ProtectedCreateView):
) )
class QRCodeTransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView): class TransfomedListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
#####################################################################
# TO DO
# - fix picture save
# - implement solution crop and convert image (reuse or recode ImageForm from members apps)
#####################################################################
""" """
A view to add a basic food Displays all Activities, and classify if they are on-going or upcoming ones.
""" """
model = TransformedFood model = TransformedFood
template_name = 'food/transformed_food_form.html' table_class = TransformedFoodTable
form_class = TransformedFoodForms ordering = ('-name',)
extra_context = {"title": _("Add a new meal")} extra_context = {"title": _("Transformed food")}
@transaction.atomic def get_queryset(self, **kwargs):
def form_valid(self, form): return super().get_queryset(**kwargs)\
form.instance.creater = self.request.user .filter(is_ready=False)\
transformed_food_form = TransformedFoodForms(data=self.request.POST) .distinct()
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 microbiological analyzes, the storage time 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()
qrcode = QRCode()
qrcode.qr_code_number = self.kwargs['slug']
qrcode.food_container = transformed_food
qrcode.save()
return super().form_valid(form)
def get_success_url(self, **kwargs):
self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk})
def get_sample_object(self):
return BasicFood(
name="",
expiry_date=timezone.now(),
)

View File

@ -69,6 +69,7 @@ INSTALLED_APPS = [
# Note apps # Note apps
'api', 'api',
'activity', 'activity',
'food',
'logs', 'logs',
'member', 'member',
'note', 'note',
@ -77,7 +78,6 @@ INSTALLED_APPS = [
'scripts', 'scripts',
'treasury', 'treasury',
'wei', 'wei',
'food',
] ]
MIDDLEWARE = [ MIDDLEWARE = [

View File

@ -66,6 +66,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a> <a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a>
</li> </li>
{% endif %} {% endif %}
<li class="nav-item">
{% url 'food:food_list' as url %}
<a data-turbolinks="false" class="nav-link" href="{{ url }}">Food</a>
</li>
{% if user.is_authenticated and user|is_member:"Kfet" %} {% if user.is_authenticated and user|is_member:"Kfet" %}
<li class="nav-item"> <li class="nav-item">
{% url 'note:transfer' as url %} {% url 'note:transfer' as url %}