mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 01:12:08 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			533 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			533 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
 | 
						|
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
						|
 | 
						|
from datetime import timedelta
 | 
						|
 | 
						|
from api.viewsets import is_regex
 | 
						|
from django_tables2.views import MultiTableMixin
 | 
						|
from django.db import transaction
 | 
						|
from django.db.models import Q
 | 
						|
from django.http import HttpResponseRedirect, Http404
 | 
						|
from django.views.generic import DetailView, UpdateView, CreateView
 | 
						|
from django.views.generic.list import ListView
 | 
						|
from django.views.generic.base import RedirectView
 | 
						|
from django.urls import reverse_lazy
 | 
						|
from django.utils import timezone
 | 
						|
from django.utils.translation import gettext_lazy as _
 | 
						|
from member.models import Club, Membership
 | 
						|
from permission.backends import PermissionBackend
 | 
						|
from permission.views import ProtectQuerysetMixin, ProtectedCreateView, LoginRequiredMixin
 | 
						|
 | 
						|
from .models import Food, BasicFood, TransformedFood, QRCode
 | 
						|
from .forms import QRCodeForms, BasicFoodForms, TransformedFoodForms, \
 | 
						|
    ManageIngredientsForm, ManageIngredientsFormSet, AddIngredientForms, \
 | 
						|
    BasicFoodUpdateForms, TransformedFoodUpdateForms
 | 
						|
from .tables import FoodTable
 | 
						|
from .utils import pretty_duration
 | 
						|
 | 
						|
 | 
						|
class FoodListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, ListView):
 | 
						|
    """
 | 
						|
    Display Food
 | 
						|
    """
 | 
						|
    model = Food
 | 
						|
    tables = [FoodTable, FoodTable, FoodTable, ]
 | 
						|
    extra_context = {"title": _('Food')}
 | 
						|
    template_name = 'food/food_list.html'
 | 
						|
 | 
						|
    def get_queryset(self, **kwargs):
 | 
						|
        return super().get_queryset(**kwargs).distinct()
 | 
						|
 | 
						|
    def get_tables(self):
 | 
						|
        bureau_role_pk = 4
 | 
						|
        clubs = Club.objects.filter(membership__in=Membership.objects.filter(
 | 
						|
            user=self.request.user, roles=bureau_role_pk).filter(
 | 
						|
                date_end__gte=timezone.now()))
 | 
						|
 | 
						|
        tables = [FoodTable] * (clubs.count() + 3)
 | 
						|
        self.tables = tables
 | 
						|
        tables = super().get_tables()
 | 
						|
        tables[0].prefix = 'search-'
 | 
						|
        tables[1].prefix = 'open-'
 | 
						|
        tables[2].prefix = 'served-'
 | 
						|
        for i in range(clubs.count()):
 | 
						|
            tables[i + 3].prefix = clubs[i].name
 | 
						|
        return tables
 | 
						|
 | 
						|
    def get_tables_data(self):
 | 
						|
        # table search
 | 
						|
        qs = self.get_queryset().order_by('name')
 | 
						|
        if "search" in self.request.GET and self.request.GET['search']:
 | 
						|
            pattern = self.request.GET['search']
 | 
						|
 | 
						|
            # check regex
 | 
						|
            valid_regex = is_regex(pattern)
 | 
						|
            suffix = '__iregex' if valid_regex else '__istartswith'
 | 
						|
            prefix = '^' if valid_regex else ''
 | 
						|
            qs = qs.filter(Q(**{f'name{suffix}': prefix + pattern})
 | 
						|
                           | Q(**{f'owner__name{suffix}': prefix + pattern})
 | 
						|
                           | Q(**{f'owner__note__alias__name{suffix}': prefix + pattern}))
 | 
						|
        else:
 | 
						|
            qs = qs.none()
 | 
						|
        if "stock" not in self.request.GET or not self.request.GET["stock"] == '1':
 | 
						|
            qs = qs.filter(end_of_life='')
 | 
						|
 | 
						|
        search_table = qs.filter(PermissionBackend.filter_queryset(self.request, Food, 'view'))
 | 
						|
        # table open
 | 
						|
        open_table = self.get_queryset().filter(
 | 
						|
            Q(polymorphic_ctype__model='transformedfood')
 | 
						|
            | Q(polymorphic_ctype__model='basicfood', basicfood__date_type='DLC')).filter(
 | 
						|
                expiry_date__lt=timezone.now(), end_of_life='').filter(
 | 
						|
                    PermissionBackend.filter_queryset(self.request, Food, 'view'))
 | 
						|
        open_table = open_table.union(self.get_queryset().filter(
 | 
						|
            Q(end_of_life='', order__iexact='open')
 | 
						|
        ).filter(
 | 
						|
            PermissionBackend.filter_queryset(self.request, Food, 'view'))).order_by('expiry_date')
 | 
						|
        # table served
 | 
						|
        served_table = self.get_queryset().order_by('-pk').filter(
 | 
						|
            end_of_life='', is_ready=True).exclude(
 | 
						|
                Q(polymorphic_ctype__model='basicfood',
 | 
						|
                  basicfood__date_type='DLC',
 | 
						|
                  expiry_date__lte=timezone.now(),)
 | 
						|
                | Q(polymorphic_ctype__model='transformedfood',
 | 
						|
                    expiry_date__lte=timezone.now(),
 | 
						|
                    ))
 | 
						|
        # tables club
 | 
						|
        bureau_role_pk = 4
 | 
						|
        clubs = Club.objects.filter(membership__in=Membership.objects.filter(
 | 
						|
            user=self.request.user, roles=bureau_role_pk).filter(
 | 
						|
                date_end__gte=timezone.now()))
 | 
						|
        club_table = []
 | 
						|
        for club in clubs:
 | 
						|
            club_table.append(self.get_queryset().order_by('expiry_date').filter(
 | 
						|
                owner=club, end_of_life='').filter(
 | 
						|
                    PermissionBackend.filter_queryset(self.request, Food, 'view')
 | 
						|
            ))
 | 
						|
 | 
						|
        return [search_table, open_table, served_table] + club_table
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
 | 
						|
        tables = context['tables']
 | 
						|
        # for extends base_search.html we need to name 'search_table' in 'table'
 | 
						|
        for name, table in zip(['table', 'open', 'served'], tables):
 | 
						|
            context[name] = table
 | 
						|
        context['club_tables'] = tables[3:]
 | 
						|
 | 
						|
        context['can_add_meal'] = PermissionBackend.check_perm(self.request, 'food.transformedfood_add')
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class QRCodeCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
 | 
						|
    """
 | 
						|
    A view to add qrcode
 | 
						|
    """
 | 
						|
    model = QRCode
 | 
						|
    template_name = 'food/qrcode.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:
 | 
						|
            pk = self.model.objects.get(qr_code_number=qrcode).food_container.pk
 | 
						|
            return HttpResponseRedirect(reverse_lazy("food:food_view", kwargs={"pk": pk}))
 | 
						|
        else:
 | 
						|
            return super().get(*args, **kwargs)
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        qrcode_food_form = QRCodeForms(data=self.request.POST)
 | 
						|
        if not qrcode_food_form.is_valid():
 | 
						|
            return self.form_invalid(form)
 | 
						|
 | 
						|
        qrcode = form.save(commit=False)
 | 
						|
        qrcode.qr_code_number = self.kwargs['slug']
 | 
						|
        qrcode._force_save = True
 | 
						|
        qrcode.save()
 | 
						|
        qrcode.refresh_from_db()
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context['slug'] = self.kwargs['slug']
 | 
						|
 | 
						|
        # get last 10 BasicFood objects with distincts 'name' ordered by '-pk'
 | 
						|
        # we can't use .distinct and .order_by with differents columns hence the generator
 | 
						|
        context['last_items'] = [food for food in BasicFood.get_lastests_objects(10, 'name', '-pk')]
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_success_url(self, **kwargs):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy('food:food_view', kwargs={'pk': self.object.food_container.pk})
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        return QRCode(
 | 
						|
            qr_code_number=self.kwargs['slug'],
 | 
						|
            food_container_id=1,
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class BasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    A view to add basicfood
 | 
						|
    """
 | 
						|
    model = BasicFood
 | 
						|
    form_class = BasicFoodForms
 | 
						|
    extra_context = {"title": _("Add an aliment")}
 | 
						|
    template_name = "food/food_update.html"
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        # We choose a club which may work or BDE else
 | 
						|
        food = BasicFood(
 | 
						|
            name="",
 | 
						|
            owner_id=1,
 | 
						|
            expiry_date=timezone.now(),
 | 
						|
            is_ready=True,
 | 
						|
            arrival_date=timezone.now(),
 | 
						|
            date_type='DLC',
 | 
						|
        )
 | 
						|
 | 
						|
        for membership in self.request.user.memberships.all():
 | 
						|
            club_id = membership.club.id
 | 
						|
            food.owner_id = club_id
 | 
						|
            if PermissionBackend.check_perm(self.request, "food.add_basicfood", food):
 | 
						|
                return food
 | 
						|
 | 
						|
        return food
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        if QRCode.objects.filter(qr_code_number=self.kwargs['slug']).count() > 0:
 | 
						|
            return HttpResponseRedirect(reverse_lazy('food:qrcode_create', kwargs={'slug': self.kwargs['slug']}))
 | 
						|
        food_form = BasicFoodForms(data=self.request.POST)
 | 
						|
        if not food_form.is_valid():
 | 
						|
            return self.form_invalid(form)
 | 
						|
 | 
						|
        food = form.save(commit=False)
 | 
						|
        food.is_ready = False
 | 
						|
        food.save()
 | 
						|
        food.refresh_from_db()
 | 
						|
 | 
						|
        qrcode = QRCode()
 | 
						|
        qrcode.qr_code_number = self.kwargs['slug']
 | 
						|
        qrcode.food_container = food
 | 
						|
        qrcode.save()
 | 
						|
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_success_url(self, **kwargs):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy('food:basicfood_view', kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
    def get_context_data(self, *args, **kwargs):
 | 
						|
        context = super().get_context_data(*args, **kwargs)
 | 
						|
 | 
						|
        copy = self.request.GET.get('copy', None)
 | 
						|
        if copy is not None:
 | 
						|
            food = BasicFood.objects.get(pk=copy)
 | 
						|
 | 
						|
            for field in context['form'].fields:
 | 
						|
                if field == 'allergens':
 | 
						|
                    context['form'].fields[field].initial = getattr(food, field).all()
 | 
						|
                else:
 | 
						|
                    context['form'].fields[field].initial = getattr(food, field)
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    A view to add transformedfood
 | 
						|
    """
 | 
						|
    model = TransformedFood
 | 
						|
    form_class = TransformedFoodForms
 | 
						|
    extra_context = {"title": _("Add a meal")}
 | 
						|
    template_name = "food/food_update.html"
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        # We choose a club which may work or BDE else
 | 
						|
        food = TransformedFood(
 | 
						|
            name="",
 | 
						|
            owner_id=1,
 | 
						|
            expiry_date=timezone.now(),
 | 
						|
            is_ready=True,
 | 
						|
        )
 | 
						|
 | 
						|
        for membership in self.request.user.memberships.all():
 | 
						|
            club_id = membership.club.id
 | 
						|
            food.owner_id = club_id
 | 
						|
            if PermissionBackend.check_perm(self.request, "food.add_transformedfood", food):
 | 
						|
                return food
 | 
						|
 | 
						|
        return food
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        form.instance.expiry_date = timezone.now() + timedelta(days=3)
 | 
						|
        form.instance.is_ready = False
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_success_url(self, **kwargs):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy('food:transformedfood_view', kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
MAX_FORMS = 100
 | 
						|
 | 
						|
 | 
						|
class ManageIngredientsView(LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    A view to manage ingredient for a transformed food
 | 
						|
    """
 | 
						|
    model = TransformedFood
 | 
						|
    fields = ['ingredients']
 | 
						|
    extra_context = {"title": _("Manage ingredients of:")}
 | 
						|
    template_name = 'food/manage_ingredients.html'
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        old_ingredients = list(self.object.ingredients.all()).copy()
 | 
						|
        old_allergens = list(self.object.allergens.all()).copy()
 | 
						|
        self.object.ingredients.clear()
 | 
						|
        for i in range(self.object.ingredients.all().count() + 1 + MAX_FORMS):
 | 
						|
            prefix = 'form-' + str(i) + '-'
 | 
						|
            if form.data[prefix + 'qrcode'] not in ['0', '']:
 | 
						|
                ingredient = QRCode.objects.get(pk=form.data[prefix + 'qrcode']).food_container
 | 
						|
                self.object.ingredients.add(ingredient)
 | 
						|
                if (prefix + 'fully_used') in form.data and form.data[prefix + 'fully_used'] == 'on':
 | 
						|
                    ingredient.end_of_life = _('Fully used in {meal}'.format(
 | 
						|
                        meal=self.object.name))
 | 
						|
                    ingredient.save()
 | 
						|
 | 
						|
            elif form.data[prefix + 'name'] != '':
 | 
						|
                ingredient = Food.objects.get(pk=form.data[prefix + 'name'])
 | 
						|
                self.object.ingredients.add(ingredient)
 | 
						|
                if (prefix + 'fully_used') in form.data and form.data[prefix + 'fully_used'] == 'on':
 | 
						|
                    ingredient.end_of_life = _('Fully used in {meal}'.format(
 | 
						|
                        meal=self.object.name))
 | 
						|
                    ingredient.save()
 | 
						|
        # We recalculate new expiry date and allergens
 | 
						|
        self.object.expiry_date = self.object.creation_date + self.object.shelf_life
 | 
						|
        self.object.allergens.clear()
 | 
						|
 | 
						|
        for ingredient in self.object.ingredients.iterator():
 | 
						|
            if not (ingredient.polymorphic_ctype.model == 'basicfood' and ingredient.date_type == 'DDM'):
 | 
						|
                self.object.expiry_date = min(self.object.expiry_date, ingredient.expiry_date)
 | 
						|
            self.object.allergens.set(self.object.allergens.union(ingredient.allergens.all()))
 | 
						|
 | 
						|
        self.object.save(old_ingredients=old_ingredients, old_allergens=old_allergens)
 | 
						|
        return HttpResponseRedirect(self.get_success_url())
 | 
						|
 | 
						|
    def get_context_data(self, *args, **kwargs):
 | 
						|
        context = super().get_context_data(*args, **kwargs)
 | 
						|
        context['title'] += ' ' + self.object.name
 | 
						|
        formset = ManageIngredientsFormSet()
 | 
						|
        ingredients = self.object.ingredients.all()
 | 
						|
        formset.extra += ingredients.count() + MAX_FORMS
 | 
						|
        context['form'] = ManageIngredientsForm()
 | 
						|
        context['ingredients_count'] = ingredients.count()
 | 
						|
        display = [True] * (1 + ingredients.count()) + [False] * (formset.extra - ingredients.count() - 1)
 | 
						|
        context['formset'] = zip(display, formset)
 | 
						|
        context['ingredients'] = []
 | 
						|
        for ingredient in ingredients:
 | 
						|
            qr = QRCode.objects.filter(food_container=ingredient)
 | 
						|
 | 
						|
            context['ingredients'].append({
 | 
						|
                'food_pk': ingredient.pk,
 | 
						|
                'food_name': ingredient.name,
 | 
						|
                'qr_pk': '' if qr.count() == 0 else qr[0].pk,
 | 
						|
                'qr_number': '' if qr.count() == 0 else qr[0].qr_code_number,
 | 
						|
                'fully_used': 'true' if ingredient.end_of_life else '',
 | 
						|
            })
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_success_url(self, **kwargs):
 | 
						|
        return reverse_lazy('food:transformedfood_view', kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class AddIngredientView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    A view to add ingredient to a meal
 | 
						|
    """
 | 
						|
    model = Food
 | 
						|
    extra_context = {"title": _("Add the ingredient:")}
 | 
						|
    form_class = AddIngredientForms
 | 
						|
    template_name = 'food/food_update.html'
 | 
						|
 | 
						|
    def get_context_data(self, *args, **kwargs):
 | 
						|
        context = super().get_context_data(*args, **kwargs)
 | 
						|
        context['title'] += ' ' + self.object.name
 | 
						|
        return context
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        meals = TransformedFood.objects.filter(pk__in=form.data.getlist('ingredients')).all()
 | 
						|
        if not meals:
 | 
						|
            return HttpResponseRedirect(reverse_lazy('food:food_view', kwargs={"pk": self.object.pk}))
 | 
						|
        for meal in meals:
 | 
						|
            old_ingredients = list(meal.ingredients.all()).copy()
 | 
						|
            old_allergens = list(meal.allergens.all()).copy()
 | 
						|
            meal.ingredients.add(self.object.pk)
 | 
						|
            # update allergen and expiry date if necessary
 | 
						|
            if not (self.object.polymorphic_ctype.model == 'basicfood'
 | 
						|
                    and self.object.date_type == 'DDM'):
 | 
						|
                meal.expiry_date = min(meal.expiry_date, self.object.expiry_date)
 | 
						|
            meal.allergens.set(meal.allergens.union(self.object.allergens.all()))
 | 
						|
            meal.save(old_ingredients=old_ingredients, old_allergens=old_allergens)
 | 
						|
            if 'fully_used' in form.data:
 | 
						|
                if not self.object.end_of_life:
 | 
						|
                    self.object.end_of_life = _(f'Food fully used in : {meal.name}')
 | 
						|
                else:
 | 
						|
                    self.object.end_of_life += ', ' + meal.name
 | 
						|
        if 'fully_used' in form.data:
 | 
						|
            self.object.is_ready = False
 | 
						|
        self.object.save()
 | 
						|
        # We redirect only the first parent
 | 
						|
        parent_pk = meals[0].pk
 | 
						|
        return HttpResponseRedirect(self.get_success_url(parent_pk=parent_pk))
 | 
						|
 | 
						|
    def get_success_url(self, **kwargs):
 | 
						|
        return reverse_lazy('food:transformedfood_view', kwargs={"pk": kwargs['parent_pk']})
 | 
						|
 | 
						|
 | 
						|
class FoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    A view to update Food
 | 
						|
    """
 | 
						|
    model = Food
 | 
						|
    extra_context = {"title": _("Update an aliment")}
 | 
						|
    template_name = 'food/food_update.html'
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        form.instance.creater = self.request.user
 | 
						|
        food = Food.objects.get(pk=self.kwargs['pk'])
 | 
						|
        old_allergens = list(food.allergens.all()).copy()
 | 
						|
 | 
						|
        if food.polymorphic_ctype.model == 'transformedfood':
 | 
						|
            old_ingredients = food.ingredients.all()
 | 
						|
            form.instance.shelf_life = timedelta(
 | 
						|
                seconds=int(form.data['shelf_life']) * 60 * 60)
 | 
						|
 | 
						|
        food_form = self.get_form_class()(data=self.request.POST)
 | 
						|
        if not food_form.is_valid():
 | 
						|
            return self.form_invalid(form)
 | 
						|
        ans = super().form_valid(form)
 | 
						|
        if food.polymorphic_ctype.model == 'transformedfood':
 | 
						|
            form.instance.save(old_ingredients=old_ingredients)
 | 
						|
        else:
 | 
						|
            form.instance.save(old_allergens=old_allergens)
 | 
						|
        return ans
 | 
						|
 | 
						|
    def get_form_class(self, **kwargs):
 | 
						|
        food = Food.objects.get(pk=self.kwargs['pk'])
 | 
						|
        if food.polymorphic_ctype.model == 'basicfood':
 | 
						|
            return BasicFoodUpdateForms
 | 
						|
        else:
 | 
						|
            return TransformedFoodUpdateForms
 | 
						|
 | 
						|
    def get_form(self, **kwargs):
 | 
						|
        form = super().get_form(**kwargs)
 | 
						|
        if 'shelf_life' in form.initial:
 | 
						|
            hours = form.initial['shelf_life'].days * 24 + form.initial['shelf_life'].seconds // 3600
 | 
						|
            form.initial['shelf_life'] = hours
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_success_url(self, **kwargs):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy('food:food_view', kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class FoodDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
 | 
						|
    """
 | 
						|
    A view to see a food
 | 
						|
    """
 | 
						|
    model = Food
 | 
						|
    extra_context = {"title": _('Details of:')}
 | 
						|
    context_object_name = "food"
 | 
						|
    template_name = "food/food_detail.html"
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        fields = ["name", "owner", "expiry_date", "allergens", "is_ready", "end_of_life", "order"]
 | 
						|
 | 
						|
        fields = dict([(field, getattr(self.object, field)) for field in fields])
 | 
						|
        if fields["is_ready"]:
 | 
						|
            fields["is_ready"] = _("Yes")
 | 
						|
        else:
 | 
						|
            fields["is_ready"] = _("No")
 | 
						|
        fields["allergens"] = ", ".join(
 | 
						|
            allergen.name for allergen in fields["allergens"].all())
 | 
						|
 | 
						|
        context["fields"] = [(
 | 
						|
            Food._meta.get_field(field).verbose_name.capitalize(),
 | 
						|
            value) for field, value in fields.items()]
 | 
						|
        if self.object.QR_code.exists():
 | 
						|
            context["QR_code"] = self.object.QR_code.first()
 | 
						|
        context["meals"] = self.object.transformed_ingredient_inv.all()
 | 
						|
        context["update"] = PermissionBackend.check_perm(self.request, "food.change_food")
 | 
						|
        context["add_ingredient"] = (self.object.end_of_life == '' and PermissionBackend.check_perm(self.request, "food.change_transformedfood"))
 | 
						|
        return context
 | 
						|
 | 
						|
    def get(self, *args, **kwargs):
 | 
						|
        if Food.objects.filter(pk=kwargs['pk']).count() != 1:
 | 
						|
            return Http404
 | 
						|
        model = Food.objects.get(pk=kwargs['pk']).polymorphic_ctype.model
 | 
						|
        if 'stop_redirect' in kwargs and kwargs['stop_redirect']:
 | 
						|
            return super().get(*args, **kwargs)
 | 
						|
        kwargs = {'pk': kwargs['pk']}
 | 
						|
        if model == 'basicfood':
 | 
						|
            return HttpResponseRedirect(reverse_lazy("food:basicfood_view", kwargs=kwargs))
 | 
						|
        return HttpResponseRedirect(reverse_lazy("food:transformedfood_view", kwargs=kwargs))
 | 
						|
 | 
						|
 | 
						|
class BasicFoodDetailView(FoodDetailView):
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        fields = ['arrival_date', 'date_type']
 | 
						|
        for field in fields:
 | 
						|
            context["fields"].append((
 | 
						|
                BasicFood._meta.get_field(field).verbose_name.capitalize(),
 | 
						|
                getattr(self.object, field)
 | 
						|
            ))
 | 
						|
        return context
 | 
						|
 | 
						|
    def get(self, *args, **kwargs):
 | 
						|
        if Food.objects.filter(pk=kwargs['pk']).count() == 1:
 | 
						|
            kwargs['stop_redirect'] = (Food.objects.get(pk=kwargs['pk']).polymorphic_ctype.model == 'basicfood')
 | 
						|
        return super().get(*args, **kwargs)
 | 
						|
 | 
						|
 | 
						|
class TransformedFoodDetailView(FoodDetailView):
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["fields"].append((
 | 
						|
            TransformedFood._meta.get_field("creation_date").verbose_name.capitalize(),
 | 
						|
            self.object.creation_date
 | 
						|
        ))
 | 
						|
        context["fields"].append((
 | 
						|
            TransformedFood._meta.get_field("shelf_life").verbose_name.capitalize(),
 | 
						|
            pretty_duration(self.object.shelf_life)
 | 
						|
        ))
 | 
						|
        context["foods"] = self.object.ingredients.all()
 | 
						|
        context["manage_ingredients"] = True
 | 
						|
        return context
 | 
						|
 | 
						|
    def get(self, *args, **kwargs):
 | 
						|
        if Food.objects.filter(pk=kwargs['pk']).count() == 1:
 | 
						|
            kwargs['stop_redirect'] = (Food.objects.get(pk=kwargs['pk']).polymorphic_ctype.model == 'transformedfood')
 | 
						|
        return super().get(*args, **kwargs)
 | 
						|
 | 
						|
 | 
						|
class QRCodeRedirectView(RedirectView):
 | 
						|
    """
 | 
						|
    Redirects to the QR code creation page from Food List
 | 
						|
    """
 | 
						|
    def get_redirect_url(self, *args, **kwargs):
 | 
						|
        slug = self.request.GET.get('slug')
 | 
						|
        if slug:
 | 
						|
            return reverse_lazy('food:qrcode_create', kwargs={'slug': slug})
 | 
						|
        return reverse_lazy('food:list')
 |