Moved the get_cash_accounts(), get_ledger_accounts(), find_imbalanced(), and find_order_holes() utilities from accounting.views.reports to accounting.utils in the accounting application.

This commit is contained in:
依瑪貓 2020-07-23 09:57:29 +08:00
parent 9602ba56c7
commit 79442085b6
2 changed files with 98 additions and 95 deletions

View File

@ -20,8 +20,10 @@
""" """
from django.conf import settings from django.conf import settings
from django.db.models import Q, Sum, Case, When, F, Count, Max, Min
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.translation import pgettext
from accounting.models import Account, Transaction, Record from accounting.models import Account, Transaction, Record
from mia_core.period import Period from mia_core.period import Period
@ -204,3 +206,87 @@ class Populator:
""" """
amount = sum([x[2] for x in debit]) amount = sum([x[2] for x in debit])
self.add_transfer_transaction(date, debit, (("1111", None, amount),)) self.add_transfer_transaction(date, debit, (("1111", None, amount),))
def get_cash_accounts():
"""Returns the cash accounts.
Returns:
list[Account]: The cash accounts.
"""
accounts = list(
Account.objects
.filter(
code__in=Record.objects
.filter(
Q(account__code__startswith="11")
| Q(account__code__startswith="12")
| Q(account__code__startswith="21")
| Q(account__code__startswith="22"))
.values("account__code"))
.order_by("code"))
accounts.insert(0, Account(
code="0",
title=pgettext(
"Accounting|", "current assets and liabilities"),
))
return accounts
def get_ledger_accounts():
"""Returns the accounts for the ledger.
Returns:
list[Account]: The accounts for the ledger.
"""
# TODO: Te be replaced with the Django model queries
return list(Account.objects.raw("""SELECT s.*
FROM accounting_accounts AS s
WHERE s.code IN (SELECT s.code
FROM accounting_accounts AS s
INNER JOIN (SELECT s.code
FROM accounting_accounts AS s
INNER JOIN accounting_records AS r ON r.account_sn = s.sn
GROUP BY s.code) AS u
ON u.code LIKE s.code || '%'
GROUP BY s.code)
ORDER BY s.code"""))
def find_imbalanced(records):
""""Finds the records with imbalanced transactions, and sets their
is_balanced attribute.
Args:
records (list[Record]): The accounting records.
"""
imbalanced = [x.sn for x in Transaction.objects
.annotate(
balance=Sum(Case(
When(record__is_credit=True, then=-1),
default=1) * F("record__amount")))
.filter(~Q(balance=0))]
for record in records:
record.is_balanced = record.transaction.sn not in imbalanced
def find_order_holes(records):
""""Finds whether the order of the transactions on this day is not
1, 2, 3, 4, 5..., and should be reordered, and sets their
has_order_holes attributes.
Args:
records (list[Record]): The accounting records.
"""
holes = [x["date"] for x in Transaction.objects
.values("date")
.annotate(count=Count("ord"),
max=Max("ord"),
min=Min("ord"))
.filter(~(Q(max=F("count")) & Q(min=1)))] +\
[x["date"] for x in Transaction.objects
.values("date", "ord")
.annotate(count=Count("sn"))
.filter(~Q(count=1))]
for record in records:
record.has_order_hole = record.transaction.date in holes

View File

@ -20,9 +20,9 @@
""" """
import re import re
from django.db.models import Sum, Case, When, F, Q, Count, Max, Min from django.db.models import Sum, Case, When, F, Q
from django.db.models.functions import TruncMonth, Coalesce from django.db.models.functions import TruncMonth, Coalesce
from django.http import HttpResponseRedirect, Http404 from django.http import HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from django.utils import dateformat, timezone from django.utils import dateformat, timezone
@ -31,7 +31,8 @@ from django.views.decorators.http import require_GET
from accounting.models import Record, Transaction, Account, \ from accounting.models import Record, Transaction, Account, \
RecordSummary RecordSummary
from accounting.utils import ReportUrl from accounting.utils import ReportUrl, get_cash_accounts, get_ledger_accounts, \
find_imbalanced, find_order_holes
from mia import settings from mia import settings
from mia_core.digest_auth import digest_login_required from mia_core.digest_auth import digest_login_required
from mia_core.period import Period from mia_core.period import Period
@ -143,9 +144,9 @@ def cash(request, account, period):
records.append(record_sum) records.append(record_sum)
pagination = Pagination(request, records, True) pagination = Pagination(request, records, True)
records = pagination.items records = pagination.items
_find_imbalanced(records) find_imbalanced(records)
_find_order_holes(records) find_order_holes(records)
accounts = _cash_accounts() accounts = get_cash_accounts()
shortcut_accounts = settings.ACCOUNTING["CASH_SHORTCUT_ACCOUNTS"] shortcut_accounts = settings.ACCOUNTING["CASH_SHORTCUT_ACCOUNTS"]
return render(request, "accounting/cash.html", { return render(request, "accounting/cash.html", {
"item_list": records, "item_list": records,
@ -191,7 +192,7 @@ def cash_summary(request, account):
HttpResponse: The response. HttpResponse: The response.
""" """
# The account # The account
accounts = _cash_accounts() accounts = get_cash_accounts()
# The month summaries # The month summaries
if account.code == "0": if account.code == "0":
months = [RecordSummary(**x) for x in Record.objects months = [RecordSummary(**x) for x in Record.objects
@ -331,15 +332,15 @@ def ledger(request, account, period):
records.insert(0, record_brought_forward) records.insert(0, record_brought_forward)
pagination = Pagination(request, records, True) pagination = Pagination(request, records, True)
records = pagination.items records = pagination.items
_find_imbalanced(records) find_imbalanced(records)
_find_order_holes(records) find_order_holes(records)
return render(request, "accounting/ledger.html", { return render(request, "accounting/ledger.html", {
"item_list": records, "item_list": records,
"pagination": pagination, "pagination": pagination,
"account": account, "account": account,
"period": period, "period": period,
"reports": ReportUrl(ledger=account, period=period), "reports": ReportUrl(ledger=account, period=period),
"accounts": _ledger_accounts(), "accounts": get_ledger_accounts(),
}) })
@ -406,7 +407,7 @@ def ledger_summary(request, account):
"pagination": pagination, "pagination": pagination,
"account": account, "account": account,
"reports": ReportUrl(ledger=account), "reports": ReportUrl(ledger=account),
"accounts": _ledger_accounts(), "accounts": get_ledger_accounts(),
}) })
@ -824,87 +825,3 @@ def search(request):
"pagination": pagination, "pagination": pagination,
"reports": ReportUrl(), "reports": ReportUrl(),
}) })
def _cash_accounts():
"""Returns the cash accounts.
Returns:
list[Account]: The cash accounts.
"""
accounts = list(
Account.objects
.filter(
code__in=Record.objects
.filter(
Q(account__code__startswith="11")
| Q(account__code__startswith="12")
| Q(account__code__startswith="21")
| Q(account__code__startswith="22"))
.values("account__code"))
.order_by("code"))
accounts.insert(0, Account(
code="0",
title=pgettext(
"Accounting|", "current assets and liabilities"),
))
return accounts
def _ledger_accounts():
"""Returns the accounts for the ledger.
Returns:
list[Account]: The accounts for the ledger.
"""
# TODO: Te be replaced with the Django model queries
return list(Account.objects.raw("""SELECT s.*
FROM accounting_accounts AS s
WHERE s.code IN (SELECT s.code
FROM accounting_accounts AS s
INNER JOIN (SELECT s.code
FROM accounting_accounts AS s
INNER JOIN accounting_records AS r ON r.account_sn = s.sn
GROUP BY s.code) AS u
ON u.code LIKE s.code || '%'
GROUP BY s.code)
ORDER BY s.code"""))
def _find_imbalanced(records):
""""Finds the records with imbalanced transactions, and sets their
is_balanced attribute.
Args:
records (list[Record]): The accounting records.
"""
imbalanced = [x.sn for x in Transaction.objects
.annotate(
balance=Sum(Case(
When(record__is_credit=True, then=-1),
default=1) * F("record__amount")))
.filter(~Q(balance=0))]
for record in records:
record.is_balanced = record.transaction.sn not in imbalanced
def _find_order_holes(records):
""""Finds whether the order of the transactions on this day is not
1, 2, 3, 4, 5..., and should be reordered, and sets their
has_order_holes attributes.
Args:
records (list[Record]): The accounting records.
"""
holes = [x["date"] for x in Transaction.objects
.values("date")
.annotate(count=Count("ord"),
max=Max("ord"),
min=Min("ord"))
.filter(~(Q(max=F("count")) & Q(min=1)))] +\
[x["date"] for x in Transaction.objects
.values("date", "ord")
.annotate(count=Count("sn"))
.filter(~Q(count=1))]
for record in records:
record.has_order_hole = record.transaction.date in holes