diff --git a/apps/note/templates/sheets/waiting_list.html b/apps/note/templates/sheets/waiting_list.html new file mode 100644 index 0000000000000000000000000000000000000000..e0883c0e1387ba9a0d57d26faa9ecb1daec18ade --- /dev/null +++ b/apps/note/templates/sheets/waiting_list.html @@ -0,0 +1,88 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +<div class="card"> +<div class="card-header text-center"> + <h1>{{ food.name }}</h1> +</div> +<div class="card-body"> + <div class="row"> + <div class="card col-xl-6"> + <div class="card-header text-center"> + <h2>{% trans "queued"|capfirst %}{% if queue %} ({{ queue|length }}){% endif %}</h2> + </div> + <div class="card-body"> + <ul> + {% for ordered_food in queue %} + <li> + {{ ordered_food.order.note }} + {% if ordered_food.priority %} + <span class="badge badge-secondary">{{ ordered_food.priority }}</span> + {% endif %} + </li> + {% empty %} + <div class="alert alert-warning"> + {% trans "There is no queued order." %} + </div> + {% endfor %} + </ul> + </div> + </div> + <div class="card col-xl-6"> + <div class="card-header text-center"> + <h2>{% trans "ready"|capfirst %}</h2> + </div> + <div class="card-body"> + <ul> + {% for ordered_food in ready %} + <li>{{ ordered_food.order.note }}</li> + {% empty %} + <div class="alert alert-warning"> + {% trans "There is no ready order." %} + </div> + {% endfor %} + </ul> + </div> + </div> + </div> + + <hr> + + <h3>{% trans "Other waiting lists:" %}</h3> + <ul> + {% for other_food in food.sheet.food_set.all %} + {% if other_food != food %} + <li> + <a href="{% url 'sheets:waiting_list' pk=other_food.pk %}">{{ other_food }}</a> + </li> + {% endif %} + {% endfor %} + </ul> +</div> +<div class="card-footer text-center"> + <a href="{% url 'sheets:queued_list' pk=food.pk %}" class="btn btn-primary"> + {% trans "Queued orders" %} + </a> + <a href="{% url 'sheets:ready_list' pk=food.pk %}" class="btn btn-primary"> + {% trans "Ready orders" %} + </a> + <a href="{% url 'sheets:sheet_detail' pk=food.sheet_id %}" class="btn btn-secondary"> + {% trans "Back to note sheet detail" %} + </a> +</div> +</div> +{% endblock %} + +{% block extrajavascript %} + <script> + function reload() { + reloadWithTurbolinks() + timeout = setTimeout(reload, 15000) + } + + if (timeout === undefined) + var timeout = setTimeout(reload, 15000) + </script> +{% endblock %} diff --git a/apps/note/templates/sheets/waiting_list_detail.html b/apps/note/templates/sheets/waiting_list_detail.html new file mode 100644 index 0000000000000000000000000000000000000000..2e80239d067a948835dd185eeac7aba243b75946 --- /dev/null +++ b/apps/note/templates/sheets/waiting_list_detail.html @@ -0,0 +1,152 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +<div class="card"> +<div class="card-header text-center"> + <h1>{{ title }}</h1> +</div> +<div class="card-body"> + {% for of in orders %} + <div class="card mb-4"> + <div class="card-header text-center"> + <h3>{{ of.order.note }}</h3> + </div> + <div class="card-body"> + <dl class="row"> + <dt class="col-xl-3">{% trans 'date'|capfirst %}</dt> + <dd class="col-xl-9">{{ of.order.date }}</dd> + + {% if of.number > 1 %} + <dt class="col-xl-3">{% trans 'order number'|capfirst %}</dt> + <dd class="col-xl-9">{{ of.number }}</dd> + {% endif %} + + {% if of.priority %} + <dt class="col-xl-3">{% trans 'priority request'|capfirst %}</dt> + <dd class="col-xl-9">{{ of.priority }}</dd> + {% endif %} + + {% if of.remark %} + <dt class="col-xl-3">{% trans 'remark'|capfirst %}</dt> + <dd class="col-xl-9">{{ of.remark }}</dd> + {% endif %} + + {% if of.options.count %} + <dt class="col-xl-3">{% trans 'options'|capfirst %}</dt> + <dd class="col-xl-9">{{ of.options.all|join:', ' }}</dd> + {% endif %} + </dl> + </div> + <div class="card-footer text-center"> + {% if list_type != 'READY' %} + <a href="#" class="btn btn-success" onclick="setOrderStatus({{ of.pk }}, 'READY')"> + {% trans "Mark as ready" %} + </a> + {% endif %} + {% if list_type != 'SERVED' %} + <a href="#" class="btn btn-primary" onclick="setOrderStatus({{ of.pk }}, 'SERVED')"> + {% trans "Mark as served" %} + </a> + {% endif %} + {% if list_type != 'QUEUED' %} + <a href="#" class="btn btn-warning" onclick="setOrderStatus({{ of.pk }}, 'QUEUED')"> + {% trans "Re-queue" %} + </a> + {% endif %} + {% if list_type != 'CANCELED' %} + <a href="#" class="btn btn-danger" onclick="setOrderStatus({{ of.pk }}, 'CANCELED')"> + {% trans "Cancel" %} + </a> + {% endif %} + </div> + </div> + {% empty %} + <div class="alert alert-warning"> + {% trans "There is no queued order." %} + </div> + {% endfor %} +</div> +</div> + +<div class="card mt-5"> +<div class="card-body"> + <h3>{% trans "Other waiting lists:" %}</h3> + <ul> + {% for other_food in food.sheet.food_set.all %} + {% if other_food != food %} + <li> + {% if list_type == 'QUEUED' %} + <a href="{% url 'sheets:queued_list' pk=other_food.pk %}">{{ other_food }}</a> + {% else %} + <a href="{% url 'sheets:ready_list' pk=other_food.pk %}">{{ other_food }}</a> + {% endif %} + </li> + {% endif %} + {% endfor %} + </ul> +</div> +<div class="card-footer text-center"> + {% if list_type != 'QUEUED' %} + <a href="{% url 'sheets:queued_list' pk=food.pk %}" class="btn btn-primary"> + {% trans "Queued orders" %} + </a> + {% endif %} + {% if list_type != 'READY' %} + <a href="{% url 'sheets:ready_list' pk=food.pk %}" class="btn btn-success"> + {% trans "Ready orders" %} + </a> + {% endif %} + {% if list_type != 'SERVED' %} + <a href="{% url 'sheets:served_list' pk=food.pk %}" class="btn btn-secondary"> + {% trans "Served orders" %} + </a> + {% endif %} + {% if list_type != 'CANCELED' %} + <a href="{% url 'sheets:canceled_list' pk=food.pk %}" class="btn btn-danger"> + {% trans "Canceled orders" %} + </a> + {% endif %} + <a href="{% url 'sheets:waiting_list' pk=food.pk %}" class="btn btn-primary"> + {% trans "Waiting list" %} + </a> + <a href="{% url 'sheets:sheet_detail' pk=food.sheet_id %}" class="btn btn-secondary"> + {% trans "Back to note sheet detail" %} + </a> +</div> +</div> +{% endblock %} + +{% block extrajavascript %} + <script> + function reload() { + reloadWithTurbolinks() + timeout = setTimeout(reload, 15000) + } + + if (timeout === undefined) + var timeout = setTimeout(reload, 15000) + + function setOrderStatus(ordered_food_id, status) { + fetch('/api/sheets/orderedfood/' + ordered_food_id + '/', { + method: 'PATCH', + body: JSON.stringify({ + status: status, + served_date: status === 'QUEUED' ? null : new Date().toISOString(), + }), + headers: { + 'Content-Type': "application/json; charset=UTF-8", + 'X-CSRFTOKEN': "{{ csrf_token }}" + } + }).then(response => response.json()).then(response => { + if ('detail' in response) + addMsg("{% trans "An error occurred" %}" + " : " + response['detail'], "danger") + else { + clearTimeout(timeout) + reload() + } + }) + } + </script> +{% endblock %} diff --git a/apps/sheets/templates/sheets/sheet_detail.html b/apps/sheets/templates/sheets/sheet_detail.html index 046799588282c22cb05abc97f72751c97c56ecfe..f33d0c71140a92065beb95b2f303a97ffbe777d0 100644 --- a/apps/sheets/templates/sheets/sheet_detail.html +++ b/apps/sheets/templates/sheets/sheet_detail.html @@ -42,6 +42,10 @@ {% for food in sheet.food_set.all %} <li{% if not food.available %} class="text-danger" style="text-decoration: line-through !important;" title="{% trans "This product is unavailable." %}"{% endif %}> {{ food }} ({{ food.price|pretty_money }}) + <a href="{% url 'sheets:waiting_list' pk=food.pk %}" class="badge badge-primary"> + <i class="fa fa-list"></i> + {% trans "Waiting list" %} + </a> {% if can_change_sheet %} <a href="{% url 'sheets:food_update' pk=food.pk %}" class="badge badge-primary"> <i class="fa fa-edit"></i> diff --git a/apps/sheets/urls.py b/apps/sheets/urls.py index 0449f93d9d132cc8f912db2cb3f062c125d7a867..e7889ad2da120ae0c8883dc48162eac10942441b 100644 --- a/apps/sheets/urls.py +++ b/apps/sheets/urls.py @@ -4,7 +4,7 @@ from django.urls import path from sheets.views import FoodCreateView, FoodUpdateView, MealCreateView, MealUpdateView, OrderView, \ - SheetCreateView, SheetDetailView, SheetListView, SheetUpdateView + SheetCreateView, SheetDetailView, SheetListView, SheetUpdateView, WaitingListDetailView, WaitingListView app_name = 'sheets' @@ -18,4 +18,9 @@ urlpatterns = [ path('meal/create/<int:pk>/', MealCreateView.as_view(), name="meal_create"), path('meal/<int:pk>/update/', MealUpdateView.as_view(), name="meal_update"), path('order/<int:pk>/', OrderView.as_view(), name="sheet_order"), + path('waiting-list/<int:pk>/', WaitingListView.as_view(), name="waiting_list"), + path('waiting-list/<int:pk>/queued/', WaitingListDetailView.as_view(), name="queued_list"), + path('waiting-list/<int:pk>/ready/', WaitingListDetailView.as_view(), name="ready_list"), + path('waiting-list/<int:pk>/served/', WaitingListDetailView.as_view(), name="served_list"), + path('waiting-list/<int:pk>/canceled/', WaitingListDetailView.as_view(), name="canceled_list"), ] diff --git a/apps/sheets/views.py b/apps/sheets/views.py index d7a461f3fc0a27221015fef899074f01ae0bf1c4..d91b4d44fb9a7baabd1d5b1c2e5d20a81d0c2d9f 100644 --- a/apps/sheets/views.py +++ b/apps/sheets/views.py @@ -235,6 +235,7 @@ class OrderView(LoginRequiredMixin, FormView, DetailView): label=_("gift").capitalize(), initial=0, widget=AmountInput(), + help_text=_("Be careful: this gift will be multiplied for each order."), ) form.fields[f'meal_{meal.id}_remark'] = forms.CharField( max_length=255, @@ -280,6 +281,7 @@ class OrderView(LoginRequiredMixin, FormView, DetailView): label=_("gift").capitalize(), initial=0, widget=AmountInput(), + help_text=_("Be careful: this gift will be multiplied for each order."), ) form.fields[f'food_{food.id}_remark'] = forms.CharField( max_length=255, @@ -406,3 +408,37 @@ class OrderView(LoginRequiredMixin, FormView, DetailView): def get_success_url(self): return reverse_lazy('sheets:sheet_detail', args=(self.kwargs['pk'],)) + + +class WaitingListView(ProtectQuerysetMixin, DetailView): + model = Food + template_name = 'sheets/waiting_list.html' + extra_context = {'title': _("Waiting list")} + + def get_context_data(self, **kwargs): + content = super().get_context_data(**kwargs) + + content['queue'] = OrderedFood.objects.filter(food_id=self.kwargs['pk'], status='QUEUED')\ + .order_by('-priority', 'number', 'order__date').all() + content['ready'] = OrderedFood.objects.filter(food_id=self.kwargs['pk'], status='READY')\ + .order_by('served_date').all() + + return content + + +class WaitingListDetailView(ProtectQuerysetMixin, DetailView): + model = Food + template_name = 'sheets/waiting_list_detail.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + list_type = 'CANCELED' if 'canceled' in self.request.path else \ + 'SERVED' if 'served' in self.request.path else \ + 'READY' if 'ready' in self.request.path else 'QUEUED' + context['list_type'] = list_type + context['orders'] = OrderedFood.objects.filter(food_id=self.kwargs['pk'], status=list_type)\ + .order_by('served_date', '-priority', 'number', 'order__date').all() + context['title'] = self.object.name + " - " + _(list_type.lower()).capitalize() + + return context diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 0fbaf922ece104918a7e0caca0a56118882adb53..d58f83beef6a3a543070c138ad99eede4c869840 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-18 17:20+0200\n" +"POT-Creation-Date: 2022-08-18 22:51+0200\n" "PO-Revision-Date: 2022-04-11 22:05+0200\n" "Last-Translator: elkmaennchen <elkmaennchen@crans.org>\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" msgstr "alias utilisé" -#: apps/note/models/transactions.py:136 apps/sheets/views.py:276 +#: apps/note/models/transactions.py:136 apps/sheets/views.py:277 msgid "quantity" msgstr "quantité" @@ -1600,7 +1600,7 @@ msgstr "Supprimer" #: apps/note/tables.py:222 apps/note/templates/note/conso_form.html:132 #: apps/sheets/templates/sheets/sheet_detail.html:21 #: apps/sheets/templates/sheets/sheet_detail.html:36 -#: apps/sheets/templates/sheets/sheet_detail.html:48 apps/wei/tables.py:49 +#: apps/sheets/templates/sheets/sheet_detail.html:52 apps/wei/tables.py:49 #: apps/wei/tables.py:50 apps/wei/templates/wei/base.html:89 #: apps/wei/templates/wei/bus_detail.html:20 #: apps/wei/templates/wei/busteam_detail.html:20 @@ -1754,6 +1754,98 @@ msgstr "Bouton affiché" msgid "An error occured" msgstr "Une erreur s'est produite" +#: apps/note/templates/sheets/waiting_list.html:14 apps/sheets/models.py:244 +msgid "queued" +msgstr "en attente" + +#: apps/note/templates/sheets/waiting_list.html:27 +#: apps/note/templates/sheets/waiting_list_detail.html:67 +msgid "There is no queued order." +msgstr "Il n'y a pas de commande en attente." + +#: apps/note/templates/sheets/waiting_list.html:35 apps/sheets/models.py:245 +msgid "ready" +msgstr "prêt" + +#: apps/note/templates/sheets/waiting_list.html:43 +msgid "There is no ready order." +msgstr "Il n'y a pas de commande prête." + +#: apps/note/templates/sheets/waiting_list.html:53 +#: apps/note/templates/sheets/waiting_list_detail.html:75 +msgid "Other waiting lists:" +msgstr "Autres listes d'attente :" + +#: apps/note/templates/sheets/waiting_list.html:66 +#: apps/note/templates/sheets/waiting_list_detail.html:93 +msgid "Queued orders" +msgstr "Commandes en attente" + +#: apps/note/templates/sheets/waiting_list.html:69 +#: apps/note/templates/sheets/waiting_list_detail.html:98 +msgid "Ready orders" +msgstr "Commandes prêtes" + +#: apps/note/templates/sheets/waiting_list.html:72 +#: apps/note/templates/sheets/waiting_list_detail.html:115 +msgid "Back to note sheet detail" +msgstr "Retour aux détails de la feuille de note" + +#: apps/note/templates/sheets/waiting_list_detail.html:18 +#: apps/sheets/models.py:161 +msgid "date" +msgstr "date" + +#: apps/note/templates/sheets/waiting_list_detail.html:22 +msgid "order number" +msgstr "nombre de commandes" + +#: apps/note/templates/sheets/waiting_list_detail.html:27 +#: apps/sheets/models.py:229 apps/sheets/views.py:249 apps/sheets/views.py:295 +msgid "priority request" +msgstr "demande de priorité" + +#: apps/note/templates/sheets/waiting_list_detail.html:32 +#: apps/sheets/models.py:222 apps/sheets/views.py:243 apps/sheets/views.py:289 +msgid "remark" +msgstr "remarques" + +#: apps/note/templates/sheets/waiting_list_detail.html:37 +#: apps/sheets/models.py:216 +msgid "options" +msgstr "options" + +#: apps/note/templates/sheets/waiting_list_detail.html:45 +msgid "Mark as ready" +msgstr "Marquer comme prêt" + +#: apps/note/templates/sheets/waiting_list_detail.html:50 +msgid "Mark as served" +msgstr "Marquer comme servi" + +#: apps/note/templates/sheets/waiting_list_detail.html:55 +msgid "Re-queue" +msgstr "Remettre en attente" + +#: apps/note/templates/sheets/waiting_list_detail.html:60 +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 +#: note_kfet/templates/oauth2_provider/authorize.html:28 +msgid "Cancel" +msgstr "Annuler" + +#: apps/note/templates/sheets/waiting_list_detail.html:103 +msgid "Served orders" +msgstr "Commandes servies" + +#: apps/note/templates/sheets/waiting_list_detail.html:108 +msgid "Canceled orders" +msgstr "Commandes annulées" + +#: apps/note/templates/sheets/waiting_list_detail.html:112 +#: apps/sheets/templates/sheets/sheet_detail.html:47 apps/sheets/views.py:416 +msgid "Waiting list" +msgstr "Liste d'attente" + #: apps/note/views.py:36 msgid "Transfer money" msgstr "Transférer de l'argent" @@ -2240,10 +2332,6 @@ msgstr "menu" msgid "meals" msgstr "menus" -#: apps/sheets/models.py:161 -msgid "date" -msgstr "date" - #: apps/sheets/models.py:166 apps/sheets/models.py:174 #: apps/sheets/models.py:196 msgid "order" @@ -2254,7 +2342,7 @@ msgid "orders" msgstr "commandes" #: apps/sheets/models.py:184 apps/sheets/models.py:233 apps/sheets/views.py:235 -#: apps/sheets/views.py:280 +#: apps/sheets/views.py:281 msgid "gift" msgstr "don" @@ -2266,18 +2354,6 @@ msgstr "menu commandé" msgid "ordered meals" msgstr "menus commandés" -#: apps/sheets/models.py:216 -msgid "options" -msgstr "options" - -#: apps/sheets/models.py:222 apps/sheets/views.py:242 apps/sheets/views.py:287 -msgid "remark" -msgstr "remarques" - -#: apps/sheets/models.py:229 apps/sheets/views.py:248 apps/sheets/views.py:293 -msgid "priority request" -msgstr "demande de priorité" - #: apps/sheets/models.py:237 msgid "number" msgstr "numéro" @@ -2286,14 +2362,6 @@ msgstr "numéro" msgid "How many times the user ordered this." msgstr "Combien de fois cet⋅te utilisateur⋅rice a commandé ceci." -#: apps/sheets/models.py:244 -msgid "queued" -msgstr "en attente" - -#: apps/sheets/models.py:245 -msgid "ready" -msgstr "prêt" - #: apps/sheets/models.py:246 msgid "served" msgstr "servi" @@ -2333,24 +2401,24 @@ msgstr "menu" #: apps/sheets/templates/sheets/sheet_detail.html:31 #: apps/sheets/templates/sheets/sheet_detail.html:43 -#: apps/sheets/templates/sheets/sheet_detail.html:54 +#: apps/sheets/templates/sheets/sheet_detail.html:58 msgid "This product is unavailable." msgstr "Ce produit est indisponible." -#: apps/sheets/templates/sheets/sheet_detail.html:63 +#: apps/sheets/templates/sheets/sheet_detail.html:67 msgid "The menu is empty for now." msgstr "Le menu est vide pour le moment." -#: apps/sheets/templates/sheets/sheet_detail.html:70 +#: apps/sheets/templates/sheets/sheet_detail.html:74 msgid "Add new food" msgstr "Ajouter un plat" -#: apps/sheets/templates/sheets/sheet_detail.html:73 +#: apps/sheets/templates/sheets/sheet_detail.html:77 msgid "Add new meal" msgstr "Ajouter un menu" -#: apps/sheets/templates/sheets/sheet_detail.html:79 apps/sheets/views.py:206 -#: apps/sheets/views.py:317 +#: apps/sheets/templates/sheets/sheet_detail.html:83 apps/sheets/views.py:206 +#: apps/sheets/views.py:319 msgid "Order now" msgstr "Commander maintenant" @@ -2391,41 +2459,45 @@ msgid "Update meal" msgstr "Modifier un menu" #: apps/sheets/views.py:217 -#, fuzzy -#| msgid "order" msgid "Orderer" -msgstr "commande" +msgstr "Commanditaire" #: apps/sheets/views.py:223 -#, fuzzy -#| msgid "orders" msgid "Who orders" -msgstr "commandes" +msgstr "Qui commande" #: apps/sheets/views.py:231 apps/treasury/models.py:140 msgid "Quantity" msgstr "Quantité" -#: apps/sheets/views.py:243 apps/sheets/views.py:288 +#: apps/sheets/views.py:238 apps/sheets/views.py:284 +msgid "Be careful: this gift will be multiplied for each order." +msgstr "Attention : ce don sera multiplié pour chaque commande." + +#: apps/sheets/views.py:244 apps/sheets/views.py:290 msgid "Allergies,…" msgstr "Allergies,…" -#: apps/sheets/views.py:249 apps/sheets/views.py:294 +#: apps/sheets/views.py:250 apps/sheets/views.py:296 msgid "Lesson at 13h30,…" msgstr "Cours à 13h30,…" -#: apps/sheets/views.py:260 +#: apps/sheets/views.py:261 msgid "Options for " msgstr "Options pour " -#: apps/sheets/views.py:304 +#: apps/sheets/views.py:306 msgid "Options" msgstr "Options" -#: apps/sheets/views.py:401 +#: apps/sheets/views.py:403 msgid "You didn't select anything." msgstr "Vous n'avez rien sélectionné." +#: apps/sheets/views.py:432 +msgid "Detailed waiting list" +msgstr "Liste d'attente détaillée" + #: apps/treasury/apps.py:12 note_kfet/templates/base.html:96 msgid "Treasury" msgstr "Trésorerie" @@ -3602,11 +3674,6 @@ msgstr "Il n'y a pas de résultat." msgid "Are you sure to delete the application" msgstr "Êtes-vous sûr⋅e de vouloir supprimer l'application" -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 -#: note_kfet/templates/oauth2_provider/authorize.html:28 -msgid "Cancel" -msgstr "Annuler" - #: note_kfet/templates/oauth2_provider/application_detail.html:11 msgid "Client id" msgstr "ID client" @@ -3817,3 +3884,6 @@ msgstr "" "vous connecter. Vous devez vous rendre à la Kfet et payer les frais " "d'adhésion. Vous devez également valider votre adresse email en suivant le " "lien que vous avez reçu." + +#~ msgid "Detailed view" +#~ msgstr "Vue détaillée"