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.

This commit is contained in:
依瑪貓 2023-03-09 07:55:36 +08:00
parent 2f27ad5bef
commit 555ad388bc
3 changed files with 50 additions and 35 deletions

View File

@ -640,3 +640,19 @@ class JournalEntry(db.Model):
:return: The account code. :return: The account code.
""" """
return self.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

View File

@ -24,14 +24,13 @@ import sqlalchemy as sa
from flask import render_template, Response from flask import render_template, Response
from sqlalchemy.orm import selectinload from sqlalchemy.orm import selectinload
from accounting import db
from accounting.locale import gettext from accounting.locale import gettext
from accounting.models import Currency, Account, Transaction, JournalEntry from accounting.models import Currency, Account, Transaction, JournalEntry
from accounting.report.period import Period from accounting.report.period import Period
from accounting.utils.pagination import Pagination from accounting.utils.pagination import Pagination
from .utils.base_page_params import BasePageParams
from .utils.base_report import BaseReport from .utils.base_report import BaseReport
from .utils.csv_export import BaseCSVRow, csv_download, period_spec 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.period_choosers import JournalPeriodChooser
from .utils.report_chooser import ReportChooser from .utils.report_chooser import ReportChooser
from .utils.report_type import ReportType from .utils.report_type import ReportType
@ -55,9 +54,9 @@ class ReportEntry:
"""The account.""" """The account."""
self.summary: str | None = entry.summary self.summary: str | None = entry.summary
"""The summary.""" """The summary."""
self.debit: Decimal | None = entry.amount if entry.is_debit else None self.debit: Decimal | None = entry.debit
"""The debit amount.""" """The debit amount."""
self.credit: Decimal | None = None if entry.is_debit else entry.amount self.credit: Decimal | None = entry.credit
"""The credit amount.""" """The credit amount."""
self.amount: Decimal = entry.amount self.amount: Decimal = entry.amount
"""The amount.""" """The amount."""
@ -110,8 +109,8 @@ class PageParams(BasePageParams):
"""The HTML page parameters.""" """The HTML page parameters."""
def __init__(self, period: Period, def __init__(self, period: Period,
pagination: Pagination[ReportEntry], pagination: Pagination[JournalEntry],
entries: list[ReportEntry]): entries: list[JournalEntry]):
"""Constructs the HTML page parameters. """Constructs the HTML page parameters.
:param period: The period. :param period: The period.
@ -119,9 +118,9 @@ class PageParams(BasePageParams):
""" """
self.period: Period = period self.period: Period = period
"""The period.""" """The period."""
self.pagination: Pagination[ReportEntry] = pagination self.pagination: Pagination[JournalEntry] = pagination
"""The pagination.""" """The pagination."""
self.entries: list[ReportEntry] = entries self.entries: list[JournalEntry] = entries
"""The entries.""" """The entries."""
self.period_chooser: JournalPeriodChooser \ self.period_chooser: JournalPeriodChooser \
= JournalPeriodChooser() = JournalPeriodChooser()
@ -145,7 +144,7 @@ class PageParams(BasePageParams):
period=self.period) 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. """Composes and returns the CSV rows from the report entries.
:param entries: The report entries. :param entries: The report entries.
@ -172,10 +171,10 @@ class Journal(BaseReport):
""" """
self.__period: Period = period self.__period: Period = period
"""The period.""" """The period."""
self.__entries: list[ReportEntry] = self.__query_entries() self.__entries: list[JournalEntry] = self.__query_entries()
"""The journal entries.""" """The journal entries."""
def __query_entries(self) -> list[ReportEntry]: def __query_entries(self) -> list[JournalEntry]:
"""Queries and returns the journal entries. """Queries and returns the journal entries.
:return: The journal entries. :return: The journal entries.
@ -185,14 +184,14 @@ class Journal(BaseReport):
conditions.append(Transaction.date >= self.__period.start) conditions.append(Transaction.date >= self.__period.start)
if self.__period.end is not None: if self.__period.end is not None:
conditions.append(Transaction.date <= self.__period.end) conditions.append(Transaction.date <= self.__period.end)
return [ReportEntry(x) for x in db.session return JournalEntry.query.join(Transaction)\
.query(JournalEntry).join(Transaction).filter(*conditions) .filter(*conditions)\
.order_by(Transaction.date, .order_by(Transaction.date,
JournalEntry.is_debit.desc(), JournalEntry.is_debit.desc(),
JournalEntry.no) JournalEntry.no)\
.options(selectinload(JournalEntry.account), .options(selectinload(JournalEntry.account),
selectinload(JournalEntry.currency), selectinload(JournalEntry.currency),
selectinload(JournalEntry.transaction)).all()] selectinload(JournalEntry.transaction)).all()
def csv(self) -> Response: def csv(self) -> Response:
"""Returns the report as CSV for download. """Returns the report as CSV for download.
@ -207,8 +206,8 @@ class Journal(BaseReport):
:return: The report as HTML. :return: The report as HTML.
""" """
pagination: Pagination[ReportEntry] \ pagination: Pagination[JournalEntry] \
= Pagination[ReportEntry](self.__entries) = Pagination[JournalEntry](self.__entries)
params: PageParams = PageParams(period=self.__period, params: PageParams = PageParams(period=self.__period,
pagination=pagination, pagination=pagination,
entries=pagination.list) entries=pagination.list)

View File

@ -29,7 +29,7 @@ from accounting.models import Currency, CurrencyL10n, Account, AccountL10n, \
Transaction, JournalEntry Transaction, JournalEntry
from accounting.utils.pagination import Pagination from accounting.utils.pagination import Pagination
from accounting.utils.query import parse_query_keywords 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_page_params import BasePageParams
from .utils.base_report import BaseReport from .utils.base_report import BaseReport
from .utils.csv_export import csv_download from .utils.csv_export import csv_download
@ -42,10 +42,10 @@ class EntryCollector:
def __init__(self): def __init__(self):
"""Constructs the report entry collector.""" """Constructs the report entry collector."""
self.entries: list[ReportEntry] = self.__query_entries() self.entries: list[JournalEntry] = self.__query_entries()
"""The report entries.""" """The report entries."""
def __query_entries(self) -> list[ReportEntry]: def __query_entries(self) -> list[JournalEntry]:
"""Queries and returns the journal entries. """Queries and returns the journal entries.
:return: The journal entries. :return: The journal entries.
@ -68,10 +68,10 @@ class EntryCollector:
except ArithmeticError: except ArithmeticError:
pass pass
conditions.append(sa.or_(*sub_conditions)) conditions.append(sa.or_(*sub_conditions))
return [ReportEntry(x) for x in JournalEntry.query.filter(*conditions) return JournalEntry.query.filter(*conditions)\
.options(selectinload(JournalEntry.account), .options(selectinload(JournalEntry.account),
selectinload(JournalEntry.currency), selectinload(JournalEntry.currency),
selectinload(JournalEntry.transaction))] selectinload(JournalEntry.transaction)).all()
@staticmethod @staticmethod
def __get_account_condition(k: str) -> sa.Select: def __get_account_condition(k: str) -> sa.Select:
@ -144,15 +144,15 @@ class EntryCollector:
class PageParams(BasePageParams): class PageParams(BasePageParams):
"""The HTML page parameters.""" """The HTML page parameters."""
def __init__(self, pagination: Pagination[ReportEntry], def __init__(self, pagination: Pagination[JournalEntry],
entries: list[ReportEntry]): entries: list[JournalEntry]):
"""Constructs the HTML page parameters. """Constructs the HTML page parameters.
:param entries: The search result entries. :param entries: The search result entries.
""" """
self.pagination: Pagination[ReportEntry] = pagination self.pagination: Pagination[JournalEntry] = pagination
"""The pagination.""" """The pagination."""
self.entries: list[ReportEntry] = entries self.entries: list[JournalEntry] = entries
"""The entries.""" """The entries."""
@property @property
@ -177,7 +177,7 @@ class Search(BaseReport):
def __init__(self): def __init__(self):
"""Constructs a search.""" """Constructs a search."""
self.__entries: list[ReportEntry] = EntryCollector().entries self.__entries: list[JournalEntry] = EntryCollector().entries
"""The journal entries.""" """The journal entries."""
def csv(self) -> Response: def csv(self) -> Response:
@ -193,8 +193,8 @@ class Search(BaseReport):
:return: The report as HTML. :return: The report as HTML.
""" """
pagination: Pagination[ReportEntry] \ pagination: Pagination[JournalEntry] \
= Pagination[ReportEntry](self.__entries) = Pagination[JournalEntry](self.__entries)
params: PageParams = PageParams(pagination=pagination, params: PageParams = PageParams(pagination=pagination,
entries=pagination.list) entries=pagination.list)
return render_template("accounting/report/search.html", return render_template("accounting/report/search.html",