From 69062f3e5802e1c73c6c756fed85369a08e01866 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 26 Aug 2025 19:39:01 +0200 Subject: [PATCH 1/3] fix(members): various bugs --- jdav_web/members/admin.py | 5 ++--- jdav_web/members/models.py | 15 +++++---------- jdav_web/members/tests/basic.py | 16 +++------------- jdav_web/members/views.py | 5 ++++- 4 files changed, 14 insertions(+), 27 deletions(-) diff --git a/jdav_web/members/admin.py b/jdav_web/members/admin.py index 28c8edf..4e37749 100644 --- a/jdav_web/members/admin.py +++ b/jdav_web/members/admin.py @@ -1267,8 +1267,9 @@ class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): sjr_application.short_description = _('Generate SJR application') def finance_overview(self, request, memberlist): - if not memberlist.statement: + if not hasattr(memberlist, 'statement'): messages.error(request, _("No statement found. Please add a statement and then retry.")) + return HttpResponseRedirect(reverse('admin:%s_%s_change' % (self.opts.app_label, self.opts.model_name), args=(memberlist.pk,))) if "apply" in request.POST: if not memberlist.statement.allowance_to_valid: messages.error(request, @@ -1329,8 +1330,6 @@ class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): def action_view(self, request, object_id): if "sjr_application" in request.POST: return self.sjr_application(request, Freizeit.objects.get(pk=object_id)) - if "seminar_vbk" in request.POST: - return self.seminar_vbk(request, Freizeit.objects.get(pk=object_id)) if "seminar_report" in request.POST: return self.seminar_report(request, Freizeit.objects.get(pk=object_id)) if "notes_list" in request.POST: diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index 660eac0..f12bac2 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -1058,9 +1058,8 @@ class MemberWaitingList(Person): @property def waiting_confirmation_needed(self): """Returns if person should be asked to confirm waiting status.""" - # TODO: Throws `NameError` (has skipped test). - return wait_confirmation_key is None \ - and last_wait_confirmation < timezone.now() -\ + return not self.wait_confirmation_key \ + and self.last_wait_confirmation < timezone.now() -\ timezone.timedelta(days=settings.WAITING_CONFIRMATION_FREQUENCY) def waiting_confirmed(self): @@ -1123,11 +1122,9 @@ class MemberWaitingList(Person): return self.wait_confirmation_key def may_register(self, key): - # TODO: Throws a `TypeError` (has skipped test). - print("may_register", key) try: invitation = InvitationToGroup.objects.get(key=key) - return self.pk == invitation.waiter.pk and timezone.now() < invitation.date + timezone.timedelta(days=30) + return self.pk == invitation.waiter.pk and timezone.now().date() < invitation.date + timezone.timedelta(days=30) except InvitationToGroup.DoesNotExist: return False @@ -1197,15 +1194,13 @@ class NewMemberOnList(CommonModel): @property def skills(self): - # TODO: Throws a `NameError` (has skipped test). - activities = [a.name for a in memberlist.activity.all()] + activities = [a.name for a in self.memberlist.activity.all()] return {k: v for k, v in self.member.get_skills().items() if k in activities} @property def qualities_tex(self): - # TODO: Throws a `NameError` (has skipped test). qualities = [] - for activity, value in self.skills: + for activity, value in self.skills.items(): qualities.append("\\textit{%s:} %s" % (activity, value)) return ", ".join(qualities) diff --git a/jdav_web/members/tests/basic.py b/jdav_web/members/tests/basic.py index bb9b280..2758c84 100644 --- a/jdav_web/members/tests/basic.py +++ b/jdav_web/members/tests/basic.py @@ -1159,10 +1159,6 @@ class FreizeitAdminTestCase(AdminTestCase, PDFActionMixin): }) self.assertEqual(response.status_code, HTTPStatus.OK) - @skip('Throws `AttributeError`: `Freizeit.seminar_vbk` does not exist.') - def test_seminar_vbk(self): - self._test_pdf('seminar_vbk', self.ex.pk) - def test_crisis_intervention_list_post(self): self._test_pdf('crisis_intervention_list', self.ex.pk) self._test_pdf('crisis_intervention_list', self.ex.pk, username='standard', invalid=True) @@ -1174,12 +1170,11 @@ class FreizeitAdminTestCase(AdminTestCase, PDFActionMixin): def test_wrong_action_freizeit(self): return self._test_pdf('asdf', self.ex.pk, invalid=True) - @skip('Currently throws a `RelatedObjectDoesNotExist` error.') def test_finance_overview_no_statement_post(self): url = reverse('admin:members_freizeit_action', args=(self.ex.pk,)) c = self._login('superuser') - # no statement yields error - response = c.post(url, data={'finance_overview': ''}) + # no statement yields redirect + response = c.post(url, data={'finance_overview': ''}, follow=True) self.assertEqual(response.status_code, HTTPStatus.OK) self.assertContains(response, _("No statement found. Please add a statement and then retry.")) @@ -1720,7 +1715,6 @@ class RegistrationFromWaiterViewTestCase(BasicMemberTestCase): )) self.assertEqual(response.status_code, HTTPStatus.OK) - @skip("This currently throws an 'AttributeError'.") def test_register_post_no_save(self): url = reverse('members:register') response = self.client.post(url, data=dict( @@ -1840,16 +1834,14 @@ class MemberWaitingListTestCase(BasicMemberTestCase): def test_latest_group_invitation(self): self.assertGreater(len(self.waiter.latest_group_invitation()), 1) - @skip("This currently throws a 'TypeError'.") def test_may_register(self): self.assertTrue(self.waiter.may_register(self.invitation.key)) def test_may_register_invalid(self): self.assertFalse(self.waiter.may_register('foobar')) - @skip("This currently throws a 'NameError'.") def test_waiting_confirmation_needed(self): - self.assertFalse(self.waiter.waiting_confirmation_needed()) + self.assertFalse(self.waiter.waiting_confirmation_needed) def test_confirm_waiting_invalid(self): self.assertEqual(self.waiter.confirm_waiting('foobar'), @@ -2330,11 +2322,9 @@ class NewMemberOnListTestCase(BasicMemberTestCase): self.ex.save() self.mol = NewMemberOnList.objects.create(memberlist=self.ex, member=self.fritz) - @skip("This currently throws a 'NameError'.") def test_skills(self): self.assertGreater(len(self.mol.skills), 0) - @skip("This currently throws a 'NameError'.") def test_qualities_tex(self): self.assertGreater(len(self.mol.qualities_tex), 0) diff --git a/jdav_web/members/views.py b/jdav_web/members/views.py index 14dd53f..29ade70 100644 --- a/jdav_web/members/views.py +++ b/jdav_web/members/views.py @@ -299,7 +299,10 @@ def register(request): else: return render_register(request, group, form, emergency_contacts_formset, waiter_key=waiter_key) # we are not saving yet - return render_register(request, group, form=None, pwd=pwd.password, waiter_key=waiter_key) + if pwd: + return render_register(request, group, form=None, pwd=pwd.password, waiter_key=waiter_key) + else: + return render_register(request, group, form=None, waiter_key=waiter_key) def render_download_registration_form(request, member): From 1b8089dd93322df41131149302cf32146c295393 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 26 Aug 2025 19:46:25 +0200 Subject: [PATCH 2/3] fix(mailer/models): __str__ method of Attachment returns string --- jdav_web/mailer/models.py | 2 +- jdav_web/mailer/tests/models.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index e276772..e9a5199 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -232,7 +232,7 @@ class Attachment(CommonModel): max_upload_size=10) def __str__(self): - return os.path.basename(self.f.name) if self.f.name else _("Empty") + return os.path.basename(self.f.name) if self.f.name else str(_("Empty")) class Meta: verbose_name = _('attachment') diff --git a/jdav_web/mailer/tests/models.py b/jdav_web/mailer/tests/models.py index feaed68..51e183f 100644 --- a/jdav_web/mailer/tests/models.py +++ b/jdav_web/mailer/tests/models.py @@ -267,6 +267,5 @@ class AttachmentTestCase(BasicMailerTestCase): self.attachment.f.name = 'attachments/test_document.pdf' self.assertEqual(str(self.attachment), 'test_document.pdf') - @skip('Fails with TypeError: __str__ returns a lazy translation object, but must return a string.') def test_str_without_file(self): self.assertEqual(str(self.attachment), _('Empty')) From 3003bbe67fe92f2952a0ea88b2fc9eb345564baf Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 26 Aug 2025 19:53:29 +0200 Subject: [PATCH 3/3] fix(finance/admin): pass participant_count only once --- jdav_web/finance/admin.py | 1 - jdav_web/finance/tests/admin.py | 1 - 2 files changed, 2 deletions(-) diff --git a/jdav_web/finance/admin.py b/jdav_web/finance/admin.py index d11b233..360cb02 100644 --- a/jdav_web/finance/admin.py +++ b/jdav_web/finance/admin.py @@ -116,7 +116,6 @@ class StatementUnSubmittedAdmin(CommonAdminMixin, admin.ModelAdmin): opts=self.opts, memberlist=memberlist, object=memberlist, - participant_count=memberlist.participant_count, ljp_contributions=memberlist.payable_ljp_contributions, total_relative_costs=memberlist.total_relative_costs, **memberlist.statement.template_context()) diff --git a/jdav_web/finance/tests/admin.py b/jdav_web/finance/tests/admin.py index 85507fc..944903b 100644 --- a/jdav_web/finance/tests/admin.py +++ b/jdav_web/finance/tests/admin.py @@ -126,7 +126,6 @@ class StatementUnSubmittedAdminTestCase(AdminTestCase): self.assertEqual(response.status_code, HTTPStatus.OK) self.assertContains(response, _('Submit statement')) - @unittest.skip('Currently fails with TypeError, because `participant_count` is passed twice.') def test_submit_view_get_with_excursion(self): url = reverse('admin:finance_statementunsubmitted_submit', args=(self.statement_with_excursion.pk,))