1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-02-23 16:41:23 +00:00

Compare commits

..

No commits in common. "a3073ba5a53c2aadb0c3725c756c633d4db50e6e" and "c8afee91d2e3f4b23af43ea26f78879fa8948c0c" have entirely different histories.

9 changed files with 33 additions and 310 deletions

View File

@ -1,10 +1,7 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib import admin
from note_kfet.admin import admin_site
from .models import QR_code, BasicFood, TransformedFood, Allergen
from .models import QR_code, Basic_food, Transformed_food, Allergen
@admin.register(QR_code, site = admin_site)
@ -13,13 +10,13 @@ class QR_codeAdmin(admin.ModelAdmin):
TEMPORARY
"""
@admin.register(BasicFood, site = admin_site)
@admin.register(Basic_food, site = admin_site)
class Basic_foodAdmin(admin.ModelAdmin):
"""
TEMPORARY
"""
@admin.register(TransformedFood, site = admin_site)
@admin.register(Transformed_food, site = admin_site)
class Transformed_foodAdmin(admin.ModelAdmin):
"""
TEMPORARY

View File

@ -1,10 +1,5 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig
class FoodkfetConfig(AppConfig):
name = 'food'
verbose_name = _('food')
name = 'foodkfet'

View File

@ -1,92 +0,0 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from random import shuffle
from django import forms
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from member.models import Club
from note_kfet.inputs import Autocomplete, DatePickerInput, DateTimePickerInput
from note_kfet.middlewares import get_current_request
from permission.backends import PermissionBackend
from .models import QR_code, Allergen, BasicFood, TransformedFood
class BasicFoodForms(forms.ModelForm):
"""
Form for add non-transformed food
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({"autofocus": "autofocus"})
self.fields['name'].required = True
self.fields['owner'].required = True
self.fields['label'].help_text = _('The lot number must be contained in the picture')
# Some example
self.fields['name'].widget.attrs.update({"placeholder": _("pasta")})
clubs = list(Club.objects.filter(PermissionBackend.filter_queryset(get_current_request(), Club, "change")).all())
shuffle(clubs)
self.fields['owner'].widget.attrs["placeholder"] = ", ".join(club.name for club in clubs[:4]) + ", ..."
def clean_dlm_or_dlc(self):
is_dlc = self.cleaned_data["is_DLC"]
is_ddm = self.cleaned_data["is_DDM"]
if is_dlc and is_ddm:
self.add_error("is_ddm", _("the product cannot be a DLC and a DDM"))
return is_ddm
class Meta:
model = BasicFood
fields = ('name', 'owner', 'is_DLC', 'is_DDM', 'expiry_date', 'label')
widgets = {
"owner": Autocomplete(
model = Club,
attrs = {"api_url": "/api/members/club/"},
),
'expiry_date': DatePickerInput(),
}
class TransformedFoodForms(forms.ModelForm):
"""
Form for add transformed food
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({"autofocus": "autofocus"})
self.fields['name'].required = True
self.fields['owner'].required = True
self.fields['creation_date'].required = True
self.fields['creation_date'].initial = timezone.now
self.fields['is_active'].initial = True
# Some example
self.fields['name'].widget.attrs.update({"placeholder": _("lasagna")})
clubs = list(Club.objects.filter(PermissionBackend.filter_queryset(get_current_request(), Club, "change")).all())
shuffle(clubs)
self.fields['owner'].widget.attrs["placeholder"] = ", ".join(club.name for club in clubs[:4]) + ", ..."
class Meta:
model = TransformedFood
fields = ('name', 'creation_date', 'owner', 'is_active',)
widgets = {
"owner": Autocomplete(
model = Club,
attrs = {"api_url": "/api/members/club/"},
),
'creation_date': DateTimePickerInput(),
}
class AllergenForms(forms.ModelForm):
"""
Form for allergen
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class Meta:
model = Allergen
exclude = ['basic_food', 'transformed_food']

View File

@ -1,4 +1,4 @@
# Generated by Django 2.2.28 on 2024-05-25 20:32
# Generated by Django 2.2.28 on 2024-05-21 12:05
from django.db import migrations, models
import django.db.models.deletion
@ -15,15 +15,14 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='BasicFood',
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')),
('arrival_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='arrival date')),
('expiry_date', models.DateTimeField(blank=True, null=True, verbose_name='expiry date')),
('label', models.ImageField(max_length=255, upload_to='label/', verbose_name='food label')),
('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')),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')),
],
@ -33,7 +32,7 @@ class Migration(migrations.Migration):
},
),
migrations.CreateModel(
name='TransformedFood',
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')),
@ -42,7 +41,7 @@ class Migration(migrations.Migration):
('is_active', models.BooleanField(default=True, verbose_name='is active')),
('was_eaten', models.BooleanField(default=False, verbose_name='was eaten')),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='owner')),
('transformed_ingredient', models.ManyToManyField(blank=True, related_name='transformed_ingredient_inv', to='food.TransformedFood', verbose_name='transformed ingredient')),
('transformed_ingredient', models.ManyToManyField(blank=True, related_name='transformed_ingredient_inv', to='food.Transformed_food', verbose_name='transformed ingredient')),
],
options={
'verbose_name': 'Transformed food',
@ -54,8 +53,8 @@ class Migration(migrations.Migration):
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')),
('basic_food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.BasicFood', verbose_name='basic food')),
('transformed_food_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.TransformedFood', verbose_name='transformed food container')),
('basic_food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.Basic_food', verbose_name='basic food')),
('transformed_food_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='QR_code', to='food.Transformed_food', verbose_name='transformed food container')),
],
options={
'verbose_name': 'QR-code',
@ -63,9 +62,9 @@ class Migration(migrations.Migration):
},
),
migrations.AddField(
model_name='basicfood',
model_name='basic_food',
name='transformed_food',
field=models.ManyToManyField(blank=True, related_name='BasicFood', to='food.TransformedFood', verbose_name='transformed food'),
field=models.ManyToManyField(blank=True, related_name='Basic_food', to='food.Transformed_food', verbose_name='transformed food'),
),
migrations.CreateModel(
name='Allergen',
@ -86,8 +85,8 @@ class Migration(migrations.Migration):
('groundnut', models.BooleanField(default=False, verbose_name='groundnut')),
('sesame', models.BooleanField(default=False, verbose_name='sesame')),
('alcohol', models.BooleanField(default=False, verbose_name='alcohol')),
('basic_food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='Allergen', to='food.BasicFood', verbose_name='basic food')),
('transformed_food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='Allergen', to='food.TransformedFood', verbose_name='transformed food')),
('basic_food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='Allergen', to='food.Basic_food', verbose_name='basic food')),
('transformed_food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='Allergen', to='food.Transformed_food', verbose_name='transformed food')),
],
options={
'verbose_name': 'Allergen',

View File

@ -7,18 +7,12 @@ 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, transaction
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
#################################################################
# TO DO
# - link allergen with one food (basic or transformed) with check
# - check on basic food
# - check on transformed food
#################################################################
class QR_code(models.Model):
"""
@ -29,7 +23,7 @@ class QR_code(models.Model):
)
transformed_food_container = models.ForeignKey(
'TransformedFood',
'Transformed_food',
on_delete = models.PROTECT,
related_name = 'QR_code',
null = True,
@ -38,7 +32,7 @@ class QR_code(models.Model):
)
basic_food = models.ForeignKey(
'BasicFood',
'Basic_food',
on_delete = models.PROTECT,
related_name = 'QR_code',
null = True,
@ -134,7 +128,7 @@ class Allergen(models.Model):
)
transformed_food = models.ForeignKey(
'TransformedFood',
'Transformed_food',
on_delete = models.CASCADE,
related_name = 'Allergen',
blank = True,
@ -143,7 +137,7 @@ class Allergen(models.Model):
)
basic_food = models.ForeignKey(
'BasicFood',
'Basic_food',
on_delete = models.CASCADE,
related_name = 'Allergen',
blank = True,
@ -156,12 +150,10 @@ class Allergen(models.Model):
verbose_name_plural = _('Allergens')
def __str__(self):
return _('Allergens of #{id}').format(id=self.id)
return _('Allergens of #{id}').format(id=self.id)
class BasicFood(models.Model):
class Basic_food(models.Model):
"""
Food which has been directly buy on supermarket
"""
@ -179,16 +171,11 @@ class BasicFood(models.Model):
verbose_name=_("is DDM"),
default=False,
)
arrival_date = models.DateTimeField(
verbose_name=_('arrival date'),
default=timezone.now,
)
expiry_date = models.DateTimeField(
verbose_name=_('expiry date'),
default=timezone.now,
blank=True,
null = True,
)
owner = models.ForeignKey(
@ -204,6 +191,7 @@ class BasicFood(models.Model):
blank=False,
null=False,
upload_to='label/',
default= 'pic/default.png',
)
was_eaten = models.BooleanField(
@ -212,8 +200,8 @@ class BasicFood(models.Model):
)
transformed_food = models.ManyToManyField(
'TransformedFood',
related_name= 'BasicFood',
'Transformed_food',
related_name= 'Basic_food',
blank = True,
verbose_name = _('transformed food'),
)
@ -226,15 +214,7 @@ class BasicFood(models.Model):
def __str__(self):
return self.name
@transaction.atomic
def save(self, force_insert=False, force_update=False, using= None, update_fields=None):
# Check if is_DLC and is DDM are not both True
if self.is_DLC and self.is_DDM:
raise ValidationError("The product cannot be a DLC and a DDM")
return super().save(force_insert, force_update, using, update_fields)
class TransformedFood(models.Model):
class Transformed_food(models.Model):
"""
Transformed food are a mix between basic food and meal
"""
@ -284,6 +264,4 @@ class TransformedFood(models.Model):
def __str__(self):
return self.name
@transaction.atomic
def save(self, force_insert=False, force_update=False, using= None, update_fields=None):
return super().save(force_insert, force_update, using, update_fields)

View File

@ -1,22 +0,0 @@
{% 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">
<form method="post">
{% csrf_token %}
{{ form|crispy }}
{{ allergenform|crispy }}
<button class="btn btn-primary" type="submit">{% trans "Submit"%}</button>
</form>
</div>
</div>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% 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">
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit">{% trans "Submit"%}</button>
</form>
</div>
</div>
{% endblock %}

View File

@ -1,19 +1,7 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path
from . import views
###############################
# TO DO
# - name url correctly, thinking about the scheme of the app
###############################
app_name = 'food'
urlpatterns = [
path('0', views.BasicFoodCreateView.as_view(), name = 'basic_food'),
path('1', views.TransformedFoodCreateView.as_view(), name = 'transformed_food'),
path('', views.index, name='index')
]

View File

@ -1,104 +1,5 @@
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import reverse_lazy
from django.db import transaction
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from datetime import timedelta
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from django.shortcuts import render
from django.http import HttpResponse
from .forms import BasicFoodForms, TransformedFoodForms, AllergenForms
from .models import BasicFood, TransformedFood, Allergen
class BasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
#####################################################################
# TO DO
# - fix picture save
# - implement solution crop and convert image (reuse or recode ImageForm from members apps
# - implement AllergenForms
# - redirect to another view after the poll is submitted
#####################################################################
"""
A view to add a basic food
"""
model = BasicFood
form_class = BasicFoodForms
template_name = 'food/basic_food_form.html'
extra_context = {"title": _("Add a new aliment")}
def get_sample_object(self):
return BasicFood(
name="",
is_DLC=False,
is_DDM=False,
expiry_date=timezone.now(),
label='pic/default.png',
)
@transaction.atomic
def form_valid(self, form):
form.instance.creater = self.request.user
basic_food_form = BasicFoodForms(data=self.request.POST)
allergen_form = AllergenForms(data=self.request.POST)
if not basic_food_form.is_valid() or not allergen_form.is_valid():
return self.form_invalid(form)
# Save the aliment and the allergens associed
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._force_save = True
basic_food.save()
basic_food.refresh_from_db()
return super().form_valid(form)
def get_success_url(self, **kwargs):
self.object.refresh_from_db()
# TEMPORARY, I create a fonctionnal view before
# return reverse_lazy('food:basicfood', kwargs={"pk": self.object.pk})
return '0'
class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
###############################################
# TO DO
# -redirect to another view after submit
###############################################
"""
A view to add a tranformed food
"""
model = TransformedFood
template_name = 'food/transformed_food_form.html'
form_class = TransformedFoodForms
extra_context = {"title": _("Add a new meal")}
def get_sample_object(self):
return TransformedFood(
name="",
creation_date=timezone.now(),
)
@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()
return super().form_valid(form)
def get_success_url(self, **kwargs):
self.object.refresh_from_db()
# TEMPORARY, I create a fonctionnal view before
# return reverse_lazy('food:tranformed_food', kwargs={"pk": self.object.pk})
return '1'
def index(request):
return HttpResponse('test')