diff --git a/rc_hip/repapp/migrations/0011_reparateur_cafe_alter_device_guest.py b/rc_hip/repapp/migrations/0011_reparateur_cafe_alter_device_guest.py new file mode 100644 index 0000000..926e49b --- /dev/null +++ b/rc_hip/repapp/migrations/0011_reparateur_cafe_alter_device_guest.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2 on 2023-06-18 07:46 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('repapp', '0010_customuser_notifications'), + ] + + operations = [ + migrations.AddField( + model_name='reparateur', + name='cafe', + field=models.ManyToManyField(to='repapp.cafe'), + ), + migrations.AlterField( + model_name='device', + name='guest', + field=models.ForeignKey(choices=[(-1, 'abgelehnt'), (0, 'neu'), (1, 'in Orga Rückfrage'), (2, 'in Orga Rückfrage beantwortet'), (3, 'in der Warteliste')], null=True, on_delete=django.db.models.deletion.CASCADE, to='repapp.guest', verbose_name='Gast'), + ), + ] diff --git a/rc_hip/repapp/migrations/0012_remove_reparateur_cafe_cafe_reparateur.py b/rc_hip/repapp/migrations/0012_remove_reparateur_cafe_cafe_reparateur.py new file mode 100644 index 0000000..3afb04a --- /dev/null +++ b/rc_hip/repapp/migrations/0012_remove_reparateur_cafe_cafe_reparateur.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2 on 2023-06-18 13:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('repapp', '0011_reparateur_cafe_alter_device_guest'), + ] + + operations = [ + migrations.RemoveField( + model_name='reparateur', + name='cafe', + ), + migrations.AddField( + model_name='cafe', + name='reparateur', + field=models.ManyToManyField(to='repapp.reparateur'), + ), + ] diff --git a/rc_hip/repapp/migrations/0013_device_reparateur.py b/rc_hip/repapp/migrations/0013_device_reparateur.py new file mode 100644 index 0000000..d54efee --- /dev/null +++ b/rc_hip/repapp/migrations/0013_device_reparateur.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-06-18 14:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('repapp', '0012_remove_reparateur_cafe_cafe_reparateur'), + ] + + operations = [ + migrations.AddField( + model_name='device', + name='reparateur', + field=models.ManyToManyField(to='repapp.reparateur'), + ), + ] diff --git a/rc_hip/repapp/models.py b/rc_hip/repapp/models.py index 7117d19..4cf763a 100644 --- a/rc_hip/repapp/models.py +++ b/rc_hip/repapp/models.py @@ -30,6 +30,21 @@ class CustomUser(AbstractUser): return f'{self.email}' +class Reparateur(models.Model): + """ + A Reparateur is a member of the Repair-Café who supports guests with fixing their devices. + """ + name = models.CharField(max_length=200, verbose_name=_("Name")) + mail = models.CharField(max_length=200, verbose_name=_("eMail")) + + class Meta: + verbose_name = _('Reparateur') + verbose_name_plural = _('Reparateure') + + def __str__(self): + return f'Reparateur {self.name} (eMail: {self.mail})' + + class Cafe(models.Model): """ A Cafe is a "Repair-Café event. @@ -39,6 +54,7 @@ class Cafe(models.Model): address = models.CharField( max_length=200, verbose_name=_("Adresse")) event_date = models.DateField(verbose_name=_("Datum")) + reparateur = models.ManyToManyField(Reparateur) class Meta: verbose_name = _('Repair-Café') @@ -48,22 +64,6 @@ class Cafe(models.Model): return f'Repair-Café am {self.event_date} (Ort: {self.location})' -class Reparateur(models.Model): - """ - A Reparateur is a member of the Repair-Café who supports guests with fixing their devices. - """ - name = models.CharField(max_length=200, verbose_name=_("Name")) - mail = models.CharField(max_length=200, verbose_name=_("eMail")) - cafe = models.ManyToManyField(Cafe) - - class Meta: - verbose_name = _('Reparateur') - verbose_name_plural = _('Reparateure') - - def __str__(self): - return f'Reparateur {self.name} (eMail: {self.mail})' - - class Organisator(models.Model): """ A Organisator is a member of the Repair-Café who arranges repair appointments with guests. @@ -108,12 +108,16 @@ class Device(models.Model): STATUS_ORGA_QUESTION = 1 STATUS_ORGA_QUESTION_ANSWERED = 2 STATUS_WAITING_LIST = 3 + STATUS_REPA_QUESTION = 4 + STATUS_REPA_QUESTION_ANSWERED = 5 STATUS = ( (STATUS_REJECTED, 'abgelehnt'), (STATUS_NEW, 'neu'), (STATUS_ORGA_QUESTION, 'in Orga Rückfrage'), (STATUS_ORGA_QUESTION_ANSWERED, 'in Orga Rückfrage beantwortet'), (STATUS_WAITING_LIST, 'in der Warteliste'), + (STATUS_REPA_QUESTION, 'in Repa Rückfrage'), + (STATUS_REPA_QUESTION_ANSWERED, 'in Repa Rückfrage beantwortet'), ) identifier = models.CharField(max_length=200, verbose_name=_("ID")) @@ -134,6 +138,7 @@ class Device(models.Model): Guest, on_delete=models.CASCADE, null=True, verbose_name=_("Gast"), choices=STATUS) cafe = models.ForeignKey( Cafe, on_delete=models.CASCADE, null=False, verbose_name=_("Repair-Café")) + reparateur = models.ManyToManyField(Reparateur) class Meta: verbose_name = _('Gerät') diff --git a/rc_hip/repapp/templates/repapp/base.html b/rc_hip/repapp/templates/repapp/base.html index 570ca00..b9783b3 100644 --- a/rc_hip/repapp/templates/repapp/base.html +++ b/rc_hip/repapp/templates/repapp/base.html @@ -52,7 +52,8 @@ background-repeat: no-repeat; background-size: cover; background-position: center; - max-width:1920px;> + max-width:1920px; + margin-bottom:10px">

{{ cafe.location }} - Nein - teilnehmen + {% if cafe.accepted %} + Ja + {% else %} + Nein + {% endif %} + + + {% if cafe.accepted %} + absagen + {% else %} + teilnehmen + {% endif %} {% empty %} @@ -47,6 +57,7 @@ Hersteller & Modell/Typ Repair-Café Ort + mir zugeordnet? @@ -58,7 +69,14 @@ {{ device.cafe.event_date|date:"l" }}, {{ device.cafe.event_date|date }} {{ device.cafe.location }} - Details + {% if device.assigned %} + Ja + {% else %} + Nein + {% endif %} + + + Details {% empty %} diff --git a/rc_hip/repapp/templates/repapp/repa/view_device.html b/rc_hip/repapp/templates/repapp/repa/view_device.html new file mode 100644 index 0000000..408e82b --- /dev/null +++ b/rc_hip/repapp/templates/repapp/repa/view_device.html @@ -0,0 +1,75 @@ +{% extends "repapp/base.html" %} +{% load crispy_forms_tags %} +{% block title %} + - Gerät +{% endblock title %} +{% block page_title %} + Gerät +{% endblock page_title %} +{% block content %} +

+ Zurück + {% if assigned %} + Gerät ablehnen + Rückfrage + {% else %} + Gerät mir zuordnen + {% endif %} +

+
+

Gerät

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Art des Geräts{{ device.device }}
Hersteller & Modell/Typ{{ device.manufacturer }}
Fehlerbeschreibung{{ device.error }}
Folgetermin + {% if device.follow_up %} + Ja + {% else %} + Nein + {% endif %} +
Foto vom Gerät + {% if device.device_picture %} + Foto vom Gerät + {% else %} + kein Bild + {% endif %} +
Foto vom Typenschild + {% if device.device_picture %} + Foto vom Typenschild + {% else %} + kein Bild + {% endif %} +
+{% endblock content %} diff --git a/rc_hip/repapp/urls.py b/rc_hip/repapp/urls.py index 3a89fa5..535373a 100644 --- a/rc_hip/repapp/urls.py +++ b/rc_hip/repapp/urls.py @@ -44,6 +44,15 @@ urlpatterns = [ path("member/question/", views.questions, name="device_questions"), path("repa/", views.repa, name="repa"), + path("repa//accept", views.repa_cafe_accept, name="repa_cafe_accept"), + path("repa//decline", + views.repa_cafe_decline, name="repa_cafe_decline"), + path("repa//", + views.repa_view_device, name="repa_view_device"), + path("repa//assign", + views.repa_device_assign, name="repa_device_assign"), + path("repa//unassign", + views.repa_device_unassign, name="repa_device_unassign"), path("cafe/", views.CafeView.as_view(), name="cafe"), path("cafe/create", views.CafeCreateView.as_view(), name="create_cafe"), path("cafe//edit", views.CafeUpdateView.as_view(), name="edit_cafe"), diff --git a/rc_hip/repapp/views.py b/rc_hip/repapp/views.py index 0f3f88e..73f1eeb 100644 --- a/rc_hip/repapp/views.py +++ b/rc_hip/repapp/views.py @@ -618,7 +618,7 @@ class QuestionDeviceFormView(LoginRequiredMixin, UserPassesTestMixin, generic.ed login_url = reverse_lazy('member') def test_func(self): - return is_organisator(self.request.user) + return is_member(self.request.user) def form_valid(self, form): device = self.kwargs['device'] @@ -628,23 +628,31 @@ class QuestionDeviceFormView(LoginRequiredMixin, UserPassesTestMixin, generic.ed message = form.cleaned_data['message'] mail = self.request.user.email organisator = Organisator.objects.filter(mail=mail).first() + reparateur = Reparateur.objects.filter(mail=mail).first() if organisator: question = Question( question=message, organisator=organisator, device=device ) + + send_device_question_mail(question, self.request) + device.status = Device.STATUS_ORGA_QUESTION + elif reparateur: + question = Question( + question=message, + reparateur=reparateur, + device=device + ) + + device.status = Device.STATUS_REPA_QUESTION else: raise PermissionDenied('Not valid member found!') question.save() - - send_device_question_mail(question, self.request) - - device.status = Device.STATUS_ORGA_QUESTION device.save() return HttpResponseRedirect( - reverse_lazy('orga') + reverse_lazy('member') ) def get_initial(self, **kwargs): @@ -782,8 +790,21 @@ def repa(request): logger.warning('The user %s is no reparateur!', str(request.user)) raise PermissionDenied('Not reparateur!') - cafes = Cafe.objects.filter(event_date__gte=datetime.date.today()) - devices = Device.objects.filter(status=Device.STATUS_WAITING_LIST) + devices = [] + for device in Device.objects.filter(status__gte=Device.STATUS_WAITING_LIST): + if device.reparateur.filter(mail=request.user.email).count() > 0: + device.assigned = True + else: + device.assigned = False + devices.append(device) + + cafes = [] + for cafe in Cafe.objects.filter(event_date__gte=datetime.date.today()): + if cafe.reparateur.filter(mail=request.user.email).count() > 0: + cafe.accepted = True + else: + cafe.accepted = False + cafes.append(cafe) return render( request, @@ -977,3 +998,81 @@ class MemberSettingsFormView(LoginRequiredMixin, UserPassesTestMixin, generic.ed def test_func(self): return is_member(self.request.user) + + +@login_required(login_url=reverse_lazy('member')) +def repa_cafe_accept(request, cafe): + if not is_reparateur(request.user): + raise PermissionDenied('Not a reparateur!') + + cafe = get_object_or_404(Cafe, pk=cafe) + reparateur = get_object_or_404(Reparateur, mail=request.user.email) + cafe.reparateur.add(reparateur) + cafe.save() + + return HttpResponseRedirect(reverse_lazy('repa')) + + +@login_required(login_url=reverse_lazy('member')) +def repa_cafe_decline(request, cafe): + if not is_reparateur(request.user): + raise PermissionDenied('Not a reparateur!') + + cafe = get_object_or_404(Cafe, pk=cafe) + reparateur = get_object_or_404(Reparateur, mail=request.user.email) + cafe.reparateur.remove(reparateur) + cafe.save() + + return HttpResponseRedirect(reverse_lazy('repa')) + + +@login_required(login_url=reverse_lazy('member')) +def repa_view_device(request, device): + """ + View device details. + """ + # TODO: test + if not is_reparateur(request.user): + raise PermissionDenied('Not reparateur!') + + device = get_object_or_404(Device, pk=device) + assigned = device.reparateur.filter(mail=request.user.email).count() > 0 + + return render( + request, + "repapp/repa/view_device.html", + { + 'device': device, + 'assigned': assigned, + } + ) + + +@login_required(login_url=reverse_lazy('member')) +def repa_device_assign(request, device): + if not is_reparateur(request.user): + raise PermissionDenied('Not a reparateur!') + + device = get_object_or_404(Device, pk=device) + reparateur = get_object_or_404(Reparateur, mail=request.user.email) + device.reparateur.add(reparateur) + device.save() + + return HttpResponseRedirect(reverse_lazy('repa_view_device', kwargs={ + 'device': device.id + })) + + +@login_required(login_url=reverse_lazy('member')) +def repa_device_unassign(request, device): + if not is_reparateur(request.user): + raise PermissionDenied('Not a reparateur!') + + device = get_object_or_404(Device, pk=device) + reparateur = get_object_or_404(Reparateur, mail=request.user.email) + device.reparateur.remove(reparateur) + device.save() + + return HttpResponseRedirect(reverse_lazy('repa_view_device', kwargs={ + 'device': device.id + }))