diff --git a/alexia/apps/general/templatetags/get_item.py b/alexia/apps/general/templatetags/get_item.py new file mode 100644 index 0000000..ccfac04 --- /dev/null +++ b/alexia/apps/general/templatetags/get_item.py @@ -0,0 +1,7 @@ +from django import template + +register = template.Library() + +@register.filter +def get_item(key, dictionary): + return dictionary.get(key) diff --git a/alexia/apps/scheduling/migrations/0022_auto_20241001_1357.py b/alexia/apps/scheduling/migrations/0022_auto_20241001_1357.py new file mode 100644 index 0000000..f139583 --- /dev/null +++ b/alexia/apps/scheduling/migrations/0022_auto_20241001_1357.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.28 on 2024-10-01 14:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scheduling', '0021_auto_20240926_1621'), + ] + + operations = [ + migrations.AlterModelOptions( + name='availability', + options={'ordering': ['position'], 'verbose_name': 'availability type', 'verbose_name_plural': 'availability types'}, + ), + migrations.AddField( + model_name='bartenderavailability', + name='comment', + field=models.TextField(blank=True, default='', max_length=100, verbose_name='comment'), + ), + ] diff --git a/alexia/apps/scheduling/models.py b/alexia/apps/scheduling/models.py index 8da802f..a63ccec 100644 --- a/alexia/apps/scheduling/models.py +++ b/alexia/apps/scheduling/models.py @@ -246,6 +246,7 @@ class BartenderAvailability(models.Model): verbose_name=_('availability'), on_delete=models.CASCADE, ) + comment = models.TextField(_('comment'), blank=True, default='', max_length=100) class Meta: verbose_name = _('bartender availability') diff --git a/alexia/apps/scheduling/urls.py b/alexia/apps/scheduling/urls.py index 8d0b044..a686ab5 100644 --- a/alexia/apps/scheduling/urls.py +++ b/alexia/apps/scheduling/urls.py @@ -28,4 +28,5 @@ # AJAT (Asynchroon Javascript en Tekst... wie gebruikt er nog in # hemelsnaam XML!?) url(r'^ajax/bartender_availability/$', views.set_bartender_availability), + url(r'^ajax/bartender_availability/comment/$', views.set_bartender_availability_comment), ] diff --git a/alexia/apps/scheduling/views.py b/alexia/apps/scheduling/views.py index b40e097..ffcace2 100644 --- a/alexia/apps/scheduling/views.py +++ b/alexia/apps/scheduling/views.py @@ -4,7 +4,7 @@ from django.contrib.auth.models import User from django.core.exceptions import PermissionDenied, SuspiciousOperation from django.db.models import Prefetch, Q -from django.http import HttpResponse, JsonResponse +from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy, reverse from django.utils import timezone @@ -108,7 +108,9 @@ def event_list_view(request): availabilities = list(request.organization.availabilities.exclude(nature=Availability.ASSIGNED)) # Net als onze BartenderAvailabilities bartender_availabilities = BartenderAvailability.objects.filter( - user_id=request.user.pk).values('event_id', 'availability_id') + user_id=request.user.pk).values('event_id', 'availability_id', 'comment') + + bartender_availabilities = {ba['event_id']: ba for ba in bartender_availabilities} return render(request, 'scheduling/event_list.html', locals()) @@ -193,11 +195,11 @@ def get_tenders(self, events): tenders = [] for tender in tenders_list: tender_availabilities = [ - next((a.availability for a in e.bartender_availabilities.all() if a.user == tender.user), None) + next((a for a in e.bartender_availabilities.all() if a.user == tender.user), None) for e in events ] tender_events = [ - {'event': event, 'availability': availability} + {'event': event, 'bartender_availability': availability} for event, availability in zip(events, tender_availabilities) ] tended = [ @@ -235,13 +237,13 @@ def get_tender_list(self): tender_list = [] for tender in tenders: try: - availability = bas[tender.user].availability + availability = bas[tender.user] except KeyError: availability = None tender_list.append({ 'tender': tender, - 'availability': availability, + 'bartender_availability': availability, 'last_tended': tender.last_tended() }) return {'tender_list': tender_list} @@ -328,6 +330,28 @@ def get_success_url(self): return super(EventDelete, self).get_success_url() +@login_required +def set_bartender_availability_comment(request): + event = get_object_or_404(Event, pk=request.POST.get('event_id')) + + if (request.organization not in event.participants.all()) or \ + not request.user.profile.is_tender(request.organization): + raise PermissionDenied + + if not (request.method == 'POST' and request.is_ajax()): + return HttpResponseBadRequest("NOTOK") + + comment = request.POST.get('comment') + if len(comment) > 100: + return HttpResponseBadRequest("TOOLONG") + availability = get_object_or_404(BartenderAvailability, event=event, user=request.user) + availability.comment = comment + availability.save() + + + return render(request, 'scheduling/partials/availability_comment.html', {'e': event, 'ba': availability}) + + @login_required def set_bartender_availability(request): event = get_object_or_404(Event, pk=request.POST.get('event_id')) diff --git a/alexia/conf/settings/local.py.default b/alexia/conf/settings/local.py.default index 680e4fc..78c2c02 100644 --- a/alexia/conf/settings/local.py.default +++ b/alexia/conf/settings/local.py.default @@ -43,6 +43,7 @@ RADIUS_IDENTIFIER = '' EMAIL_HOST = 'localhost' EMAIL_SUBJECT_PREFIX = '[Alexia] ' EMAIL_FROM = 'Alexia ' +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # Log mail messages to console instead of SMTP server! DEFAULT_FROM_EMAIL = EMAIL_FROM SERVER_EMAIL = EMAIL_FROM diff --git a/assets/css/application.css b/assets/css/application.css index f4416e5..d961d26 100644 --- a/assets/css/application.css +++ b/assets/css/application.css @@ -36,6 +36,10 @@ body { padding-bottom: 0; } +.label.label-has-ba-comment { + border: 2px dotted black; +} + .input-static { padding-top: 7px; } diff --git a/assets/js/application.js b/assets/js/application.js index 7d94a4a..893f7b3 100644 --- a/assets/js/application.js +++ b/assets/js/application.js @@ -43,6 +43,32 @@ $.ajaxSetup({ } }); +function resetCommentPrompts() { + $('.bartender_availability_comment').click(function () { + let event_id = $(this).data('event-id'); + let comment = prompt('Enter a comment'); + + if (comment == null || comment == '') { + return; + } + + if (comment.length > 100) { + alert('Comment is too long. Maximum 100 characters allowed.'); + return; + } + + const $this = $(this); + + $.post('/scheduling/ajax/bartender_availability/comment/', { + event_id, + comment + }, function (data) { + $this.replaceWith(data); + resetCommentPrompts(); + }, "text"); + }); +} + $(function () { $('.bartender_availability').change(function () { @@ -52,10 +78,13 @@ $(function () { event_id: event_id, availability_id: $(this).val() }, function (data) { - $('#assigned_bartenders_' + event_id).html(data).effect("highlight"); + $('#assigned_bartenders_' + event_id).html(data); + $('#bartender_availability_comment_' + event_id).css('visibility', 'visible'); }, "text"); }); + resetCommentPrompts(); + $('.dateinput').datepicker({ autoclose: true, format: dateformats[LOCALE], diff --git a/locale/nl/LC_MESSAGES/django.mo b/locale/nl/LC_MESSAGES/django.mo index 0dba830..ed4cd6c 100644 Binary files a/locale/nl/LC_MESSAGES/django.mo and b/locale/nl/LC_MESSAGES/django.mo differ diff --git a/locale/nl/LC_MESSAGES/django.po b/locale/nl/LC_MESSAGES/django.po index b563640..2ac973d 100644 --- a/locale/nl/LC_MESSAGES/django.po +++ b/locale/nl/LC_MESSAGES/django.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: alexia\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-11 12:32+0200\n" -"PO-Revision-Date: 2024-10-11 12:35+0018\n" +"POT-Creation-Date: 2024-10-11 13:14+0200\n" +"PO-Revision-Date: 2024-10-11 13:14+0018\n" "Last-Translator: b'Kevin Alberts '\n" "Language-Team: WWW-commissie \n" "Language: nl\n" @@ -221,7 +221,6 @@ msgid "purchases" msgstr "aankopen" #: alexia/apps/billing/models.py:339 -#| msgid "description" msgid "short description" msgstr "korte omschrijving" @@ -230,13 +229,11 @@ msgid "color" msgstr "kleur" #: alexia/apps/billing/models.py:346 -#| msgid "Active" msgid "active" msgstr "actief" #: alexia/apps/billing/models.py:349 #, python-brace-format -#| msgid "{user} of {organization}" msgid "{name} for {organization}" msgstr "{name} van {organization}" @@ -254,7 +251,6 @@ msgstr "Afschrijvingstransacties" #: alexia/apps/billing/models.py:378 #, python-brace-format -#| msgid "{user} at {time} on {event}" msgid "{time} on {event}" msgstr "{time} bij {event}" @@ -278,7 +274,7 @@ msgstr "Verbruik" msgid "General" msgstr "Generiek" -#: alexia/apps/config.py:24 alexia/apps/scheduling/forms.py:73 templates/billing/permanentproduct_detail.html:31 templates/billing/pricegroup_detail.html:31 templates/consumption/consumptionform_list.html:31 templates/consumption/consumptionform_list.html:68 templates/consumption/pdf/page.html:9 templates/general/about.html:40 templates/organization/certificate_form.html:27 templates/profile/profile.html:121 templates/profile/profile.html:146 templates/scheduling/event_calendar.html:26 templates/scheduling/event_list.html:37 templates/scheduling/mailtemplate_detail.html:24 +#: alexia/apps/config.py:24 alexia/apps/scheduling/forms.py:73 templates/billing/permanentproduct_detail.html:31 templates/billing/pricegroup_detail.html:31 templates/consumption/consumptionform_list.html:31 templates/consumption/consumptionform_list.html:68 templates/consumption/pdf/page.html:9 templates/general/about.html:40 templates/organization/certificate_form.html:27 templates/profile/profile.html:121 templates/profile/profile.html:146 templates/scheduling/event_calendar.html:26 templates/scheduling/event_list.html:38 templates/scheduling/mailtemplate_detail.html:24 msgid "Organization" msgstr "Organisatie" @@ -462,7 +458,6 @@ msgid "This consumption form has been completed." msgstr "Dit verbruiksformulier is al afgerond." #: alexia/apps/general/views.py:129 -#| msgid "organizations" msgid "This organization is inactive." msgstr "Deze organisatie is inactief." @@ -780,11 +775,16 @@ msgstr "tapper" msgid "availability" msgstr "beschikbaarheid" -#: alexia/apps/scheduling/models.py:251 +#: alexia/apps/scheduling/models.py:249 +#| msgid "comments" +msgid "comment" +msgstr "commentaar" + +#: alexia/apps/scheduling/models.py:252 msgid "bartender availability" msgstr "tapperbeschikbaarheid" -#: alexia/apps/scheduling/models.py:252 +#: alexia/apps/scheduling/models.py:253 msgid "bartender availabilities" msgstr "tapperbeschikbaarheden" @@ -872,7 +872,7 @@ msgstr "individuele bijdragers" msgid "Local login" msgstr "Lokale login" -#: templates/base_app.html:21 templates/scheduling/event_calendar.html:3 templates/scheduling/event_list.html:3 templates/scheduling/event_list.html:8 +#: templates/base_app.html:21 templates/scheduling/event_calendar.html:3 templates/scheduling/event_list.html:4 templates/scheduling/event_list.html:9 msgid "Planning" msgstr "Planning" @@ -968,11 +968,11 @@ msgstr "Evenementinformatie" msgid "Event" msgstr "Activiteit" -#: templates/billing/order_detail.html:28 templates/billing/order_export_result.html:35 templates/billing/order_list.html:47 templates/billing/permanentproduct_detail.html:27 templates/billing/permanentproduct_list.html:21 templates/billing/pricegroup_detail.html:27 templates/billing/pricegroup_list.html:20 templates/billing/productgroup_list.html:20 templates/billing/temporaryproduct_detail.html:27 templates/consumption/consumptionproduct_list.html:25 templates/consumption/consumptionproduct_list.html:65 templates/organization/membership_detail.html:45 templates/organization/membership_iva.html:15 templates/organization/membership_list.html:26 templates/scheduling/availability_list.html:20 templates/scheduling/event_bartender.html:16 templates/scheduling/event_detail.html:79 templates/scheduling/event_list.html:39 templates/scheduling/mailtemplate_detail.html:20 templates/scheduling/mailtemplate_list.html:15 +#: templates/billing/order_detail.html:28 templates/billing/order_export_result.html:35 templates/billing/order_list.html:47 templates/billing/permanentproduct_detail.html:27 templates/billing/permanentproduct_list.html:21 templates/billing/pricegroup_detail.html:27 templates/billing/pricegroup_list.html:20 templates/billing/productgroup_list.html:20 templates/billing/temporaryproduct_detail.html:27 templates/consumption/consumptionproduct_list.html:25 templates/consumption/consumptionproduct_list.html:65 templates/organization/membership_detail.html:45 templates/organization/membership_iva.html:15 templates/organization/membership_list.html:26 templates/scheduling/availability_list.html:20 templates/scheduling/event_bartender.html:16 templates/scheduling/event_detail.html:79 templates/scheduling/event_list.html:40 templates/scheduling/mailtemplate_detail.html:20 templates/scheduling/mailtemplate_list.html:15 msgid "Name" msgstr "Naam" -#: templates/billing/order_detail.html:32 templates/billing/order_export_result.html:34 templates/billing/order_list.html:46 templates/billing/order_month.html:15 templates/consumption/consumptionform_detail.html:43 templates/consumption/consumptionform_list.html:30 templates/consumption/consumptionform_list.html:67 templates/consumption/dcf_check.html:30 templates/consumption/pdf/page.html:15 templates/organization/membership_detail.html:66 templates/profile/expenditure_list.html:15 templates/scheduling/event_bartender.html:13 templates/scheduling/event_list.html:35 +#: templates/billing/order_detail.html:32 templates/billing/order_export_result.html:34 templates/billing/order_list.html:46 templates/billing/order_month.html:15 templates/consumption/consumptionform_detail.html:43 templates/consumption/consumptionform_list.html:30 templates/consumption/consumptionform_list.html:67 templates/consumption/dcf_check.html:30 templates/consumption/pdf/page.html:15 templates/organization/membership_detail.html:66 templates/profile/expenditure_list.html:15 templates/scheduling/event_bartender.html:13 templates/scheduling/event_list.html:36 msgid "Date" msgstr "Datum" @@ -1025,7 +1025,6 @@ msgid "Synchronized" msgstr "Gesynchroniseerd" #: templates/billing/order_detail.html:164 -#| msgid "writeoff orders" msgid "Written off orders" msgstr "Afgeschreven orders" @@ -1232,7 +1231,6 @@ msgid "New temporary product" msgstr "Nieuw tijdelijk product" #: templates/billing/writeoff_order_detail.html:3 templates/billing/writeoff_order_detail.html:7 -#| msgid "Written off" msgid "Write off" msgstr "Afschrijven" @@ -1240,7 +1238,7 @@ msgstr "Afschrijven" msgid "PDF" msgstr "PDF" -#: templates/consumption/consumptionform_detail.html:47 templates/consumption/consumptionform_list.html:32 templates/consumption/consumptionform_list.html:69 templates/consumption/dcf_check.html:34 templates/consumption/pdf/page.html:11 templates/scheduling/event_bartender.html:15 templates/scheduling/event_calendar.html:25 templates/scheduling/event_detail.html:56 templates/scheduling/event_list.html:38 +#: templates/consumption/consumptionform_detail.html:47 templates/consumption/consumptionform_list.html:32 templates/consumption/consumptionform_list.html:69 templates/consumption/dcf_check.html:34 templates/consumption/pdf/page.html:11 templates/scheduling/event_bartender.html:15 templates/scheduling/event_calendar.html:25 templates/scheduling/event_detail.html:56 templates/scheduling/event_list.html:39 msgid "Location" msgstr "Locatie" @@ -1522,7 +1520,7 @@ msgstr "Tappers van %(organization)s" msgid "Authorization" msgstr "Autorisatie" -#: templates/organization/membership_iva.html:17 templates/organization/membership_list.html:29 templates/scheduling/event_list.html:41 +#: templates/organization/membership_iva.html:17 templates/organization/membership_list.html:29 templates/scheduling/event_list.html:42 msgid "IVA" msgstr "IVA" @@ -1772,11 +1770,11 @@ msgstr "Soort" msgid "No availabilities defined." msgstr "Geen beschikbaarheden gedefinieerd." -#: templates/scheduling/event_bartender.html:14 templates/scheduling/event_list.html:36 +#: templates/scheduling/event_bartender.html:14 templates/scheduling/event_list.html:37 msgid "Time" msgstr "Tijd" -#: templates/scheduling/event_bartender.html:17 templates/scheduling/event_calendar.html:27 templates/scheduling/event_detail.html:130 templates/scheduling/event_list.html:42 +#: templates/scheduling/event_bartender.html:17 templates/scheduling/event_calendar.html:27 templates/scheduling/event_detail.html:130 templates/scheduling/event_list.html:43 msgid "Bartenders" msgstr "Tappers" @@ -1972,7 +1970,7 @@ msgstr "Week" msgid "Loading..." msgstr "Laden..." -#: templates/scheduling/event_calendar.html:101 templates/scheduling/event_form.html:7 templates/scheduling/event_form.html:17 templates/scheduling/event_list.html:13 +#: templates/scheduling/event_calendar.html:101 templates/scheduling/event_form.html:7 templates/scheduling/event_form.html:17 templates/scheduling/event_list.html:14 msgid "Add event" msgstr "Activiteit toevoegen" @@ -2025,49 +2023,54 @@ msgstr "Nooit" msgid "Unknown" msgstr "Onbekend" +#: templates/scheduling/event_detail.html:148 +#| msgid "bartender" +msgid "Comment by bartender" +msgstr "Commentaar van tapper" + #: templates/scheduling/event_form.html:5 templates/scheduling/event_form.html:15 msgid "Edit event" msgstr "Activiteit bewerken" -#: templates/scheduling/event_list.html:22 +#: templates/scheduling/event_list.html:23 msgid "Filters" msgstr "Filters" -#: templates/scheduling/event_list.html:40 +#: templates/scheduling/event_list.html:41 msgid "Kegs" msgstr "Fusten" -#: templates/scheduling/event_list.html:78 templates/scheduling/event_list.html:79 +#: templates/scheduling/event_list.html:79 templates/scheduling/event_list.html:80 msgid "Has tender comment:" msgstr "Heeft tappersinstructie:" -#: templates/scheduling/event_list.html:82 +#: templates/scheduling/event_list.html:83 msgid "Risky activity" msgstr "Risicoactiviteit" -#: templates/scheduling/event_list.html:92 +#: templates/scheduling/event_list.html:93 msgid "Some bartenders have IVA, but not everyone" msgstr "Sommige tappers hebben IVA, maar niet allemaal" -#: templates/scheduling/event_list.html:129 +#: templates/scheduling/event_list.html:135 msgid "Point of sale" msgstr "Kassa" -#: templates/scheduling/event_list.html:131 +#: templates/scheduling/event_list.html:137 msgid "DCF" msgstr "DVF" -#: templates/scheduling/event_list.html:143 +#: templates/scheduling/event_list.html:149 #, python-format msgid "There's nothing scheduled between %(a)s and %(b)s." msgstr "Er is niks ingepland tussen %(a)s en %(b)s." -#: templates/scheduling/event_list.html:145 +#: templates/scheduling/event_list.html:151 #, python-format msgid "There's nothing scheduled after %(datetime)s." msgstr "Er is niks ingepland na %(datetime)s." -#: templates/scheduling/event_matrix.html:46 +#: templates/scheduling/event_matrix.html:47 msgid "No events have been planned." msgstr "Er zijn geen evenementen gepland." diff --git a/templates/scheduling/event_detail.html b/templates/scheduling/event_detail.html index ed06ae7..4ebc4f0 100644 --- a/templates/scheduling/event_detail.html +++ b/templates/scheduling/event_detail.html @@ -135,13 +135,19 @@

{% trans 'Bartenders' %}

{{ obj.tender.user.get_full_name }} - + - - {{ obj.availability|default:_("Unknown") }} + + {{ obj.bartender_availability.availability|default:_("Unknown") }} + + {% if obj.bartender_availability.comment %} + + {% endif %} + {{ obj.bartender_availability.comment }} + {% endfor %} diff --git a/templates/scheduling/event_list.html b/templates/scheduling/event_list.html index ee7583d..a1fd4f3 100644 --- a/templates/scheduling/event_list.html +++ b/templates/scheduling/event_list.html @@ -1,4 +1,5 @@ {% extends 'base_app.html' %} +{% load get_item %} {% block title %}{% trans 'Planning' %}{% endblock title %} @@ -105,12 +106,17 @@

{% if not e.is_closed and request.organization in e.participants.all %} {% if not e.organizer.assigns_tenders or not user in e.get_assigned_bartenders %} - + {% with ba=e.pk|get_item:bartender_availabilities %} +
+ + {% include "scheduling/partials/availability_comment.html" %} +
+ {% endwith %} {% endif %} {% endif %} diff --git a/templates/scheduling/event_matrix.html b/templates/scheduling/event_matrix.html index f2c418b..88dd6f5 100644 --- a/templates/scheduling/event_matrix.html +++ b/templates/scheduling/event_matrix.html @@ -32,8 +32,9 @@

{% for e in t.events %} - - {{ e.availability|default:'?' }} + + {{ e.bartender_availability.availability|default:'?' }} {% endfor %} diff --git a/templates/scheduling/partials/availability_comment.html b/templates/scheduling/partials/availability_comment.html new file mode 100644 index 0000000..8c4de3d --- /dev/null +++ b/templates/scheduling/partials/availability_comment.html @@ -0,0 +1,3 @@ +
+ +