diff --git a/README.md b/README.md index b825aa75..c8727c23 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,15 @@ # Traçabilité de la bouffe +<<<<<<< HEAD doc provisoire ici : https://pad.crans.org/p/tracabilite et ici : https://pad.crans.org/p/noteBouffe +======= +doc provisoire ici : https://pad.crans.org/p/tracabilite +et ici : https://pad.crans.org/p/noteBouffe +>>>>>>> bouffe # NoteKfet 2020 diff --git a/apps/food/__init__.py b/apps/food/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/food/admin.py b/apps/food/admin.py new file mode 100644 index 00000000..820036c3 --- /dev/null +++ b/apps/food/admin.py @@ -0,0 +1,29 @@ +from django.contrib import admin +from note_kfet.admin import admin_site + +from .models import QR_code, Basic_food, Transformed_food, Allergen + + +@admin.register(QR_code, site = admin_site) +class QR_codeAdmin(admin.ModelAdmin): + """ + TEMPORARY + """ + +@admin.register(Basic_food, site = admin_site) +class Basic_foodAdmin(admin.ModelAdmin): + """ + TEMPORARY + """ + +@admin.register(Transformed_food, site = admin_site) +class Transformed_foodAdmin(admin.ModelAdmin): + """ + TEMPORARY + """ + +@admin.register(Allergen, site = admin_site) +class AllergenAdmin(admin.ModelAdmin): + """ + TEMPORARY + """ diff --git a/apps/food/apps.py b/apps/food/apps.py new file mode 100644 index 00000000..092961b7 --- /dev/null +++ b/apps/food/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class FoodkfetConfig(AppConfig): + name = 'foodkfet' diff --git a/apps/food/migrations/0001_initial.py b/apps/food/migrations/0001_initial.py new file mode 100644 index 00000000..46899dd6 --- /dev/null +++ b/apps/food/migrations/0001_initial.py @@ -0,0 +1,96 @@ +# Generated by Django 2.2.28 on 2024-05-17 18:44 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('member', '0011_profile_vss_charter_read'), + ] + + operations = [ + migrations.CreateModel( + name='Allergen', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('gluten', models.BooleanField(default=False, verbose_name='gluten')), + ('nut', models.BooleanField(default=False, verbose_name='nut')), + ('crustecean', models.BooleanField(default=False, verbose_name='crustacean')), + ('celery', models.BooleanField(default=False, verbose_name='celery')), + ('egg', models.BooleanField(default=False, verbose_name='egg')), + ('mustard', models.BooleanField(default=False, verbose_name='mustard')), + ('fish', models.BooleanField(default=False, verbose_name='fish')), + ('soy', models.BooleanField(default=False, verbose_name='soy')), + ('milk', models.BooleanField(default=False, verbose_name='milk')), + ('sulphite', models.BooleanField(default=False, verbose_name='sulphite')), + ('lupine', models.BooleanField(default=False, verbose_name='lupine')), + ('mollusc', models.BooleanField(default=False, verbose_name='mollusc')), + ('groundnut', models.BooleanField(default=False, verbose_name='groundnut')), + ('sesame', models.BooleanField(default=False, verbose_name='sesame')), + ('alcohol', models.BooleanField(default=False, verbose_name='alcohol')), + ], + options={ + 'verbose_name': 'Allergen', + 'verbose_name_plural': 'Allergens', + }, + ), + migrations.CreateModel( + name='Basic_food', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='name')), + ('is_DLC', models.BooleanField(default=False, verbose_name='is DLC')), + ('is_DDM', models.BooleanField(default=False, verbose_name='is DDM')), + ('expiry_date', models.DateTimeField(blank=True, default=django.utils.timezone.now, verbose_name='expiry date')), + ('label', models.ImageField(default='pic/default.png', max_length=255, upload_to='label/', verbose_name='food label')), + ('was_eaten', models.BooleanField(default=False, verbose_name='was eaten')), + ('allergen', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='food.Allergen', verbose_name='allergen')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')), + ], + options={ + 'verbose_name': 'Basic food', + 'verbose_name_plural': 'Basic foods', + }, + ), + migrations.CreateModel( + name='QR_code', + 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')), + ], + options={ + 'verbose_name': 'QR-code', + 'verbose_name_plural': 'QR-codes', + }, + ), + migrations.CreateModel( + name='Transformed_food', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='name')), + ('creation_date', models.DateTimeField(verbose_name='creation date')), + ('expiry_date', models.DateTimeField(verbose_name='expiry date')), + ('is_active', models.BooleanField(default=True, verbose_name='is active')), + ('was_eaten', models.BooleanField(default=False, verbose_name='was eaten')), + ('allergen', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='food.Allergen', verbose_name='allergen')), + ('basic_ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='food.Basic_food', verbose_name='basic ingredient')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')), + ('qr_code', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='food.QR_code', verbose_name='QR code')), + ('transformed_ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='food.Transformed_food', verbose_name='transformed ingredient')), + ], + options={ + 'verbose_name': 'Transformed food', + 'verbose_name_plural': 'Transformed foods', + }, + ), + migrations.AddField( + model_name='basic_food', + name='qr_code', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='food.QR_code', verbose_name='QR code'), + ), + ] diff --git a/apps/food/migrations/0002_auto_20240521_1103.py b/apps/food/migrations/0002_auto_20240521_1103.py new file mode 100644 index 00000000..6bdb8677 --- /dev/null +++ b/apps/food/migrations/0002_auto_20240521_1103.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.28 on 2024-05-21 09:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('food', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='transformed_food', + name='transformed_ingredient', + field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='food.Transformed_food', verbose_name='transformed ingredient'), + ), + ] diff --git a/apps/food/migrations/0003_auto_20240521_1110.py b/apps/food/migrations/0003_auto_20240521_1110.py new file mode 100644 index 00000000..9f92f534 --- /dev/null +++ b/apps/food/migrations/0003_auto_20240521_1110.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.28 on 2024-05-21 09:10 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('food', '0002_auto_20240521_1103'), + ] + + operations = [ + migrations.AlterField( + model_name='transformed_food', + name='transformed_ingredient', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='food.Transformed_food', verbose_name='transformed ingredient'), + ), + ] diff --git a/apps/food/migrations/__init__.py b/apps/food/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/food/models.py b/apps/food/models.py new file mode 100644 index 00000000..5347abc5 --- /dev/null +++ b/apps/food/models.py @@ -0,0 +1,259 @@ +# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from datetime import date + +from django.conf import settings +from django.contrib.auth.models import User +from django.core.exceptions import ValidationError +from django.core.validators import MinValueValidator +from django.db import models +from django.db.models import Q +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from member.models import Club + + +class QR_code(models.Model): + """ + An QR_code model + """ + qr_code_number = models.PositiveIntegerField( + verbose_name=_("QR-code number"), + ) + + class Meta: + verbose_name = _("QR-code") + verbose_name_plural = _("QR-codes") + + def __str__(self): + return _("QR-code number {qr_code_number}").format(qr_code_number=self.qr_code_number) + +class Allergen(models.Model): + """ + A list of allergen and alimentary restrictions + """ + + gluten = models.BooleanField( + default = False, + verbose_name = _('gluten'), + ) + + nut = models.BooleanField( + default = False, + verbose_name = _('nut'), + ) + + crustecean = models.BooleanField( + default = False, + verbose_name = _('crustacean'), + ) + + celery = models.BooleanField( + default = False, + verbose_name = _('celery'), + ) + + egg = models.BooleanField( + default = False, + verbose_name = _('egg'), + ) + + mustard = models.BooleanField( + default = False, + verbose_name = _('mustard'), + ) + + fish = models.BooleanField( + default = False, + verbose_name = _('fish'), + ) + + soy = models.BooleanField( + default = False, + verbose_name = _('soy'), + ) + + milk = models.BooleanField( + default = False, + verbose_name = _('milk'), + ) + + sulphite = models.BooleanField( + default = False, + verbose_name = _('sulphite'), + ) + + lupine = models.BooleanField( + default = False, + verbose_name = _('lupine'), + ) + + mollusc = models.BooleanField( + default = False, + verbose_name = _('mollusc'), + ) + + groundnut = models.BooleanField( + default = False, + verbose_name = _('groundnut'), + ) + + sesame = models.BooleanField( + default = False, + verbose_name = _('sesame'), + ) + + alcohol = models.BooleanField( + default = False, + verbose_name = _('alcohol'), + ) + + class Meta: + verbose_name = _('Allergen') + verbose_name_plural = _('Allergens') + + def __str__(self): + return _('Allergens of #{id}').format(id=self.id) + + +class Basic_food(models.Model): + """ + Food which has been directly buy on supermarket + """ + name = models.CharField( + verbose_name=_('name'), + max_length=255, + ) + + is_DLC = models.BooleanField( + verbose_name=_("is DLC"), + default=False, + ) + + is_DDM = models.BooleanField( + verbose_name=_("is DDM"), + default=False, + ) + + expiry_date = models.DateTimeField( + verbose_name=_('expiry date'), + default=timezone.now, + blank=True, + ) + + owner = models.ForeignKey( + Club, + on_delete=models.PROTECT, + related_name= '+', + verbose_name=_('owner'), + ) + + label = models.ImageField( + verbose_name=_('food label'), + max_length=255, + blank=False, + null=False, + upload_to='label/', + default= 'pic/default.png', + ) + + qr_code = models.ForeignKey( + QR_code, + on_delete=models.PROTECT, + related_name= '+', + verbose_name=_('QR code'), + ) + + was_eaten = models.BooleanField( + verbose_name=_('was eaten'), + default = False, + ) + + allergen = models.ForeignKey( + Allergen, + on_delete = models.PROTECT, + related_name = '+', + verbose_name = _('allergen'), + ) + + class Meta: + verbose_name=_('Basic food') + verbose_name_plural=_('Basic foods') + + def __str__(self): + return self.name + +class Transformed_food(models.Model): + """ + Transformed food are a mix between basic food and meal + """ + name = models.CharField( + max_length = 255, + verbose_name =_('name'), + ) + + creation_date = models.DateTimeField( + verbose_name =_('creation date'), + ) + + expiry_date = models.DateTimeField( + verbose_name =_('expiry date'), + ) + + owner = models.ForeignKey( + Club, + on_delete = models.PROTECT, + related_name = '+', + verbose_name =_('owner'), + ) + + transformed_ingredient = models.ForeignKey( + "self", + on_delete = models.CASCADE, + blank = True, + null = True, + related_name = '+', + verbose_name = _('transformed ingredient'), + ) + + basic_ingredient = models.ForeignKey( + Basic_food, + on_delete = models.CASCADE, + related_name = '+', + verbose_name = _('basic ingredient'), + ) + + + is_active = models.BooleanField( + default = True, + verbose_name = _('is active'), + ) + + qr_code = models.ForeignKey( + QR_code, + on_delete = models.CASCADE, + related_name = '+', + verbose_name = _('QR code'), + ) + + was_eaten = models.BooleanField( + default = False, + verbose_name = _('was eaten'), + ) + + allergen = models.ForeignKey( + Allergen, + on_delete = models.PROTECT, + related_name= '+', + verbose_name = _('allergen'), + ) + + class Meta: + verbose_name = _('Transformed food') + verbose_name_plural = _('Transformed foods') + + def __str__(self): + return self.name + + diff --git a/apps/food/tests.py b/apps/food/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/apps/food/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/food/urls.py b/apps/food/urls.py new file mode 100644 index 00000000..2fcca0db --- /dev/null +++ b/apps/food/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.index, name='index') +] diff --git a/apps/food/views.py b/apps/food/views.py new file mode 100644 index 00000000..c4cfa086 --- /dev/null +++ b/apps/food/views.py @@ -0,0 +1,5 @@ +from django.shortcuts import render +from django.http import HttpResponse + +def index(request): + return HttpResponse('test') diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 74fed818..93ae0afd 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -77,6 +77,7 @@ INSTALLED_APPS = [ 'scripts', 'treasury', 'wei', + 'food', ] MIDDLEWARE = [ diff --git a/note_kfet/urls.py b/note_kfet/urls.py index d222c239..01bec0ba 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ path('activity/', include('activity.urls')), path('treasury/', include('treasury.urls')), path('wei/', include('wei.urls')), + path('food/',include('food.urls')), # Include Django Contrib and Core routers path('i18n/', include('django.conf.urls.i18n')),