diff --git a/members/models.py b/members/models.py index ff023b1..64856ba 100644 --- a/members/models.py +++ b/members/models.py @@ -3,8 +3,7 @@ from django.db import models from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from django.db.models import Q - +from django.db.models import Q, F, OuterRef, Subquery import csv @@ -125,6 +124,11 @@ class Member(BaseMember): qs = qs.filter(Q(first_name__icontains=term) | Q(last_name__icontains=term)) return qs + def get_members_with_latest_payment(members_query): + """Return QuerySet of given members QS with last_paid attribute.""" + latest = Payment.objects.filter(member=OuterRef('pk')).order_by('-date') + return members_query.annotate(last_paid=Subquery(latest.values('date')[:1])) + # To avoid problems with a cyclical import, this is at the bottom of the file from members.forms import MemberForm # nopep8 diff --git a/members/tables.py b/members/tables.py index a70aff6..89ecca1 100644 --- a/members/tables.py +++ b/members/tables.py @@ -4,6 +4,7 @@ import django_tables2 as tables from django.utils.translation import ugettext as _ from django.core.exceptions import ObjectDoesNotExist from django.db.models import F, OuterRef, Subquery +from django.utils import timezone from members.models import Member, Payment, Request @@ -15,10 +16,7 @@ class MemberTable(tables.Table): options = tables.TemplateColumn( ('') + - _('Edit') + - '', - verbose_name="" + 'href="/members/edit/{{ record.id }}">') + _('Edit') + '', verbose_name="" ) class Meta: @@ -28,13 +26,12 @@ class MemberTable(tables.Table): def render_last_paid(self, record): try: - return record.payments.filter(member=record).latest('date').date.strftime('%e.%m.%Y %H:%M') + return timezone.localtime(record.payments.filter(member=record).latest('date').date).strftime('%-d.%-m.%Y %H:%M') except ObjectDoesNotExist: - return record.created.strftime('%e.%m.%Y %H:%M') + _(" (not paid)") + return timezone.localtime(record.created).strftime('%-d.%-m.%Y %H:%M') + _(" (not paid)") def order_last_paid(self, queryset, is_descending): - latest = Payment.objects.filter(member=OuterRef('pk')).order_by('-date') - queryset = queryset.annotate(last_paid=Subquery(latest.values('date')[:1])).order_by(('-' if is_descending else '') + 'last_paid') + queryset = Member.get_members_with_latest_payment(queryset).order_by(('-' if is_descending else '') + 'last_paid') return (queryset, True) @@ -45,9 +42,7 @@ class PaymentTable(tables.Table): options = tables.TemplateColumn( ('') + - _('Edit') + - '', + 'href="/members/edit_payment/{{ record.id }}">') + _('Edit') + '', verbose_name="" ) @@ -62,9 +57,7 @@ class RequestTable(tables.Table): options = tables.TemplateColumn( ('') + - _('Edit') + - '', + 'href="/members/edit_application/{{ record.id }}">') + _('Edit') + '', verbose_name="" ) diff --git a/members/templates/error.html b/members/templates/error.html deleted file mode 100644 index 3d09501..0000000 --- a/members/templates/error.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "members:base.html" %} - -{% load static %} -{% load i18n %} -{% block content %} -
-
-

{% trans "Error" %}

-
- -
- {{ error|safe }} -
-
- -
-
-{% endblock content %} diff --git a/members/templates/member_list.html b/members/templates/member_list.html index 8b65bb6..6952362 100644 --- a/members/templates/member_list.html +++ b/members/templates/member_list.html @@ -18,7 +18,7 @@ {% endif %}
- {% trans "Members in register:" %} {{ member_count }} + {% trans "Members in register:" %} {{ member_count }} ({{ paid_count }})
diff --git a/members/views/members.py b/members/views/members.py index 4ae9a6b..00a2122 100644 --- a/members/views/members.py +++ b/members/views/members.py @@ -7,6 +7,7 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, HttpRe from django.core.mail import send_mail from django.conf import settings from django.utils.translation import ugettext as _ +from django.utils import timezone from django.forms.models import model_to_dict from dal import autocomplete @@ -44,9 +45,12 @@ def member_list(request, *args, **kwargs): table.paginate(page=request.GET.get('page', 1), per_page=25) table_html = convert_table_to_html(table, request) + + queryset = Member.get_members_with_latest_payment(members) context = { 'table': table_html, 'member_count': len(members), + 'paid_count': len(queryset.exclude(last_paid=None)), 'notification': request.GET.get('notification', None), } return render(request, 'member_list.html', context) diff --git a/requirements.txt b/requirements.txt index dcacff6..bf70437 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,7 +30,7 @@ six==1.10.0 django-suit==0.2.25 telepot==12.3 django-password-reset==1.0 -pyexcel==0.5.7 +pyexcel==0.5.8 pyexcel-xlsx==0.5.5 django-import-export==0.7.0 openpyxl==2.4.11 diff --git a/sikweb/base.py b/sikweb/base.py index 2cd946a..94ef3eb 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -24,9 +24,22 @@ else: LOGGERLEVEL = logging.DEBUG LOGPATH = os.path.join(BASE_DIR, "logs", "debug.log") + +def disable_pyexcel_logs(record): + if record.module in ['loader', 'utils', 'source_plugin', 'plugin']: + return False + return True + + LOGGING = { 'version': 1, 'disable_existing_loggers': False, + 'filters': { + 'disable_pyexcel_logs': { + '()': 'django.utils.log.CallbackFilter', + 'callback': disable_pyexcel_logs + }, + }, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s: %(message)s' @@ -43,6 +56,7 @@ LOGGING = { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'verbose', + 'filters': ['disable_pyexcel_logs'], }, }, 'root': { diff --git a/templates/error.html b/templates/error.html index 745eb56..3d09501 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1,4 +1,4 @@ -{% extends "members_base.html" %} +{% extends "members:base.html" %} {% load static %} {% load i18n %}