diff --git a/src/accounting/account/commands.py b/src/accounting/account/commands.py index 6f41ae1..ad85c44 100644 --- a/src/accounting/account/commands.py +++ b/src/accounting/account/commands.py @@ -100,11 +100,11 @@ def init_accounts_command(username: str) -> None: def __is_need_offset(base_code: str) -> bool: - """Checks that whether voucher line items in the account need offset. + """Checks that whether journal entry line items in the account need offset. :param base_code: The code of the base account. - :return: True if voucher line items in the account need offset, or False - otherwise. + :return: True if journal entry line items in the account need offset, or + False otherwise. """ # Assets if base_code[0] == "1": diff --git a/src/accounting/account/forms.py b/src/accounting/account/forms.py index cf745b0..a87883d 100644 --- a/src/accounting/account/forms.py +++ b/src/accounting/account/forms.py @@ -82,7 +82,7 @@ class AccountForm(FlaskForm): """The title.""" is_need_offset = BooleanField( validators=[NoOffsetNominalAccount()]) - """Whether the the voucher line items of this account need offset.""" + """Whether the the journal entry line items of this account need offset.""" def populate_obj(self, obj: Account) -> None: """Populates the form data into an account object. diff --git a/src/accounting/models.py b/src/accounting/models.py index 3d23706..f9e4ad3 100644 --- a/src/accounting/models.py +++ b/src/accounting/models.py @@ -115,7 +115,7 @@ class Account(db.Model): title_l10n = db.Column("title", db.String, nullable=False) """The title.""" is_need_offset = db.Column(db.Boolean, nullable=False, default=False) - """Whether the voucher line items of this account need offset.""" + """Whether the journal entry line items of this account need offset.""" created_at = db.Column(db.DateTime(timezone=True), nullable=False, server_default=db.func.now()) """The time of creation.""" @@ -139,8 +139,9 @@ class Account(db.Model): l10n = db.relationship("AccountL10n", back_populates="account", lazy=False) """The localized titles.""" - line_items = db.relationship("VoucherLineItem", back_populates="account") - """The voucher line items.""" + line_items = db.relationship("JournalEntryLineItem", + back_populates="account") + """The journal entry line items.""" CASH_CODE: str = "1111-001" """The code of the cash account,""" @@ -363,8 +364,9 @@ class Currency(db.Model): l10n = db.relationship("CurrencyL10n", back_populates="currency", lazy=False) """The localized names.""" - line_items = db.relationship("VoucherLineItem", back_populates="currency") - """The voucher line items.""" + line_items = db.relationship("JournalEntryLineItem", + back_populates="currency") + """The journal entry line items.""" def __str__(self) -> str: """Returns the string representation of the currency. @@ -450,8 +452,8 @@ class CurrencyL10n(db.Model): class VoucherCurrency: """A currency in a voucher.""" - def __init__(self, code: str, debit: list[VoucherLineItem], - credit: list[VoucherLineItem]): + def __init__(self, code: str, debit: list[JournalEntryLineItem], + credit: list[JournalEntryLineItem]): """Constructs the currency in the voucher. :param code: The currency code. @@ -460,9 +462,9 @@ class VoucherCurrency: """ self.code: str = code """The currency code.""" - self.debit: list[VoucherLineItem] = debit + self.debit: list[JournalEntryLineItem] = debit """The debit line items.""" - self.credit: list[VoucherLineItem] = credit + self.credit: list[JournalEntryLineItem] = credit """The credit line items.""" @property @@ -523,7 +525,8 @@ class Voucher(db.Model): """The ID of the updator.""" updated_by = db.relationship(user_cls, foreign_keys=updated_by_id) """The updator.""" - line_items = db.relationship("VoucherLineItem", back_populates="voucher") + line_items = db.relationship("JournalEntryLineItem", + back_populates="voucher") """The line items.""" def __str__(self) -> str: @@ -543,10 +546,10 @@ class Voucher(db.Model): :return: The currency categories. """ - line_items: list[VoucherLineItem] = sorted(self.line_items, - key=lambda x: x.no) + line_items: list[JournalEntryLineItem] = sorted(self.line_items, + key=lambda x: x.no) codes: list[str] = [] - by_currency: dict[str, list[VoucherLineItem]] = {} + by_currency: dict[str, list[JournalEntryLineItem]] = {} for line_item in line_items: if line_item.currency_code not in by_currency: codes.append(line_item.currency_code) @@ -606,14 +609,14 @@ class Voucher(db.Model): :return: None. """ - VoucherLineItem.query\ - .filter(VoucherLineItem.voucher_id == self.id).delete() + JournalEntryLineItem.query\ + .filter(JournalEntryLineItem.voucher_id == self.id).delete() db.session.delete(self) -class VoucherLineItem(db.Model): - """A line item in the voucher.""" - __tablename__ = "accounting_voucher_line_items" +class JournalEntryLineItem(db.Model): + """A line item in the journal entry.""" + __tablename__ = "accounting_journal_entry_line_items" """The table name.""" id = db.Column(db.Integer, nullable=False, primary_key=True, autoincrement=False) @@ -633,11 +636,11 @@ class VoucherLineItem(db.Model): db.ForeignKey(id, onupdate="CASCADE"), nullable=True) """The ID of the original line item.""" - original_line_item = db.relationship("VoucherLineItem", + original_line_item = db.relationship("JournalEntryLineItem", back_populates="offsets", remote_side=id, passive_deletes=True) """The original line item.""" - offsets = db.relationship("VoucherLineItem", + offsets = db.relationship("JournalEntryLineItem", back_populates="original_line_item") """The offset items.""" currency_code = db.Column(db.String, diff --git a/src/accounting/report/reports/balance_sheet.py b/src/accounting/report/reports/balance_sheet.py index 0a1bb6c..7588c7d 100644 --- a/src/accounting/report/reports/balance_sheet.py +++ b/src/accounting/report/reports/balance_sheet.py @@ -25,7 +25,7 @@ from flask import render_template, Response from accounting import db from accounting.locale import gettext from accounting.models import Currency, BaseAccount, Account, Voucher, \ - VoucherLineItem + 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 @@ -124,13 +124,13 @@ class AccountCollector: sub_conditions: list[sa.BinaryExpression] \ = [Account.base_code.startswith(x) for x in {"1", "2", "3"}] conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code, + = [JournalEntryLineItem.currency_code == self.__currency.code, sa.or_(*sub_conditions)] if self.__period.end is not None: conditions.append(Voucher.date <= self.__period.end) balance_func: sa.Function = sa.func.sum(sa.case( - (VoucherLineItem.is_debit, VoucherLineItem.amount), - else_=-VoucherLineItem.amount)).label("balance") + (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)\ @@ -178,7 +178,7 @@ class AccountCollector: if self.__period.start is None: return None conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code, + = [JournalEntryLineItem.currency_code == self.__currency.code, Voucher.date < self.__period.start] return self.__query_balance(conditions) @@ -197,7 +197,7 @@ class AccountCollector: :return: The net income or loss for current period. """ conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code] + = [JournalEntryLineItem.currency_code == self.__currency.code] if self.__period.start is not None: conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: @@ -215,8 +215,8 @@ class AccountCollector: conditions.extend([sa.not_(Account.base_code.startswith(x)) for x in {"1", "2", "3"}]) balance_func: sa.Function = sa.func.sum(sa.case( - (VoucherLineItem.is_debit, VoucherLineItem.amount), - else_=-VoucherLineItem.amount)) + (JournalEntryLineItem.is_debit, JournalEntryLineItem.amount), + else_=-JournalEntryLineItem.amount)) select_balance: sa.Select = sa.select(balance_func)\ .join(Voucher).join(Account).filter(*conditions) return db.session.scalar(select_balance) diff --git a/src/accounting/report/reports/income_expenses.py b/src/accounting/report/reports/income_expenses.py index 77d1568..34e0b18 100644 --- a/src/accounting/report/reports/income_expenses.py +++ b/src/accounting/report/reports/income_expenses.py @@ -26,7 +26,7 @@ from sqlalchemy.orm import selectinload from accounting import db from accounting.locale import gettext -from accounting.models import Currency, Account, Voucher, VoucherLineItem +from accounting.models import Currency, Account, Voucher, 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 @@ -44,10 +44,10 @@ from accounting.utils.pagination import Pagination class ReportLineItem: """A line item in the report.""" - def __init__(self, line_item: VoucherLineItem | None = None): + def __init__(self, line_item: JournalEntryLineItem | None = None): """Constructs the line item in the report. - :param line_item: The voucher line item. + :param line_item: The journal entry line item. """ self.is_brought_forward: bool = False """Whether this is the brought-forward line item.""" @@ -68,7 +68,7 @@ class ReportLineItem: self.note: str | None = None """The note.""" self.url: str | None = None - """The URL to the voucher line item.""" + """The URL to the journal entry line item.""" if line_item is not None: self.date = line_item.voucher.date self.account = line_item.account @@ -117,11 +117,12 @@ class LineItemCollector: if self.__period.start is None: return None balance_func: sa.Function = sa.func.sum(sa.case( - (VoucherLineItem.is_debit, VoucherLineItem.amount), - else_=-VoucherLineItem.amount)) + (JournalEntryLineItem.is_debit, JournalEntryLineItem.amount), + else_=-JournalEntryLineItem.amount)) select: sa.Select = sa.Select(balance_func)\ .join(Voucher).join(Account)\ - .filter(be(VoucherLineItem.currency_code == self.__currency.code), + .filter(be(JournalEntryLineItem.currency_code + == self.__currency.code), self.__account_condition, Voucher.date < self.__period.start) balance: int | None = db.session.scalar(select) @@ -145,26 +146,28 @@ class LineItemCollector: :return: The line items. """ conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code, + = [JournalEntryLineItem.currency_code == self.__currency.code, self.__account_condition] if self.__period.start is not None: conditions.append(Voucher.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).\ - join(VoucherLineItem).join(Account).filter(*conditions) + join(JournalEntryLineItem).join(Account).filter(*conditions) return [ReportLineItem(x) - for x in VoucherLineItem.query.join(Voucher).join(Account) - .filter(VoucherLineItem.voucher_id.in_(voucher_with_account), - VoucherLineItem.currency_code == self.__currency.code, + for x in JournalEntryLineItem.query.join(Voucher).join(Account) + .filter(JournalEntryLineItem.voucher_id + .in_(voucher_with_account), + JournalEntryLineItem.currency_code + == self.__currency.code, sa.not_(self.__account_condition)) .order_by(Voucher.date, Voucher.no, - VoucherLineItem.is_debit, - VoucherLineItem.no) - .options(selectinload(VoucherLineItem.account), - selectinload(VoucherLineItem.voucher))] + JournalEntryLineItem.is_debit, + JournalEntryLineItem.no) + .options(selectinload(JournalEntryLineItem.account), + selectinload(JournalEntryLineItem.voucher))] @property def __account_condition(self) -> sa.BinaryExpression: @@ -343,14 +346,15 @@ class PageParams(BasePageParams): income_expenses_url(self.currency, current_al, self.period), self.account.id == 0)] - in_use: sa.Select = sa.Select(VoucherLineItem.account_id)\ + in_use: sa.Select = sa.Select(JournalEntryLineItem.account_id)\ .join(Account)\ - .filter(be(VoucherLineItem.currency_code == self.currency.code), + .filter(be(JournalEntryLineItem.currency_code + == self.currency.code), sa.or_(Account.base_code.startswith("11"), Account.base_code.startswith("12"), Account.base_code.startswith("21"), Account.base_code.startswith("22")))\ - .group_by(VoucherLineItem.account_id) + .group_by(JournalEntryLineItem.account_id) options.extend([OptionLink(str(x), income_expenses_url( self.currency, diff --git a/src/accounting/report/reports/income_statement.py b/src/accounting/report/reports/income_statement.py index 6cf369b..01edbcb 100644 --- a/src/accounting/report/reports/income_statement.py +++ b/src/accounting/report/reports/income_statement.py @@ -25,7 +25,7 @@ from flask import render_template, Response from accounting import db from accounting.locale import gettext from accounting.models import Currency, BaseAccount, Account, Voucher, \ - VoucherLineItem + 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 @@ -256,15 +256,15 @@ class IncomeStatement(BaseReport): sub_conditions: list[sa.BinaryExpression] \ = [Account.base_code.startswith(str(x)) for x in range(4, 10)] conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code, + = [JournalEntryLineItem.currency_code == self.__currency.code, sa.or_(*sub_conditions)] if self.__period.start is not None: conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: conditions.append(Voucher.date <= self.__period.end) balance_func: sa.Function = sa.func.sum(sa.case( - (VoucherLineItem.is_debit, -VoucherLineItem.amount), - else_=VoucherLineItem.amount)).label("balance") + (JournalEntryLineItem.is_debit, -JournalEntryLineItem.amount), + else_=JournalEntryLineItem.amount)).label("balance") select_balances: sa.Select = sa.select(Account.id, balance_func)\ .join(Voucher).join(Account)\ .filter(*conditions)\ diff --git a/src/accounting/report/reports/journal.py b/src/accounting/report/reports/journal.py index 4ae6dd0..fb6b874 100644 --- a/src/accounting/report/reports/journal.py +++ b/src/accounting/report/reports/journal.py @@ -25,7 +25,7 @@ from flask import render_template, Response from sqlalchemy.orm import selectinload from accounting.locale import gettext -from accounting.models import Currency, Account, Voucher, VoucherLineItem +from accounting.models import Currency, Account, Voucher, 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 @@ -40,13 +40,13 @@ from accounting.utils.pagination import Pagination class ReportLineItem: """A line item in the report.""" - def __init__(self, line_item: VoucherLineItem): + def __init__(self, line_item: JournalEntryLineItem): """Constructs the line item in the report. - :param line_item: The voucher line item. + :param line_item: The journal entry line item. """ - self.line_item: VoucherLineItem = line_item - """The voucher line item.""" + self.line_item: JournalEntryLineItem = line_item + """The journal entry line item.""" self.voucher: Voucher = line_item.voucher """The voucher.""" self.currency: Currency = line_item.currency @@ -110,8 +110,8 @@ class PageParams(BasePageParams): """The HTML page parameters.""" def __init__(self, period: Period, - pagination: Pagination[VoucherLineItem], - line_items: list[VoucherLineItem]): + pagination: Pagination[JournalEntryLineItem], + line_items: list[JournalEntryLineItem]): """Constructs the HTML page parameters. :param period: The period. @@ -119,9 +119,9 @@ class PageParams(BasePageParams): """ self.period: Period = period """The period.""" - self.pagination: Pagination[VoucherLineItem] = pagination + self.pagination: Pagination[JournalEntryLineItem] = pagination """The pagination.""" - self.line_items: list[VoucherLineItem] = line_items + self.line_items: list[JournalEntryLineItem] = line_items """The line items.""" self.period_chooser: PeriodChooser = PeriodChooser( lambda x: journal_url(x)) @@ -145,7 +145,7 @@ class PageParams(BasePageParams): period=self.period) -def get_csv_rows(line_items: list[VoucherLineItem]) -> list[CSVRow]: +def get_csv_rows(line_items: list[JournalEntryLineItem]) -> list[CSVRow]: """Composes and returns the CSV rows from the line items. :param line_items: The line items. @@ -172,10 +172,11 @@ class Journal(BaseReport): """ self.__period: Period = period """The period.""" - self.__line_items: list[VoucherLineItem] = self.__query_line_items() + self.__line_items: list[JournalEntryLineItem] \ + = self.__query_line_items() """The line items.""" - def __query_line_items(self) -> list[VoucherLineItem]: + def __query_line_items(self) -> list[JournalEntryLineItem]: """Queries and returns the line items. :return: The line items. @@ -185,15 +186,15 @@ class Journal(BaseReport): conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: conditions.append(Voucher.date <= self.__period.end) - return VoucherLineItem.query.join(Voucher)\ + return JournalEntryLineItem.query.join(Voucher)\ .filter(*conditions)\ .order_by(Voucher.date, Voucher.no, - VoucherLineItem.is_debit.desc(), - VoucherLineItem.no)\ - .options(selectinload(VoucherLineItem.account), - selectinload(VoucherLineItem.currency), - selectinload(VoucherLineItem.voucher)).all() + JournalEntryLineItem.is_debit.desc(), + JournalEntryLineItem.no)\ + .options(selectinload(JournalEntryLineItem.account), + selectinload(JournalEntryLineItem.currency), + selectinload(JournalEntryLineItem.voucher)).all() def csv(self) -> Response: """Returns the report as CSV for download. @@ -208,8 +209,9 @@ class Journal(BaseReport): :return: The report as HTML. """ - pagination: Pagination[VoucherLineItem] \ - = Pagination[VoucherLineItem](self.__line_items, is_reversed=True) + pagination: Pagination[JournalEntryLineItem] \ + = Pagination[JournalEntryLineItem](self.__line_items, + is_reversed=True) params: PageParams = PageParams(period=self.__period, pagination=pagination, line_items=pagination.list) diff --git a/src/accounting/report/reports/ledger.py b/src/accounting/report/reports/ledger.py index fe1a41b..cb3629a 100644 --- a/src/accounting/report/reports/ledger.py +++ b/src/accounting/report/reports/ledger.py @@ -26,7 +26,7 @@ from sqlalchemy.orm import selectinload from accounting import db from accounting.locale import gettext -from accounting.models import Currency, Account, Voucher, VoucherLineItem +from accounting.models import Currency, Account, Voucher, 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 @@ -43,10 +43,10 @@ from accounting.utils.pagination import Pagination class ReportLineItem: """A line item in the report.""" - def __init__(self, line_item: VoucherLineItem | None = None): + def __init__(self, line_item: JournalEntryLineItem | None = None): """Constructs the line item in the report. - :param line_item: The voucher line item. + :param line_item: The journal entry line item. """ self.is_brought_forward: bool = False """Whether this is the brought-forward line item.""" @@ -65,7 +65,7 @@ class ReportLineItem: self.note: str | None = None """The note.""" self.url: str | None = None - """The URL to the voucher line item.""" + """The URL to the journal entry line item.""" if line_item is not None: self.date = line_item.voucher.date self.description = line_item.description @@ -114,11 +114,13 @@ class LineItemCollector: if self.__account.is_nominal: return None balance_func: sa.Function = sa.func.sum(sa.case( - (VoucherLineItem.is_debit, VoucherLineItem.amount), - else_=-VoucherLineItem.amount)) + (JournalEntryLineItem.is_debit, JournalEntryLineItem.amount), + else_=-JournalEntryLineItem.amount)) select: sa.Select = sa.Select(balance_func).join(Voucher)\ - .filter(be(VoucherLineItem.currency_code == self.__currency.code), - be(VoucherLineItem.account_id == self.__account.id), + .filter(be(JournalEntryLineItem.currency_code + == self.__currency.code), + be(JournalEntryLineItem.account_id + == self.__account.id), Voucher.date < self.__period.start) balance: int | None = db.session.scalar(select) if balance is None: @@ -140,19 +142,20 @@ class LineItemCollector: :return: The line items. """ conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code, - VoucherLineItem.account_id == self.__account.id] + = [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) if self.__period.end is not None: conditions.append(Voucher.date <= self.__period.end) - return [ReportLineItem(x) for x in VoucherLineItem.query.join(Voucher) + return [ReportLineItem(x) for x in JournalEntryLineItem.query + .join(Voucher) .filter(*conditions) .order_by(Voucher.date, Voucher.no, - VoucherLineItem.is_debit.desc(), - VoucherLineItem.no) - .options(selectinload(VoucherLineItem.voucher)).all()] + JournalEntryLineItem.is_debit.desc(), + JournalEntryLineItem.no) + .options(selectinload(JournalEntryLineItem.voucher)).all()] def __get_total(self) -> ReportLineItem | None: """Composes the total line item. @@ -307,9 +310,10 @@ class PageParams(BasePageParams): :return: The account options. """ - in_use: sa.Select = sa.Select(VoucherLineItem.account_id)\ - .filter(be(VoucherLineItem.currency_code == self.currency.code))\ - .group_by(VoucherLineItem.account_id) + in_use: sa.Select = sa.Select(JournalEntryLineItem.account_id)\ + .filter(be(JournalEntryLineItem.currency_code + == self.currency.code))\ + .group_by(JournalEntryLineItem.account_id) return [OptionLink(str(x), ledger_url(self.currency, x, self.period), x.id == self.account.id) for x in Account.query.filter(Account.id.in_(in_use)) diff --git a/src/accounting/report/reports/search.py b/src/accounting/report/reports/search.py index 45e7ae0..c0cf38f 100644 --- a/src/accounting/report/reports/search.py +++ b/src/accounting/report/reports/search.py @@ -26,7 +26,7 @@ from sqlalchemy.orm import selectinload from accounting.locale import gettext from accounting.models import Currency, CurrencyL10n, Account, AccountL10n, \ - Voucher, VoucherLineItem + Voucher, 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 @@ -43,10 +43,10 @@ class LineItemCollector: def __init__(self): """Constructs the line item collector.""" - self.line_items: list[VoucherLineItem] = self.__query_line_items() + self.line_items: list[JournalEntryLineItem] = self.__query_line_items() """The line items.""" - def __query_line_items(self) -> list[VoucherLineItem]: + def __query_line_items(self) -> list[JournalEntryLineItem]: """Queries and returns the line items. :return: The line items. @@ -57,26 +57,27 @@ class LineItemCollector: conditions: list[sa.BinaryExpression] = [] for k in keywords: sub_conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.description.contains(k), - VoucherLineItem.account_id.in_( + = [JournalEntryLineItem.description.contains(k), + JournalEntryLineItem.account_id.in_( self.__get_account_condition(k)), - VoucherLineItem.currency_code.in_( + JournalEntryLineItem.currency_code.in_( self.__get_currency_condition(k)), - VoucherLineItem.voucher_id.in_( + JournalEntryLineItem.voucher_id.in_( self.__get_voucher_condition(k))] try: - sub_conditions.append(VoucherLineItem.amount == Decimal(k)) + sub_conditions.append( + JournalEntryLineItem.amount == Decimal(k)) except ArithmeticError: pass conditions.append(sa.or_(*sub_conditions)) - return VoucherLineItem.query.join(Voucher).filter(*conditions)\ + return JournalEntryLineItem.query.join(Voucher).filter(*conditions)\ .order_by(Voucher.date, Voucher.no, - VoucherLineItem.is_debit, - VoucherLineItem.no)\ - .options(selectinload(VoucherLineItem.account), - selectinload(VoucherLineItem.currency), - selectinload(VoucherLineItem.voucher)).all() + JournalEntryLineItem.is_debit, + JournalEntryLineItem.no)\ + .options(selectinload(JournalEntryLineItem.account), + selectinload(JournalEntryLineItem.currency), + selectinload(JournalEntryLineItem.voucher)).all() @staticmethod def __get_account_condition(k: str) -> sa.Select: @@ -149,15 +150,15 @@ class LineItemCollector: class PageParams(BasePageParams): """The HTML page parameters.""" - def __init__(self, pagination: Pagination[VoucherLineItem], - line_items: list[VoucherLineItem]): + def __init__(self, pagination: Pagination[JournalEntryLineItem], + line_items: list[JournalEntryLineItem]): """Constructs the HTML page parameters. :param line_items: The search result line items. """ - self.pagination: Pagination[VoucherLineItem] = pagination + self.pagination: Pagination[JournalEntryLineItem] = pagination """The pagination.""" - self.line_items: list[VoucherLineItem] = line_items + self.line_items: list[JournalEntryLineItem] = line_items """The line items.""" @property @@ -182,7 +183,7 @@ class Search(BaseReport): def __init__(self): """Constructs a search.""" - self.__line_items: list[VoucherLineItem] \ + self.__line_items: list[JournalEntryLineItem] \ = LineItemCollector().line_items """The line items.""" @@ -199,8 +200,9 @@ class Search(BaseReport): :return: The report as HTML. """ - pagination: Pagination[VoucherLineItem] \ - = Pagination[VoucherLineItem](self.__line_items, is_reversed=True) + pagination: Pagination[JournalEntryLineItem] \ + = Pagination[JournalEntryLineItem](self.__line_items, + is_reversed=True) params: PageParams = PageParams(pagination=pagination, line_items=pagination.list) return render_template("accounting/report/search.html", diff --git a/src/accounting/report/reports/trial_balance.py b/src/accounting/report/reports/trial_balance.py index 2e6a9ae..f9c32b8 100644 --- a/src/accounting/report/reports/trial_balance.py +++ b/src/accounting/report/reports/trial_balance.py @@ -24,7 +24,7 @@ from flask import Response, render_template from accounting import db from accounting.locale import gettext -from accounting.models import Currency, Account, Voucher, VoucherLineItem +from accounting.models import Currency, Account, Voucher, 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 @@ -178,14 +178,14 @@ class TrialBalance(BaseReport): :return: None. """ conditions: list[sa.BinaryExpression] \ - = [VoucherLineItem.currency_code == self.__currency.code] + = [JournalEntryLineItem.currency_code == self.__currency.code] if self.__period.start is not None: conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: conditions.append(Voucher.date <= self.__period.end) balance_func: sa.Function = sa.func.sum(sa.case( - (VoucherLineItem.is_debit, VoucherLineItem.amount), - else_=-VoucherLineItem.amount)).label("balance") + (JournalEntryLineItem.is_debit, JournalEntryLineItem.amount), + else_=-JournalEntryLineItem.amount)).label("balance") select_balances: sa.Select = sa.select(Account.id, balance_func)\ .join(Voucher).join(Account)\ .filter(*conditions)\ diff --git a/src/accounting/report/utils/base_page_params.py b/src/accounting/report/utils/base_page_params.py index 3edb7db..bbb7968 100644 --- a/src/accounting/report/utils/base_page_params.py +++ b/src/accounting/report/utils/base_page_params.py @@ -26,7 +26,7 @@ import sqlalchemy as sa from flask import request from accounting import db -from accounting.models import Currency, VoucherLineItem +from accounting.models import Currency, JournalEntryLineItem from accounting.utils.voucher_types import VoucherType from .option_link import OptionLink from .report_chooser import ReportChooser @@ -81,8 +81,8 @@ class BasePageParams(ABC): :return: The currency options. """ in_use: set[str] = set(db.session.scalars( - sa.select(VoucherLineItem.currency_code) - .group_by(VoucherLineItem.currency_code)).all()) + sa.select(JournalEntryLineItem.currency_code) + .group_by(JournalEntryLineItem.currency_code)).all()) return [OptionLink(str(x), get_url(x), x.code == active_currency.code) for x in Currency.query.filter(Currency.code.in_(in_use)) .order_by(Currency.code).all()] diff --git a/src/accounting/static/css/style.css b/src/accounting/static/css/style.css index 36f8a92..78629ee 100644 --- a/src/accounting/static/css/style.css +++ b/src/accounting/static/css/style.css @@ -166,14 +166,14 @@ .accounting-list-group-hover .list-group-item:hover { background-color: #ececec; } -.accounting-voucher-line-item { +.accounting-journal-entry-line-item { border: none; } -.accounting-voucher-line-item-header { +.accounting-journal-entry-line-item-header { font-weight: bolder; border-bottom: thick double slategray; } -.list-group-item.accounting-voucher-line-item-total { +.list-group-item.accounting-journal-entry-line-item-total { font-weight: bolder; border-top: thick double slategray; } diff --git a/src/accounting/static/js/account-selector.js b/src/accounting/static/js/account-selector.js index c81458f..2716277 100644 --- a/src/accounting/static/js/account-selector.js +++ b/src/accounting/static/js/account-selector.js @@ -30,7 +30,7 @@ class AccountSelector { /** * The line item editor - * @type {VoucherLineItemEditor} + * @type {JournalEntryLineItemEditor} */ #lineItemEditor; @@ -85,7 +85,7 @@ class AccountSelector { /** * Constructs an account selector. * - * @param lineItemEditor {VoucherLineItemEditor} the line item editor + * @param lineItemEditor {JournalEntryLineItemEditor} the line item editor * @param debitCredit {string} either "debit" or "credit" */ constructor(lineItemEditor, debitCredit) { @@ -210,7 +210,7 @@ class AccountSelector { /** * Returns the account selector instances. * - * @param lineItemEditor {VoucherLineItemEditor} the line item editor + * @param lineItemEditor {JournalEntryLineItemEditor} the line item editor * @return {{debit: AccountSelector, credit: AccountSelector}} */ static getInstances(lineItemEditor) { diff --git a/src/accounting/static/js/description-editor.js b/src/accounting/static/js/description-editor.js index 26c2c89..fe815b2 100644 --- a/src/accounting/static/js/description-editor.js +++ b/src/accounting/static/js/description-editor.js @@ -30,7 +30,7 @@ class DescriptionEditor { /** * The line item editor - * @type {VoucherLineItemEditor} + * @type {JournalEntryLineItemEditor} */ #lineItemEditor; @@ -109,7 +109,7 @@ class DescriptionEditor { /** * Constructs a description editor. * - * @param lineItemEditor {VoucherLineItemEditor} the line item editor + * @param lineItemEditor {JournalEntryLineItemEditor} the line item editor * @param debitCredit {string} either "debit" or "credit" */ constructor(lineItemEditor, debitCredit) { @@ -246,7 +246,7 @@ class DescriptionEditor { /** * Returns the description editor instances. * - * @param lineItemEditor {VoucherLineItemEditor} the line item editor + * @param lineItemEditor {JournalEntryLineItemEditor} the line item editor * @return {{debit: DescriptionEditor, credit: DescriptionEditor}} */ static getInstances(lineItemEditor) { diff --git a/src/accounting/static/js/voucher-line-item-editor.js b/src/accounting/static/js/journal-entry-line-item-editor.js similarity index 97% rename from src/accounting/static/js/voucher-line-item-editor.js rename to src/accounting/static/js/journal-entry-line-item-editor.js index 408004d..3e13aae 100644 --- a/src/accounting/static/js/voucher-line-item-editor.js +++ b/src/accounting/static/js/journal-entry-line-item-editor.js @@ -1,5 +1,5 @@ /* The Mia! Accounting Flask Project - * voucher-line-item-editor.js: The JavaScript for the voucher line item editor + * journal-entry-line-item-editor.js: The JavaScript for the journal entry line item editor */ /* Copyright (c) 2023 imacat. @@ -23,10 +23,10 @@ "use strict"; /** - * The voucher line item editor. + * The journal entry line item editor. * */ -class VoucherLineItemEditor { +class JournalEntryLineItemEditor { /** * The voucher form @@ -35,7 +35,7 @@ class VoucherLineItemEditor { form; /** - * The voucher line item editor + * The journal entry line item editor * @type {HTMLFormElement} */ #element; @@ -137,7 +137,7 @@ class VoucherLineItemEditor { #amountError; /** - * The voucher line item to edit + * The journal entry line item to edit * @type {LineItemSubForm|null} */ lineItem; @@ -149,7 +149,7 @@ class VoucherLineItemEditor { #debitCreditSubForm; /** - * Whether the voucher line item needs offset + * Whether the journal entry line item needs offset * @type {boolean} */ isNeedOffset = false; @@ -215,7 +215,7 @@ class VoucherLineItemEditor { originalLineItemSelector; /** - * Constructs a new voucher line item editor. + * Constructs a new journal entry line item editor. * * @param form {VoucherForm} the voucher form */ @@ -476,7 +476,7 @@ class VoucherLineItemEditor { } /** - * The callback when adding a new voucher line item. + * The callback when adding a new journal entry line item. * * @param debitCredit {DebitCreditSubForm} the debit or credit sub-form */ @@ -512,9 +512,9 @@ class VoucherLineItemEditor { } /** - * The callback when editing a voucher line item. + * The callback when editing a journal entry line item. * - * @param lineItem {LineItemSubForm} the voucher line item sub-form + * @param lineItem {LineItemSubForm} the journal entry line item sub-form */ onEdit(lineItem) { this.lineItem = lineItem; diff --git a/src/accounting/static/js/original-line-item-selector.js b/src/accounting/static/js/original-line-item-selector.js index 46cbfc4..895dcc8 100644 --- a/src/accounting/static/js/original-line-item-selector.js +++ b/src/accounting/static/js/original-line-item-selector.js @@ -30,7 +30,7 @@ class OriginalLineItemSelector { /** * The line item editor - * @type {VoucherLineItemEditor} + * @type {JournalEntryLineItemEditor} */ lineItemEditor; @@ -84,7 +84,7 @@ class OriginalLineItemSelector { /** * Constructs an original line item selector. * - * @param lineItemEditor {VoucherLineItemEditor} the line item editor + * @param lineItemEditor {JournalEntryLineItemEditor} the line item editor */ constructor(lineItemEditor) { this.lineItemEditor = lineItemEditor; diff --git a/src/accounting/static/js/voucher-form.js b/src/accounting/static/js/voucher-form.js index 5f7cc93..53cfaa8 100644 --- a/src/accounting/static/js/voucher-form.js +++ b/src/accounting/static/js/voucher-form.js @@ -100,7 +100,7 @@ class VoucherForm { /** * The line item editor - * @type {VoucherLineItemEditor} + * @type {JournalEntryLineItemEditor} */ lineItemEditor; @@ -121,7 +121,7 @@ class VoucherForm { this.#addCurrencyButton = document.getElementById("accounting-add-currency"); this.#note = document.getElementById("accounting-note"); this.#noteError = document.getElementById("accounting-note-error"); - this.lineItemEditor = new VoucherLineItemEditor(this); + this.lineItemEditor = new JournalEntryLineItemEditor(this); this.#addCurrencyButton.onclick = () => { const newIndex = 1 + (this.#currencies.length === 0? 0: Math.max(...this.#currencies.map((currency) => currency.index))); @@ -993,7 +993,7 @@ class LineItemSubForm { /** * Stores the data into the line item sub-form. * - * @param editor {VoucherLineItemEditor} the line item editor + * @param editor {JournalEntryLineItemEditor} the line item editor */ save(editor) { if (editor.isNeedOffset) { diff --git a/src/accounting/templates/accounting/voucher/disbursement/detail.html b/src/accounting/templates/accounting/voucher/disbursement/detail.html index be97d8f..d6a3215 100644 --- a/src/accounting/templates/accounting/voucher/disbursement/detail.html +++ b/src/accounting/templates/accounting/voucher/disbursement/detail.html @@ -34,11 +34,11 @@ First written: 2023/2/26