donors

git clone git://ce9e.org/donors

commit
f0984391c11a1395d43a8a9f080c23165570ca1f
parent
5f9ebb60577734730b67b8f85f7187217c6f50f2
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2021-03-07 15:40
cleanup view

Diffstat

M donors/admin.py 10 ++++++++++
M donors/gnucash.py 5 +++++
M donors/settings/base.py 3 +++
A donors/templates/admin/donors/app_index.html 11 +++++++++++
A donors/templates/cleanup.html 29 +++++++++++++++++++++++++++++
M donors/views.py 42 ++++++++++++++++++++++++++++++++++++++++++

6 files changed, 100 insertions, 0 deletions


diff --git a/donors/admin.py b/donors/admin.py

@@ -10,6 +10,7 @@ from .helpers import AnnotatedModelAdminMixin
   10    10 from .helpers import format_currency
   11    11 from .models import Donation
   12    12 from .models import Donor
   -1    13 from .views import CleanupView
   13    14 from .views import merge_action
   14    15 from .views import MergeView
   15    16 
@@ -21,6 +22,15 @@ class Site(admin.AdminSite):
   21    22     index_title = _('Home')
   22    23     enable_nav_sidebar = False
   23    24 
   -1    25     def get_urls(self):
   -1    26         return [
   -1    27             path(
   -1    28                 'donors/cleanup/',
   -1    29                 site.admin_view(CleanupView.as_view()),
   -1    30                 name='cleanup',
   -1    31             ),
   -1    32         ] + super().get_urls()
   -1    33 
   24    34 
   25    35 class DonorAdmin(AnnotatedModelAdminMixin, admin.ModelAdmin):
   26    36     search_fields = ['name']

diff --git a/donors/gnucash.py b/donors/gnucash.py

@@ -1,5 +1,6 @@
    1     1 import datetime
    2     2 
   -1     3 from django.conf import settings
    3     4 from gnucash import Session
    4     5 
    5     6 from .models import Donation
@@ -43,6 +44,10 @@ def add_split(split):
   43    44     if Donation.objects.filter(gnucash_id=data['gnucash_id']).exists():
   44    45         return
   45    46 
   -1    47     min_date = datetime.date.today() - settings.DONATION_STORAGE_DURATION
   -1    48     if data['date'] < min_date:
   -1    49         return
   -1    50 
   46    51     ref = Donation.objects.filter(description=data['description']).first()
   47    52     if ref:
   48    53         donor_id = ref.donor_id

diff --git a/donors/settings/base.py b/donors/settings/base.py

@@ -10,6 +10,7 @@ For the full list of settings and their values, see
   10    10 https://docs.djangoproject.com/en/3.1/ref/settings/
   11    11 """
   12    12 
   -1    13 import datetime
   13    14 import locale
   14    15 
   15    16 ALLOWED_HOSTS = ['localhost']
@@ -97,3 +98,5 @@ locale.setlocale(locale.LC_ALL, 'en_US.UTF8')
   97    98 # https://docs.djangoproject.com/en/3.1/howto/static-files/
   98    99 
   99   100 STATIC_URL = '/static/'
   -1   101 
   -1   102 DONATION_STORAGE_DURATION = datetime.timedelta(365 * 5)

diff --git a/donors/templates/admin/donors/app_index.html b/donors/templates/admin/donors/app_index.html

@@ -0,0 +1,11 @@
   -1     1 {% extends "admin/app_index.html" %}
   -1     2 {% load i18n %}
   -1     3 
   -1     4 {% block content %}
   -1     5     <ul class="object-tools">
   -1     6         <li>
   -1     7             <a href="{% url 'admin:cleanup' %}">{% translate 'Cleanup' %}</a>
   -1     8         </li>
   -1     9     </ul>
   -1    10     {{ block.super }}
   -1    11 {% endblock %}

diff --git a/donors/templates/cleanup.html b/donors/templates/cleanup.html

@@ -0,0 +1,29 @@
   -1     1 {% extends "admin/base_site.html" %}
   -1     2 {% load i18n static %}
   -1     3 
   -1     4 {% block extrahead %}
   -1     5     {{ block.super }}
   -1     6     <script src="{% static 'admin/js/cancel.js' %}" async></script>
   -1     7 {% endblock %}
   -1     8 
   -1     9 {% block breadcrumbs %}
   -1    10     <div class="breadcrumbs">
   -1    11         <a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
   -1    12         &rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
   -1    13         &rsaquo; {{ title }}
   -1    14     </div>
   -1    15 {% endblock %}
   -1    16 
   -1    17 {% block bodyclass %}{{ block.super }} delete-confirmation{% endblock %}
   -1    18 
   -1    19 {% block content %}
   -1    20     <p>{% blocktranslate with escaped_object=object %}Are you sure you want to delete all old donations? All of the following related items will be deleted:{% endblocktranslate %}</p>
   -1    21     {% include "admin/includes/object_delete_summary.html" %}
   -1    22     <h2>{% translate "Objects" %}</h2>
   -1    23     <ul>{{ deleted_objects|unordered_list }}</ul>
   -1    24     <form method="post">
   -1    25         {% csrf_token %}
   -1    26         <input type="submit" value="{% translate 'Yes, I’m sure' %}">
   -1    27         <a href="#" class="button cancel-link">{% translate "No, take me back" %}</a>
   -1    28     </form>
   -1    29 {% endblock %}

diff --git a/donors/views.py b/donors/views.py

@@ -1,7 +1,12 @@
   -1     1 import datetime
   -1     2 
    1     3 from django import forms
   -1     4 from django.contrib import messages
   -1     5 from django.db import models
    2     6 from django.shortcuts import redirect
    3     7 from django.utils.translation import gettext_lazy as _
    4     8 from django.views.generic import FormView
   -1     9 from django.views.generic import TemplateView
    5    10 
    6    11 from .helpers import annotate
    7    12 from .models import Donation
@@ -48,3 +53,40 @@ def merge_action(modeladmin, request, qs):
   48    53     ids = qs.values_list('id', flat=True)
   49    54     query = '&'.join('id=%i' % i for i in ids)
   50    55     return redirect('merge/?%s' % query)
   -1    56 
   -1    57 
   -1    58 class CleanupView(TemplateView):
   -1    59     template_name = 'cleanup.html'
   -1    60 
   -1    61     def get_querysets(self):
   -1    62         max_date = datetime.date.today() - settings.DONATION_STORAGE_DURATION
   -1    63         donations = Donation.objects.filter(date__lt=max_date)
   -1    64         donors = Donor.objects.annotate(
   -1    65             count=models.Count(
   -1    66                 'donation', filter=~models.Q(pk__in=donations.values('pk'))
   -1    67             )
   -1    68         ).filter(count=0)
   -1    69         return donors, donations
   -1    70 
   -1    71     def get(self, request, *args, **kwargs):
   -1    72         from .admin import site
   -1    73 
   -1    74         donors, donations = self.get_querysets()
   -1    75         context = {
   -1    76             **site.each_context(request),
   -1    77             'opts': Donor._meta,
   -1    78             'title': _('Cleanup'),
   -1    79             'deleted_objects': set(donors) | set(donations),
   -1    80             'model_count': [
   -1    81                 (Donor._meta.verbose_name_plural, donors.count()),
   -1    82                 (Donation._meta.verbose_name_plural, donations.count()),
   -1    83             ],
   -1    84         }
   -1    85         return self.render_to_response(context)
   -1    86 
   -1    87     def post(self, request, *args, **kwargs):
   -1    88         donors, donations = self.get_querysets()
   -1    89         donations.delete()
   -1    90         donors.delete()
   -1    91         messages.success(request, _('Cleanup successful'))
   -1    92         return redirect('admin:app_list', 'donors')