From 9d88da3bd3f0a925effdef15d18277b3052ee67e Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Fri, 7 May 2021 22:06:05 +0200 Subject: [PATCH 1/7] #334 Allow admin bulk delete on Action model --- chcemvediet/apps/inforequests/admin.py | 61 +++++++++++++++++-- .../action/delete_selected_confirmation.html | 34 +++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index 5f478cf2..4cfa8944 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -2,15 +2,16 @@ # -*- coding: utf-8 -*- import datetime -from django.contrib import admin +from django.contrib.admin.actions import delete_selected +from django.contrib import admin, messages from django.contrib.admin.utils import NestedObjects from django.core.exceptions import PermissionDenied -from django.db import router +from django.db import router, transaction from django.forms.models import BaseInlineFormSet from django.utils.html import format_html from poleno.utils.date import local_today -from poleno.utils.misc import decorate +from poleno.utils.misc import decorate, squeeze from poleno.utils.admin import (simple_list_filter_factory, admin_obj_format, ReadOnlyAdminInlineMixin, NoBulkDeleteAdminMixin) from chcemvediet.apps.inforequests.constants import ADMIN_EXTEND_SNOOZE_BY_DAYS @@ -333,7 +334,7 @@ def delete_model(self, request, obj): return super(BranchAdmin, self).delete_model(request, obj) @admin.register(Action, site=admin.site) -class ActionAdmin(NoBulkDeleteAdminMixin, DeleteNestedInforequestEmailAdminMixin, admin.ModelAdmin): +class ActionAdmin(DeleteNestedInforequestEmailAdminMixin, admin.ModelAdmin): date_hierarchy = u'created' list_display = [ u'id', @@ -374,6 +375,9 @@ class ActionAdmin(NoBulkDeleteAdminMixin, DeleteNestedInforequestEmailAdminMixin inlines = [ BranchInline, ] + actions = [ + u'delete_selected' + ] def get_queryset(self, request): queryset = super(ActionAdmin, self).get_queryset(request) @@ -399,6 +403,55 @@ def render_delete_form(self, request, context): context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS return super(ActionAdmin, self).render_delete_form(request, context) + @transaction.atomic + def delete_selected(self, request, queryset): + constraints = [] + warnings = [] + outbound = InforequestEmail.objects.none() + inbound = InforequestEmail.objects.none() + for obj in queryset: + obj_constraints = self.delete_constraints(obj) + constraints += obj_constraints + inforequestemails = self.nested_inforequestemail_queryset(obj) + outbound |= inforequestemails[0] + inbound |= inforequestemails[1] + if not obj_constraints: + if not obj.is_last_action and obj.next_action not in queryset: + warnings.append(format_html(squeeze(u""" + {} is not the last action in the branch. Deleting it may cause logical + errors in the inforequest history. + """).format(admin_obj_format(obj)))) + + if request.POST.get(u'post'): + if constraints: + raise PermissionDenied + + template_response = delete_selected(self, request, queryset) + + if request.POST.get(u'post'): + n = outbound.count() + if n: + outbound.delete() + self.message_user(request, + u'Successfully deleted {} applicant_action inforequestemails.'.format(n), + messages.SUCCESS) + m = inbound.count() + if m: + inbound.update(type=InforequestEmail.TYPES.UNDECIDED) + self.message_user(request, + u'Successfully updated {} obligee_action inforequestemails.'.format(m), + messages.SUCCESS) + return None + + template_response.context_data.update({ + u'outbound': [admin_obj_format(inforequestemail) for inforequestemail in outbound], + u'inbound': [admin_obj_format(inforequestemail) for inforequestemail in inbound], + u'delete_constraints': constraints, + u'warnings': warnings, + }) + return template_response + delete_selected.short_description = u'Delete selected actions' + def delete_model(self, request, obj): if self.delete_constraints(obj): raise PermissionDenied diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html new file mode 100644 index 00000000..fe1b6645 --- /dev/null +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html @@ -0,0 +1,34 @@ +{% extends "admin/delete_selected_confirmation.html" %} +{% load amend before after set_attributes from poleno.amend %} + +{% block content %} + {% amend %} + {{ block.super }} + {% after path="./ul[last()]" %} + {% if outbound %} +

Outbound messages will be deleted:

+ + {% endif %} + {% if inbound %} +

Inbound messages will be marked undecided:

+ + {% endif %} + {% endafter %} + {% before path=".//form" %} + {% if warnings %} + + {% endif %} + {% if delete_constraints %} +
+

Delete not allowed.

+ +
+ {% set_attributes path=".//form//input[@type='submit']" disabled=True %} + {% endif %} + {% endbefore %} + {% endamend %} +{% endblock %} From 288536552d46585afedc535d316fc699d8afa083 Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Mon, 17 May 2021 18:06:33 +0200 Subject: [PATCH 2/7] #334 Various refactoring --- chcemvediet/apps/inforequests/admin.py | 53 +++++++++---------- .../action/delete_confirmation.html | 25 +++++---- .../action/delete_selected_confirmation.html | 4 +- chcemvediet/urls.py | 5 ++ poleno/utils/admin.py | 7 --- 5 files changed, 43 insertions(+), 51 deletions(-) diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index 4cfa8944..fba2943e 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- import datetime +from django.contrib import admin from django.contrib.admin.actions import delete_selected -from django.contrib import admin, messages from django.contrib.admin.utils import NestedObjects from django.core.exceptions import PermissionDenied from django.db import router, transaction @@ -13,7 +13,7 @@ from poleno.utils.date import local_today from poleno.utils.misc import decorate, squeeze from poleno.utils.admin import (simple_list_filter_factory, admin_obj_format, - ReadOnlyAdminInlineMixin, NoBulkDeleteAdminMixin) + ReadOnlyAdminInlineMixin) from chcemvediet.apps.inforequests.constants import ADMIN_EXTEND_SNOOZE_BY_DAYS from .models import Inforequest, InforequestDraft, InforequestEmail, Branch, Action @@ -261,7 +261,7 @@ def get_queryset(self, request): return queryset @admin.register(Branch, site=admin.site) -class BranchAdmin(NoBulkDeleteAdminMixin, DeleteNestedInforequestEmailAdminMixin, admin.ModelAdmin): +class BranchAdmin(DeleteNestedInforequestEmailAdminMixin, admin.ModelAdmin): date_hierarchy = None list_display = [ u'id', @@ -388,6 +388,15 @@ def get_queryset(self, request): def get_inforequest(self, obj): return obj.branch.inforequest + def delete_warnings(self, obj): + warnings = [] + if not obj.is_last_action: + warnings.append(format_html(squeeze(u""" + {} is not the last action in the branch. Deleting it may cause logical errors in + the inforequest history. + """).format(admin_obj_format(obj)))) + return warnings + def delete_constraints(self, obj): constraints = [] if obj.type in [Action.TYPES.REQUEST, Action.TYPES.ADVANCED_REQUEST]: @@ -399,58 +408,44 @@ def delete_constraints(self, obj): return constraints def render_delete_form(self, request, context): + context[u'delete_warnings'] = self.delete_warnings(context[u'object']) context[u'delete_constraints'] = self.delete_constraints(context[u'object']) context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS return super(ActionAdmin, self).render_delete_form(request, context) + @decorate(short_description=u'Delete selected actions') @transaction.atomic def delete_selected(self, request, queryset): - constraints = [] - warnings = [] + delete_warnings = [] + delete_constraints = [] outbound = InforequestEmail.objects.none() inbound = InforequestEmail.objects.none() for obj in queryset: - obj_constraints = self.delete_constraints(obj) - constraints += obj_constraints + if obj.next_action not in queryset: + delete_warnings += self.delete_warnings(obj) + delete_constraints += self.delete_constraints(obj) inforequestemails = self.nested_inforequestemail_queryset(obj) outbound |= inforequestemails[0] inbound |= inforequestemails[1] - if not obj_constraints: - if not obj.is_last_action and obj.next_action not in queryset: - warnings.append(format_html(squeeze(u""" - {} is not the last action in the branch. Deleting it may cause logical - errors in the inforequest history. - """).format(admin_obj_format(obj)))) if request.POST.get(u'post'): - if constraints: + if delete_constraints: raise PermissionDenied template_response = delete_selected(self, request, queryset) if request.POST.get(u'post'): - n = outbound.count() - if n: - outbound.delete() - self.message_user(request, - u'Successfully deleted {} applicant_action inforequestemails.'.format(n), - messages.SUCCESS) - m = inbound.count() - if m: - inbound.update(type=InforequestEmail.TYPES.UNDECIDED) - self.message_user(request, - u'Successfully updated {} obligee_action inforequestemails.'.format(m), - messages.SUCCESS) + outbound.delete() + inbound.update(type=InforequestEmail.TYPES.UNDECIDED) return None template_response.context_data.update({ u'outbound': [admin_obj_format(inforequestemail) for inforequestemail in outbound], u'inbound': [admin_obj_format(inforequestemail) for inforequestemail in inbound], - u'delete_constraints': constraints, - u'warnings': warnings, + u'delete_warnings': delete_warnings, + u'delete_constraints': delete_constraints, }) return template_response - delete_selected.short_description = u'Delete selected actions' def delete_model(self, request, obj): if self.delete_constraints(obj): diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html index 2cf0038a..5cda4a86 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html @@ -14,27 +14,26 @@ {% endif %} {% endafter %} - {% if not object.is_last_action %} - {% before path=".//form" %} -

- Warning: The deleted action is not the last action in the branch. Deleting it may - cause logical errors in the inforequest history. -

- {% endbefore %} - {% endif %} {% if object.type == object.TYPES.EXPIRATION or object.type == object.TYPES.APPEAL_EXPIRATION %} {% prepend path=".//form" %}

{% endprepend %} {% endif %} - {% if delete_constraints %} - {% before path=".//form" %} + {% before path=".//form" %} + {% if delete_warnings %} + + {% endif %} + {% if delete_constraints %}

Delete not allowed.

    {{ delete_constraints|unordered_list }}
- {% endbefore %} - {% set_attributes path=".//form//input[@type='submit']" disabled=True %} - {% endif %} + {% set_attributes path=".//form//input[@type='submit']" disabled=True %} + {% endif %} + {% endbefore %} {% endamend %} {% endblock %} diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html index fe1b6645..a445fd54 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html @@ -15,9 +15,9 @@ {% endif %} {% endafter %} {% before path=".//form" %} - {% if warnings %} + {% if delete_warnings %} diff --git a/chcemvediet/urls.py b/chcemvediet/urls.py index 48b52434..640d1fec 100644 --- a/chcemvediet/urls.py +++ b/chcemvediet/urls.py @@ -32,6 +32,11 @@ url(r'', include(u'poleno.pages.urls', namespace=u'pages')), ) +try: + admin.site.disable_action(u'delete_selected') +except KeyError: + pass + if settings.DEBUG: # pragma: no cover urlpatterns = patterns(u'', url(r'^media/(?P.*)$', u'django.views.static.serve', {u'document_root': settings.MEDIA_ROOT, u'show_indexes': True}), diff --git a/poleno/utils/admin.py b/poleno/utils/admin.py index 4c57d51b..4e5d6889 100644 --- a/poleno/utils/admin.py +++ b/poleno/utils/admin.py @@ -58,10 +58,3 @@ def has_add_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None): return False - -class NoBulkDeleteAdminMixin(admin.ModelAdmin): - - def get_actions(self, request): - actions = super(NoBulkDeleteAdminMixin, self).get_actions(request) - actions.pop(u'delete_selected', None) - return actions From 37744545d9ad1af0bd5af99e9e6b7250f7abad23 Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Sun, 23 May 2021 21:59:36 +0200 Subject: [PATCH 3/7] #334 Snooze previous actions --- chcemvediet/apps/__init__.py | 1 + chcemvediet/apps/inforequests/admin.py | 68 +++++++++++-------- .../action/delete_confirmation.html | 2 +- .../action/delete_selected_confirmation.html | 12 +++- chcemvediet/urls.py | 5 -- 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/chcemvediet/apps/__init__.py b/chcemvediet/apps/__init__.py index 4bdd2e33..9f2a1f58 100644 --- a/chcemvediet/apps/__init__.py +++ b/chcemvediet/apps/__init__.py @@ -8,6 +8,7 @@ def init_admin_site_plus(self): from adminplus.sites import AdminSitePlus from django.contrib import admin admin.site = AdminSitePlus() + admin.site.disable_action(u'delete_selected') admin.autodiscover() def workaround_sqlite_format_dtdelta_bug(self): diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index fba2943e..22b8f21a 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -21,19 +21,19 @@ class DeleteNestedInforequestEmailAdminMixin(admin.ModelAdmin): - def get_inforequest(self, obj): + def get_inforequest(self, objs): raise NotImplementedError - def nested_inforequestemail_queryset(self, obj): + def nested_inforequestemail_queryset(self, objs): using = router.db_for_write(self.model) collector = NestedObjects(using) - collector.collect([obj]) + collector.collect(objs) to_delete = collector.nested() - inforequest = self.get_inforequest(obj) + inforequests = self.get_inforequest(objs) actions = [obj for obj in self.nested_objects_traverse(to_delete) if isinstance(obj, Action)] emails = [action.email for action in actions if action.email] - inforequestemails_qs = InforequestEmail.objects.filter(inforequest=inforequest, + inforequestemails_qs = InforequestEmail.objects.filter(inforequest=inforequests, email__in=emails) outbound = inforequestemails_qs.filter(type=InforequestEmail.TYPES.APPLICANT_ACTION) inbound = inforequestemails_qs.filter(type=InforequestEmail.TYPES.OBLIGEE_ACTION) @@ -48,14 +48,14 @@ def nested_objects_traverse(self, to_delete): yield to_delete def render_delete_form(self, request, context): - outbound, inbound = self.nested_inforequestemail_queryset(context[u'object']) + outbound, inbound = self.nested_inforequestemail_queryset([context[u'object']]) context[u'outbound'] = [admin_obj_format(inforequestemail) for inforequestemail in outbound] context[u'inbound'] = [admin_obj_format(inforequestemail) for inforequestemail in inbound] return super(DeleteNestedInforequestEmailAdminMixin, self).render_delete_form(request, context) def delete_model(self, request, obj): - outbound, inbound = self.nested_inforequestemail_queryset(obj) + outbound, inbound = self.nested_inforequestemail_queryset([obj]) outbound.delete() inbound.update(type=InforequestEmail.TYPES.UNDECIDED) super(DeleteNestedInforequestEmailAdminMixin, self).delete_model(request, obj) @@ -317,8 +317,8 @@ def get_queryset(self, request): queryset = queryset.select_related(u'advanced_by') return queryset - def get_inforequest(self, obj): - return obj.inforequest + def get_inforequest(self, objs): + return Inforequest.objects.filter(branch__in=objs) def delete_constraints(self, obj): if obj.is_main: @@ -385,12 +385,15 @@ def get_queryset(self, request): queryset = queryset.select_related(u'email') return queryset - def get_inforequest(self, obj): - return obj.branch.inforequest + def get_inforequest(self, objs): + return Inforequest.objects.filter(branch__action__in=objs) - def delete_warnings(self, obj): + def delete_warnings(self, obj, to_delete=None): + if self.delete_constraints(obj): + return [] + to_delete = to_delete or [] warnings = [] - if not obj.is_last_action: + if not obj.is_last_action and obj.next_action not in to_delete: warnings.append(format_html(squeeze(u""" {} is not the last action in the branch. Deleting it may cause logical errors in the inforequest history. @@ -407,10 +410,18 @@ def delete_constraints(self, obj): u'{} is the only action in the branch.'.format(admin_obj_format(obj)))) return constraints + def can_snooze(self, obj): + if (obj.type in [Action.TYPES.EXPIRATION, Action.TYPES.APPEAL_EXPIRATION] + and obj.previous_action): + return True + return False + def render_delete_form(self, request, context): - context[u'delete_warnings'] = self.delete_warnings(context[u'object']) - context[u'delete_constraints'] = self.delete_constraints(context[u'object']) - context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS + obj = context[u'object'] + context[u'delete_warnings'] = self.delete_warnings(obj) + context[u'delete_constraints'] = self.delete_constraints(obj) + if self.can_snooze(obj): + context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS return super(ActionAdmin, self).render_delete_form(request, context) @decorate(short_description=u'Delete selected actions') @@ -418,15 +429,13 @@ def render_delete_form(self, request, context): def delete_selected(self, request, queryset): delete_warnings = [] delete_constraints = [] - outbound = InforequestEmail.objects.none() - inbound = InforequestEmail.objects.none() + snoozed_actions = [] for obj in queryset: - if obj.next_action not in queryset: - delete_warnings += self.delete_warnings(obj) + delete_warnings += self.delete_warnings(obj, queryset) delete_constraints += self.delete_constraints(obj) - inforequestemails = self.nested_inforequestemail_queryset(obj) - outbound |= inforequestemails[0] - inbound |= inforequestemails[1] + if self.can_snooze(obj): + snoozed_actions.append(obj.previous_action) + outbound, inbound = self.nested_inforequestemail_queryset(queryset) if request.POST.get(u'post'): if delete_constraints: @@ -435,6 +444,10 @@ def delete_selected(self, request, queryset): template_response = delete_selected(self, request, queryset) if request.POST.get(u'post'): + if request.POST.get(u'snooze'): + for action in snoozed_actions: + action.snooze = local_today() + datetime.timedelta(days=ADMIN_EXTEND_SNOOZE_BY_DAYS) + action.save(update_fields=[u'snooze']) outbound.delete() inbound.update(type=InforequestEmail.TYPES.UNDECIDED) return None @@ -442,8 +455,9 @@ def delete_selected(self, request, queryset): template_response.context_data.update({ u'outbound': [admin_obj_format(inforequestemail) for inforequestemail in outbound], u'inbound': [admin_obj_format(inforequestemail) for inforequestemail in inbound], - u'delete_warnings': delete_warnings, - u'delete_constraints': delete_constraints, + u'snoozed_actions': [admin_obj_format(action) for action in snoozed_actions], + u'delete_warnings': delete_warnings, + u'delete_constraints': delete_constraints, }) return template_response @@ -451,9 +465,7 @@ def delete_model(self, request, obj): if self.delete_constraints(obj): raise PermissionDenied if request.POST: - if (request.POST.get(u'snooze') - and obj.type in [Action.TYPES.EXPIRATION, Action.TYPES.APPEAL_EXPIRATION] - and obj.previous_action): + if request.POST.get(u'snooze') and self.can_snooze(obj): previous = obj.previous_action previous.snooze = local_today() + datetime.timedelta(days=ADMIN_EXTEND_SNOOZE_BY_DAYS) previous.save(update_fields=[u'snooze']) diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html index 5cda4a86..22c8c478 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html @@ -14,7 +14,7 @@
    {{ inbound|unordered_list }}
{% endif %} {% endafter %} - {% if object.type == object.TYPES.EXPIRATION or object.type == object.TYPES.APPEAL_EXPIRATION %} + {% if ADMIN_EXTEND_SNOOZE_BY_DAYS %} {% prepend path=".//form" %}

{% endprepend %} diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html index a445fd54..aba5c968 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html @@ -1,5 +1,5 @@ {% extends "admin/delete_selected_confirmation.html" %} -{% load amend before after set_attributes from poleno.amend %} +{% load amend prepend before after set_attributes from poleno.amend %} {% block content %} {% amend %} @@ -14,6 +14,16 @@
    {{ inbound|unordered_list }}
{% endif %} {% endafter %} + {% if snoozed_actions %} + {% prepend path=".//form" %} +

+ +

+
    {{ snoozed_actions|unordered_list }}
+ {% endprepend %} + {% endif %} {% before path=".//form" %} {% if delete_warnings %}
    diff --git a/chcemvediet/urls.py b/chcemvediet/urls.py index 640d1fec..48b52434 100644 --- a/chcemvediet/urls.py +++ b/chcemvediet/urls.py @@ -32,11 +32,6 @@ url(r'', include(u'poleno.pages.urls', namespace=u'pages')), ) -try: - admin.site.disable_action(u'delete_selected') -except KeyError: - pass - if settings.DEBUG: # pragma: no cover urlpatterns = patterns(u'', url(r'^media/(?P.*)$', u'django.views.static.serve', {u'document_root': settings.MEDIA_ROOT, u'show_indexes': True}), From f507fa909b2ab7c08ae88b904a1074120b378dca Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Thu, 3 Jun 2021 18:34:55 +0200 Subject: [PATCH 4/7] #334 Refactor methods for snooze --- chcemvediet/apps/inforequests/admin.py | 42 +++++++++---------- .../action/delete_confirmation.html | 2 +- .../action/delete_selected_confirmation.html | 5 ++- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index 22b8f21a..aeab4891 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -21,7 +21,7 @@ class DeleteNestedInforequestEmailAdminMixin(admin.ModelAdmin): - def get_inforequest(self, objs): + def get_inforequests(self, objs): raise NotImplementedError def nested_inforequestemail_queryset(self, objs): @@ -29,7 +29,7 @@ def nested_inforequestemail_queryset(self, objs): collector = NestedObjects(using) collector.collect(objs) to_delete = collector.nested() - inforequests = self.get_inforequest(objs) + inforequests = self.get_inforequests(objs) actions = [obj for obj in self.nested_objects_traverse(to_delete) if isinstance(obj, Action)] emails = [action.email for action in actions if action.email] @@ -317,7 +317,7 @@ def get_queryset(self, request): queryset = queryset.select_related(u'advanced_by') return queryset - def get_inforequest(self, objs): + def get_inforequests(self, objs): return Inforequest.objects.filter(branch__in=objs) def delete_constraints(self, obj): @@ -385,12 +385,10 @@ def get_queryset(self, request): queryset = queryset.select_related(u'email') return queryset - def get_inforequest(self, objs): + def get_inforequests(self, objs): return Inforequest.objects.filter(branch__action__in=objs) def delete_warnings(self, obj, to_delete=None): - if self.delete_constraints(obj): - return [] to_delete = to_delete or [] warnings = [] if not obj.is_last_action and obj.next_action not in to_delete: @@ -410,18 +408,23 @@ def delete_constraints(self, obj): u'{} is the only action in the branch.'.format(admin_obj_format(obj)))) return constraints - def can_snooze(self, obj): - if (obj.type in [Action.TYPES.EXPIRATION, Action.TYPES.APPEAL_EXPIRATION] - and obj.previous_action): - return True - return False + def can_snooze_previous_action(self, obj): + if obj.type not in [Action.TYPES.EXPIRATION, Action.TYPES.APPEAL_EXPIRATION]: + return False + if not obj.previous_action: + return False + return True + + def snooze_action(self, obj): + obj.snooze = local_today() + datetime.timedelta(days=ADMIN_EXTEND_SNOOZE_BY_DAYS) + obj.save(update_fields=[u'snooze']) def render_delete_form(self, request, context): obj = context[u'object'] context[u'delete_warnings'] = self.delete_warnings(obj) context[u'delete_constraints'] = self.delete_constraints(obj) - if self.can_snooze(obj): - context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS + context[u'can_snooze_previous_action'] = self.can_snooze_previous_action(obj) + context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS return super(ActionAdmin, self).render_delete_form(request, context) @decorate(short_description=u'Delete selected actions') @@ -433,7 +436,7 @@ def delete_selected(self, request, queryset): for obj in queryset: delete_warnings += self.delete_warnings(obj, queryset) delete_constraints += self.delete_constraints(obj) - if self.can_snooze(obj): + if self.can_snooze_previous_action(obj) and obj.previous_action not in queryset: snoozed_actions.append(obj.previous_action) outbound, inbound = self.nested_inforequestemail_queryset(queryset) @@ -446,8 +449,7 @@ def delete_selected(self, request, queryset): if request.POST.get(u'post'): if request.POST.get(u'snooze'): for action in snoozed_actions: - action.snooze = local_today() + datetime.timedelta(days=ADMIN_EXTEND_SNOOZE_BY_DAYS) - action.save(update_fields=[u'snooze']) + self.snooze_action(action) outbound.delete() inbound.update(type=InforequestEmail.TYPES.UNDECIDED) return None @@ -456,6 +458,7 @@ def delete_selected(self, request, queryset): u'outbound': [admin_obj_format(inforequestemail) for inforequestemail in outbound], u'inbound': [admin_obj_format(inforequestemail) for inforequestemail in inbound], u'snoozed_actions': [admin_obj_format(action) for action in snoozed_actions], + u'ADMIN_EXTEND_SNOOZE_BY_DAYS': ADMIN_EXTEND_SNOOZE_BY_DAYS, u'delete_warnings': delete_warnings, u'delete_constraints': delete_constraints, }) @@ -464,9 +467,6 @@ def delete_selected(self, request, queryset): def delete_model(self, request, obj): if self.delete_constraints(obj): raise PermissionDenied - if request.POST: - if request.POST.get(u'snooze') and self.can_snooze(obj): - previous = obj.previous_action - previous.snooze = local_today() + datetime.timedelta(days=ADMIN_EXTEND_SNOOZE_BY_DAYS) - previous.save(update_fields=[u'snooze']) + if request.POST.get(u'snooze') and self.can_snooze_previous_action(obj): + self.snooze_action(obj.previous_action) return super(ActionAdmin, self).delete_model(request, obj) diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html index 22c8c478..117bce73 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html @@ -14,7 +14,7 @@
      {{ inbound|unordered_list }}
    {% endif %} {% endafter %} - {% if ADMIN_EXTEND_SNOOZE_BY_DAYS %} + {% if can_snooze_previous_action %} {% prepend path=".//form" %}

    {% endprepend %} diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html index aba5c968..25488c10 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html @@ -17,8 +17,9 @@ {% if snoozed_actions %} {% prepend path=".//form" %}

    -

      {{ snoozed_actions|unordered_list }}
    From 2f3f35250b3315762414ab699b8db843f26305af Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Thu, 3 Jun 2021 18:48:53 +0200 Subject: [PATCH 5/7] #334 Unify delete_confirmation and delete_selected_confirmation templates --- chcemvediet/apps/inforequests/admin.py | 5 +++-- .../inforequests/action/delete_confirmation.html | 12 +++++++++--- .../action/delete_selected_confirmation.html | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index aeab4891..139fe777 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -423,8 +423,9 @@ def render_delete_form(self, request, context): obj = context[u'object'] context[u'delete_warnings'] = self.delete_warnings(obj) context[u'delete_constraints'] = self.delete_constraints(obj) - context[u'can_snooze_previous_action'] = self.can_snooze_previous_action(obj) - context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS + if self.can_snooze_previous_action(obj): + context[u'snoozed_actions'] = [admin_obj_format(obj.previous_action)] + context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS return super(ActionAdmin, self).render_delete_form(request, context) @decorate(short_description=u'Delete selected actions') diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html index 117bce73..dd39fc29 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html @@ -14,12 +14,18 @@
      {{ inbound|unordered_list }}
    {% endif %} {% endafter %} - {% if can_snooze_previous_action %} + {% if snoozed_actions %} {% prepend path=".//form" %} -

    +

    + +

    +
      {{ snoozed_actions|unordered_list }}
    {% endprepend %} {% endif %} - {% before path=".//form" %} + {% before path=".//form//input[@type='submit']" %} {% if delete_warnings %}
      {% for warning in delete_warnings %} diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html index 25488c10..3ef672d7 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html @@ -25,7 +25,7 @@
        {{ snoozed_actions|unordered_list }}
      {% endprepend %} {% endif %} - {% before path=".//form" %} + {% before path=".//form//input[@type='submit']" %} {% if delete_warnings %}
        {% for warning in delete_warnings %} From e89900b498f20e24f1ed6b048374c706bd25fe55 Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Mon, 14 Jun 2021 16:49:02 +0200 Subject: [PATCH 6/7] #394 Change inforequestemails queryset --- chcemvediet/apps/inforequests/admin.py | 20 +++++++------------ .../action/delete_confirmation.html | 4 ++-- .../action/delete_selected_confirmation.html | 4 ++-- .../branch/delete_confirmation.html | 4 ++-- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index 139fe777..1e6fbfb9 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -21,20 +21,20 @@ class DeleteNestedInforequestEmailAdminMixin(admin.ModelAdmin): - def get_inforequests(self, objs): - raise NotImplementedError - def nested_inforequestemail_queryset(self, objs): using = router.db_for_write(self.model) collector = NestedObjects(using) collector.collect(objs) to_delete = collector.nested() - inforequests = self.get_inforequests(objs) actions = [obj for obj in self.nested_objects_traverse(to_delete) if isinstance(obj, Action)] - emails = [action.email for action in actions if action.email] - inforequestemails_qs = InforequestEmail.objects.filter(inforequest=inforequests, - email__in=emails) + inforequestemails_qs = InforequestEmail.objects.none() + for action in actions: + if action.email: + inforequestemails_qs |= InforequestEmail.objects.filter( + inforequest=action.branch.inforequest, + email=action.email, + ) outbound = inforequestemails_qs.filter(type=InforequestEmail.TYPES.APPLICANT_ACTION) inbound = inforequestemails_qs.filter(type=InforequestEmail.TYPES.OBLIGEE_ACTION) return outbound, inbound @@ -317,9 +317,6 @@ def get_queryset(self, request): queryset = queryset.select_related(u'advanced_by') return queryset - def get_inforequests(self, objs): - return Inforequest.objects.filter(branch__in=objs) - def delete_constraints(self, obj): if obj.is_main: return [format_html(u'{} is main.'.format(admin_obj_format(obj)))] @@ -385,9 +382,6 @@ def get_queryset(self, request): queryset = queryset.select_related(u'email') return queryset - def get_inforequests(self, objs): - return Inforequest.objects.filter(branch__action__in=objs) - def delete_warnings(self, obj, to_delete=None): to_delete = to_delete or [] warnings = [] diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html index dd39fc29..10fd2ac0 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_confirmation.html @@ -6,11 +6,11 @@ {{ block.super }} {% after path="./ul[last()]" %} {% if outbound %} -

        Outbound messages will be deleted:

        +

        The following outbound messages will be deleted:

          {{ outbound|unordered_list }}
        {% endif %} {% if inbound %} -

        Inbound messages will be marked undecided:

        +

        The following inbound messages will be marked undecided:

          {{ inbound|unordered_list }}
        {% endif %} {% endafter %} diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html index 3ef672d7..8be8a9cc 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/action/delete_selected_confirmation.html @@ -6,11 +6,11 @@ {{ block.super }} {% after path="./ul[last()]" %} {% if outbound %} -

        Outbound messages will be deleted:

        +

        The following outbound messages will be deleted:

          {{ outbound|unordered_list }}
        {% endif %} {% if inbound %} -

        Inbound messages will be marked undecided:

        +

        The following inbound messages will be marked undecided:

          {{ inbound|unordered_list }}
        {% endif %} {% endafter %} diff --git a/chcemvediet/apps/inforequests/templates/admin/inforequests/branch/delete_confirmation.html b/chcemvediet/apps/inforequests/templates/admin/inforequests/branch/delete_confirmation.html index 94983660..48cb5a58 100644 --- a/chcemvediet/apps/inforequests/templates/admin/inforequests/branch/delete_confirmation.html +++ b/chcemvediet/apps/inforequests/templates/admin/inforequests/branch/delete_confirmation.html @@ -6,11 +6,11 @@ {{ block.super }} {% after path="./ul[last()]" %} {% if outbound %} -

        Outbound messages will be deleted:

        +

        The following outbound messages will be deleted:

          {{ outbound|unordered_list }}
        {% endif %} {% if inbound %} -

        Inbound messages will be marked undecided:

        +

        The following inbound messages will be marked undecided:

          {{ inbound|unordered_list }}
        {% endif %} {% endafter %} From 6c0d9443de1b2e2ec7039dd943ebe6af11ccb865 Mon Sep 17 00:00:00 2001 From: viliambalaz Date: Fri, 25 Jun 2021 09:45:39 +0200 Subject: [PATCH 7/7] #334 Send queryset as parameter to delete_constraints and delete_warning methods --- chcemvediet/apps/inforequests/admin.py | 58 +++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/chcemvediet/apps/inforequests/admin.py b/chcemvediet/apps/inforequests/admin.py index 1e6fbfb9..0a30c0cc 100644 --- a/chcemvediet/apps/inforequests/admin.py +++ b/chcemvediet/apps/inforequests/admin.py @@ -317,16 +317,19 @@ def get_queryset(self, request): queryset = queryset.select_related(u'advanced_by') return queryset - def delete_constraints(self, obj): - if obj.is_main: - return [format_html(u'{} is main.'.format(admin_obj_format(obj)))] + def delete_constraints(self, objs): + constraints = [] + for obj in objs: + if obj.is_main: + constraints.append(format_html(u'{} is main.'.format(admin_obj_format(obj)))) + return constraints def render_delete_form(self, request, context): - context[u'delete_constraints'] = self.delete_constraints(context[u'object']) + context[u'delete_constraints'] = self.delete_constraints([context[u'object']]) return super(BranchAdmin, self).render_delete_form(request, context) def delete_model(self, request, obj): - if self.delete_constraints(obj): + if self.delete_constraints([obj]): raise PermissionDenied return super(BranchAdmin, self).delete_model(request, obj) @@ -382,24 +385,25 @@ def get_queryset(self, request): queryset = queryset.select_related(u'email') return queryset - def delete_warnings(self, obj, to_delete=None): - to_delete = to_delete or [] + def delete_warnings(self, objs): warnings = [] - if not obj.is_last_action and obj.next_action not in to_delete: - warnings.append(format_html(squeeze(u""" - {} is not the last action in the branch. Deleting it may cause logical errors in - the inforequest history. - """).format(admin_obj_format(obj)))) + for obj in objs: + if not obj.is_last_action and obj.next_action not in objs: + warnings.append(format_html(squeeze(u""" + {} is not the last action in the branch. Deleting it may cause logical + errors in the inforequest history. + """).format(admin_obj_format(obj)))) return warnings - def delete_constraints(self, obj): + def delete_constraints(self, objs): constraints = [] - if obj.type in [Action.TYPES.REQUEST, Action.TYPES.ADVANCED_REQUEST]: - constraints.append(format_html( - u'{} is type {}.'.format(admin_obj_format(obj), obj.get_type_display()))) - if len(obj.branch.actions) == 1: - constraints.append(format_html( - u'{} is the only action in the branch.'.format(admin_obj_format(obj)))) + for obj in objs: + if obj.type in [Action.TYPES.REQUEST, Action.TYPES.ADVANCED_REQUEST]: + constraints.append(format_html( + u'{} is type {}.'.format(admin_obj_format(obj), obj.get_type_display()))) + if len(obj.branch.actions) == 1: + constraints.append(format_html( + u'{} is the only action in the branch.'.format(admin_obj_format(obj)))) return constraints def can_snooze_previous_action(self, obj): @@ -415,8 +419,8 @@ def snooze_action(self, obj): def render_delete_form(self, request, context): obj = context[u'object'] - context[u'delete_warnings'] = self.delete_warnings(obj) - context[u'delete_constraints'] = self.delete_constraints(obj) + context[u'delete_warnings'] = self.delete_warnings([obj]) + context[u'delete_constraints'] = self.delete_constraints([obj]) if self.can_snooze_previous_action(obj): context[u'snoozed_actions'] = [admin_obj_format(obj.previous_action)] context[u'ADMIN_EXTEND_SNOOZE_BY_DAYS'] = ADMIN_EXTEND_SNOOZE_BY_DAYS @@ -425,18 +429,14 @@ def render_delete_form(self, request, context): @decorate(short_description=u'Delete selected actions') @transaction.atomic def delete_selected(self, request, queryset): - delete_warnings = [] - delete_constraints = [] snoozed_actions = [] for obj in queryset: - delete_warnings += self.delete_warnings(obj, queryset) - delete_constraints += self.delete_constraints(obj) if self.can_snooze_previous_action(obj) and obj.previous_action not in queryset: snoozed_actions.append(obj.previous_action) outbound, inbound = self.nested_inforequestemail_queryset(queryset) if request.POST.get(u'post'): - if delete_constraints: + if self.delete_constraints(queryset): raise PermissionDenied template_response = delete_selected(self, request, queryset) @@ -454,13 +454,13 @@ def delete_selected(self, request, queryset): u'inbound': [admin_obj_format(inforequestemail) for inforequestemail in inbound], u'snoozed_actions': [admin_obj_format(action) for action in snoozed_actions], u'ADMIN_EXTEND_SNOOZE_BY_DAYS': ADMIN_EXTEND_SNOOZE_BY_DAYS, - u'delete_warnings': delete_warnings, - u'delete_constraints': delete_constraints, + u'delete_warnings': self.delete_warnings(queryset), + u'delete_constraints': self.delete_constraints(queryset), }) return template_response def delete_model(self, request, obj): - if self.delete_constraints(obj): + if self.delete_constraints([obj]): raise PermissionDenied if request.POST.get(u'snooze') and self.can_snooze_previous_action(obj): self.snooze_action(obj.previous_action)