From 68964c5ed5b9c5d023a27f3db2b1d02779287ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=9D=E7=91=AA=E8=B2=93?= Date: Wed, 19 Aug 2020 14:13:30 +0800 Subject: [PATCH] Moved the get_summary_categories() utility to TransactionFormView in the accounting application. --- accounting/utils.py | 55 +----------------------------------------- accounting/views.py | 59 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/accounting/utils.py b/accounting/utils.py index 5d52ed5..30b731e 100644 --- a/accounting/utils.py +++ b/accounting/utils.py @@ -19,13 +19,10 @@ """ import datetime -import json from typing import Union, Tuple, List, Optional, Iterable from django.conf import settings -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.db.models import Q, Sum, Case, When, F, Count, Max, Min from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext as _ @@ -466,53 +463,3 @@ def find_existing_equipments(account: Account, if x.pk is not None and F"{x.account.code}-{x.summary}" in keys]: 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) diff --git a/accounting/views.py b/accounting/views.py index 27a0d93..d666bd8 100644 --- a/accounting/views.py +++ b/accounting/views.py @@ -25,8 +25,8 @@ from typing import Dict, Optional from django.contrib import messages from django.db import transaction from django.db.models import Sum, Case, When, F, Q, Count, BooleanField, \ - ExpressionWrapper, Exists, OuterRef -from django.db.models.functions import TruncMonth, Coalesce + ExpressionWrapper, Exists, OuterRef, Value, CharField +from django.db.models.functions import TruncMonth, Coalesce, Left, StrIndex from django.http import JsonResponse, HttpResponseRedirect, Http404, \ HttpRequest, HttpResponse from django.shortcuts import render, redirect @@ -805,10 +805,63 @@ class TransactionFormView(FormView): def get_context_data(self, **kwargs): """Returns the context data for the template.""" 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() 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: context = {"record_type": "TTT", "no": "NNN"} template_name = "accounting/include/record_form-transfer.html"\