mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-12-18 13:32:28 +00:00
Add order interface
Signed-off-by: Emmy D'ANELLO <ynerant@crans.org>
This commit is contained in:
parent
5174c84b33
commit
45334e4e02
17
apps/note/templates/sheets/order.html
Normal file
17
apps/note/templates/sheets/order.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% comment %}
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
{% endcomment %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="card bg-light mb-3">
|
||||||
|
<h3 class="card-header text-center">
|
||||||
|
{{ title }}
|
||||||
|
</h3>
|
||||||
|
<div class="card-body">
|
||||||
|
{% crispy form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
34
apps/sheets/migrations/0002_auto_20220818_1713.py
Normal file
34
apps/sheets/migrations/0002_auto_20220818_1713.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 2.2.27 on 2022-08-18 15:13
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sheets', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='order',
|
||||||
|
name='gift',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='orderedfood',
|
||||||
|
name='gift',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='gift'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='orderedmeal',
|
||||||
|
name='gift',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='gift'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='orderedfood',
|
||||||
|
name='status',
|
||||||
|
field=models.CharField(choices=[('QUEUED', 'queued'), ('READY', 'ready'), ('SERVED', 'served'), ('CANCELED', 'canceled')], default='QUEUED', max_length=8, verbose_name='status'),
|
||||||
|
),
|
||||||
|
]
|
@ -137,7 +137,7 @@ class Meal(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return _("meal").capitalize() + " " + self.name
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("meal")
|
verbose_name = _("meal")
|
||||||
@ -162,10 +162,6 @@ class Order(models.Model):
|
|||||||
auto_now_add=True,
|
auto_now_add=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
gift = models.IntegerField(
|
|
||||||
verbose_name=_("gift"),
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("order")
|
verbose_name = _("order")
|
||||||
verbose_name_plural = _("orders")
|
verbose_name_plural = _("orders")
|
||||||
@ -184,6 +180,10 @@ class OrderedMeal(models.Model):
|
|||||||
verbose_name=_("meal"),
|
verbose_name=_("meal"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
gift = models.IntegerField(
|
||||||
|
verbose_name=_("gift"),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("ordered meal")
|
verbose_name = _("ordered meal")
|
||||||
verbose_name_plural = _("ordered meals")
|
verbose_name_plural = _("ordered meals")
|
||||||
@ -229,6 +229,10 @@ class OrderedFood(models.Model):
|
|||||||
verbose_name=_("priority request"),
|
verbose_name=_("priority request"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
gift = models.IntegerField(
|
||||||
|
verbose_name=_("gift"),
|
||||||
|
)
|
||||||
|
|
||||||
number = models.IntegerField(
|
number = models.IntegerField(
|
||||||
verbose_name=_("number"),
|
verbose_name=_("number"),
|
||||||
help_text=_("How many times the user ordered this."),
|
help_text=_("How many times the user ordered this."),
|
||||||
@ -242,6 +246,7 @@ class OrderedFood(models.Model):
|
|||||||
('SERVED', _("served")),
|
('SERVED', _("served")),
|
||||||
('CANCELED', _("canceled")),
|
('CANCELED', _("canceled")),
|
||||||
],
|
],
|
||||||
|
default='QUEUED',
|
||||||
verbose_name=_("status"),
|
verbose_name=_("status"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -268,14 +273,16 @@ class SheetOrderTransaction(Transaction):
|
|||||||
return _("note sheet")
|
return _("note sheet")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def price(self):
|
def get_price(self):
|
||||||
if self.ordered_food.meal:
|
if self.ordered_food.meal:
|
||||||
return sum(ordered_food.price + sum(opt.extra_cost for opt in ordered_food.options.all())
|
return self.ordered_food.meal.meal.price + self.ordered_food.meal.gift + sum(
|
||||||
|
sum(opt.extra_cost for opt in ordered_food.options.all())
|
||||||
for ordered_food in self.ordered_food.meal.orderedfood_set.exclude(status='CANCELED').all())
|
for ordered_food in self.ordered_food.meal.orderedfood_set.exclude(status='CANCELED').all())
|
||||||
elif self.ordered_food.status == 'CANCELED':
|
elif self.ordered_food.status == 'CANCELED':
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
return self.ordered_food.food.price + sum(opt.extra_cost for opt in self.ordered_food.options.all())
|
return self.ordered_food.food.price + self.ordered_food.gift \
|
||||||
|
+ sum(opt.extra_cost for opt in self.ordered_food.options.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("sheet order transaction")
|
verbose_name = _("sheet order transaction")
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{% extends "wei/base.html" %}
|
{% extends "base.html" %}
|
||||||
{% comment %}
|
{% comment %}
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block profile_content %}
|
{% block content %}
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<h3 class="card-header text-center">
|
<h3 class="card-header text-center">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{% extends "wei/base.html" %}
|
{% extends "base.html" %}
|
||||||
{% comment %}
|
{% comment %}
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block profile_content %}
|
{% block content %}
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<h3 class="card-header text-center">
|
<h3 class="card-header text-center">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
<a class="btn btn-success">
|
<a href="{% url 'sheets:sheet_order' pk=sheet.pk %}" class="btn btn-success">
|
||||||
{% trans "Order now" %}
|
{% trans "Order now" %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{% extends "wei/base.html" %}
|
{% extends "base.html" %}
|
||||||
{% comment %}
|
{% comment %}
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block profile_content %}
|
{% block content %}
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<h3 class="card-header text-center">
|
<h3 class="card-header text-center">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from sheets.views import FoodCreateView, FoodUpdateView, MealCreateView, MealUpdateView, \
|
from sheets.views import FoodCreateView, FoodUpdateView, MealCreateView, MealUpdateView, OrderView, \
|
||||||
SheetCreateView, SheetDetailView, SheetListView, SheetUpdateView
|
SheetCreateView, SheetDetailView, SheetListView, SheetUpdateView
|
||||||
|
|
||||||
app_name = 'sheets'
|
app_name = 'sheets'
|
||||||
@ -17,4 +17,5 @@ urlpatterns = [
|
|||||||
path('food/<int:pk>/update/', FoodUpdateView.as_view(), name="food_update"),
|
path('food/<int:pk>/update/', FoodUpdateView.as_view(), name="food_update"),
|
||||||
path('meal/create/<int:pk>/', MealCreateView.as_view(), name="meal_create"),
|
path('meal/create/<int:pk>/', MealCreateView.as_view(), name="meal_create"),
|
||||||
path('meal/<int:pk>/update/', MealUpdateView.as_view(), name="meal_update"),
|
path('meal/<int:pk>/update/', MealUpdateView.as_view(), name="meal_update"),
|
||||||
|
path('order/<int:pk>/', OrderView.as_view(), name="sheet_order"),
|
||||||
]
|
]
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from crispy_forms.bootstrap import Accordion, AccordionGroup, FormActions
|
||||||
from crispy_forms.helper import FormHelper
|
from crispy_forms.helper import FormHelper
|
||||||
|
from crispy_forms.layout import Fieldset, Submit, Row, Field
|
||||||
|
from django import forms
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.db import transaction
|
||||||
|
from django.forms import Form
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import DetailView, UpdateView
|
from django.views.generic import DetailView, UpdateView, FormView
|
||||||
from django_tables2 import SingleTableView
|
from django_tables2 import SingleTableView
|
||||||
|
|
||||||
|
from note.models import Alias, Note
|
||||||
|
from note.templatetags.pretty_money import pretty_money
|
||||||
|
from note_kfet.inputs import AmountInput, Autocomplete
|
||||||
from permission.backends import PermissionBackend
|
from permission.backends import PermissionBackend
|
||||||
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
||||||
|
|
||||||
from .forms import FoodForm, MealForm, SheetForm, FoodOptionsFormSet, FoodOptionFormSetHelper
|
from .forms import FoodForm, MealForm, SheetForm, FoodOptionsFormSet, FoodOptionFormSetHelper
|
||||||
from .models import Sheet, Food, Meal
|
from .models import Sheet, Food, Meal, Order, OrderedMeal, OrderedFood, SheetOrderTransaction
|
||||||
from .tables import SheetTable
|
from .tables import SheetTable
|
||||||
|
|
||||||
|
|
||||||
@ -45,13 +55,13 @@ class SheetCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SheetUpdateView(ProtectQuerysetMixin, UpdateView):
|
class SheetUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Sheet
|
model = Sheet
|
||||||
form_class = SheetForm
|
form_class = SheetForm
|
||||||
extra_context = {"title": _("Update note sheet")}
|
extra_context = {"title": _("Update note sheet")}
|
||||||
|
|
||||||
|
|
||||||
class SheetDetailView(ProtectQuerysetMixin, DetailView):
|
class SheetDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
model = Sheet
|
model = Sheet
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
@ -114,7 +124,7 @@ class FoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
return reverse_lazy('sheets:sheet_detail', args=(self.kwargs['pk'],))
|
return reverse_lazy('sheets:sheet_detail', args=(self.kwargs['pk'],))
|
||||||
|
|
||||||
|
|
||||||
class FoodUpdateView(ProtectQuerysetMixin, UpdateView):
|
class FoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Food
|
model = Food
|
||||||
form_class = FoodForm
|
form_class = FoodForm
|
||||||
extra_context = {"title": _("Update food")}
|
extra_context = {"title": _("Update food")}
|
||||||
@ -176,7 +186,7 @@ class MealCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
return reverse_lazy('sheets:sheet_detail', args=(self.object.sheet_id,))
|
return reverse_lazy('sheets:sheet_detail', args=(self.object.sheet_id,))
|
||||||
|
|
||||||
|
|
||||||
class MealUpdateView(ProtectQuerysetMixin, UpdateView):
|
class MealUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Meal
|
model = Meal
|
||||||
form_class = MealForm
|
form_class = MealForm
|
||||||
extra_context = {"title": _("Update meal")}
|
extra_context = {"title": _("Update meal")}
|
||||||
@ -188,3 +198,211 @@ class MealUpdateView(ProtectQuerysetMixin, UpdateView):
|
|||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse_lazy('sheets:sheet_detail', args=(self.object.sheet_id,))
|
return reverse_lazy('sheets:sheet_detail', args=(self.object.sheet_id,))
|
||||||
|
|
||||||
|
|
||||||
|
class OrderView(LoginRequiredMixin, FormView, DetailView):
|
||||||
|
model = Sheet
|
||||||
|
template_name = 'sheets/order.html'
|
||||||
|
extra_context = {'title': _("Order now")}
|
||||||
|
|
||||||
|
def get_form(self, form_class=None):
|
||||||
|
form = Form()
|
||||||
|
form.helper = FormHelper()
|
||||||
|
layout_fields = []
|
||||||
|
|
||||||
|
self.object = self.get_object()
|
||||||
|
|
||||||
|
form.fields['note'] = forms.ModelChoiceField(
|
||||||
|
queryset=Note.objects.filter(PermissionBackend.filter_queryset(self.request, Note, 'note.view_note')),
|
||||||
|
label=_("Orderer"),
|
||||||
|
initial=self.request.user.note,
|
||||||
|
widget=Autocomplete(
|
||||||
|
model=Note,
|
||||||
|
attrs={
|
||||||
|
"api_url": "/api/note/note/",
|
||||||
|
'placeholder': _("Who orders")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
layout_fields.append(Field('note', css_class='is-valid'))
|
||||||
|
|
||||||
|
for meal in self.object.meal_set.filter(available=True).all():
|
||||||
|
form.fields[f'meal_{meal.id}_quantity'] = forms.IntegerField(
|
||||||
|
label=_("Quantity"),
|
||||||
|
initial=0,
|
||||||
|
)
|
||||||
|
form.fields[f'meal_{meal.id}_gift'] = forms.IntegerField(
|
||||||
|
label=_("gift").capitalize(),
|
||||||
|
initial=0,
|
||||||
|
widget=AmountInput(),
|
||||||
|
)
|
||||||
|
form.fields[f'meal_{meal.id}_remark'] = forms.CharField(
|
||||||
|
max_length=255,
|
||||||
|
required=False,
|
||||||
|
label=_("remark").capitalize(),
|
||||||
|
help_text=_("Allergies,…"),
|
||||||
|
)
|
||||||
|
form.fields[f'meal_{meal.id}_priority'] = forms.CharField(
|
||||||
|
max_length=64,
|
||||||
|
required=False,
|
||||||
|
label=_("priority request").capitalize(),
|
||||||
|
help_text=_("Lesson at 13h30,…"),
|
||||||
|
)
|
||||||
|
|
||||||
|
ag = AccordionGroup(f"{meal} ({pretty_money(meal.price)})",
|
||||||
|
Row(Field(f'meal_{meal.id}_quantity', wrapper_class='col-sm-9'),
|
||||||
|
Field(f'meal_{meal.id}_gift', wrapper_class='col-sm-3')),
|
||||||
|
Row(Field(f'meal_{meal.id}_remark', wrapper_class='col-sm-9'),
|
||||||
|
Field(f'meal_{meal.id}_priority', wrapper_class='col-sm-3')))
|
||||||
|
|
||||||
|
for food in meal.content.filter(available=True).all():
|
||||||
|
if food.foodoption_set.count():
|
||||||
|
options_fieldset = Fieldset(_("Options for ") + str(food))
|
||||||
|
options_row = Row(css_class='ml-0')
|
||||||
|
for option in food.foodoption_set.filter(available=True).all():
|
||||||
|
form.fields[f'meal_{meal.id}_food_{food.id}_option_{option.id}'] = forms.BooleanField(
|
||||||
|
label=f"{option}{f' ({pretty_money(option.extra_cost)})' if option.extra_cost else ''}",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
options_row.fields.append(
|
||||||
|
Field(f'meal_{meal.id}_food_{food.id}_option_{option.id}', wrapper_class='col-sm-12'))
|
||||||
|
options_fieldset.fields.append(options_row)
|
||||||
|
ag.fields.append(options_fieldset)
|
||||||
|
|
||||||
|
layout_fields.append(ag)
|
||||||
|
|
||||||
|
for food in self.object.food_set.filter(available=True).all():
|
||||||
|
form.fields[f'food_{food.id}_quantity'] = forms.IntegerField(
|
||||||
|
label=_("quantity").capitalize(),
|
||||||
|
initial=0,
|
||||||
|
)
|
||||||
|
form.fields[f'food_{food.id}_gift'] = forms.IntegerField(
|
||||||
|
label=_("gift").capitalize(),
|
||||||
|
initial=0,
|
||||||
|
widget=AmountInput(),
|
||||||
|
)
|
||||||
|
form.fields[f'food_{food.id}_remark'] = forms.CharField(
|
||||||
|
max_length=255,
|
||||||
|
required=False,
|
||||||
|
label=_("remark").capitalize(),
|
||||||
|
help_text=_("Allergies,…"),
|
||||||
|
)
|
||||||
|
form.fields[f'food_{food.id}_priority'] = forms.CharField(
|
||||||
|
max_length=255,
|
||||||
|
required=False,
|
||||||
|
label=_("priority request").capitalize(),
|
||||||
|
help_text=_("Lesson at 13h30,…"),
|
||||||
|
)
|
||||||
|
|
||||||
|
ag = AccordionGroup(f"{food} ({pretty_money(food.price)})",
|
||||||
|
Row(Field(f'food_{food.id}_quantity', wrapper_class='col-sm-9'),
|
||||||
|
Field(f'food_{food.id}_gift', wrapper_class='col-sm-3')),
|
||||||
|
Row(Field(f'food_{food.id}_remark', wrapper_class='col-sm-9'),
|
||||||
|
Field(f'food_{food.id}_priority', wrapper_class='col-sm-3')))
|
||||||
|
|
||||||
|
if food.foodoption_set.count():
|
||||||
|
options_fieldset = Fieldset(_("Options"))
|
||||||
|
options_row = Row(css_class='ml-0')
|
||||||
|
for option in food.foodoption_set.all():
|
||||||
|
form.fields[f'food_{food.id}_option_{option.id}'] = forms.BooleanField(
|
||||||
|
label=f"{option}{f' ({pretty_money(option.extra_cost)})' if option.extra_cost else ''}",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
options_row.fields.append(Field(f'food_{food.id}_option_{option.id}', wrapper_class='col-sm-12'))
|
||||||
|
options_fieldset.fields.append(options_row)
|
||||||
|
ag.fields.append(options_fieldset)
|
||||||
|
|
||||||
|
layout_fields.append(ag)
|
||||||
|
|
||||||
|
layout_fields.append(FormActions(Submit('submit', _("Order now"))))
|
||||||
|
|
||||||
|
form.helper.layout = Accordion(*layout_fields)
|
||||||
|
|
||||||
|
if self.request.method in ['PUT', 'POST']:
|
||||||
|
form.data = self.request.POST
|
||||||
|
form.files = self.request.FILES
|
||||||
|
form.is_bound = not form.data or not form.files
|
||||||
|
|
||||||
|
return form
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
data = form.cleaned_data
|
||||||
|
sheet = self.get_object()
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
order = Order.objects.create(sheet_id=self.kwargs['pk'], note=data['note'])
|
||||||
|
|
||||||
|
total_quantity = 0
|
||||||
|
|
||||||
|
for meal in sheet.meal_set.filter(available=True).all():
|
||||||
|
quantity = data[f'meal_{meal.id}_quantity']
|
||||||
|
if not quantity:
|
||||||
|
continue
|
||||||
|
|
||||||
|
total_quantity += quantity
|
||||||
|
gift = data[f'meal_{meal.id}_gift']
|
||||||
|
remark = data[f'meal_{meal.id}_remark'] or ''
|
||||||
|
priority = data[f'meal_{meal.id}_priority'] or ''
|
||||||
|
ordered_meal = OrderedMeal.objects.create(order=order, meal=meal, gift=gift)
|
||||||
|
|
||||||
|
for ignored in range(quantity):
|
||||||
|
for food in meal.content.filter(available=True).all():
|
||||||
|
n = OrderedFood.objects.filter(order__sheet_id=self.kwargs['pk'],
|
||||||
|
order__note=order.note,
|
||||||
|
order__date__gte=timezone.now() - timedelta(hours=6),
|
||||||
|
food=food).exclude(status='CANCELED').count()
|
||||||
|
of = OrderedFood.objects.create(order=order, meal=ordered_meal, food=food,
|
||||||
|
remark=remark, priority=priority, number=n + 1, gift=0)
|
||||||
|
|
||||||
|
for option in food.foodoption_set.filter(available=True).all():
|
||||||
|
if data[f'meal_{meal.id}_food_{food.id}_option_{option.id}']:
|
||||||
|
of.options.add(option)
|
||||||
|
of.save()
|
||||||
|
|
||||||
|
first_food = ordered_meal.orderedfood_set.first()
|
||||||
|
tr = SheetOrderTransaction(source_id=order.note_id, destination=first_food.food.club.note,
|
||||||
|
source_alias=str(order.note), destination_alias=first_food.food.club.name,
|
||||||
|
quantity=quantity, ordered_food=first_food,
|
||||||
|
reason=f"{meal.name} - {sheet.name}")
|
||||||
|
tr.amount = tr.get_price / tr.quantity
|
||||||
|
tr.save()
|
||||||
|
|
||||||
|
for food in sheet.food_set.filter(available=True).all():
|
||||||
|
quantity = data[f'food_{food.id}_quantity']
|
||||||
|
if not quantity:
|
||||||
|
continue
|
||||||
|
|
||||||
|
total_quantity += quantity
|
||||||
|
gift = data[f'food_{meal.id}_gift']
|
||||||
|
remark = data[f'food_{meal.id}_remark'] or ''
|
||||||
|
priority = data[f'food_{meal.id}_priority'] or ''
|
||||||
|
|
||||||
|
for ignored in range(quantity):
|
||||||
|
n = OrderedFood.objects.filter(order__sheet_id=self.kwargs['pk'],
|
||||||
|
order__note=order.note,
|
||||||
|
order__date__gte=timezone.now() - timedelta(hours=6),
|
||||||
|
food=food).exclude(state='CANCELED').count()
|
||||||
|
of = OrderedFood.objects.create(order=order, food=food, gift=gift,
|
||||||
|
remark=remark, priority=priority, number=n + 1)
|
||||||
|
|
||||||
|
for option in food.foodoption_set.filter(available=True).all():
|
||||||
|
if data[f'meal_{meal.id}_food_{food.id}_option_{option.id}']:
|
||||||
|
of.options.add(option)
|
||||||
|
of.options.save()
|
||||||
|
|
||||||
|
tr = SheetOrderTransaction(source_id=order.note_id, destination_id=first_food.club.note,
|
||||||
|
source_alias=str(order.note), destination_alias=first_food.club.name,
|
||||||
|
quantity=quantity, ordered_food=of,
|
||||||
|
reason=f"{food.name} - {sheet.name}")
|
||||||
|
tr.amount = tr.get_price / tr.quantity
|
||||||
|
tr.save()
|
||||||
|
|
||||||
|
if total_quantity == 0:
|
||||||
|
form.add_error(None, _("You didn't select anything."))
|
||||||
|
transaction.rollback()
|
||||||
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse_lazy('sheets:sheet_detail', args=(self.kwargs['pk'],))
|
||||||
|
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-08-18 14:49+0200\n"
|
"POT-Creation-Date: 2022-08-18 17:20+0200\n"
|
||||||
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
|
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
|
||||||
"Last-Translator: elkmaennchen <elkmaennchen@crans.org>\n"
|
"Last-Translator: elkmaennchen <elkmaennchen@crans.org>\n"
|
||||||
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
|
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
|
||||||
@ -1476,7 +1476,7 @@ msgstr "modèles de transaction"
|
|||||||
msgid "used alias"
|
msgid "used alias"
|
||||||
msgstr "alias utilisé"
|
msgstr "alias utilisé"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:136
|
#: apps/note/models/transactions.py:136 apps/sheets/views.py:276
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr "quantité"
|
msgstr "quantité"
|
||||||
|
|
||||||
@ -2188,7 +2188,7 @@ msgid "the note sheet will be private until this field is checked."
|
|||||||
msgstr "la feuille de note restera privée tant que ce champ n'est pas coché."
|
msgstr "la feuille de note restera privée tant que ce champ n'est pas coché."
|
||||||
|
|
||||||
#: apps/sheets/models.py:41 apps/sheets/models.py:54 apps/sheets/models.py:116
|
#: apps/sheets/models.py:41 apps/sheets/models.py:54 apps/sheets/models.py:116
|
||||||
#: apps/sheets/models.py:151 apps/sheets/models.py:268
|
#: apps/sheets/models.py:151 apps/sheets/models.py:273
|
||||||
msgid "note sheet"
|
msgid "note sheet"
|
||||||
msgstr "feuille de note"
|
msgstr "feuille de note"
|
||||||
|
|
||||||
@ -2231,7 +2231,8 @@ msgstr "options de nourriture"
|
|||||||
msgid "content"
|
msgid "content"
|
||||||
msgstr "contenu"
|
msgstr "contenu"
|
||||||
|
|
||||||
#: apps/sheets/models.py:143 apps/sheets/models.py:184
|
#: apps/sheets/models.py:140 apps/sheets/models.py:143
|
||||||
|
#: apps/sheets/models.py:180
|
||||||
msgid "meal"
|
msgid "meal"
|
||||||
msgstr "menu"
|
msgstr "menu"
|
||||||
|
|
||||||
@ -2243,19 +2244,20 @@ msgstr "menus"
|
|||||||
msgid "date"
|
msgid "date"
|
||||||
msgstr "date"
|
msgstr "date"
|
||||||
|
|
||||||
#: apps/sheets/models.py:166
|
#: apps/sheets/models.py:166 apps/sheets/models.py:174
|
||||||
msgid "gift"
|
|
||||||
msgstr "don"
|
|
||||||
|
|
||||||
#: apps/sheets/models.py:170 apps/sheets/models.py:178
|
|
||||||
#: apps/sheets/models.py:196
|
#: apps/sheets/models.py:196
|
||||||
msgid "order"
|
msgid "order"
|
||||||
msgstr "commande"
|
msgstr "commande"
|
||||||
|
|
||||||
#: apps/sheets/models.py:171
|
#: apps/sheets/models.py:167
|
||||||
msgid "orders"
|
msgid "orders"
|
||||||
msgstr "commandes"
|
msgstr "commandes"
|
||||||
|
|
||||||
|
#: apps/sheets/models.py:184 apps/sheets/models.py:233 apps/sheets/views.py:235
|
||||||
|
#: apps/sheets/views.py:280
|
||||||
|
msgid "gift"
|
||||||
|
msgstr "don"
|
||||||
|
|
||||||
#: apps/sheets/models.py:188 apps/sheets/models.py:204
|
#: apps/sheets/models.py:188 apps/sheets/models.py:204
|
||||||
msgid "ordered meal"
|
msgid "ordered meal"
|
||||||
msgstr "menu commandé"
|
msgstr "menu commandé"
|
||||||
@ -2268,56 +2270,56 @@ msgstr "menus commandés"
|
|||||||
msgid "options"
|
msgid "options"
|
||||||
msgstr "options"
|
msgstr "options"
|
||||||
|
|
||||||
#: apps/sheets/models.py:222
|
#: apps/sheets/models.py:222 apps/sheets/views.py:242 apps/sheets/views.py:287
|
||||||
msgid "remark"
|
msgid "remark"
|
||||||
msgstr "remarques"
|
msgstr "remarques"
|
||||||
|
|
||||||
#: apps/sheets/models.py:229
|
#: apps/sheets/models.py:229 apps/sheets/views.py:248 apps/sheets/views.py:293
|
||||||
msgid "priority request"
|
msgid "priority request"
|
||||||
msgstr "demande de priorité"
|
msgstr "demande de priorité"
|
||||||
|
|
||||||
#: apps/sheets/models.py:233
|
#: apps/sheets/models.py:237
|
||||||
msgid "number"
|
msgid "number"
|
||||||
msgstr "numéro"
|
msgstr "numéro"
|
||||||
|
|
||||||
#: apps/sheets/models.py:234
|
#: apps/sheets/models.py:238
|
||||||
msgid "How many times the user ordered this."
|
msgid "How many times the user ordered this."
|
||||||
msgstr "Combien de fois cet⋅te utilisateur⋅rice a commandé ceci."
|
msgstr "Combien de fois cet⋅te utilisateur⋅rice a commandé ceci."
|
||||||
|
|
||||||
#: apps/sheets/models.py:240
|
#: apps/sheets/models.py:244
|
||||||
msgid "queued"
|
msgid "queued"
|
||||||
msgstr "en attente"
|
msgstr "en attente"
|
||||||
|
|
||||||
#: apps/sheets/models.py:241
|
#: apps/sheets/models.py:245
|
||||||
msgid "ready"
|
msgid "ready"
|
||||||
msgstr "prêt"
|
msgstr "prêt"
|
||||||
|
|
||||||
#: apps/sheets/models.py:242
|
#: apps/sheets/models.py:246
|
||||||
msgid "served"
|
msgid "served"
|
||||||
msgstr "servi"
|
msgstr "servi"
|
||||||
|
|
||||||
#: apps/sheets/models.py:243
|
#: apps/sheets/models.py:247
|
||||||
msgid "canceled"
|
msgid "canceled"
|
||||||
msgstr "annulé"
|
msgstr "annulé"
|
||||||
|
|
||||||
#: apps/sheets/models.py:245
|
#: apps/sheets/models.py:250
|
||||||
msgid "status"
|
msgid "status"
|
||||||
msgstr "statut"
|
msgstr "statut"
|
||||||
|
|
||||||
#: apps/sheets/models.py:251
|
#: apps/sheets/models.py:256
|
||||||
msgid "served date"
|
msgid "served date"
|
||||||
msgstr "date de service"
|
msgstr "date de service"
|
||||||
|
|
||||||
#: apps/sheets/models.py:255 apps/sheets/models.py:256
|
#: apps/sheets/models.py:260 apps/sheets/models.py:261
|
||||||
#: apps/sheets/models.py:263
|
#: apps/sheets/models.py:268
|
||||||
msgid "ordered food"
|
msgid "ordered food"
|
||||||
msgstr "nourriture commandée"
|
msgstr "nourriture commandée"
|
||||||
|
|
||||||
#: apps/sheets/models.py:281
|
#: apps/sheets/models.py:288
|
||||||
msgid "sheet order transaction"
|
msgid "sheet order transaction"
|
||||||
msgstr "transaction de commande sur feuille de note"
|
msgstr "transaction de commande sur feuille de note"
|
||||||
|
|
||||||
#: apps/sheets/models.py:282
|
#: apps/sheets/models.py:289
|
||||||
msgid "sheet order transactions"
|
msgid "sheet order transactions"
|
||||||
msgstr "transactions de commande sur feuille de note"
|
msgstr "transactions de commande sur feuille de note"
|
||||||
|
|
||||||
@ -2347,7 +2349,8 @@ msgstr "Ajouter un plat"
|
|||||||
msgid "Add new meal"
|
msgid "Add new meal"
|
||||||
msgstr "Ajouter un menu"
|
msgstr "Ajouter un menu"
|
||||||
|
|
||||||
#: apps/sheets/templates/sheets/sheet_detail.html:79
|
#: apps/sheets/templates/sheets/sheet_detail.html:79 apps/sheets/views.py:206
|
||||||
|
#: apps/sheets/views.py:317
|
||||||
msgid "Order now"
|
msgid "Order now"
|
||||||
msgstr "Commander maintenant"
|
msgstr "Commander maintenant"
|
||||||
|
|
||||||
@ -2359,34 +2362,70 @@ msgstr "Créer une feuille de note"
|
|||||||
msgid "Note sheet listing"
|
msgid "Note sheet listing"
|
||||||
msgstr "Liste des feuilles de notes"
|
msgstr "Liste des feuilles de notes"
|
||||||
|
|
||||||
#: apps/sheets/views.py:23
|
#: apps/sheets/views.py:33
|
||||||
msgid "Search note sheet"
|
msgid "Search note sheet"
|
||||||
msgstr "Chercher une feuille de note"
|
msgstr "Chercher une feuille de note"
|
||||||
|
|
||||||
#: apps/sheets/views.py:38
|
#: apps/sheets/views.py:48
|
||||||
msgid "Create note sheet"
|
msgid "Create note sheet"
|
||||||
msgstr "Créer une feuille de note"
|
msgstr "Créer une feuille de note"
|
||||||
|
|
||||||
#: apps/sheets/views.py:51
|
#: apps/sheets/views.py:61
|
||||||
msgid "Update note sheet"
|
msgid "Update note sheet"
|
||||||
msgstr "Modifier une feuille de note"
|
msgstr "Modifier une feuille de note"
|
||||||
|
|
||||||
#: apps/sheets/views.py:74
|
#: apps/sheets/views.py:84
|
||||||
msgid "Create new food"
|
msgid "Create new food"
|
||||||
msgstr "Créer un plat"
|
msgstr "Créer un plat"
|
||||||
|
|
||||||
#: apps/sheets/views.py:120
|
#: apps/sheets/views.py:130
|
||||||
msgid "Update food"
|
msgid "Update food"
|
||||||
msgstr "Modifier un plat"
|
msgstr "Modifier un plat"
|
||||||
|
|
||||||
#: apps/sheets/views.py:157
|
#: apps/sheets/views.py:167
|
||||||
msgid "Create new meal"
|
msgid "Create new meal"
|
||||||
msgstr "Créer un menu"
|
msgstr "Créer un menu"
|
||||||
|
|
||||||
#: apps/sheets/views.py:182
|
#: apps/sheets/views.py:192
|
||||||
msgid "Update meal"
|
msgid "Update meal"
|
||||||
msgstr "Modifier un menu"
|
msgstr "Modifier un menu"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:217
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "order"
|
||||||
|
msgid "Orderer"
|
||||||
|
msgstr "commande"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:223
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "orders"
|
||||||
|
msgid "Who orders"
|
||||||
|
msgstr "commandes"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:231 apps/treasury/models.py:140
|
||||||
|
msgid "Quantity"
|
||||||
|
msgstr "Quantité"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:243 apps/sheets/views.py:288
|
||||||
|
msgid "Allergies,…"
|
||||||
|
msgstr "Allergies,…"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:249 apps/sheets/views.py:294
|
||||||
|
msgid "Lesson at 13h30,…"
|
||||||
|
msgstr "Cours à 13h30,…"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:260
|
||||||
|
msgid "Options for "
|
||||||
|
msgstr "Options pour "
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:304
|
||||||
|
msgid "Options"
|
||||||
|
msgstr "Options"
|
||||||
|
|
||||||
|
#: apps/sheets/views.py:401
|
||||||
|
msgid "You didn't select anything."
|
||||||
|
msgstr "Vous n'avez rien sélectionné."
|
||||||
|
|
||||||
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:96
|
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:96
|
||||||
msgid "Treasury"
|
msgid "Treasury"
|
||||||
msgstr "Trésorerie"
|
msgstr "Trésorerie"
|
||||||
@ -2473,10 +2512,6 @@ msgstr "Facture n°{id}"
|
|||||||
msgid "Designation"
|
msgid "Designation"
|
||||||
msgstr "Désignation"
|
msgstr "Désignation"
|
||||||
|
|
||||||
#: apps/treasury/models.py:140
|
|
||||||
msgid "Quantity"
|
|
||||||
msgstr "Quantité"
|
|
||||||
|
|
||||||
#: apps/treasury/models.py:145
|
#: apps/treasury/models.py:145
|
||||||
msgid "Unit price"
|
msgid "Unit price"
|
||||||
msgstr "Prix unitaire"
|
msgstr "Prix unitaire"
|
||||||
|
Loading…
Reference in New Issue
Block a user