mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 01:12:08 +01:00 
			
		
		
		
	Adding ingredients to a preparation
This commit is contained in:
		@@ -11,7 +11,20 @@ from note_kfet.inputs import Autocomplete, DateTimePickerInput
 | 
			
		||||
from note_kfet.middlewares import get_current_request
 | 
			
		||||
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):
 | 
			
		||||
@@ -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):
 | 
			
		||||
    """
 | 
			
		||||
    Form for add transformed food
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
@@ -10,8 +10,8 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('member', '0011_profile_vss_charter_read'),
 | 
			
		||||
        ('contenttypes', '0002_remove_content_type_name'),
 | 
			
		||||
        ('member', '0011_profile_vss_charter_read'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@@ -19,7 +19,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
            name='Allergen',
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('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={
 | 
			
		||||
                'verbose_name': 'Allergen',
 | 
			
		||||
@@ -33,7 +33,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                ('name', models.CharField(max_length=255, verbose_name='name')),
 | 
			
		||||
                ('expiry_date', models.DateTimeField(verbose_name='expiry date')),
 | 
			
		||||
                ('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')),
 | 
			
		||||
                ('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')),
 | 
			
		||||
@@ -47,7 +47,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
            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')),
 | 
			
		||||
                ('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={
 | 
			
		||||
                'verbose_name': 'Basic food',
 | 
			
		||||
@@ -55,6 +55,18 @@ class Migration(migrations.Migration):
 | 
			
		||||
            },
 | 
			
		||||
            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(
 | 
			
		||||
            name='TransformedFood',
 | 
			
		||||
            fields=[
 | 
			
		||||
 
 | 
			
		||||
@@ -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',
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -7,13 +7,6 @@ from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from member.models import Club
 | 
			
		||||
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):
 | 
			
		||||
    """
 | 
			
		||||
@@ -21,13 +14,13 @@ class QRCode(models.Model):
 | 
			
		||||
    """
 | 
			
		||||
    qr_code_number = models.PositiveIntegerField(
 | 
			
		||||
        verbose_name=_("QR-code number"),
 | 
			
		||||
        unique=True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    food_container = models.ForeignKey(
 | 
			
		||||
    food_container = models.OneToOneField(
 | 
			
		||||
        'Food',
 | 
			
		||||
        on_delete=models.PROTECT,
 | 
			
		||||
        related_name='QR_code',
 | 
			
		||||
        unique=True,
 | 
			
		||||
        verbose_name=_('food container'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@@ -77,6 +70,7 @@ class Food(PolymorphicModel):
 | 
			
		||||
 | 
			
		||||
    expiry_date = models.DateTimeField(
 | 
			
		||||
        verbose_name=_('expiry date'),
 | 
			
		||||
        null=False,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    was_eaten = models.BooleanField(
 | 
			
		||||
@@ -84,6 +78,11 @@ class Food(PolymorphicModel):
 | 
			
		||||
        verbose_name=_('was eaten'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    is_ready = models.BooleanField(
 | 
			
		||||
        default=False,
 | 
			
		||||
        verbose_name=_('is ready'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
@@ -111,7 +110,6 @@ class BasicFood(Food):
 | 
			
		||||
    arrival_date = models.DateTimeField(
 | 
			
		||||
        verbose_name=_('arrival date'),
 | 
			
		||||
        default=timezone.now,
 | 
			
		||||
        blank=True,  # TEMPORARY
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # label = models.ImageField(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								apps/food/tables.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								apps/food/tables.py
									
									
									
									
									
										Normal 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', )
 | 
			
		||||
							
								
								
									
										21
									
								
								apps/food/templates/food/add_ingredient_form.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								apps/food/templates/food/add_ingredient_form.html
									
									
									
									
									
										Normal 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 %}
 | 
			
		||||
@@ -11,8 +11,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
    {{ title }}
 | 
			
		||||
  </h3>
 | 
			
		||||
  <div class="card-body">
 | 
			
		||||
      <p>name : {{ food.name }}</p>
 | 
			
		||||
      <a href="{% url "food:basic_update" pk=food.pk %}">Update</a>
 | 
			
		||||
    <p>name : {{ food.name }}</p>
 | 
			
		||||
    <a href="{% url "food:basic_update" pk=food.pk %}">Update</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
    {{ title }}
 | 
			
		||||
  </h3>
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-xl-12">
 | 
			
		||||
            <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:transformed_create" %}" class="btn btn-sm btn-outline-primary">Transformed</a>
 | 
			
		||||
            </div>
 | 
			
		||||
      <div class="col-xl-12">
 | 
			
		||||
        <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:transformed_create" %}" class="btn btn-sm btn-outline-primary">Transformed</a>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
{% comment %}
 | 
			
		||||
SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
{% load i18n crispy_forms_tags %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="card bg-white mb-3">
 | 
			
		||||
@@ -9,13 +10,20 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
    HTML not finished <br>
 | 
			
		||||
    {{ title }}
 | 
			
		||||
  </h3>
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-xl-12">
 | 
			
		||||
            <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_transformed_create" slug=slug %}" class="btn btn-sm btn-outline-primary">Transformed</a>
 | 
			
		||||
            </div>
 | 
			
		||||
  <div class="row">
 | 
			
		||||
     <div class="col-xl-12">
 | 
			
		||||
        <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_transformed_create" slug=slug %}" class="btn btn-sm btn-outline-primary">Transformed</a>
 | 
			
		||||
        </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>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,13 +11,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
    {{ title }}
 | 
			
		||||
  </h3>
 | 
			
		||||
  <div class="card-body">
 | 
			
		||||
      <p>qrcode : {{ qrcode.qr_code_number }}</p>
 | 
			
		||||
      <p>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 %}">Update</a>
 | 
			
		||||
      {% else %}
 | 
			
		||||
          <a href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">Update</a>
 | 
			
		||||
      {% endif %}
 | 
			
		||||
    <p>qrcode : {{ qrcode.qr_code_number }}</p>
 | 
			
		||||
    <p>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 %}">Update</a>
 | 
			
		||||
    {% else %}
 | 
			
		||||
      <a href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">Update</a>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    <a href="{% url "food:add_ingredient" pk=qrcode.food_container.pk %}">Add the ingrdient</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,18 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
  <div class="card-body">
 | 
			
		||||
    <p>name : {{ food.name }}</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>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								apps/food/templates/food/transformedfood_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								apps/food/templates/food/transformedfood_list.html
									
									
									
									
									
										Normal 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 %}
 | 
			
		||||
@@ -8,6 +8,7 @@ from . import views
 | 
			
		||||
app_name = 'food'
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path('', views.TransfomedListView.as_view(), name='food_list'),
 | 
			
		||||
    path('<int:slug>', views.QRCodeView.as_view(), name='qrcode_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('<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('create/basic', views.BasicFoodCreateView.as_view(), name='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'),
 | 
			
		||||
]
 | 
			
		||||
 
 | 
			
		||||
@@ -6,69 +6,62 @@ from datetime import timedelta
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import HttpResponseRedirect
 | 
			
		||||
from django_tables2.views import SingleTableView
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
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.edit import FormView
 | 
			
		||||
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 .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
 | 
			
		||||
    extra_context = {"title": _("Add a new meal")}
 | 
			
		||||
    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 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")}
 | 
			
		||||
    model = Food
 | 
			
		||||
    template_name = 'food/add_ingredient_form.html'
 | 
			
		||||
    extra_context = {"title": _("Add the ingredient")}
 | 
			
		||||
    form_class = AddIngredientForms
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context["slug"] = kwargs["slug"]
 | 
			
		||||
        context["pk"] = self.kwargs["pk"]
 | 
			
		||||
        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):
 | 
			
		||||
    """
 | 
			
		||||
    A view to add a basic food
 | 
			
		||||
    """
 | 
			
		||||
    model = Food
 | 
			
		||||
    extra_context = {"title": _("Add a new meal")}
 | 
			
		||||
    context_object_name = "food"
 | 
			
		||||
        food = Food.objects.get(pk=self.kwargs['pk'])
 | 
			
		||||
        # Save the aliment and the allergens associed
 | 
			
		||||
        for transformed_pk in self.request.POST.getlist('ingredient'):
 | 
			
		||||
            transformed = TransformedFood.objects.get(pk=transformed_pk)
 | 
			
		||||
            transformed.ingredient.add(food)
 | 
			
		||||
            transformed._force_save = True
 | 
			
		||||
            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):
 | 
			
		||||
    """
 | 
			
		||||
    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)
 | 
			
		||||
    #####################################################################
 | 
			
		||||
class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
			
		||||
    """
 | 
			
		||||
    A view to add a basic food
 | 
			
		||||
    """
 | 
			
		||||
@@ -98,16 +91,21 @@ class BasicFoodFormView(ProtectQuerysetMixin):
 | 
			
		||||
        return reverse('food:food_view', kwargs={"pk": self.object.pk})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BasicFoodUpdateView(BasicFoodFormView, LoginRequiredMixin, UpdateView):
 | 
			
		||||
    pass
 | 
			
		||||
class FoodCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView):
 | 
			
		||||
    """
 | 
			
		||||
    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):
 | 
			
		||||
    def get_sample_object(self):
 | 
			
		||||
        return BasicFood(
 | 
			
		||||
            name="",
 | 
			
		||||
            expiry_date=timezone.now(),
 | 
			
		||||
        )
 | 
			
		||||
class FoodView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
 | 
			
		||||
    """
 | 
			
		||||
    A view to see a food
 | 
			
		||||
    """
 | 
			
		||||
    model = Food
 | 
			
		||||
    extra_context = {"title": _("Details")}
 | 
			
		||||
    context_object_name = "food"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
    #####################################################################
 | 
			
		||||
    """
 | 
			
		||||
    A view to add a basic food
 | 
			
		||||
    A view to add a basic food with a qrcode
 | 
			
		||||
    """
 | 
			
		||||
    model = BasicFood
 | 
			
		||||
    form_class = BasicFoodForms
 | 
			
		||||
    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
 | 
			
		||||
    def form_valid(self, form):
 | 
			
		||||
@@ -135,6 +133,7 @@ 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._force_save = True
 | 
			
		||||
        basic_food.save()
 | 
			
		||||
        basic_food.refresh_from_db()
 | 
			
		||||
@@ -148,7 +147,7 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
			
		||||
 | 
			
		||||
    def get_success_url(self, **kwargs):
 | 
			
		||||
        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):
 | 
			
		||||
        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):
 | 
			
		||||
    #####################################################################
 | 
			
		||||
    # 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
 | 
			
		||||
    """
 | 
			
		||||
@@ -204,48 +308,16 @@ class TransformedFoodCreateView(TransformedFoodFormView, ProtectedCreateView):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QRCodeTransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
			
		||||
    #####################################################################
 | 
			
		||||
    # TO DO
 | 
			
		||||
    # - fix picture save
 | 
			
		||||
    # - implement solution crop and convert image (reuse or recode ImageForm from members apps)
 | 
			
		||||
    #####################################################################
 | 
			
		||||
class TransfomedListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
			
		||||
    """
 | 
			
		||||
    A view to add a basic food
 | 
			
		||||
    Displays all Activities, and classify if they are on-going or upcoming ones.
 | 
			
		||||
    """
 | 
			
		||||
    model = TransformedFood
 | 
			
		||||
    template_name = 'food/transformed_food_form.html'
 | 
			
		||||
    form_class = TransformedFoodForms
 | 
			
		||||
    extra_context = {"title": _("Add a new meal")}
 | 
			
		||||
    table_class = TransformedFoodTable
 | 
			
		||||
    ordering = ('-name',)
 | 
			
		||||
    extra_context = {"title": _("Transformed food")}
 | 
			
		||||
 | 
			
		||||
    @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._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(),
 | 
			
		||||
        )
 | 
			
		||||
    def get_queryset(self, **kwargs):
 | 
			
		||||
        return super().get_queryset(**kwargs)\
 | 
			
		||||
            .filter(is_ready=False)\
 | 
			
		||||
            .distinct()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user