diff --git a/src/accounting/__init__.py b/src/accounting/__init__.py index e195c96..32b7693 100644 --- a/src/accounting/__init__.py +++ b/src/accounting/__init__.py @@ -80,8 +80,8 @@ def init_app(app: Flask, user_utils: UserUtilityInterface, from . import currency currency.init_app(app, bp) - from . import transaction - transaction.init_app(app, bp) + from . import voucher + voucher.init_app(app, bp) from . import report report.init_app(app, bp) diff --git a/src/accounting/models.py b/src/accounting/models.py index e37604b..c20096c 100644 --- a/src/accounting/models.py +++ b/src/accounting/models.py @@ -447,12 +447,12 @@ class CurrencyL10n(db.Model): """The localized name.""" -class TransactionCurrency: - """A currency in a transaction.""" +class VoucherCurrency: + """A currency in a voucher.""" def __init__(self, code: str, debit: list[JournalEntry], credit: list[JournalEntry]): - """Constructs the currency in the transaction. + """Constructs the currency in the voucher. :param code: The currency code. :param debit: The debit entries. @@ -490,13 +490,13 @@ class TransactionCurrency: return sum([x.amount for x in self.credit]) -class Transaction(db.Model): - """A transaction.""" - __tablename__ = "accounting_transactions" +class Voucher(db.Model): + """A voucher.""" + __tablename__ = "accounting_vouchers" """The table name.""" id = db.Column(db.Integer, nullable=False, primary_key=True, autoincrement=False) - """The transaction ID.""" + """The voucher ID.""" date = db.Column(db.Date, nullable=False) """The date.""" no = db.Column(db.Integer, nullable=False, default=text("1")) @@ -523,22 +523,22 @@ class Transaction(db.Model): """The ID of the updator.""" updated_by = db.relationship(user_cls, foreign_keys=updated_by_id) """The updator.""" - entries = db.relationship("JournalEntry", back_populates="transaction") + entries = db.relationship("JournalEntry", back_populates="voucher") """The journal entries.""" def __str__(self) -> str: - """Returns the string representation of this transaction. + """Returns the string representation of this voucher. - :return: The string representation of this transaction. + :return: The string representation of this voucher. """ - if self.is_cash_expense: - return gettext("Cash Expense Transaction#%(id)s", id=self.id) - if self.is_cash_income: - return gettext("Cash Income Transaction#%(id)s", id=self.id) - return gettext("Transfer Transaction#%(id)s", id=self.id) + if self.is_cash_disbursement: + return gettext("Cash Disbursement Voucher#%(id)s", id=self.id) + if self.is_cash_receipt: + return gettext("Cash Receipt Voucher#%(id)s", id=self.id) + return gettext("Transfer Voucher#%(id)s", id=self.id) @property - def currencies(self) -> list[TransactionCurrency]: + def currencies(self) -> list[VoucherCurrency]: """Returns the journal entries categorized by their currencies. :return: The currency categories. @@ -551,18 +551,18 @@ class Transaction(db.Model): codes.append(entry.currency_code) by_currency[entry.currency_code] = [] by_currency[entry.currency_code].append(entry) - return [TransactionCurrency(code=x, - debit=[y for y in by_currency[x] - if y.is_debit], - credit=[y for y in by_currency[x] - if not y.is_debit]) + return [VoucherCurrency(code=x, + debit=[y for y in by_currency[x] + if y.is_debit], + credit=[y for y in by_currency[x] + if not y.is_debit]) for x in codes] @property - def is_cash_income(self) -> bool: - """Returns whether this is a cash income transaction. + def is_cash_receipt(self) -> bool: + """Returns whether this is a cash receipt voucher. - :return: True if this is a cash income transaction, or False otherwise. + :return: True if this is a cash receipt voucher, or False otherwise. """ for currency in self.currencies: if len(currency.debit) > 1: @@ -572,10 +572,10 @@ class Transaction(db.Model): return True @property - def is_cash_expense(self) -> bool: - """Returns whether this is a cash expense transaction. + def is_cash_disbursement(self) -> bool: + """Returns whether this is a cash disbursement voucher. - :return: True if this is a cash expense transaction, or False + :return: True if this is a cash disbursement voucher, or False otherwise. """ for currency in self.currencies: @@ -587,9 +587,9 @@ class Transaction(db.Model): @property def can_delete(self) -> bool: - """Returns whether the transaction can be deleted. + """Returns whether the voucher can be deleted. - :return: True if the transaction can be deleted, or False otherwise. + :return: True if the voucher can be deleted, or False otherwise. """ if not hasattr(self, "__can_delete"): def has_offset() -> bool: @@ -601,12 +601,12 @@ class Transaction(db.Model): return getattr(self, "__can_delete") def delete(self) -> None: - """Deletes the transaction. + """Deletes the voucher. :return: None. """ JournalEntry.query\ - .filter(JournalEntry.transaction_id == self.id).delete() + .filter(JournalEntry.voucher_id == self.id).delete() db.session.delete(self) @@ -617,18 +617,17 @@ class JournalEntry(db.Model): id = db.Column(db.Integer, nullable=False, primary_key=True, autoincrement=False) """The entry ID.""" - transaction_id = db.Column(db.Integer, - db.ForeignKey(Transaction.id, - onupdate="CASCADE", - ondelete="CASCADE"), - nullable=False) - """The transaction ID.""" - transaction = db.relationship(Transaction, back_populates="entries") - """The transaction.""" + voucher_id = db.Column(db.Integer, + db.ForeignKey(Voucher.id, onupdate="CASCADE", + ondelete="CASCADE"), + nullable=False) + """The voucher ID.""" + voucher = db.relationship(Voucher, back_populates="entries") + """The voucher.""" is_debit = db.Column(db.Boolean, nullable=False) """True for a debit entry, or False for a credit entry.""" no = db.Column(db.Integer, nullable=False) - """The entry number under the transaction and debit or credit.""" + """The entry number under the voucher and debit or credit.""" original_entry_id = db.Column(db.Integer, db.ForeignKey(id, onupdate="CASCADE"), nullable=True) @@ -665,7 +664,7 @@ class JournalEntry(db.Model): from accounting.template_filters import format_date, format_amount setattr(self, "__str", gettext("%(date)s %(summary)s %(amount)s", - date=format_date(self.transaction.date), + date=format_date(self.voucher.date), summary="" if self.summary is None else self.summary, amount=format_amount(self.amount))) @@ -750,12 +749,13 @@ class JournalEntry(db.Model): frac: Decimal = (value - whole).normalize() return str(whole) + str(abs(frac))[1:] - txn_day: date = self.transaction.date + voucher_day: date = self.voucher.date summary: str = "" if self.summary is None else self.summary return ([summary], - [str(txn_day.year), - "{}/{}".format(txn_day.year, txn_day.month), - "{}/{}".format(txn_day.month, txn_day.day), - "{}/{}/{}".format(txn_day.year, txn_day.month, txn_day.day), + [str(voucher_day.year), + "{}/{}".format(voucher_day.year, voucher_day.month), + "{}/{}".format(voucher_day.month, voucher_day.day), + "{}/{}/{}".format(voucher_day.year, voucher_day.month, + voucher_day.day), format_amount(self.amount), format_amount(self.net_balance)]) diff --git a/src/accounting/report/period/chooser.py b/src/accounting/report/period/chooser.py index 223c112..0dd684a 100644 --- a/src/accounting/report/period/chooser.py +++ b/src/accounting/report/period/chooser.py @@ -23,7 +23,7 @@ This file is largely taken from the NanoParma ERP project, first written in import typing as t from datetime import date -from accounting.models import Transaction +from accounting.models import Voucher from .period import Period from .shortcuts import ThisMonth, LastMonth, SinceLastMonth, ThisYear, \ LastYear, Today, Yesterday, AllTime, TemplatePeriod, YearPeriod @@ -61,8 +61,8 @@ class PeriodChooser: self.url_template: str = get_url(TemplatePeriod()) """The URL template.""" - first: Transaction | None \ - = Transaction.query.order_by(Transaction.date).first() + first: Voucher | None \ + = Voucher.query.order_by(Voucher.date).first() start: date | None = None if first is None else first.date # Attributes diff --git a/src/accounting/report/reports/balance_sheet.py b/src/accounting/report/reports/balance_sheet.py index ced86ce..04d228d 100644 --- a/src/accounting/report/reports/balance_sheet.py +++ b/src/accounting/report/reports/balance_sheet.py @@ -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, Transaction, \ +from accounting.models import Currency, BaseAccount, Account, Voucher, \ JournalEntry from accounting.report.period import Period, PeriodChooser from accounting.report.utils.base_page_params import BasePageParams @@ -127,14 +127,14 @@ class AccountCollector: = [JournalEntry.currency_code == self.__currency.code, sa.or_(*sub_conditions)] if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) + conditions.append(Voucher.date <= self.__period.end) balance_func: sa.Function = sa.func.sum(sa.case( (JournalEntry.is_debit, JournalEntry.amount), else_=-JournalEntry.amount)).label("balance") select_balance: sa.Select \ = sa.select(Account.id, Account.base_code, Account.no, balance_func)\ - .join(Transaction).join(Account)\ + .join(Voucher).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] \ = [JournalEntry.currency_code == self.__currency.code, - Transaction.date < self.__period.start] + Voucher.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] \ = [JournalEntry.currency_code == self.__currency.code] if self.__period.start is not None: - conditions.append(Transaction.date >= self.__period.start) + conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) + conditions.append(Voucher.date <= self.__period.end) return self.__query_balance(conditions) @staticmethod @@ -218,7 +218,7 @@ class AccountCollector: (JournalEntry.is_debit, JournalEntry.amount), else_=-JournalEntry.amount)) select_balance: sa.Select = sa.select(balance_func)\ - .join(Transaction).join(Account).filter(*conditions) + .join(Voucher).join(Account).filter(*conditions) return db.session.scalar(select_balance) def __add_owner_s_equity(self, code: str, amount: Decimal | None, diff --git a/src/accounting/report/reports/income_expenses.py b/src/accounting/report/reports/income_expenses.py index 23655fa..c9131f5 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, Transaction, JournalEntry +from accounting.models import Currency, Account, Voucher, JournalEntry 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 +70,14 @@ class ReportEntry: self.url: str | None = None """The URL to the journal entry.""" if entry is not None: - self.date = entry.transaction.date + self.date = entry.voucher.date self.account = entry.account self.summary = entry.summary self.income = None if entry.is_debit else entry.amount self.expense = entry.amount if entry.is_debit else None - self.note = entry.transaction.note - self.url = url_for("accounting.transaction.detail", - txn=entry.transaction) + self.note = entry.voucher.note + self.url = url_for("accounting.voucher.detail", + voucher=entry.voucher) class EntryCollector: @@ -120,10 +120,10 @@ class EntryCollector: (JournalEntry.is_debit, JournalEntry.amount), else_=-JournalEntry.amount)) select: sa.Select = sa.Select(balance_func)\ - .join(Transaction).join(Account)\ + .join(Voucher).join(Account)\ .filter(be(JournalEntry.currency_code == self.__currency.code), self.__account_condition, - Transaction.date < self.__period.start) + Voucher.date < self.__period.start) balance: int | None = db.session.scalar(select) if balance is None: return None @@ -148,23 +148,23 @@ class EntryCollector: = [JournalEntry.currency_code == self.__currency.code, self.__account_condition] if self.__period.start is not None: - conditions.append(Transaction.date >= self.__period.start) + conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) - txn_with_account: sa.Select = sa.Select(Transaction.id).\ + conditions.append(Voucher.date <= self.__period.end) + voucher_with_account: sa.Select = sa.Select(Voucher.id).\ join(JournalEntry).join(Account).filter(*conditions) return [ReportEntry(x) - for x in JournalEntry.query.join(Transaction).join(Account) - .filter(JournalEntry.transaction_id.in_(txn_with_account), + for x in JournalEntry.query.join(Voucher).join(Account) + .filter(JournalEntry.voucher_id.in_(voucher_with_account), JournalEntry.currency_code == self.__currency.code, sa.not_(self.__account_condition)) - .order_by(Transaction.date, - Transaction.no, + .order_by(Voucher.date, + Voucher.no, JournalEntry.is_debit, JournalEntry.no) .options(selectinload(JournalEntry.account), - selectinload(JournalEntry.transaction))] + selectinload(JournalEntry.voucher))] @property def __account_condition(self) -> sa.BinaryExpression: @@ -212,7 +212,7 @@ class EntryCollector: class CSVRow(BaseCSVRow): """A row in the CSV.""" - def __init__(self, txn_date: date | str | None, + def __init__(self, voucher_date: date | str | None, account: str | None, summary: str | None, income: str | Decimal | None, @@ -221,7 +221,7 @@ class CSVRow(BaseCSVRow): note: str | None): """Constructs a row in the CSV. - :param txn_date: The transaction date. + :param voucher_date: The voucher date. :param account: The account. :param summary: The summary. :param income: The income. @@ -229,7 +229,7 @@ class CSVRow(BaseCSVRow): :param balance: The balance. :param note: The note. """ - self.date: date | str | None = txn_date + self.date: date | str | None = voucher_date """The date.""" self.account: str | None = account """The account.""" diff --git a/src/accounting/report/reports/income_statement.py b/src/accounting/report/reports/income_statement.py index 655ae6e..f36e226 100644 --- a/src/accounting/report/reports/income_statement.py +++ b/src/accounting/report/reports/income_statement.py @@ -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, Transaction, \ +from accounting.models import Currency, BaseAccount, Account, Voucher, \ JournalEntry from accounting.report.period import Period, PeriodChooser from accounting.report.utils.base_page_params import BasePageParams @@ -259,14 +259,14 @@ class IncomeStatement(BaseReport): = [JournalEntry.currency_code == self.__currency.code, sa.or_(*sub_conditions)] if self.__period.start is not None: - conditions.append(Transaction.date >= self.__period.start) + conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) + conditions.append(Voucher.date <= self.__period.end) balance_func: sa.Function = sa.func.sum(sa.case( (JournalEntry.is_debit, -JournalEntry.amount), else_=JournalEntry.amount)).label("balance") select_balances: sa.Select = sa.select(Account.id, balance_func)\ - .join(Transaction).join(Account)\ + .join(Voucher).join(Account)\ .filter(*conditions)\ .group_by(Account.id)\ .order_by(Account.base_code, Account.no) diff --git a/src/accounting/report/reports/journal.py b/src/accounting/report/reports/journal.py index 2cb82dd..ec7e65d 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, Transaction, JournalEntry +from accounting.models import Currency, Account, Voucher, JournalEntry 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 +47,8 @@ class ReportEntry: """ self.entry: JournalEntry = entry """The journal entry.""" - self.transaction: Transaction = entry.transaction - """The transaction.""" + self.voucher: Voucher = entry.voucher + """The voucher.""" self.currency: Currency = entry.currency """The account.""" self.account: Account = entry.account @@ -66,7 +66,7 @@ class ReportEntry: class CSVRow(BaseCSVRow): """A row in the CSV.""" - def __init__(self, txn_date: str | date, + def __init__(self, voucher_date: str | date, currency: str, account: str, summary: str | None, @@ -75,13 +75,13 @@ class CSVRow(BaseCSVRow): note: str | None): """Constructs a row in the CSV. - :param txn_date: The transaction date. + :param voucher_date: The voucher date. :param summary: The summary. :param debit: The debit amount. :param credit: The credit amount. :param note: The note. """ - self.date: str | date = txn_date + self.date: str | date = voucher_date """The date.""" self.currency: str = currency """The currency.""" @@ -155,9 +155,9 @@ def get_csv_rows(entries: list[JournalEntry]) -> list[CSVRow]: gettext("Account"), gettext("Summary"), gettext("Debit"), gettext("Credit"), gettext("Note"))] - rows.extend([CSVRow(x.transaction.date, x.currency.code, + rows.extend([CSVRow(x.voucher.date, x.currency.code, str(x.account).title(), x.summary, - x.debit, x.credit, x.transaction.note) + x.debit, x.credit, x.voucher.note) for x in entries]) return rows @@ -182,18 +182,18 @@ class Journal(BaseReport): """ conditions: list[sa.BinaryExpression] = [] if self.__period.start is not None: - conditions.append(Transaction.date >= self.__period.start) + conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) - return JournalEntry.query.join(Transaction)\ + conditions.append(Voucher.date <= self.__period.end) + return JournalEntry.query.join(Voucher)\ .filter(*conditions)\ - .order_by(Transaction.date, - Transaction.no, + .order_by(Voucher.date, + Voucher.no, JournalEntry.is_debit.desc(), JournalEntry.no)\ .options(selectinload(JournalEntry.account), selectinload(JournalEntry.currency), - selectinload(JournalEntry.transaction)).all() + selectinload(JournalEntry.voucher)).all() def csv(self) -> Response: """Returns the report as CSV for download. diff --git a/src/accounting/report/reports/ledger.py b/src/accounting/report/reports/ledger.py index b452c67..de455d1 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, Transaction, JournalEntry +from accounting.models import Currency, Account, Voucher, JournalEntry 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 +67,13 @@ class ReportEntry: self.url: str | None = None """The URL to the journal entry.""" if entry is not None: - self.date = entry.transaction.date + self.date = entry.voucher.date self.summary = entry.summary self.debit = entry.amount if entry.is_debit else None self.credit = None if entry.is_debit else entry.amount - self.note = entry.transaction.note - self.url = url_for("accounting.transaction.detail", - txn=entry.transaction) + self.note = entry.voucher.note + self.url = url_for("accounting.voucher.detail", + voucher=entry.voucher) class EntryCollector: @@ -116,10 +116,10 @@ class EntryCollector: balance_func: sa.Function = sa.func.sum(sa.case( (JournalEntry.is_debit, JournalEntry.amount), else_=-JournalEntry.amount)) - select: sa.Select = sa.Select(balance_func).join(Transaction)\ + select: sa.Select = sa.Select(balance_func).join(Voucher)\ .filter(be(JournalEntry.currency_code == self.__currency.code), be(JournalEntry.account_id == self.__account.id), - Transaction.date < self.__period.start) + Voucher.date < self.__period.start) balance: int | None = db.session.scalar(select) if balance is None: return None @@ -143,16 +143,16 @@ class EntryCollector: = [JournalEntry.currency_code == self.__currency.code, JournalEntry.account_id == self.__account.id] if self.__period.start is not None: - conditions.append(Transaction.date >= self.__period.start) + conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) - return [ReportEntry(x) for x in JournalEntry.query.join(Transaction) + conditions.append(Voucher.date <= self.__period.end) + return [ReportEntry(x) for x in JournalEntry.query.join(Voucher) .filter(*conditions) - .order_by(Transaction.date, - Transaction.no, + .order_by(Voucher.date, + Voucher.no, JournalEntry.is_debit.desc(), JournalEntry.no) - .options(selectinload(JournalEntry.transaction)).all()] + .options(selectinload(JournalEntry.voucher)).all()] def __get_total_entry(self) -> ReportEntry | None: """Composes the total entry. @@ -193,7 +193,7 @@ class EntryCollector: class CSVRow(BaseCSVRow): """A row in the CSV.""" - def __init__(self, txn_date: date | str | None, + def __init__(self, voucher_date: date | str | None, summary: str | None, debit: str | Decimal | None, credit: str | Decimal | None, @@ -201,14 +201,14 @@ class CSVRow(BaseCSVRow): note: str | None): """Constructs a row in the CSV. - :param txn_date: The transaction date. + :param voucher_date: The voucher date. :param summary: The summary. :param debit: The debit amount. :param credit: The credit amount. :param balance: The balance. :param note: The note. """ - self.date: date | str | None = txn_date + self.date: date | str | None = voucher_date """The date.""" self.summary: str | None = summary """The summary.""" diff --git a/src/accounting/report/reports/search.py b/src/accounting/report/reports/search.py index b2d14e3..9bbf6cc 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, \ - Transaction, JournalEntry + Voucher, JournalEntry 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,21 +62,21 @@ class EntryCollector: self.__get_account_condition(k)), JournalEntry.currency_code.in_( self.__get_currency_condition(k)), - JournalEntry.transaction_id.in_( - self.__get_transaction_condition(k))] + JournalEntry.voucher_id.in_( + self.__get_voucher_condition(k))] try: sub_conditions.append(JournalEntry.amount == Decimal(k)) except ArithmeticError: pass conditions.append(sa.or_(*sub_conditions)) - return JournalEntry.query.join(Transaction).filter(*conditions)\ - .order_by(Transaction.date, - Transaction.no, + return JournalEntry.query.join(Voucher).filter(*conditions)\ + .order_by(Voucher.date, + Voucher.no, JournalEntry.is_debit, JournalEntry.no)\ .options(selectinload(JournalEntry.account), selectinload(JournalEntry.currency), - selectinload(JournalEntry.transaction)).all() + selectinload(JournalEntry.voucher)).all() @staticmethod def __get_account_condition(k: str) -> sa.Select: @@ -115,35 +115,35 @@ class EntryCollector: Currency.code.in_(select_l10n))) @staticmethod - def __get_transaction_condition(k: str) -> sa.Select: - """Composes and returns the condition to filter the transaction. + def __get_voucher_condition(k: str) -> sa.Select: + """Composes and returns the condition to filter the voucher. :param k: The keyword. - :return: The condition to filter the transaction. + :return: The condition to filter the voucher. """ - conditions: list[sa.BinaryExpression] = [Transaction.note.contains(k)] - txn_date: datetime + conditions: list[sa.BinaryExpression] = [Voucher.note.contains(k)] + voucher_date: datetime try: - txn_date = datetime.strptime(k, "%Y") + voucher_date = datetime.strptime(k, "%Y") conditions.append( - be(sa.extract("year", Transaction.date) == txn_date.year)) + be(sa.extract("year", Voucher.date) == voucher_date.year)) except ValueError: pass try: - txn_date = datetime.strptime(k, "%Y/%m") + voucher_date = datetime.strptime(k, "%Y/%m") conditions.append(sa.and_( - sa.extract("year", Transaction.date) == txn_date.year, - sa.extract("month", Transaction.date) == txn_date.month)) + sa.extract("year", Voucher.date) == voucher_date.year, + sa.extract("month", Voucher.date) == voucher_date.month)) except ValueError: pass try: - txn_date = datetime.strptime(f"2000/{k}", "%Y/%m/%d") + voucher_date = datetime.strptime(f"2000/{k}", "%Y/%m/%d") conditions.append(sa.and_( - sa.extract("month", Transaction.date) == txn_date.month, - sa.extract("day", Transaction.date) == txn_date.day)) + sa.extract("month", Voucher.date) == voucher_date.month, + sa.extract("day", Voucher.date) == voucher_date.day)) except ValueError: pass - return sa.select(Transaction.id).filter(sa.or_(*conditions)) + return sa.select(Voucher.id).filter(sa.or_(*conditions)) class PageParams(BasePageParams): diff --git a/src/accounting/report/reports/trial_balance.py b/src/accounting/report/reports/trial_balance.py index d6a84c2..e98f22d 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, Transaction, JournalEntry +from accounting.models import Currency, Account, Voucher, JournalEntry 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 +180,14 @@ class TrialBalance(BaseReport): conditions: list[sa.BinaryExpression] \ = [JournalEntry.currency_code == self.__currency.code] if self.__period.start is not None: - conditions.append(Transaction.date >= self.__period.start) + conditions.append(Voucher.date >= self.__period.start) if self.__period.end is not None: - conditions.append(Transaction.date <= self.__period.end) + conditions.append(Voucher.date <= self.__period.end) balance_func: sa.Function = sa.func.sum(sa.case( (JournalEntry.is_debit, JournalEntry.amount), else_=-JournalEntry.amount)).label("balance") select_balances: sa.Select = sa.select(Account.id, balance_func)\ - .join(Transaction).join(Account)\ + .join(Voucher).join(Account)\ .filter(*conditions)\ .group_by(Account.id)\ .order_by(Account.base_code, Account.no) diff --git a/src/accounting/report/utils/base_page_params.py b/src/accounting/report/utils/base_page_params.py index 436942c..a78def3 100644 --- a/src/accounting/report/utils/base_page_params.py +++ b/src/accounting/report/utils/base_page_params.py @@ -27,7 +27,7 @@ from flask import request from accounting import db from accounting.models import Currency, JournalEntry -from accounting.utils.txn_types import TransactionType +from accounting.utils.voucher_types import VoucherType from .option_link import OptionLink from .report_chooser import ReportChooser @@ -52,12 +52,12 @@ class BasePageParams(ABC): """ @property - def txn_types(self) -> t.Type[TransactionType]: - """Returns the transaction types. + def voucher_types(self) -> t.Type[VoucherType]: + """Returns the voucher types. - :return: The transaction types. + :return: The voucher types. """ - return TransactionType + return VoucherType @property def csv_uri(self) -> str: diff --git a/src/accounting/static/css/style.css b/src/accounting/static/css/style.css index 4713fbb..b914c4d 100644 --- a/src/accounting/static/css/style.css +++ b/src/accounting/static/css/style.css @@ -149,7 +149,7 @@ overflow-y: scroll; } -/** The transaction management */ +/** The voucher management */ .accounting-currency-control { background-color: transparent; } @@ -169,14 +169,14 @@ .accounting-list-group-hover .list-group-item:hover { background-color: #ececec; } -.accounting-transaction-entry { +.accounting-voucher-entry { border: none; } -.accounting-transaction-entry-header { +.accounting-voucher-entry-header { font-weight: bolder; border-bottom: thick double slategray; } -.list-group-item.accounting-transaction-entry-total { +.list-group-item.accounting-voucher-entry-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 c4a7f8d..84be852 100644 --- a/src/accounting/static/js/account-selector.js +++ b/src/accounting/static/js/account-selector.js @@ -1,5 +1,5 @@ /* The Mia! Accounting Flask Project - * transaction-transfer-form.js: The JavaScript for the transfer transaction form + * account-selector.js: The JavaScript for the account selector */ /* Copyright (c) 2023 imacat. diff --git a/src/accounting/static/js/journal-entry-editor.js b/src/accounting/static/js/journal-entry-editor.js index 63ec09d..ef488b8 100644 --- a/src/accounting/static/js/journal-entry-editor.js +++ b/src/accounting/static/js/journal-entry-editor.js @@ -29,8 +29,8 @@ class JournalEntryEditor { /** - * The transaction form - * @type {TransactionForm} + * The voucher form + * @type {VoucherForm} */ form; @@ -217,7 +217,7 @@ class JournalEntryEditor { /** * Constructs a new journal entry editor. * - * @param form {TransactionForm} the transaction form + * @param form {VoucherForm} the voucher form */ constructor(form) { this.form = form; diff --git a/src/accounting/static/js/original-entry-selector.js b/src/accounting/static/js/original-entry-selector.js index 79d091b..3bd0700 100644 --- a/src/accounting/static/js/original-entry-selector.js +++ b/src/accounting/static/js/original-entry-selector.js @@ -105,7 +105,7 @@ class OriginalEntrySelector { * Returns the net balance for an original entry. * * @param currentEntry {JournalEntrySubForm} the journal entry sub-form that is currently editing - * @param form {TransactionForm} the transaction form + * @param form {VoucherForm} the voucher form * @param originalEntryId {string} the ID of the original entry * @return {Decimal} the net balance of the original entry */ diff --git a/src/accounting/static/js/transaction-form.js b/src/accounting/static/js/voucher-form.js similarity index 98% rename from src/accounting/static/js/transaction-form.js rename to src/accounting/static/js/voucher-form.js index 7b6b325..5b7ac9c 100644 --- a/src/accounting/static/js/transaction-form.js +++ b/src/accounting/static/js/voucher-form.js @@ -1,5 +1,5 @@ /* The Mia! Accounting Flask Project - * transaction-form.js: The JavaScript for the transaction form + * voucher-form.js: The JavaScript for the voucher form */ /* Copyright (c) 2023 imacat. @@ -23,14 +23,14 @@ "use strict"; document.addEventListener("DOMContentLoaded", () => { - TransactionForm.initialize(); + VoucherForm.initialize(); }); /** - * The transaction form + * The voucher form * */ -class TransactionForm { +class VoucherForm { /** * The form element @@ -105,7 +105,7 @@ class TransactionForm { entryEditor; /** - * Constructs the transaction form. + * Constructs the voucher form. * */ constructor() { @@ -325,17 +325,17 @@ class TransactionForm { } /** - * The transaction form - * @type {TransactionForm} + * The voucher form + * @type {VoucherForm} */ static #form; /** - * Initializes the transaction form. + * Initializes the voucher form. * */ static initialize() { - this.#form = new TransactionForm() + this.#form = new VoucherForm() } } @@ -352,8 +352,8 @@ class CurrencySubForm { element; /** - * The transaction form - * @type {TransactionForm} + * The voucher form + * @type {VoucherForm} */ form; @@ -420,7 +420,7 @@ class CurrencySubForm { /** * Constructs a currency sub-form * - * @param form {TransactionForm} the transaction form + * @param form {VoucherForm} the voucher form * @param element {HTMLDivElement} the currency sub-form element */ constructor(form, element) { diff --git a/src/accounting/static/js/transaction-order.js b/src/accounting/static/js/voucher-order.js similarity index 95% rename from src/accounting/static/js/transaction-order.js rename to src/accounting/static/js/voucher-order.js index be8e29d..6c7d44c 100644 --- a/src/accounting/static/js/transaction-order.js +++ b/src/accounting/static/js/voucher-order.js @@ -1,5 +1,5 @@ /* The Mia! Accounting Flask Project - * transaction-order.js: The JavaScript for the transaction order + * voucher-order.js: The JavaScript for the voucher order */ /* Copyright (c) 2023 imacat. diff --git a/src/accounting/template_globals.py b/src/accounting/template_globals.py index 07d2c35..ff9169e 100644 --- a/src/accounting/template_globals.py +++ b/src/accounting/template_globals.py @@ -14,7 +14,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""The template globals for the transaction management. +"""The template globals. """ from flask import current_app diff --git a/src/accounting/templates/accounting/report/balance-sheet.html b/src/accounting/templates/accounting/report/balance-sheet.html index 245d098..9ce54d8 100644 --- a/src/accounting/templates/accounting/report/balance-sheet.html +++ b/src/accounting/templates/accounting/report/balance-sheet.html @@ -37,7 +37,7 @@ First written: 2023/3/7 {% endwith %} -{% include "accounting/report/include/add-txn-material-fab.html" %} +{% include "accounting/report/include/add-voucher-material-fab.html" %} {% include "accounting/report/include/period-chooser.html" %} diff --git a/src/accounting/templates/accounting/report/include/add-txn-material-fab.html b/src/accounting/templates/accounting/report/include/add-voucher-material-fab.html similarity index 71% rename from src/accounting/templates/accounting/report/include/add-txn-material-fab.html rename to src/accounting/templates/accounting/report/include/add-voucher-material-fab.html index bd62aa9..fa00b65 100644 --- a/src/accounting/templates/accounting/report/include/add-txn-material-fab.html +++ b/src/accounting/templates/accounting/report/include/add-voucher-material-fab.html @@ -1,6 +1,6 @@ {# The Mia! Accounting Flask Project -add-txn-material-fab.html: The material floating action buttons to add a new transaction +add-voucher-material-fab.html: The material floating action buttons to add a new voucher Copyright (c) 2023 imacat. @@ -22,13 +22,13 @@ First written: 2023/2/25 {% if accounting_can_edit() %}