diff --git a/project/config/urls.py b/project/config/urls.py
index b69923e4..5925233d 100644
--- a/project/config/urls.py
+++ b/project/config/urls.py
@@ -37,6 +37,7 @@
# Your stuff: custom urls includes go here
url(r'^members/', include('members.urls')),
url(r'^velkoja/', include('velkoja.urls')),
+ url(settings.ADMIN_URL, include('creditor.urls_admin')),
url(r'^api/', include(router.urls)),
url(r'^api-auth/get-token/', authtoken_views.obtain_auth_token),
diff --git a/project/creditor/admin.py b/project/creditor/admin.py
index 842fa486..9694a3aa 100644
--- a/project/creditor/admin.py
+++ b/project/creditor/admin.py
@@ -9,6 +9,9 @@
from .models import RecurringTransaction, Transaction, TransactionTag
+from django.contrib.admin import AdminSite
+from django.http import HttpResponse
+
class TransactionTagAdmin(VersionAdmin):
pass
@@ -148,6 +151,7 @@ def dates_formatted(self, obj):
dates_formatted.admin_order_field = 'start'
+
admin.site.register(TransactionTag, TransactionTagAdmin)
admin.site.register(Transaction, TransactionAdmin)
admin.site.register(RecurringTransaction, RecurringTransactionAdmin)
diff --git a/project/creditor/locale/fi/LC_MESSAGES/django.po b/project/creditor/locale/fi/LC_MESSAGES/django.po
index 47bf984b..b4df0d94 100644
--- a/project/creditor/locale/fi/LC_MESSAGES/django.po
+++ b/project/creditor/locale/fi/LC_MESSAGES/django.po
@@ -4,7 +4,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-12-30 13:20+0200\n"
+"POT-Creation-Date: 2017-04-23 09:21+0300\n"
"PO-Revision-Date: 2015-11-29 03:01+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -15,139 +15,195 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.6\n"
-#: admin.py:15
+#: admin.py:18
#, fuzzy
#| msgid "Transaction Tags"
msgid "Transaction tags"
msgstr "Tapahtuman tägit"
-#: admin.py:29 admin.py:68 admin.py:130 handlers.py:9 models.py:39
-#: models.py:75
+#: admin.py:32 admin.py:71 admin.py:133 handlers.py:13 models.py:47
+#: models.py:84 templates/admin/table.html:71
msgid "Amount"
-msgstr "Määrä"
+msgstr "Arvo"
-#: admin.py:34
+#: admin.py:37
msgid "Negative amount"
-msgstr "Negatiivinen summa"
+msgstr "Negatiivinen arvo"
-#: admin.py:35
+#: admin.py:38
msgid "Positive amount"
-msgstr "Positiivinen summa"
+msgstr "Positiivinen arvo"
-#: admin.py:60 handlers.py:6 models.py:35
+#: admin.py:63 handlers.py:9 models.py:43
msgid "Datetime"
msgstr "Aika"
-#: admin.py:73 admin.py:80
+#: admin.py:76 admin.py:83
msgid "Active"
-msgstr ""
+msgstr "Aktiiviset"
-#: admin.py:78
+#: admin.py:81
msgid "All"
msgstr "Kaikki"
-#: admin.py:79
+#: admin.py:82
msgid "Inactive"
msgstr "Ei-aktiiviset"
-#: admin.py:122 models.py:38 models.py:74
+#: admin.py:125 models.py:46 models.py:83
msgid "Member"
msgstr "Jäsen"
-#: admin.py:144
+#: admin.py:147
msgid "Start / End"
msgstr "Alku / Loppu"
-#: handlers.py:7
+#: handlers.py:10 handlers.py:11
msgid "Name"
msgstr "Nimi"
-#: handlers.py:8 models.py:37
+#: handlers.py:12 models.py:45
msgid "Reference"
msgstr "Viite"
-#: handlers.py:10 models.py:40
+#: handlers.py:14 models.py:48
msgid "Unique transaction id"
msgstr "Transaktion yksilöllinen tunniste"
-#: handlers.py:17
+#: handlers.py:21
#, python-format
msgid "AbstractTransaction %s: %+.2f "
msgstr ""
-#: handlers.py:44
+#: handlers.py:49
msgid "Transaction handler baseclass, this does nothing"
msgstr "Transaktioiden baseclass, ei tee mitään"
-#: models.py:12 models.py:71
+#: models.py:18 models.py:80
msgid "Label"
msgstr "Nimiö"
-#: models.py:13
+#: models.py:19
#, fuzzy
#| msgid "Transaction Tag"
msgid "Transaction match"
msgstr "Tapahtuman tägi"
-#: models.py:19
+#: models.py:20
+msgid "Holvi category code"
+msgstr "Holvi-kategorian koodi"
+
+#: models.py:26
msgid "Transaction Tag"
msgstr "Tapahtuman tägi"
-#: models.py:20
+#: models.py:27
msgid "Transaction Tags"
msgstr "Tapahtuman tägit"
-#: models.py:36 models.py:73
+#: models.py:44 models.py:82
msgid "Tag"
msgstr "Tägi"
-#: models.py:44
+#: models.py:52
#, python-format
msgid "%+.2f for %s (%s)"
msgstr ""
-#: models.py:45
+#: models.py:53
#, python-format
msgid "%+.2f for %s"
msgstr ""
-#: models.py:48
+#: models.py:56
msgid "Transaction"
msgstr "Tapahtuma"
-#: models.py:49
+#: models.py:57 templates/admin/table.html:84
msgid "Transactions"
msgstr "Tapahtumat"
-#: models.py:59 models.py:64
+#: models.py:68 models.py:73
msgid "Monthly"
msgstr "Kuukausittain"
-#: models.py:60 models.py:65
+#: models.py:69 models.py:74
msgid "Yearly"
msgstr "Vuosittain"
-#: models.py:68
+#: models.py:77
msgid "Since"
msgstr "Alkaen"
-#: models.py:69
+#: models.py:78
msgid "Until"
msgstr "Asti"
-#: models.py:72
+#: models.py:81
msgid "Recurrence type"
msgstr "Toistuvuuden tyyppi"
-#: models.py:80
+#: models.py:89
#, python-format
msgid "%+.2f %s for %s (%s)"
msgstr ""
-#: models.py:141
+#: models.py:156
msgid "Recurring Transaction"
msgstr "Toistuva tapahtuma"
-#: models.py:142
+#: models.py:157
msgid "Recurring Transactions"
msgstr "Toistuvat tapahtumat"
+
+#: templates/admin/table.html:19 templates/admin/table_year.html:19
+msgid "Django site admin"
+msgstr ""
+
+#: templates/admin/table.html:26 templates/admin/table_year.html:27
+msgid "Filter by transaction types"
+msgstr "Suodata tapahtumatyypin mukaan"
+
+#: templates/admin/table.html:27 templates/admin/table_year.html:28
+msgid "All types"
+msgstr "Kaikki tyypit"
+
+#: templates/admin/table.html:36 templates/admin/table_year.html:38
+msgid "Month selection"
+msgstr "Valitse kuukausi"
+
+#: templates/admin/table.html:60 templates/admin/table_year.html:57
+msgid "Summary"
+msgstr "Yhteenveto"
+
+#: templates/admin/table.html:62 templates/admin/table_year.html:63
+msgid "Income"
+msgstr "Tulot"
+
+#: templates/admin/table.html:63 templates/admin/table_year.html:64
+msgid "Receivables"
+msgstr "Saatavat"
+
+#: templates/admin/table.html:64
+msgid "Balance"
+msgstr "Balanssi"
+
+#: templates/admin/table.html:68
+msgid "Frequency table"
+msgstr "Frekvenssit"
+
+#: templates/admin/table.html:72
+msgid "Freq"
+msgstr "Frekv."
+
+#: templates/admin/table_year.html:58
+msgid "Year"
+msgstr "Vuosi"
+
+#: templates/admin/table_year.html:62
+msgid "Month"
+msgstr "Kuukausi"
+
+#: templates/admin/table_year.html:65
+msgid "Total"
+msgstr "Yhteensä"
diff --git a/project/creditor/templates/admin/table.html b/project/creditor/templates/admin/table.html
new file mode 100755
index 00000000..3fc72c3f
--- /dev/null
+++ b/project/creditor/templates/admin/table.html
@@ -0,0 +1,99 @@
+{% extends "admin/base.html" %}
+
+{% load i18n %}
+
+
+{% block extrastyle %}
+
+{% endblock %}
+
+
+{% block title %} {{ site_title|default:_('Summary')|add:' '|add:month|add:'-'|add:year }}{% endblock %}
+
+
+{% block content %}
+
+
+
+
{% trans "Filter by transaction types" %}
+
{% trans "All types" %}
+{% for t in tags %}
+{% if t.pk = tag_pk %}
+
{{ t.label }}
+{% else %}
+
{{ t.label }}
+{% endif %}
+{% endfor %}
+
+
{% trans "Month selection" %}
+
+{% for y in years %}
+
+{% if tag %}
+{{ y }} |
+{% else %}
+{{ y }} |
+{% endif %}
+{% for m in months %}
+{% if y = year and m = month %}
+{{ m }} |
+{% else %}
+{{ m }} |
+{% endif %}
+{% endfor %}
+
+{% endfor %}
+
+
+
+
+{{ month }}-{{ year }} {{ tag.label }}
+
+{% trans "Summary" %}
+
+{% trans "Income" %} | {{ income.sum }} |
+{% trans "Receivables" %} | {{ receivables.sum }} |
+{% trans "Balance" %} | {{ total.sum }} |
+
+
+
+{% trans "Frequency table" %}
+
+
+{% trans "Amount" %} |
+{% trans "Freq" %} |
+
+{% for f in freq_table %}
+
+{{ f.amount }} |
+{{ f.freq }} |
+
+{% endfor %}
+
+
+
+
+{% trans "Transactions" %}
+
+
+ {% for list_item in object_list %}
+
+ {{ list_item.owner }} |
+ {% if list_item.amount < 0 %}{{ list_item.amount }} |
+ {% else %}+{{ list_item.amount }} | {% endif %}
+ {{ list_item.tag }} |
+ {{ list_item.stamp }} |
+
+ {% endfor %}
+
+
+{% endblock content %}
+
diff --git a/project/creditor/templates/admin/table_year.html b/project/creditor/templates/admin/table_year.html
new file mode 100755
index 00000000..2b9fd901
--- /dev/null
+++ b/project/creditor/templates/admin/table_year.html
@@ -0,0 +1,80 @@
+{% extends "admin/base.html" %}
+
+{% load i18n %}
+{% load aggregation_utils %}
+
+{% block extrastyle %}
+
+{% endblock %}
+
+
+{% block title %} {{ site_title|default:_('Summary')|add:' '|add:year }}{% endblock %}
+
+
+{% block content %}
+
+
+
+
+
{% trans "Filter by transaction types" %}
+
{% trans "All types" %}
+{% for t in tags %}
+{% if t.pk = tag_pk %}
+
{{ t.label }}
+{% else %}
+
{{ t.label }}
+{% endif %}
+{% endfor %}
+
+
+
{% trans "Month selection" %}
+
+{% for y in years %}
+
+{{ y }} |
+{% for m in months %}
+{{ m }} |
+{% endfor %}
+
+{% endfor %}
+
+
+
+
+
+
+
+
{{ year }} {{ tag.label }}
+
+
{% trans "Summary" %}
+
{% trans "Year" %} {{ year }}
+
+
+
+{% trans "Month" %} |
+{% trans "Income" %} |
+{% trans "Receivables" %} |
+{% trans "Total" %} |
+
+{% for m in months %}
+
+{{ m }} |
+{{income|month_sum_value:m}} |
+{{receivables|month_sum_value:m}} |
+{% if total|month_sum_value:m < 0 %}{% else %}{% endif %}{{total|month_sum_value:m}} |
+
+{% endfor %}
+
+
+
+
+{% endblock content %}
+
diff --git a/project/creditor/templatetags/__init__.py b/project/creditor/templatetags/__init__.py
new file mode 100644
index 00000000..40a96afc
--- /dev/null
+++ b/project/creditor/templatetags/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/project/creditor/templatetags/aggregation_utils.py b/project/creditor/templatetags/aggregation_utils.py
new file mode 100644
index 00000000..5febc897
--- /dev/null
+++ b/project/creditor/templatetags/aggregation_utils.py
@@ -0,0 +1,11 @@
+from django import template
+
+register = template.Library()
+
+@register.filter
+def month_sum_value(month_array, month):
+ for d in month_array:
+ if str(month) == d['month']:
+ return d['sum']
+ return '.'
+
diff --git a/project/creditor/tests/test_transaction_table.py b/project/creditor/tests/test_transaction_table.py
new file mode 100644
index 00000000..2fd44918
--- /dev/null
+++ b/project/creditor/tests/test_transaction_table.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+import pytest
+
+# Nonadmins should be redirected
+@pytest.mark.django_db
+def test_views_nonadmin2(client):
+ assert client.get('/admin/transaction_table/').status_code == 302
+ assert client.get('/admin/transaction_table/2000/').status_code == 302
+ assert client.get('/admin/transaction_table/2000/01/').status_code == 302
+ assert client.get('/admin/transaction_table/2000/tag=0').status_code == 302
+ assert client.get('/admin/transaction_table/2000/01/tag=0').status_code == 302
+
+
+# Only admins should be able to see the table
+def test_views_admin(admin_client):
+ assert admin_client.get('/admin/transaction_table/').status_code == 200
+ assert admin_client.get('/admin/transaction_table/2000/').status_code == 200
+ assert admin_client.get('/admin/transaction_table/2000/01/').status_code == 200
+ assert admin_client.get('/admin/transaction_table/2000/tag=0').status_code == 200
+ assert admin_client.get('/admin/transaction_table/2000/01/tag=0').status_code == 200
+
diff --git a/project/creditor/urls_admin.py b/project/creditor/urls_admin.py
new file mode 100644
index 00000000..8b94243c
--- /dev/null
+++ b/project/creditor/urls_admin.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+from django.conf.urls import url
+from django.contrib.auth.decorators import permission_required
+
+#from creditor.admin import transaction_table_admin
+
+
+from . import views
+
+urlpatterns = [
+ url(r'^transaction_table/$', permission_required('is_staff',login_url='/admin/login/')(views.TransactionYearView.as_view()), name="table_y"),
+ url(r'^transaction_table/(?P[0-9]{4})/$', permission_required('is_staff',login_url='/admin/login/')(views.TransactionYearView.as_view()), name="table_y"),
+ url(r'^transaction_table/(?P[0-9]{4})/tag=(?P[0-9]+)$', permission_required('is_staff',login_url='/admin/login/')(views.TransactionYearView.as_view()), name="table_y"),
+
+ url(r'^transaction_table/(?P[0-9]{4})/(?P(1[0-2]|0[1-9]))/$', permission_required('is_staff',login_url='/admin/login/')(views.TransactionMonthView.as_view()), name="table_m"),
+ url(r'^transaction_table/(?P[0-9]{4})/(?P(1[0-2]|0[1-9]))/tag=(?P[0-9]+)$', permission_required('is_staff',login_url='/admin/login/')(views.TransactionMonthView.as_view()), name="table_m"),
+]
diff --git a/project/creditor/views.py b/project/creditor/views.py
index d3ff201c..71704ab0 100644
--- a/project/creditor/views.py
+++ b/project/creditor/views.py
@@ -1,4 +1,73 @@
# -*- coding: utf-8 -*-
from django.shortcuts import render
+from django.views.generic import ListView
+from creditor.models import Transaction, TransactionTag
+from django.db.models import Sum, Count
+from django.utils import timezone
-# Create your views here.
+
+class TransactionMonthView(ListView):
+ model = Transaction
+ template_name = "admin/table.html"
+
+ param_tag = None
+ def get_queryset(self):
+
+ self.param_year = self.kwargs['year']
+ self.param_month = self.kwargs['month']
+
+ if('tag' in self.kwargs and int(self.kwargs['tag']) in TransactionTag.objects.values_list('pk', flat=True)):
+ self.param_tag = TransactionTag.objects.filter(pk=int(self.kwargs['tag']))[0]
+ return Transaction.objects.filter(stamp__year=self.param_year).filter(stamp__month=self.param_month).filter(tag__pk=self.param_tag.pk).order_by('owner__lname','owner__fname')
+
+ return Transaction.objects.filter(stamp__year=self.param_year).filter(stamp__month=self.param_month).order_by('owner__lname','owner__fname')
+
+
+ def get_context_data(self, **kwargs):
+ context = super(TransactionMonthView, self).get_context_data(**kwargs)
+ context['income'] = self.get_queryset().filter(amount__gte=0).aggregate(sum=Sum('amount'))
+ context['receivables'] = self.get_queryset().filter(amount__lt=0).aggregate(sum=Sum('amount'))
+ context['freq_table'] = self.get_queryset().values('amount').annotate(freq=Count('amount')).order_by('-amount')
+ context['total'] = self.get_queryset().aggregate(sum=Sum('amount'))
+ context['year'] = self.param_year
+ context['tag'] = self.param_tag
+ context['tag_pk'] = 0 if self.param_tag == None else self.param_tag.pk
+ context['month'] = self.param_month.rjust(2, "0")
+ context['months'] = ['01','02','03','04','05','06','07','08','09','10','11','12']
+ context['years'] = [str(d.year) for d in Transaction.objects.datetimes('stamp', 'year')]
+ context['tags'] = TransactionTag.objects.values('pk','label').order_by('pk')
+
+ return context
+
+class TransactionYearView(ListView):
+ model = Transaction
+ template_name = "admin/table_year.html"
+
+ param_year = timezone.now().year
+ param_tag = None
+ def get_queryset(self):
+
+ if('year' in self.kwargs):
+ self.param_year = self.kwargs['year']
+
+ # tag number must refer to existing TransactionTag
+ if('tag' in self.kwargs and int(self.kwargs['tag']) in TransactionTag.objects.values_list('pk', flat=True)):
+ self.param_tag = TransactionTag.objects.filter(pk=int(self.kwargs['tag']))[0]
+ return Transaction.objects.filter(stamp__year=self.param_year).filter(tag__pk=self.param_tag.pk)
+
+ return Transaction.objects.filter(stamp__year=self.param_year)
+
+
+ def get_context_data(self, **kwargs):
+ context = super(TransactionYearView, self).get_context_data(**kwargs)
+ context['receivables'] = self.get_queryset().filter(amount__lt=0).extra(select={'month': "to_char(stamp, 'MM' )"}).values('month').annotate(sum=Sum('amount')).order_by()
+ context['income'] = self.get_queryset().filter(amount__gte=0).extra(select={'month': "to_char(stamp, 'MM' )"}).values('month').annotate(sum=Sum('amount')).order_by()
+ context['total'] = self.get_queryset().extra(select={'month': "to_char(stamp, 'MM' )"}).values('month').annotate(sum=Sum('amount')).order_by()
+ context['tag'] = self.param_tag
+ context['tag_pk'] = 0 if self.param_tag == None else self.param_tag.pk
+ context['year'] = self.param_year
+ context['months'] = ['01','02','03','04','05','06','07','08','09','10','11','12']
+ context['years'] = [d.year for d in Transaction.objects.datetimes('stamp', 'year')]
+ context['tags'] = TransactionTag.objects.values('pk','label').order_by('pk')
+
+ return context
\ No newline at end of file