Moved the get_summary_categories() utility to TransactionFormView in the accounting application.

This commit is contained in:
依瑪貓 2020-08-19 14:13:30 +08:00
parent 274d8dfeec
commit 68964c5ed5
2 changed files with 57 additions and 57 deletions

View File

@ -19,13 +19,10 @@
""" """
import datetime import datetime
import json
from typing import Union, Tuple, List, Optional, Iterable from typing import Union, Tuple, List, Optional, Iterable
from django.conf import settings from django.conf import settings
from django.db.models import Q, Sum, Case, When, F, Count, Max, Min, Value, \ from django.db.models import Q, Sum, Case, When, F, Count, Max, Min
CharField
from django.db.models.functions import StrIndex, Left
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 gettext as _ from django.utils.translation import gettext as _
@ -466,53 +463,3 @@ def find_existing_equipments(account: Account,
if x.pk is not None if x.pk is not None
and F"{x.account.code}-{x.summary}" in keys]: and F"{x.account.code}-{x.summary}" in keys]:
x.is_existing_equipment = True x.is_existing_equipment = True
def get_summary_categories() -> str:
"""Finds and returns the summary categories and their corresponding account
hints as JSON.
Returns:
The summary categories and their account hints, by their record types
and category types.
"""
rows = Record.objects\
.filter(Q(summary__contains=""),
~Q(account__code__startswith="114"),
~Q(account__code__startswith="214"),
~Q(account__code__startswith="128"),
~Q(account__code__startswith="228"))\
.annotate(rec_type=Case(When(is_credit=True, then=Value("credit")),
default=Value("debit"),
output_field=CharField()),
cat_type=Case(
When(summary__regex=".+—.+—.+→.+", then=Value("bus")),
When(summary__regex=".+—.+[→↔].+", then=Value("travel")),
default=Value("general"),
output_field=CharField()),
category=Left("summary",
StrIndex("summary", Value("")) - 1,
output_field=CharField()))\
.values("rec_type", "cat_type", "category", "account__code")\
.annotate(count=Count("category"))\
.order_by("rec_type", "cat_type", "category", "-count",
"account__code")
# Sorts the rows by the record type and the category type
categories = {}
for row in rows:
key = "%s-%s" % (row["rec_type"], row["cat_type"])
if key not in categories:
categories[key] = {}
if row["category"] not in categories[key]:
categories[key][row["category"]] = []
categories[key][row["category"]].append(row)
for key in categories:
# Keeps only the first account with most records
categories[key] = [categories[key][x][0] for x in categories[key]]
# Sorts the categories by the frequency
categories[key].sort(key=lambda x: (-x["count"], x["category"]))
# Keeps only the category and the account
categories[key] = [[x["category"], x["account__code"]]
for x in categories[key]]
# Converts the dictionary to a list, as the category may not be US-ASCII
return json.dumps(categories)

View File

@ -25,8 +25,8 @@ from typing import Dict, Optional
from django.contrib import messages from django.contrib import messages
from django.db import transaction from django.db import transaction
from django.db.models import Sum, Case, When, F, Q, Count, BooleanField, \ from django.db.models import Sum, Case, When, F, Q, Count, BooleanField, \
ExpressionWrapper, Exists, OuterRef ExpressionWrapper, Exists, OuterRef, Value, CharField
from django.db.models.functions import TruncMonth, Coalesce from django.db.models.functions import TruncMonth, Coalesce, Left, StrIndex
from django.http import JsonResponse, HttpResponseRedirect, Http404, \ from django.http import JsonResponse, HttpResponseRedirect, Http404, \
HttpRequest, HttpResponse HttpRequest, HttpResponse
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
@ -805,10 +805,63 @@ class TransactionFormView(FormView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Returns the context data for the template.""" """Returns the context data for the template."""
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["summary_categories"] = utils.get_summary_categories() context["summary_categories"] = self._get_summary_categories()
context["new_record_template"] = self._get_new_record_template_json() context["new_record_template"] = self._get_new_record_template_json()
return context return context
@staticmethod
def _get_summary_categories() -> str:
"""Finds and returns the summary categories and their corresponding
account hints as JSON.
Returns:
The summary categories and their account hints, by their record
types and category types.
"""
rows = Record.objects \
.filter(Q(summary__contains=""),
~Q(account__code__startswith="114"),
~Q(account__code__startswith="214"),
~Q(account__code__startswith="128"),
~Q(account__code__startswith="228")) \
.annotate(rec_type=Case(When(is_credit=True, then=Value("credit")),
default=Value("debit"),
output_field=CharField()),
cat_type=Case(
When(summary__regex=".+—.+—.+→.+",
then=Value("bus")),
When(summary__regex=".+—.+[→↔].+",
then=Value("travel")),
default=Value("general"),
output_field=CharField()),
category=Left("summary",
StrIndex("summary", Value("")) - 1,
output_field=CharField())) \
.values("rec_type", "cat_type", "category", "account__code") \
.annotate(count=Count("category")) \
.order_by("rec_type", "cat_type", "category", "-count",
"account__code")
# Sorts the rows by the record type and the category type
categories = {}
for row in rows:
key = "%s-%s" % (row["rec_type"], row["cat_type"])
if key not in categories:
categories[key] = {}
if row["category"] not in categories[key]:
categories[key][row["category"]] = []
categories[key][row["category"]].append(row)
for key in categories:
# Keeps only the first account with most records
categories[key] = [categories[key][x][0] for x in categories[key]]
# Sorts the categories by the frequency
categories[key].sort(key=lambda x: (-x["count"], x["category"]))
# Keeps only the category and the account
categories[key] = [[x["category"], x["account__code"]]
for x in categories[key]]
# Converts the dictionary to a list, as the category may not be
# US-ASCII
return json.dumps(categories)
def _get_new_record_template_json(self) -> str: def _get_new_record_template_json(self) -> str:
context = {"record_type": "TTT", "no": "NNN"} context = {"record_type": "TTT", "no": "NNN"}
template_name = "accounting/include/record_form-transfer.html"\ template_name = "accounting/include/record_form-transfer.html"\