From 9fa9848eda1f2f714d0c65eee0ffc6b65e1de4cc Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 13 Jan 2020 11:44:12 +0100 Subject: [PATCH 1/1] Year summaries. --- .../migrations/0022_payuorder_completed_at.py | 18 ++++++++++ src/club/migrations/0023_completed_at.py | 26 +++++++++++++++ src/club/payu/models.py | 4 +++ src/club/templates/club/year_summary.html | 33 +++++++++++++++++++ src/club/urls.py | 1 + src/club/views.py | 16 +++++++++ src/wolnelektury/static/scss/main/base.scss | 12 +++++++ 7 files changed, 110 insertions(+) create mode 100644 src/club/migrations/0022_payuorder_completed_at.py create mode 100644 src/club/migrations/0023_completed_at.py create mode 100644 src/club/templates/club/year_summary.html diff --git a/src/club/migrations/0022_payuorder_completed_at.py b/src/club/migrations/0022_payuorder_completed_at.py new file mode 100644 index 000000000..916f4e02b --- /dev/null +++ b/src/club/migrations/0022_payuorder_completed_at.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.9 on 2020-01-13 10:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('club', '0021_auto_20191127_1545'), + ] + + operations = [ + migrations.AddField( + model_name='payuorder', + name='completed_at', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/src/club/migrations/0023_completed_at.py b/src/club/migrations/0023_completed_at.py new file mode 100644 index 000000000..d23c28964 --- /dev/null +++ b/src/club/migrations/0023_completed_at.py @@ -0,0 +1,26 @@ +import json +from django.db import migrations + + +def populate_completed_at(apps, schema_editor): + PayUOrder = apps.get_model('club', 'PayUOrder') + for order in PayUOrder.objects.filter(status='COMPLETED'): + for n in order.notification_set.order_by('received_at'): + if json.loads(n.body)['order']['status'] == 'COMPLETED': + order.completed_at = n.received_at + order.save() + break + + +class Migration(migrations.Migration): + + dependencies = [ + ('club', '0022_payuorder_completed_at'), + ] + + operations = [ + migrations.RunPython( + populate_completed_at, + migrations.RunPython.noop, + ) + ] diff --git a/src/club/payu/models.py b/src/club/payu/models.py index f7c35352d..5764f8842 100644 --- a/src/club/payu/models.py +++ b/src/club/payu/models.py @@ -7,6 +7,7 @@ from urllib.request import HTTPError from django.contrib.sites.models import Site from django.db import models from django.urls import reverse +from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from . import POSS @@ -36,6 +37,7 @@ class Order(models.Model): ('CANCELED', _('Canceled')), ('REJECTED', _('Rejected')), ]) + completed_at = models.DateTimeField(null=True, blank=True) class Meta: abstract = True @@ -150,5 +152,7 @@ class Notification(models.Model): status = self.get_status() if self.order.status not in (status, 'COMPLETED'): self.order.status = status + if status == 'COMPLETED': + self.order.completed_at = now() self.order.save() self.order.status_updated() diff --git a/src/club/templates/club/year_summary.html b/src/club/templates/club/year_summary.html new file mode 100644 index 000000000..20ed198e2 --- /dev/null +++ b/src/club/templates/club/year_summary.html @@ -0,0 +1,33 @@ +{% extends request.session.from_app|yesno:"base/app.html,base/base.html" %} +{% load chunks i18n %} + + +{% block titleextra %}Towarzystwo Przyjaciół Wolnych Lektur{% endblock %} + + +{% block body %} +
+

{% blocktrans with year=view.kwargs.year email=object.email %}Summary of donations in the year {{ year }} for the address {{ email }}.{% endblocktrans %}

+ + + + + + + + + + {% for order in payments %} + + + + + {% endfor %} + + + + + +
{% trans "Date" %}{% trans "Amount" %}
{{ order.completed_at.date }}{{ order.get_amount }} zł
{% trans "Total" %}:{{ total_amount|default:0 }} zł
+
+{% endblock %} diff --git a/src/club/urls.py b/src/club/urls.py index 7a3795a8b..8bbb849b2 100644 --- a/src/club/urls.py +++ b/src/club/urls.py @@ -12,6 +12,7 @@ urlpatterns = [ path('plan//', banner_exempt(views.ScheduleView.as_view()), name='club_schedule'), path('plan//dziekujemy/', banner_exempt(views.ScheduleThanksView.as_view()), name='club_thanks'), + path('plan//zestawienie//', banner_exempt(views.YearSummaryView.as_view()), name='club_year_summary'), path('przylacz//', views.claim, name='club_claim'), path('anuluj//', views.cancel, name='club_cancel'), diff --git a/src/club/views.py b/src/club/views.py index 920180a49..d673cc021 100644 --- a/src/club/views.py +++ b/src/club/views.py @@ -3,6 +3,7 @@ # from django.conf import settings from django.contrib.auth.decorators import login_required +from django.db.models import Sum from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.utils.decorators import method_decorator @@ -168,3 +169,18 @@ class ScheduleThanksView(DetailView): ctx['active_menu_item'] = 'club' return ctx + +class YearSummaryView(DetailView): + model = models.Schedule + slug_field = slug_url_kwarg = 'key' + template_name = 'club/year_summary.html' + + def get_context_data(self, *args, **kwargs): + ctx = super().get_context_data(*args, **kwargs) + ctx['payments'] = models.PayUOrder.objects.filter( + status='COMPLETED', + completed_at__year=self.kwargs['year'], + schedule__email=self.object.email, + ).order_by('completed_at') + ctx['total_amount'] = ctx['payments'].aggregate(s=Sum('schedule__amount'))['s'] + return ctx diff --git a/src/wolnelektury/static/scss/main/base.scss b/src/wolnelektury/static/scss/main/base.scss index 870f7a19f..0c8dc8973 100755 --- a/src/wolnelektury/static/scss/main/base.scss +++ b/src/wolnelektury/static/scss/main/base.scss @@ -226,3 +226,15 @@ ul.plain { @media screen and (max-width: 62.5em) { .mobile-margins {margin-left: 1em; margin-right: 1em;} } + + +table.table { + margin: auto; + border-collapse: collapse; + + td, th { + border: 1px solid #444; + padding: .5em; + text-align: center; + } +} -- 2.20.1