From 555ad388bc5cca0c0e64b5923fb6d934ee0382f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=9D=E7=91=AA=E8=B2=93?= Date: Thu, 9 Mar 2023 07:55:36 +0800 Subject: [PATCH] Added the debit and credit pseudo properties to the JournalEntry data model, and retired the redundant ReportEntry model from the "accounting.report.reports.journal" module. --- src/accounting/models.py | 16 +++++++++ src/accounting/report/reports/journal.py | 41 ++++++++++++------------ src/accounting/report/reports/search.py | 28 ++++++++-------- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/accounting/models.py b/src/accounting/models.py index 693c7f6..86f9dbc 100644 --- a/src/accounting/models.py +++ b/src/accounting/models.py @@ -640,3 +640,19 @@ class JournalEntry(db.Model): :return: The account code. """ return self.account.code + + @property + def debit(self) -> Decimal | None: + """Returns the debit amount. + + :return: The debit amount, or None if this is not a debit entry. + """ + return self.amount if self.is_debit else None + + @property + def credit(self) -> Decimal | None: + """Returns the credit amount. + + :return: The credit amount, or None if this is not a credit entry. + """ + return None if self.is_debit else self.amount diff --git a/src/accounting/report/reports/journal.py b/src/accounting/report/reports/journal.py index 7d15163..0080b0e 100644 --- a/src/accounting/report/reports/journal.py +++ b/src/accounting/report/reports/journal.py @@ -24,14 +24,13 @@ import sqlalchemy as sa from flask import render_template, Response from sqlalchemy.orm import selectinload -from accounting import db from accounting.locale import gettext from accounting.models import Currency, Account, Transaction, JournalEntry from accounting.report.period import Period from accounting.utils.pagination import Pagination +from .utils.base_page_params import BasePageParams from .utils.base_report import BaseReport from .utils.csv_export import BaseCSVRow, csv_download, period_spec -from .utils.base_page_params import BasePageParams from .utils.period_choosers import JournalPeriodChooser from .utils.report_chooser import ReportChooser from .utils.report_type import ReportType @@ -55,9 +54,9 @@ class ReportEntry: """The account.""" self.summary: str | None = entry.summary """The summary.""" - self.debit: Decimal | None = entry.amount if entry.is_debit else None + self.debit: Decimal | None = entry.debit """The debit amount.""" - self.credit: Decimal | None = None if entry.is_debit else entry.amount + self.credit: Decimal | None = entry.credit """The credit amount.""" self.amount: Decimal = entry.amount """The amount.""" @@ -110,8 +109,8 @@ class PageParams(BasePageParams): """The HTML page parameters.""" def __init__(self, period: Period, - pagination: Pagination[ReportEntry], - entries: list[ReportEntry]): + pagination: Pagination[JournalEntry], + entries: list[JournalEntry]): """Constructs the HTML page parameters. :param period: The period. @@ -119,9 +118,9 @@ class PageParams(BasePageParams): """ self.period: Period = period """The period.""" - self.pagination: Pagination[ReportEntry] = pagination + self.pagination: Pagination[JournalEntry] = pagination """The pagination.""" - self.entries: list[ReportEntry] = entries + self.entries: list[JournalEntry] = entries """The entries.""" self.period_chooser: JournalPeriodChooser \ = JournalPeriodChooser() @@ -145,7 +144,7 @@ class PageParams(BasePageParams): period=self.period) -def get_csv_rows(entries: list[ReportEntry]) -> list[CSVRow]: +def get_csv_rows(entries: list[JournalEntry]) -> list[CSVRow]: """Composes and returns the CSV rows from the report entries. :param entries: The report entries. @@ -172,10 +171,10 @@ class Journal(BaseReport): """ self.__period: Period = period """The period.""" - self.__entries: list[ReportEntry] = self.__query_entries() + self.__entries: list[JournalEntry] = self.__query_entries() """The journal entries.""" - def __query_entries(self) -> list[ReportEntry]: + def __query_entries(self) -> list[JournalEntry]: """Queries and returns the journal entries. :return: The journal entries. @@ -185,14 +184,14 @@ class Journal(BaseReport): conditions.append(Transaction.date >= self.__period.start) if self.__period.end is not None: conditions.append(Transaction.date <= self.__period.end) - return [ReportEntry(x) for x in db.session - .query(JournalEntry).join(Transaction).filter(*conditions) - .order_by(Transaction.date, - JournalEntry.is_debit.desc(), - JournalEntry.no) - .options(selectinload(JournalEntry.account), - selectinload(JournalEntry.currency), - selectinload(JournalEntry.transaction)).all()] + return JournalEntry.query.join(Transaction)\ + .filter(*conditions)\ + .order_by(Transaction.date, + JournalEntry.is_debit.desc(), + JournalEntry.no)\ + .options(selectinload(JournalEntry.account), + selectinload(JournalEntry.currency), + selectinload(JournalEntry.transaction)).all() def csv(self) -> Response: """Returns the report as CSV for download. @@ -207,8 +206,8 @@ class Journal(BaseReport): :return: The report as HTML. """ - pagination: Pagination[ReportEntry] \ - = Pagination[ReportEntry](self.__entries) + pagination: Pagination[JournalEntry] \ + = Pagination[JournalEntry](self.__entries) params: PageParams = PageParams(period=self.__period, pagination=pagination, entries=pagination.list) diff --git a/src/accounting/report/reports/search.py b/src/accounting/report/reports/search.py index 050fd1a..b11c416 100644 --- a/src/accounting/report/reports/search.py +++ b/src/accounting/report/reports/search.py @@ -29,7 +29,7 @@ from accounting.models import Currency, CurrencyL10n, Account, AccountL10n, \ Transaction, JournalEntry from accounting.utils.pagination import Pagination from accounting.utils.query import parse_query_keywords -from .journal import ReportEntry, get_csv_rows +from .journal import get_csv_rows from .utils.base_page_params import BasePageParams from .utils.base_report import BaseReport from .utils.csv_export import csv_download @@ -42,10 +42,10 @@ class EntryCollector: def __init__(self): """Constructs the report entry collector.""" - self.entries: list[ReportEntry] = self.__query_entries() + self.entries: list[JournalEntry] = self.__query_entries() """The report entries.""" - def __query_entries(self) -> list[ReportEntry]: + def __query_entries(self) -> list[JournalEntry]: """Queries and returns the journal entries. :return: The journal entries. @@ -68,10 +68,10 @@ class EntryCollector: except ArithmeticError: pass conditions.append(sa.or_(*sub_conditions)) - return [ReportEntry(x) for x in JournalEntry.query.filter(*conditions) - .options(selectinload(JournalEntry.account), - selectinload(JournalEntry.currency), - selectinload(JournalEntry.transaction))] + return JournalEntry.query.filter(*conditions)\ + .options(selectinload(JournalEntry.account), + selectinload(JournalEntry.currency), + selectinload(JournalEntry.transaction)).all() @staticmethod def __get_account_condition(k: str) -> sa.Select: @@ -144,15 +144,15 @@ class EntryCollector: class PageParams(BasePageParams): """The HTML page parameters.""" - def __init__(self, pagination: Pagination[ReportEntry], - entries: list[ReportEntry]): + def __init__(self, pagination: Pagination[JournalEntry], + entries: list[JournalEntry]): """Constructs the HTML page parameters. :param entries: The search result entries. """ - self.pagination: Pagination[ReportEntry] = pagination + self.pagination: Pagination[JournalEntry] = pagination """The pagination.""" - self.entries: list[ReportEntry] = entries + self.entries: list[JournalEntry] = entries """The entries.""" @property @@ -177,7 +177,7 @@ class Search(BaseReport): def __init__(self): """Constructs a search.""" - self.__entries: list[ReportEntry] = EntryCollector().entries + self.__entries: list[JournalEntry] = EntryCollector().entries """The journal entries.""" def csv(self) -> Response: @@ -193,8 +193,8 @@ class Search(BaseReport): :return: The report as HTML. """ - pagination: Pagination[ReportEntry] \ - = Pagination[ReportEntry](self.__entries) + pagination: Pagination[JournalEntry] \ + = Pagination[JournalEntry](self.__entries) params: PageParams = PageParams(pagination=pagination, entries=pagination.list) return render_template("accounting/report/search.html",