Added a simple pagination filter and refined the cash report.
This commit is contained in:
parent
06b8d470fb
commit
42fe685d53
@ -1,11 +1,32 @@
|
|||||||
<h1>Cash Report</h1>
|
<h1>Cash Report</h1>
|
||||||
|
|
||||||
{% if records %}
|
{% if records %}
|
||||||
<ul>
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Date</th>
|
||||||
|
<th scope="col">Subject</th>
|
||||||
|
<th scope="col">Summary</th>
|
||||||
|
<th scope="col">Income</th>
|
||||||
|
<th scope="col">Expense</th>
|
||||||
|
<th scope="col">Balance</th>
|
||||||
|
<th scope="col">View</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% for record in records %}
|
{% for record in records %}
|
||||||
<li>{{record.transaction.date}} {{record.summary}}</li>
|
<tr>
|
||||||
|
<td>{{ record.transaction.date }}</td>
|
||||||
|
<td>{{ record.subject.title_zhtw }}</td>
|
||||||
|
<td>{{ record.summary }}</td>
|
||||||
|
<td>{{ record.debit_amount }}</td>
|
||||||
|
<td>{{ record.credit_amount }}</td>
|
||||||
|
<td>{{ record.amount }}</td>
|
||||||
|
<td><a href="{% url "accounting:transaction" "transfer" record.transaction.sn %}">View</a></td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</tbody>
|
||||||
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No data.</p>
|
<p>No data.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -19,13 +19,29 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.urls import path
|
from django.urls import path, register_converter
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionTypeConverter:
|
||||||
|
"""The path converter for the transaction types."""
|
||||||
|
regex = "income|expense|transfer"
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
return value
|
||||||
|
|
||||||
|
def to_url(self, value):
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
register_converter(TransactionTypeConverter, "txn-type")
|
||||||
|
|
||||||
app_name = "accounting"
|
app_name = "accounting"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.home, name="home"),
|
path("", views.home, name="home"),
|
||||||
path("cash", views.cash_home, name="cash.home"),
|
path("cash", views.cash_home, name="cash.home"),
|
||||||
path("cash/<str:subject_code>/<str:period_spec>", views.CashReportView.as_view(), name="cash"),
|
path("cash/<str:subject_code>/<str:period_spec>", views.CashReportView.as_view(), name="cash"),
|
||||||
|
path("transactions/<txn-type:type>/<int:pk>", views.CashReportView.as_view(), name="transaction"),
|
||||||
|
path("transactions/<txn-type:type>/<int:pk>/edit", views.CashReportView.as_view(), name="transaction.edit"),
|
||||||
]
|
]
|
||||||
|
@ -38,3 +38,36 @@ class PeriodParser:
|
|||||||
"""
|
"""
|
||||||
self.start = period_spec + "-01"
|
self.start = period_spec + "-01"
|
||||||
self.end = period_spec + "-30"
|
self.end = period_spec + "-30"
|
||||||
|
|
||||||
|
|
||||||
|
class Pagination:
|
||||||
|
"""The pagination.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
page_no (int): The current page number
|
||||||
|
page_size (int): The page size
|
||||||
|
"""
|
||||||
|
page_no = None
|
||||||
|
page_size = None
|
||||||
|
|
||||||
|
DEFAULT_PAGE_SIZE = 10
|
||||||
|
|
||||||
|
def __init__(self, count, page_no, page_size, is_reverse = False):
|
||||||
|
"""Constructs a new pagination.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
count (int): The total number of records
|
||||||
|
page_no (int): The specified page number
|
||||||
|
page_size (int): The specified number of records per page
|
||||||
|
is_reverse (bool): Whether we should display the last
|
||||||
|
page first
|
||||||
|
"""
|
||||||
|
self.page_size = page_size \
|
||||||
|
if page_size is not None \
|
||||||
|
else self.DEFAULT_PAGE_SIZE
|
||||||
|
total_pages = int((count - 1) / self.page_size) + 1
|
||||||
|
self.page_no = page_no \
|
||||||
|
if page_no is not None \
|
||||||
|
else 1 if not is_reverse else total_pages
|
||||||
|
if self.page_no > total_pages:
|
||||||
|
self.page_no = total_pages
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
"""The view controllers of the accounting application.
|
"""The view controllers of the accounting application.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
@ -28,7 +30,7 @@ from django.views import generic
|
|||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
|
|
||||||
from accounting.models import Record
|
from accounting.models import Record
|
||||||
from accounting.utils import PeriodParser
|
from accounting.utils import PeriodParser, Pagination
|
||||||
from mia import settings
|
from mia import settings
|
||||||
|
|
||||||
|
|
||||||
@ -62,55 +64,95 @@ class CashReportView(generic.ListView):
|
|||||||
context_object_name = "records"
|
context_object_name = "records"
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Return the records for the accounting cash report."""
|
"""Return the accounting records for the cash report.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The accounting records for the cash report
|
||||||
|
"""
|
||||||
period = PeriodParser(self.kwargs["period_spec"])
|
period = PeriodParser(self.kwargs["period_spec"])
|
||||||
if self.kwargs["subject_code"] == "0":
|
if self.kwargs["subject_code"] == "0":
|
||||||
records = Record.objects.raw(
|
records = Record.objects.raw(
|
||||||
"""SELECT r.*
|
"""SELECT r.*
|
||||||
FROM accounting_records AS r
|
FROM accounting_records AS r
|
||||||
INNER JOIN (SELECT
|
INNER JOIN (SELECT
|
||||||
t1.sn AS sn,
|
t1.sn AS sn,
|
||||||
t1.date AS date,
|
t1.date AS date,
|
||||||
t1.ord AS ord
|
t1.ord AS ord
|
||||||
FROM accounting_records AS r1
|
FROM accounting_records AS r1
|
||||||
LEFT JOIN accounting_transactions AS t1 ON r1.transaction_sn=t1.sn
|
LEFT JOIN accounting_transactions AS t1
|
||||||
LEFT JOIN accounting_subjects AS s1 ON r1.subject_sn = s1.sn
|
ON r1.transaction_sn=t1.sn
|
||||||
WHERE (s1.code LIKE '11%%'
|
LEFT JOIN accounting_subjects AS s1
|
||||||
OR s1.code LIKE '12%%'
|
ON r1.subject_sn = s1.sn
|
||||||
OR s1.code LIKE '21%%'
|
WHERE (s1.code LIKE '11%%'
|
||||||
OR s1.code LIKE '22%%')
|
OR s1.code LIKE '12%%'
|
||||||
AND t1.date >= %s
|
OR s1.code LIKE '21%%'
|
||||||
AND t1.date <= %s
|
OR s1.code LIKE '22%%')
|
||||||
GROUP BY t1.sn) AS t
|
AND t1.date >= %s
|
||||||
ON r.transaction_sn=t.sn
|
AND t1.date <= %s
|
||||||
LEFT JOIN accounting_subjects AS s ON r.subject_sn = s.sn
|
GROUP BY t1.sn) AS t
|
||||||
|
ON r.transaction_sn=t.sn
|
||||||
|
LEFT JOIN accounting_subjects AS s ON r.subject_sn = s.sn
|
||||||
WHERE s.code NOT LIKE '11%%'
|
WHERE s.code NOT LIKE '11%%'
|
||||||
AND s.code NOT LIKE '12%%'
|
AND s.code NOT LIKE '12%%'
|
||||||
AND s.code NOT LIKE '21%%'
|
AND s.code NOT LIKE '21%%'
|
||||||
AND s.code NOT LIKE '22%%'
|
AND s.code NOT LIKE '22%%'
|
||||||
ORDER BY t.date, t.ord, CASE WHEN is_credit THEN 1 ELSE 2 END, r.ord""",
|
ORDER BY
|
||||||
|
t.date,
|
||||||
|
t.ord,
|
||||||
|
CASE WHEN is_credit THEN 1 ELSE 2 END,
|
||||||
|
r.ord""",
|
||||||
[period.start, period.end])
|
[period.start, period.end])
|
||||||
else:
|
else:
|
||||||
records = Record.objects.raw(
|
records = Record.objects.raw(
|
||||||
"""SELECT r.*
|
"""SELECT r.*
|
||||||
FROM accounting_records AS r
|
FROM accounting_records AS r
|
||||||
INNER JOIN (SELECT
|
INNER JOIN (SELECT
|
||||||
t1.sn AS sn,
|
t1.sn AS sn,
|
||||||
t1.date AS date,
|
t1.date AS date,
|
||||||
t1.ord AS ord
|
t1.ord AS ord
|
||||||
FROM accounting_records AS r1
|
FROM accounting_records AS r1
|
||||||
LEFT JOIN accounting_transactions AS t1 ON r1.transaction_sn=t1.sn
|
LEFT JOIN accounting_transactions AS t1
|
||||||
LEFT JOIN accounting_subjects AS s1 ON r1.subject_sn = s1.sn
|
ON r1.transaction_sn=t1.sn
|
||||||
WHERE t1.date >= %s
|
LEFT JOIN accounting_subjects AS s1
|
||||||
AND t1.date <= %s
|
ON r1.subject_sn = s1.sn
|
||||||
AND s1.code LIKE %s
|
WHERE t1.date >= %s
|
||||||
GROUP BY t1.sn) AS t
|
AND t1.date <= %s
|
||||||
ON r.transaction_sn=t.sn
|
AND s1.code LIKE %s
|
||||||
LEFT JOIN accounting_subjects AS s ON r.subject_sn = s.sn
|
GROUP BY t1.sn) AS t
|
||||||
|
ON r.transaction_sn=t.sn
|
||||||
|
LEFT JOIN accounting_subjects AS s ON r.subject_sn = s.sn
|
||||||
WHERE s.code NOT LIKE %s
|
WHERE s.code NOT LIKE %s
|
||||||
ORDER BY t.date, t.ord, CASE WHEN is_credit THEN 1 ELSE 2 END, r.ord""",
|
ORDER BY
|
||||||
|
t.date,
|
||||||
|
t.ord,
|
||||||
|
CASE WHEN is_credit THEN 1 ELSE 2 END,
|
||||||
|
r.ord""",
|
||||||
[period.start,
|
[period.start,
|
||||||
period.end,
|
period.end,
|
||||||
self.kwargs["subject_code"] + "%",
|
self.kwargs["subject_code"] + "%",
|
||||||
self.kwargs["subject_code"] + "%"])
|
self.kwargs["subject_code"] + "%"])
|
||||||
return records
|
get = self.request.GET
|
||||||
|
pagination = Pagination(
|
||||||
|
len(records),
|
||||||
|
self.get_number_query("page"),
|
||||||
|
self.get_number_query("page-size"),
|
||||||
|
True)
|
||||||
|
start_no = pagination.page_size * (pagination.page_no - 1)
|
||||||
|
return records[start_no:start_no + pagination.page_size]
|
||||||
|
|
||||||
|
def get_number_query(self, name):
|
||||||
|
"""Returns a positive number query parameter.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name (str): The name of the query parameter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The parameter value, or None if this parameter does not
|
||||||
|
exist or is not a positive number
|
||||||
|
"""
|
||||||
|
if name not in self.request.GET:
|
||||||
|
return None
|
||||||
|
elif not re.match("^[1-9][0-9]*$", self.request.GET[name]):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return int(self.request.GET)
|
||||||
|
Loading…
Reference in New Issue
Block a user