Added the get_summary_categories() utility and put the categories in the transaction forms in the accounting application.

This commit is contained in:
依瑪貓 2020-08-04 09:55:27 +08:00
parent 12d4af06a0
commit 245e4c6573
5 changed files with 56 additions and 14 deletions

View File

@ -44,9 +44,7 @@ First written: 2020/7/23
{# TODO: To be done #}
<input id="l10n-messages" type="hidden" value="{{ l10n_messages }}" />
<input id="account-option-url" type="hidden" value="{% url "accounting:accounts.options" %}" />
<input id="debit-general-categories" type="hidden" value="{{ debit_general_categories }}" />
<input id="debit-travel-categories" type="hidden" value="{{ debit_travel_categories }}" />
<input id="debit-bus-categories" type="hidden" value="{{ debit_bus_categories }}" />
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-date">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</label>

View File

@ -44,9 +44,7 @@ First written: 2020/7/23
{# TODO: To be done #}
<input id="l10n-messages" type="hidden" value="{{ l10n_messages }}" />
<input id="account-option-url" type="hidden" value="{% url "accounting:accounts.options" %}" />
<input id="credit-general-categories" type="hidden" value="{{ credit_general_categories }}" />
<input id="credit-travel-categories" type="hidden" value="{{ credit_travel_categories }}" />
<input id="credit-bus-categories" type="hidden" value="{{ credit_bus_categories }}" />
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-date">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</label>

View File

@ -44,12 +44,7 @@ First written: 2020/7/23
{# TODO: To be done #}
<input id="l10n-messages" type="hidden" value="{{ l10n_messages }}" />
<input id="account-option-url" type="hidden" value="{% url "accounting:accounts.options" %}" />
<input id="debit-general-categories" type="hidden" value="{{ debit_general_categories }}" />
<input id="debit-travel-categories" type="hidden" value="{{ debit_travel_categories }}" />
<input id="debit-bus-categories" type="hidden" value="{{ debit_bus_categories }}" />
<input id="credit-general-categories" type="hidden" value="{{ credit_general_categories }}" />
<input id="credit-travel-categories" type="hidden" value="{{ credit_travel_categories }}" />
<input id="credit-bus-categories" type="hidden" value="{{ credit_bus_categories }}" />
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-date">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</label>

View File

@ -18,11 +18,14 @@
"""The utilities of the accounting application.
"""
import json
import re
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Sum, Case, When, F, Count, Max, Min
from django.db.models import Q, Sum, Case, When, F, Count, Max, Min, Value, \
CharField
from django.db.models.functions import StrIndex, Left
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import pgettext
@ -319,6 +322,52 @@ def find_order_holes(records):
record.has_order_hole = record.transaction.date in holes
def get_summary_categories():
"""Finds and returns the summary categories and their corresponding account
hints.
Returns:
dict[str,str]: The summary categories and their account hints, by
their record types and category types.
"""
filters = {
"general": Q(summary__contains="") & ~Q(summary__regex=".+—.+→.+"),
"travel": Q(summary__regex=".+—.+→.+")
& ~Q(summary__regex=".+—.+—.+→.+"),
"bus": Q(summary__regex=".+—.+—.+→.+"),
}
categories = {
"credit": {},
"debit": {},
}
for cat_type in filters:
rows = Record.objects\
.filter(
~Q(account__code__startswith="114"),
~Q(account__code__startswith="214"),
~Q(account__code__startswith="128"),
~Q(account__code__startswith="228"),
filters[cat_type])\
.annotate(category=Left("summary",
StrIndex("summary", Value("")) - 1,
output_field=CharField()))\
.values("category", "account__code", "is_credit")\
.annotate(count=Count("category"))\
.order_by("category", "is_credit", "-count", "account__code")
for row in rows:
rec_type = "credit" if row["is_credit"] else "debit"
if cat_type not in categories[rec_type]:
categories[rec_type][cat_type] = {}
if row["category"] not in categories[rec_type][cat_type]:
categories[rec_type][cat_type][row["category"]]\
= row["account__code"]
return {F"{r}-{t}": json.dumps(
[{"category": c, "account": categories[r][t][c]}
for c in categories[r][t]])
for r in categories
for t in categories[r]}
def fill_txn_from_post(txn_type, txn, post):
"""Fills the transaction from the POSTed data. The POSTed data must be
validated and clean at this moment.

View File

@ -42,7 +42,8 @@ from .models import Record, Transaction, Account
from .utils import ReportUrl, get_cash_accounts, get_ledger_accounts, \
find_imbalanced, find_order_holes, fill_txn_from_post, \
sort_post_txn_records, make_txn_form_from_status, \
make_txn_form_from_model, make_txn_form_from_post, MonthlySummary
make_txn_form_from_model, make_txn_form_from_post, MonthlySummary, \
get_summary_categories
@method_decorator(require_GET, name="dispatch")
@ -836,6 +837,7 @@ def txn_edit(request, txn_type, txn=None):
form = make_txn_form_from_model(txn_type, txn)
return render(request, F"accounting/transactions/{txn_type}/form.html", {
"item": form,
"summary_categories": get_summary_categories,
})