Renamed "voucher" to "journal entry".

This commit is contained in:
2023-03-20 22:08:58 +08:00
parent 8f909965a9
commit b1af1d7425
74 changed files with 1956 additions and 1816 deletions

View File

@ -24,7 +24,7 @@ from flask import render_template, Response
from accounting import db
from accounting.locale import gettext
from accounting.models import Currency, BaseAccount, Account, Voucher, \
from accounting.models import Currency, BaseAccount, Account, JournalEntry, \
JournalEntryLineItem
from accounting.report.period import Period, PeriodChooser
from accounting.report.utils.base_page_params import BasePageParams
@ -127,14 +127,14 @@ class AccountCollector:
= [JournalEntryLineItem.currency_code == self.__currency.code,
sa.or_(*sub_conditions)]
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
conditions.append(JournalEntry.date <= self.__period.end)
balance_func: sa.Function = sa.func.sum(sa.case(
(JournalEntryLineItem.is_debit, JournalEntryLineItem.amount),
else_=-JournalEntryLineItem.amount)).label("balance")
select_balance: sa.Select \
= sa.select(Account.id, Account.base_code, Account.no,
balance_func)\
.join(Voucher).join(Account)\
.join(JournalEntry).join(Account)\
.filter(*conditions)\
.group_by(Account.id, Account.base_code, Account.no)\
.order_by(Account.base_code, Account.no)
@ -179,7 +179,7 @@ class AccountCollector:
return None
conditions: list[sa.BinaryExpression] \
= [JournalEntryLineItem.currency_code == self.__currency.code,
Voucher.date < self.__period.start]
JournalEntry.date < self.__period.start]
return self.__query_balance(conditions)
def __add_current_period(self) -> None:
@ -199,9 +199,9 @@ class AccountCollector:
conditions: list[sa.BinaryExpression] \
= [JournalEntryLineItem.currency_code == self.__currency.code]
if self.__period.start is not None:
conditions.append(Voucher.date >= self.__period.start)
conditions.append(JournalEntry.date >= self.__period.start)
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
conditions.append(JournalEntry.date <= self.__period.end)
return self.__query_balance(conditions)
@staticmethod
@ -218,7 +218,7 @@ class AccountCollector:
(JournalEntryLineItem.is_debit, JournalEntryLineItem.amount),
else_=-JournalEntryLineItem.amount))
select_balance: sa.Select = sa.select(balance_func)\
.join(Voucher).join(Account).filter(*conditions)
.join(JournalEntry).join(Account).filter(*conditions)
return db.session.scalar(select_balance)
def __add_owner_s_equity(self, code: str, amount: Decimal | None,

View File

@ -26,7 +26,8 @@ from sqlalchemy.orm import selectinload
from accounting import db
from accounting.locale import gettext
from accounting.models import Currency, Account, Voucher, JournalEntryLineItem
from accounting.models import Currency, Account, JournalEntry, \
JournalEntryLineItem
from accounting.report.period import Period, PeriodChooser
from accounting.report.utils.base_page_params import BasePageParams
from accounting.report.utils.base_report import BaseReport
@ -70,14 +71,14 @@ class ReportLineItem:
self.url: str | None = None
"""The URL to the journal entry line item."""
if line_item is not None:
self.date = line_item.voucher.date
self.date = line_item.journal_entry.date
self.account = line_item.account
self.description = line_item.description
self.income = None if line_item.is_debit else line_item.amount
self.expense = line_item.amount if line_item.is_debit else None
self.note = line_item.voucher.note
self.url = url_for("accounting.voucher.detail",
voucher=line_item.voucher)
self.note = line_item.journal_entry.note
self.url = url_for("accounting.journal-entry.detail",
journal_entry=line_item.journal_entry)
class LineItemCollector:
@ -120,11 +121,11 @@ class LineItemCollector:
(JournalEntryLineItem.is_debit, JournalEntryLineItem.amount),
else_=-JournalEntryLineItem.amount))
select: sa.Select = sa.Select(balance_func)\
.join(Voucher).join(Account)\
.join(JournalEntry).join(Account)\
.filter(be(JournalEntryLineItem.currency_code
== self.__currency.code),
self.__account_condition,
Voucher.date < self.__period.start)
JournalEntry.date < self.__period.start)
balance: int | None = db.session.scalar(select)
if balance is None:
return None
@ -149,25 +150,26 @@ class LineItemCollector:
= [JournalEntryLineItem.currency_code == self.__currency.code,
self.__account_condition]
if self.__period.start is not None:
conditions.append(Voucher.date >= self.__period.start)
conditions.append(JournalEntry.date >= self.__period.start)
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
voucher_with_account: sa.Select = sa.Select(Voucher.id).\
conditions.append(JournalEntry.date <= self.__period.end)
journal_entry_with_account: sa.Select = sa.Select(JournalEntry.id).\
join(JournalEntryLineItem).join(Account).filter(*conditions)
return [ReportLineItem(x)
for x in JournalEntryLineItem.query.join(Voucher).join(Account)
.filter(JournalEntryLineItem.voucher_id
.in_(voucher_with_account),
for x in JournalEntryLineItem.query
.join(JournalEntry).join(Account)
.filter(JournalEntryLineItem.journal_entry_id
.in_(journal_entry_with_account),
JournalEntryLineItem.currency_code
== self.__currency.code,
sa.not_(self.__account_condition))
.order_by(Voucher.date,
Voucher.no,
.order_by(JournalEntry.date,
JournalEntry.no,
JournalEntryLineItem.is_debit,
JournalEntryLineItem.no)
.options(selectinload(JournalEntryLineItem.account),
selectinload(JournalEntryLineItem.voucher))]
selectinload(JournalEntryLineItem.journal_entry))]
@property
def __account_condition(self) -> sa.BinaryExpression:
@ -216,7 +218,7 @@ class LineItemCollector:
class CSVRow(BaseCSVRow):
"""A row in the CSV."""
def __init__(self, voucher_date: date | str | None,
def __init__(self, journal_entry_date: date | str | None,
account: str | None,
description: str | None,
income: str | Decimal | None,
@ -225,7 +227,7 @@ class CSVRow(BaseCSVRow):
note: str | None):
"""Constructs a row in the CSV.
:param voucher_date: The voucher date.
:param journal_entry_date: The journal entry date.
:param account: The account.
:param description: The description.
:param income: The income.
@ -233,7 +235,7 @@ class CSVRow(BaseCSVRow):
:param balance: The balance.
:param note: The note.
"""
self.date: date | str | None = voucher_date
self.date: date | str | None = journal_entry_date
"""The date."""
self.account: str | None = account
"""The account."""

View File

@ -24,7 +24,7 @@ from flask import render_template, Response
from accounting import db
from accounting.locale import gettext
from accounting.models import Currency, BaseAccount, Account, Voucher, \
from accounting.models import Currency, BaseAccount, Account, JournalEntry, \
JournalEntryLineItem
from accounting.report.period import Period, PeriodChooser
from accounting.report.utils.base_page_params import BasePageParams
@ -259,14 +259,14 @@ class IncomeStatement(BaseReport):
= [JournalEntryLineItem.currency_code == self.__currency.code,
sa.or_(*sub_conditions)]
if self.__period.start is not None:
conditions.append(Voucher.date >= self.__period.start)
conditions.append(JournalEntry.date >= self.__period.start)
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
conditions.append(JournalEntry.date <= self.__period.end)
balance_func: sa.Function = sa.func.sum(sa.case(
(JournalEntryLineItem.is_debit, -JournalEntryLineItem.amount),
else_=JournalEntryLineItem.amount)).label("balance")
select_balances: sa.Select = sa.select(Account.id, balance_func)\
.join(Voucher).join(Account)\
.join(JournalEntry).join(Account)\
.filter(*conditions)\
.group_by(Account.id)\
.order_by(Account.base_code, Account.no)

View File

@ -25,7 +25,8 @@ from flask import render_template, Response
from sqlalchemy.orm import selectinload
from accounting.locale import gettext
from accounting.models import Currency, Account, Voucher, JournalEntryLineItem
from accounting.models import Currency, Account, JournalEntry, \
JournalEntryLineItem
from accounting.report.period import Period, PeriodChooser
from accounting.report.utils.base_page_params import BasePageParams
from accounting.report.utils.base_report import BaseReport
@ -47,8 +48,8 @@ class ReportLineItem:
"""
self.line_item: JournalEntryLineItem = line_item
"""The journal entry line item."""
self.voucher: Voucher = line_item.voucher
"""The voucher."""
self.journal_entry: JournalEntry = line_item.journal_entry
"""The journal entry."""
self.currency: Currency = line_item.currency
"""The account."""
self.account: Account = line_item.account
@ -66,7 +67,7 @@ class ReportLineItem:
class CSVRow(BaseCSVRow):
"""A row in the CSV."""
def __init__(self, voucher_date: str | date,
def __init__(self, journal_entry_date: str | date,
currency: str,
account: str,
description: str | None,
@ -75,13 +76,13 @@ class CSVRow(BaseCSVRow):
note: str | None):
"""Constructs a row in the CSV.
:param voucher_date: The voucher date.
:param journal_entry_date: The journal entry date.
:param description: The description.
:param debit: The debit amount.
:param credit: The credit amount.
:param note: The note.
"""
self.date: str | date = voucher_date
self.date: str | date = journal_entry_date
"""The date."""
self.currency: str = currency
"""The currency."""
@ -155,9 +156,9 @@ def get_csv_rows(line_items: list[JournalEntryLineItem]) -> list[CSVRow]:
gettext("Account"), gettext("Description"),
gettext("Debit"), gettext("Credit"),
gettext("Note"))]
rows.extend([CSVRow(x.voucher.date, x.currency.code,
rows.extend([CSVRow(x.journal_entry.date, x.currency.code,
str(x.account).title(), x.description,
x.debit, x.credit, x.voucher.note)
x.debit, x.credit, x.journal_entry.note)
for x in line_items])
return rows
@ -183,18 +184,18 @@ class Journal(BaseReport):
"""
conditions: list[sa.BinaryExpression] = []
if self.__period.start is not None:
conditions.append(Voucher.date >= self.__period.start)
conditions.append(JournalEntry.date >= self.__period.start)
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
return JournalEntryLineItem.query.join(Voucher)\
conditions.append(JournalEntry.date <= self.__period.end)
return JournalEntryLineItem.query.join(JournalEntry)\
.filter(*conditions)\
.order_by(Voucher.date,
Voucher.no,
.order_by(JournalEntry.date,
JournalEntry.no,
JournalEntryLineItem.is_debit.desc(),
JournalEntryLineItem.no)\
.options(selectinload(JournalEntryLineItem.account),
selectinload(JournalEntryLineItem.currency),
selectinload(JournalEntryLineItem.voucher)).all()
selectinload(JournalEntryLineItem.journal_entry)).all()
def csv(self) -> Response:
"""Returns the report as CSV for download.

View File

@ -26,7 +26,8 @@ from sqlalchemy.orm import selectinload
from accounting import db
from accounting.locale import gettext
from accounting.models import Currency, Account, Voucher, JournalEntryLineItem
from accounting.models import Currency, Account, JournalEntry, \
JournalEntryLineItem
from accounting.report.period import Period, PeriodChooser
from accounting.report.utils.base_page_params import BasePageParams
from accounting.report.utils.base_report import BaseReport
@ -67,13 +68,13 @@ class ReportLineItem:
self.url: str | None = None
"""The URL to the journal entry line item."""
if line_item is not None:
self.date = line_item.voucher.date
self.date = line_item.journal_entry.date
self.description = line_item.description
self.debit = line_item.amount if line_item.is_debit else None
self.credit = None if line_item.is_debit else line_item.amount
self.note = line_item.voucher.note
self.url = url_for("accounting.voucher.detail",
voucher=line_item.voucher)
self.note = line_item.journal_entry.note
self.url = url_for("accounting.journal-entry.detail",
journal_entry=line_item.journal_entry)
class LineItemCollector:
@ -116,12 +117,12 @@ class LineItemCollector:
balance_func: sa.Function = sa.func.sum(sa.case(
(JournalEntryLineItem.is_debit, JournalEntryLineItem.amount),
else_=-JournalEntryLineItem.amount))
select: sa.Select = sa.Select(balance_func).join(Voucher)\
select: sa.Select = sa.Select(balance_func).join(JournalEntry)\
.filter(be(JournalEntryLineItem.currency_code
== self.__currency.code),
be(JournalEntryLineItem.account_id
== self.__account.id),
Voucher.date < self.__period.start)
JournalEntry.date < self.__period.start)
balance: int | None = db.session.scalar(select)
if balance is None:
return None
@ -145,17 +146,18 @@ class LineItemCollector:
= [JournalEntryLineItem.currency_code == self.__currency.code,
JournalEntryLineItem.account_id == self.__account.id]
if self.__period.start is not None:
conditions.append(Voucher.date >= self.__period.start)
conditions.append(JournalEntry.date >= self.__period.start)
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
conditions.append(JournalEntry.date <= self.__period.end)
return [ReportLineItem(x) for x in JournalEntryLineItem.query
.join(Voucher)
.join(JournalEntry)
.filter(*conditions)
.order_by(Voucher.date,
Voucher.no,
.order_by(JournalEntry.date,
JournalEntry.no,
JournalEntryLineItem.is_debit.desc(),
JournalEntryLineItem.no)
.options(selectinload(JournalEntryLineItem.voucher)).all()]
.options(selectinload(JournalEntryLineItem.journal_entry))
.all()]
def __get_total(self) -> ReportLineItem | None:
"""Composes the total line item.
@ -197,7 +199,7 @@ class LineItemCollector:
class CSVRow(BaseCSVRow):
"""A row in the CSV."""
def __init__(self, voucher_date: date | str | None,
def __init__(self, journal_entry_date: date | str | None,
description: str | None,
debit: str | Decimal | None,
credit: str | Decimal | None,
@ -205,14 +207,14 @@ class CSVRow(BaseCSVRow):
note: str | None):
"""Constructs a row in the CSV.
:param voucher_date: The voucher date.
:param journal_entry_date: The journal entry date.
:param description: The description.
:param debit: The debit amount.
:param credit: The credit amount.
:param balance: The balance.
:param note: The note.
"""
self.date: date | str | None = voucher_date
self.date: date | str | None = journal_entry_date
"""The date."""
self.description: str | None = description
"""The description."""

View File

@ -26,7 +26,7 @@ from sqlalchemy.orm import selectinload
from accounting.locale import gettext
from accounting.models import Currency, CurrencyL10n, Account, AccountL10n, \
Voucher, JournalEntryLineItem
JournalEntry, JournalEntryLineItem
from accounting.report.utils.base_page_params import BasePageParams
from accounting.report.utils.base_report import BaseReport
from accounting.report.utils.csv_export import csv_download
@ -62,22 +62,23 @@ class LineItemCollector:
self.__get_account_condition(k)),
JournalEntryLineItem.currency_code.in_(
self.__get_currency_condition(k)),
JournalEntryLineItem.voucher_id.in_(
self.__get_voucher_condition(k))]
JournalEntryLineItem.journal_entry_id.in_(
self.__get_journal_entry_condition(k))]
try:
sub_conditions.append(
JournalEntryLineItem.amount == Decimal(k))
except ArithmeticError:
pass
conditions.append(sa.or_(*sub_conditions))
return JournalEntryLineItem.query.join(Voucher).filter(*conditions)\
.order_by(Voucher.date,
Voucher.no,
return JournalEntryLineItem.query.join(JournalEntry)\
.filter(*conditions)\
.order_by(JournalEntry.date,
JournalEntry.no,
JournalEntryLineItem.is_debit,
JournalEntryLineItem.no)\
.options(selectinload(JournalEntryLineItem.account),
selectinload(JournalEntryLineItem.currency),
selectinload(JournalEntryLineItem.voucher)).all()
selectinload(JournalEntryLineItem.journal_entry)).all()
@staticmethod
def __get_account_condition(k: str) -> sa.Select:
@ -116,35 +117,40 @@ class LineItemCollector:
Currency.code.in_(select_l10n)))
@staticmethod
def __get_voucher_condition(k: str) -> sa.Select:
"""Composes and returns the condition to filter the voucher.
def __get_journal_entry_condition(k: str) -> sa.Select:
"""Composes and returns the condition to filter the journal entry.
:param k: The keyword.
:return: The condition to filter the voucher.
:return: The condition to filter the journal entry.
"""
conditions: list[sa.BinaryExpression] = [Voucher.note.contains(k)]
voucher_date: datetime
conditions: list[sa.BinaryExpression] = [JournalEntry.note.contains(k)]
journal_entry_date: datetime
try:
voucher_date = datetime.strptime(k, "%Y")
journal_entry_date = datetime.strptime(k, "%Y")
conditions.append(
be(sa.extract("year", Voucher.date) == voucher_date.year))
be(sa.extract("year", JournalEntry.date)
== journal_entry_date.year))
except ValueError:
pass
try:
voucher_date = datetime.strptime(k, "%Y/%m")
journal_entry_date = datetime.strptime(k, "%Y/%m")
conditions.append(sa.and_(
sa.extract("year", Voucher.date) == voucher_date.year,
sa.extract("month", Voucher.date) == voucher_date.month))
sa.extract("year", JournalEntry.date)
== journal_entry_date.year,
sa.extract("month", JournalEntry.date)
== journal_entry_date.month))
except ValueError:
pass
try:
voucher_date = datetime.strptime(f"2000/{k}", "%Y/%m/%d")
journal_entry_date = datetime.strptime(f"2000/{k}", "%Y/%m/%d")
conditions.append(sa.and_(
sa.extract("month", Voucher.date) == voucher_date.month,
sa.extract("day", Voucher.date) == voucher_date.day))
sa.extract("month", JournalEntry.date)
== journal_entry_date.month,
sa.extract("day", JournalEntry.date)
== journal_entry_date.day))
except ValueError:
pass
return sa.select(Voucher.id).filter(sa.or_(*conditions))
return sa.select(JournalEntry.id).filter(sa.or_(*conditions))
class PageParams(BasePageParams):

View File

@ -24,7 +24,8 @@ from flask import Response, render_template
from accounting import db
from accounting.locale import gettext
from accounting.models import Currency, Account, Voucher, JournalEntryLineItem
from accounting.models import Currency, Account, JournalEntry, \
JournalEntryLineItem
from accounting.report.period import Period, PeriodChooser
from accounting.report.utils.base_page_params import BasePageParams
from accounting.report.utils.base_report import BaseReport
@ -180,14 +181,14 @@ class TrialBalance(BaseReport):
conditions: list[sa.BinaryExpression] \
= [JournalEntryLineItem.currency_code == self.__currency.code]
if self.__period.start is not None:
conditions.append(Voucher.date >= self.__period.start)
conditions.append(JournalEntry.date >= self.__period.start)
if self.__period.end is not None:
conditions.append(Voucher.date <= self.__period.end)
conditions.append(JournalEntry.date <= self.__period.end)
balance_func: sa.Function = sa.func.sum(sa.case(
(JournalEntryLineItem.is_debit, JournalEntryLineItem.amount),
else_=-JournalEntryLineItem.amount)).label("balance")
select_balances: sa.Select = sa.select(Account.id, balance_func)\
.join(Voucher).join(Account)\
.join(JournalEntry).join(Account)\
.filter(*conditions)\
.group_by(Account.id)\
.order_by(Account.base_code, Account.no)