Added the TransactionTypeEnum in the new "accounting.utils.txn_types" module to remove the dependency from the "accounting.report" module to the "accounting.transaction" module.
This commit is contained in:
parent
7d412b20d7
commit
9833bac6e4
@ -27,13 +27,14 @@ from flask_sqlalchemy.query import Query
|
|||||||
|
|
||||||
from accounting import db
|
from accounting import db
|
||||||
from accounting.models import JournalEntry, Transaction, Account, Currency
|
from accounting.models import JournalEntry, Transaction, Account, Currency
|
||||||
from accounting.transaction.dispatcher import TXN_TYPE_OBJ, TransactionTypes
|
|
||||||
from accounting.utils.pagination import Pagination
|
from accounting.utils.pagination import Pagination
|
||||||
|
from accounting.utils.txn_types import TransactionTypeEnum
|
||||||
from .period import Period
|
from .period import Period
|
||||||
from .period_choosers import PeriodChooser, \
|
from .period_choosers import PeriodChooser, \
|
||||||
JournalPeriodChooser
|
JournalPeriodChooser
|
||||||
from .report_chooser import ReportChooser, ReportType
|
from .report_chooser import ReportChooser, ReportType
|
||||||
from .report_rows import ReportRow, JournalRow
|
from .report_rows import ReportRow, JournalRow
|
||||||
|
import typing as t
|
||||||
|
|
||||||
|
|
||||||
class JournalEntryReport(ABC):
|
class JournalEntryReport(ABC):
|
||||||
@ -104,12 +105,12 @@ class JournalEntryReport(ABC):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def txn_types(self) -> TransactionTypes:
|
def txn_types(self) -> t.Type[TransactionTypeEnum]:
|
||||||
"""Returns the transaction types.
|
"""Returns the transaction types.
|
||||||
|
|
||||||
:return: The transaction types.
|
:return: The transaction types.
|
||||||
"""
|
"""
|
||||||
return TXN_TYPE_OBJ
|
return TransactionTypeEnum
|
||||||
|
|
||||||
def as_csv_download(self) -> Response:
|
def as_csv_download(self) -> Response:
|
||||||
"""Returns the journal entries as CSV download.
|
"""Returns the journal entries as CSV download.
|
||||||
|
@ -22,13 +22,13 @@ First written: 2023/2/25
|
|||||||
{% if accounting_can_edit() %}
|
{% if accounting_can_edit() %}
|
||||||
<div id="accounting-material-fab-speed-dial" class="d-md-none accounting-material-fab">
|
<div id="accounting-material-fab-speed-dial" class="d-md-none accounting-material-fab">
|
||||||
<div id="accounting-material-fab-speed-dial-actions" class="d-md-none accounting-material-fab-speed-dial-group">
|
<div id="accounting-material-fab-speed-dial-actions" class="d-md-none accounting-material-fab-speed-dial-group">
|
||||||
<a class="btn rounded-pill" href="{{ url_for("accounting.transaction.create", txn_type=types.expense)|accounting_append_next }}">
|
<a class="btn rounded-pill" href="{{ url_for("accounting.transaction.create", txn_type=txn_types.CASH_EXPENSE)|accounting_append_next }}">
|
||||||
{{ A_("Cash expense") }}
|
{{ A_("Cash expense") }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn rounded-pill" href="{{ url_for("accounting.transaction.create", txn_type=types.income)|accounting_append_next }}">
|
<a class="btn rounded-pill" href="{{ url_for("accounting.transaction.create", txn_type=txn_types.CASH_INCOME)|accounting_append_next }}">
|
||||||
{{ A_("Cash income") }}
|
{{ A_("Cash income") }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn rounded-pill" href="{{ url_for("accounting.transaction.create", txn_type=types.transfer)|accounting_append_next }}">
|
<a class="btn rounded-pill" href="{{ url_for("accounting.transaction.create", txn_type=txn_types.TRANSFER)|accounting_append_next }}">
|
||||||
{{ A_("Transfer") }}
|
{{ A_("Transfer") }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,16 +40,16 @@ First written: 2023/3/4
|
|||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=report.txn_types.expense)|accounting_append_next }}">
|
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=report.txn_types.CASH_EXPENSE)|accounting_append_next }}">
|
||||||
{{ A_("Cash Expense") }}</a>
|
{{ A_("Cash Expense") }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=report.txn_types.income)|accounting_append_next }}">
|
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=report.txn_types.CASH_INCOME)|accounting_append_next }}">
|
||||||
{{ A_("Cash Income") }}
|
{{ A_("Cash Income") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=report.txn_types.transfer)|accounting_append_next }}">
|
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=report.txn_types.TRANSFER)|accounting_append_next }}">
|
||||||
{{ A_("Transfer") }}
|
{{ A_("Transfer") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -69,7 +69,7 @@ First written: 2023/3/4
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% with types = report.txn_types %}
|
{% with txn_types = report.txn_types %}
|
||||||
{% include "accounting/include/add-txn-material-fab.html" %}
|
{% include "accounting/include/add-txn-material-fab.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
|
@ -38,16 +38,16 @@ First written: 2023/2/18
|
|||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=types.expense)|accounting_append_next }}">
|
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=txn_types.CASH_EXPENSE)|accounting_append_next }}">
|
||||||
{{ A_("Cash Expense") }}</a>
|
{{ A_("Cash Expense") }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=types.income)|accounting_append_next }}">
|
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=txn_types.CASH_INCOME)|accounting_append_next }}">
|
||||||
{{ A_("Cash Income") }}
|
{{ A_("Cash Income") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=types.transfer)|accounting_append_next }}">
|
<a class="dropdown-item" href="{{ url_for("accounting.transaction.create", txn_type=txn_types.TRANSFER)|accounting_append_next }}">
|
||||||
{{ A_("Transfer") }}
|
{{ A_("Transfer") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -24,8 +24,7 @@ from werkzeug.routing import BaseConverter
|
|||||||
|
|
||||||
from accounting import db
|
from accounting import db
|
||||||
from accounting.models import Transaction
|
from accounting.models import Transaction
|
||||||
from accounting.transaction.dispatcher import TransactionType, \
|
from accounting.utils.txn_types import TransactionTypeEnum
|
||||||
TXN_TYPE_DICT
|
|
||||||
|
|
||||||
|
|
||||||
class TransactionConverter(BaseConverter):
|
class TransactionConverter(BaseConverter):
|
||||||
@ -56,24 +55,26 @@ class TransactionTypeConverter(BaseConverter):
|
|||||||
"""The transaction converter to convert the transaction type ID from and to
|
"""The transaction converter to convert the transaction type ID from and to
|
||||||
the corresponding transaction type in the routes."""
|
the corresponding transaction type in the routes."""
|
||||||
|
|
||||||
def to_python(self, value: str) -> TransactionType:
|
def to_python(self, value: str) -> TransactionTypeEnum:
|
||||||
"""Converts a transaction ID to a transaction.
|
"""Converts a transaction ID to a transaction.
|
||||||
|
|
||||||
:param value: The transaction ID.
|
:param value: The transaction ID.
|
||||||
:return: The corresponding transaction.
|
:return: The corresponding transaction.
|
||||||
"""
|
"""
|
||||||
txn_type: TransactionType | None = TXN_TYPE_DICT.get(value)
|
type_dict: dict[str, TransactionTypeEnum] \
|
||||||
|
= {x.value: x for x in TransactionTypeEnum}
|
||||||
|
txn_type: TransactionTypeEnum | None = type_dict.get(value)
|
||||||
if txn_type is None:
|
if txn_type is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
return txn_type
|
return txn_type
|
||||||
|
|
||||||
def to_url(self, value: TransactionType) -> str:
|
def to_url(self, value: TransactionTypeEnum) -> str:
|
||||||
"""Converts a transaction type to its ID.
|
"""Converts a transaction type to its ID.
|
||||||
|
|
||||||
:param value: The transaction type.
|
:param value: The transaction type.
|
||||||
:return: The ID.
|
:return: The ID.
|
||||||
"""
|
"""
|
||||||
return str(value.ID)
|
return str(value.value)
|
||||||
|
|
||||||
|
|
||||||
class DateConverter(BaseConverter):
|
class DateConverter(BaseConverter):
|
||||||
|
@ -24,15 +24,14 @@ from flask import render_template, request, abort
|
|||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
|
|
||||||
from accounting.models import Transaction
|
from accounting.models import Transaction
|
||||||
|
from accounting.template_globals import default_currency_code
|
||||||
|
from accounting.utils.txn_types import TransactionTypeEnum
|
||||||
from .forms import TransactionForm, IncomeTransactionForm, \
|
from .forms import TransactionForm, IncomeTransactionForm, \
|
||||||
ExpenseTransactionForm, TransferTransactionForm
|
ExpenseTransactionForm, TransferTransactionForm
|
||||||
from accounting.template_globals import default_currency_code
|
|
||||||
|
|
||||||
|
|
||||||
class TransactionType(ABC):
|
class TransactionType(ABC):
|
||||||
"""An abstract transaction type."""
|
"""An abstract transaction type."""
|
||||||
ID: str = ""
|
|
||||||
"""The transaction type ID."""
|
|
||||||
CHECK_ORDER: int = -1
|
CHECK_ORDER: int = -1
|
||||||
"""The order when checking the transaction type."""
|
"""The order when checking the transaction type."""
|
||||||
|
|
||||||
@ -93,8 +92,6 @@ class TransactionType(ABC):
|
|||||||
|
|
||||||
class IncomeTransaction(TransactionType):
|
class IncomeTransaction(TransactionType):
|
||||||
"""An income transaction."""
|
"""An income transaction."""
|
||||||
ID: str = "income"
|
|
||||||
"""The transaction type ID."""
|
|
||||||
CHECK_ORDER: int = 2
|
CHECK_ORDER: int = 2
|
||||||
"""The order when checking the transaction type."""
|
"""The order when checking the transaction type."""
|
||||||
|
|
||||||
@ -113,7 +110,8 @@ class IncomeTransaction(TransactionType):
|
|||||||
:return: the form to create a transaction.
|
:return: the form to create a transaction.
|
||||||
"""
|
"""
|
||||||
return render_template("accounting/transaction/income/create.html",
|
return render_template("accounting/transaction/income/create.html",
|
||||||
form=form, txn_type=self,
|
form=form,
|
||||||
|
txn_type=TransactionTypeEnum.CASH_INCOME,
|
||||||
currency_template=self.__currency_template,
|
currency_template=self.__currency_template,
|
||||||
entry_template=self._entry_template)
|
entry_template=self._entry_template)
|
||||||
|
|
||||||
@ -163,8 +161,6 @@ class IncomeTransaction(TransactionType):
|
|||||||
|
|
||||||
class ExpenseTransaction(TransactionType):
|
class ExpenseTransaction(TransactionType):
|
||||||
"""An expense transaction."""
|
"""An expense transaction."""
|
||||||
ID: str = "expense"
|
|
||||||
"""The transaction type ID."""
|
|
||||||
CHECK_ORDER: int = 1
|
CHECK_ORDER: int = 1
|
||||||
"""The order when checking the transaction type."""
|
"""The order when checking the transaction type."""
|
||||||
|
|
||||||
@ -183,7 +179,8 @@ class ExpenseTransaction(TransactionType):
|
|||||||
:return: the form to create a transaction.
|
:return: the form to create a transaction.
|
||||||
"""
|
"""
|
||||||
return render_template("accounting/transaction/expense/create.html",
|
return render_template("accounting/transaction/expense/create.html",
|
||||||
form=form, txn_type=self,
|
form=form,
|
||||||
|
txn_type=TransactionTypeEnum.CASH_EXPENSE,
|
||||||
currency_template=self.__currency_template,
|
currency_template=self.__currency_template,
|
||||||
entry_template=self._entry_template)
|
entry_template=self._entry_template)
|
||||||
|
|
||||||
@ -233,8 +230,6 @@ class ExpenseTransaction(TransactionType):
|
|||||||
|
|
||||||
class TransferTransaction(TransactionType):
|
class TransferTransaction(TransactionType):
|
||||||
"""A transfer transaction."""
|
"""A transfer transaction."""
|
||||||
ID: str = "transfer"
|
|
||||||
"""The transaction type ID."""
|
|
||||||
CHECK_ORDER: int = 3
|
CHECK_ORDER: int = 3
|
||||||
"""The order when checking the transaction type."""
|
"""The order when checking the transaction type."""
|
||||||
|
|
||||||
@ -253,7 +248,8 @@ class TransferTransaction(TransactionType):
|
|||||||
:return: the form to create a transaction.
|
:return: the form to create a transaction.
|
||||||
"""
|
"""
|
||||||
return render_template("accounting/transaction/transfer/create.html",
|
return render_template("accounting/transaction/transfer/create.html",
|
||||||
form=form, txn_type=self,
|
form=form,
|
||||||
|
txn_type=TransactionTypeEnum.TRANSFER,
|
||||||
currency_template=self.__currency_template,
|
currency_template=self.__currency_template,
|
||||||
entry_template=self._entry_template)
|
entry_template=self._entry_template)
|
||||||
|
|
||||||
@ -301,44 +297,28 @@ class TransferTransaction(TransactionType):
|
|||||||
debit_total="-", credit_total="-")
|
debit_total="-", credit_total="-")
|
||||||
|
|
||||||
|
|
||||||
class TransactionTypes:
|
TXN_ENUM_TO_OP: dict[TransactionTypeEnum, TransactionType] \
|
||||||
"""The transaction types, as object properties."""
|
= {TransactionTypeEnum.CASH_INCOME: IncomeTransaction(),
|
||||||
|
TransactionTypeEnum.CASH_EXPENSE: ExpenseTransaction(),
|
||||||
def __init__(self, income: IncomeTransaction, expense: ExpenseTransaction,
|
TransactionTypeEnum.TRANSFER: TransferTransaction()}
|
||||||
transfer: TransferTransaction):
|
"""The map from the transaction type enum to its operator."""
|
||||||
"""Constructs the transaction types as object properties.
|
|
||||||
|
|
||||||
:param income: The income transaction type.
|
|
||||||
:param expense: The expense transaction type.
|
|
||||||
:param transfer: The transfer transaction type.
|
|
||||||
"""
|
|
||||||
self.income: IncomeTransaction = income
|
|
||||||
self.expense: ExpenseTransaction = expense
|
|
||||||
self.transfer: TransferTransaction = transfer
|
|
||||||
|
|
||||||
|
|
||||||
TXN_TYPE_DICT: dict[str, TransactionType] \
|
def get_txn_type_op(txn: Transaction) -> TransactionType:
|
||||||
= {x.ID: x() for x in {IncomeTransaction,
|
"""Returns the transaction type operator that may be specified in the "as"
|
||||||
ExpenseTransaction,
|
query parameter. If it is not specified, check the transaction type from
|
||||||
TransferTransaction}}
|
the transaction.
|
||||||
"""The transaction types, as a dictionary."""
|
|
||||||
TXN_TYPE_OBJ: TransactionTypes = TransactionTypes(**TXN_TYPE_DICT)
|
|
||||||
"""The transaction types, as an object."""
|
|
||||||
|
|
||||||
|
|
||||||
def get_txn_type(txn: Transaction) -> TransactionType:
|
|
||||||
"""Returns the transaction type that may be specified in the "as" query
|
|
||||||
parameter. If it is not specified, check the transaction type from the
|
|
||||||
transaction.
|
|
||||||
|
|
||||||
:param txn: The transaction.
|
:param txn: The transaction.
|
||||||
:return: None.
|
:return: None.
|
||||||
"""
|
"""
|
||||||
if "as" in request.args:
|
if "as" in request.args:
|
||||||
if request.args["as"] not in TXN_TYPE_DICT:
|
type_dict: dict[str, TransactionTypeEnum] \
|
||||||
|
= {x.value: x for x in TransactionTypeEnum}
|
||||||
|
if request.args["as"] not in type_dict:
|
||||||
abort(404)
|
abort(404)
|
||||||
return TXN_TYPE_DICT[request.args["as"]]
|
return TXN_ENUM_TO_OP[type_dict[request.args["as"]]]
|
||||||
for txn_type in sorted(TXN_TYPE_DICT.values(),
|
for txn_type in sorted(TXN_ENUM_TO_OP.values(),
|
||||||
key=lambda x: x.CHECK_ORDER):
|
key=lambda x: x.CHECK_ORDER):
|
||||||
if txn_type.is_my_type(txn):
|
if txn_type.is_my_type(txn):
|
||||||
return txn_type
|
return txn_type
|
||||||
|
@ -32,8 +32,9 @@ from accounting.utils.flash_errors import flash_form_errors
|
|||||||
from accounting.utils.next_uri import inherit_next, or_next
|
from accounting.utils.next_uri import inherit_next, or_next
|
||||||
from accounting.utils.pagination import Pagination
|
from accounting.utils.pagination import Pagination
|
||||||
from accounting.utils.permission import has_permission, can_view, can_edit
|
from accounting.utils.permission import has_permission, can_view, can_edit
|
||||||
|
from accounting.utils.txn_types import TransactionTypeEnum
|
||||||
from accounting.utils.user import get_current_user_pk
|
from accounting.utils.user import get_current_user_pk
|
||||||
from .dispatcher import TransactionType, get_txn_type, TXN_TYPE_OBJ
|
from .dispatcher import TransactionType, TXN_ENUM_TO_OP, get_txn_type_op
|
||||||
from .forms import sort_transactions_in, TransactionReorderForm
|
from .forms import sort_transactions_in, TransactionReorderForm
|
||||||
from .queries import get_transaction_query
|
from .queries import get_transaction_query
|
||||||
from .template_filters import with_type, to_transfer, format_amount_input, \
|
from .template_filters import with_type, to_transfer, format_amount_input, \
|
||||||
@ -59,37 +60,39 @@ def list_transactions() -> str:
|
|||||||
pagination: Pagination = Pagination[Transaction](transactions)
|
pagination: Pagination = Pagination[Transaction](transactions)
|
||||||
return render_template("accounting/transaction/list.html",
|
return render_template("accounting/transaction/list.html",
|
||||||
list=pagination.list, pagination=pagination,
|
list=pagination.list, pagination=pagination,
|
||||||
types=TXN_TYPE_OBJ)
|
txn_types=TransactionTypeEnum)
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/create/<transactionType:txn_type>", endpoint="create")
|
@bp.get("/create/<transactionType:txn_type>", endpoint="create")
|
||||||
@has_permission(can_edit)
|
@has_permission(can_edit)
|
||||||
def show_add_transaction_form(txn_type: TransactionType) -> str:
|
def show_add_transaction_form(txn_type: TransactionTypeEnum) -> str:
|
||||||
"""Shows the form to add a transaction.
|
"""Shows the form to add a transaction.
|
||||||
|
|
||||||
:param txn_type: The transaction type.
|
:param txn_type: The transaction type.
|
||||||
:return: The form to add a transaction.
|
:return: The form to add a transaction.
|
||||||
"""
|
"""
|
||||||
form: txn_type.form
|
txn_type_op: TransactionType = TXN_ENUM_TO_OP[txn_type]
|
||||||
|
form: txn_type_op.form
|
||||||
if "form" in session:
|
if "form" in session:
|
||||||
form = txn_type.form(ImmutableMultiDict(parse_qsl(session["form"])))
|
form = txn_type_op.form(ImmutableMultiDict(parse_qsl(session["form"])))
|
||||||
del session["form"]
|
del session["form"]
|
||||||
form.validate()
|
form.validate()
|
||||||
else:
|
else:
|
||||||
form = txn_type.form()
|
form = txn_type_op.form()
|
||||||
return txn_type.render_create_template(form)
|
return txn_type_op.render_create_template(form)
|
||||||
|
|
||||||
|
|
||||||
@bp.post("/store/<transactionType:txn_type>", endpoint="store")
|
@bp.post("/store/<transactionType:txn_type>", endpoint="store")
|
||||||
@has_permission(can_edit)
|
@has_permission(can_edit)
|
||||||
def add_transaction(txn_type: TransactionType) -> redirect:
|
def add_transaction(txn_type: TransactionTypeEnum) -> redirect:
|
||||||
"""Adds a transaction.
|
"""Adds a transaction.
|
||||||
|
|
||||||
:param txn_type: The transaction type.
|
:param txn_type: The transaction type.
|
||||||
:return: The redirection to the transaction detail on success, or the
|
:return: The redirection to the transaction detail on success, or the
|
||||||
transaction creation form on error.
|
transaction creation form on error.
|
||||||
"""
|
"""
|
||||||
form: txn_type.form = txn_type.form(request.form)
|
txn_type_op: TransactionType = TXN_ENUM_TO_OP[txn_type]
|
||||||
|
form: txn_type_op.form = txn_type_op.form(request.form)
|
||||||
if not form.validate():
|
if not form.validate():
|
||||||
flash_form_errors(form)
|
flash_form_errors(form)
|
||||||
session["form"] = urlencode(list(request.form.items()))
|
session["form"] = urlencode(list(request.form.items()))
|
||||||
@ -111,8 +114,8 @@ def show_transaction_detail(txn: Transaction) -> str:
|
|||||||
:param txn: The transaction.
|
:param txn: The transaction.
|
||||||
:return: The detail.
|
:return: The detail.
|
||||||
"""
|
"""
|
||||||
txn_type: TransactionType = get_txn_type(txn)
|
txn_type_op: TransactionType = get_txn_type_op(txn)
|
||||||
return txn_type.render_detail_template(txn)
|
return txn_type_op.render_detail_template(txn)
|
||||||
|
|
||||||
|
|
||||||
@bp.get("/<transaction:txn>/edit", endpoint="edit")
|
@bp.get("/<transaction:txn>/edit", endpoint="edit")
|
||||||
@ -123,15 +126,15 @@ def show_transaction_edit_form(txn: Transaction) -> str:
|
|||||||
:param txn: The transaction.
|
:param txn: The transaction.
|
||||||
:return: The form to edit the transaction.
|
:return: The form to edit the transaction.
|
||||||
"""
|
"""
|
||||||
txn_type: TransactionType = get_txn_type(txn)
|
txn_type_op: TransactionType = get_txn_type_op(txn)
|
||||||
form: txn_type.form
|
form: txn_type_op.form
|
||||||
if "form" in session:
|
if "form" in session:
|
||||||
form = txn_type.form(ImmutableMultiDict(parse_qsl(session["form"])))
|
form = txn_type_op.form(ImmutableMultiDict(parse_qsl(session["form"])))
|
||||||
del session["form"]
|
del session["form"]
|
||||||
form.validate()
|
form.validate()
|
||||||
else:
|
else:
|
||||||
form = txn_type.form(obj=txn)
|
form = txn_type_op.form(obj=txn)
|
||||||
return txn_type.render_edit_template(txn, form)
|
return txn_type_op.render_edit_template(txn, form)
|
||||||
|
|
||||||
|
|
||||||
@bp.post("/<transaction:txn>/update", endpoint="update")
|
@bp.post("/<transaction:txn>/update", endpoint="update")
|
||||||
@ -143,8 +146,8 @@ def update_transaction(txn: Transaction) -> redirect:
|
|||||||
:return: The redirection to the transaction detail on success, or the
|
:return: The redirection to the transaction detail on success, or the
|
||||||
transaction edit form on error.
|
transaction edit form on error.
|
||||||
"""
|
"""
|
||||||
txn_type: TransactionType = get_txn_type(txn)
|
txn_type_op: TransactionType = get_txn_type_op(txn)
|
||||||
form: txn_type.form = txn_type.form(request.form)
|
form: txn_type_op.form = txn_type_op.form(request.form)
|
||||||
if not form.validate():
|
if not form.validate():
|
||||||
flash_form_errors(form)
|
flash_form_errors(form)
|
||||||
session["form"] = urlencode(list(request.form.items()))
|
session["form"] = urlencode(list(request.form.items()))
|
||||||
|
30
src/accounting/utils/txn_types.py
Normal file
30
src/accounting/utils/txn_types.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# The Mia! Accounting Flask Project.
|
||||||
|
# Author: imacat@mail.imacat.idv.tw (imacat), 2023/3/4
|
||||||
|
|
||||||
|
# Copyright (c) 2023 imacat.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# 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 transaction types.
|
||||||
|
|
||||||
|
"""
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionTypeEnum(Enum):
|
||||||
|
"""The transaction types."""
|
||||||
|
CASH_INCOME: str = "income"
|
||||||
|
"""The cash income transaction."""
|
||||||
|
CASH_EXPENSE: str = "expense"
|
||||||
|
"""The cash expense transaction."""
|
||||||
|
TRANSFER: str = "transfer"
|
||||||
|
"""The transfer transaction."""
|
Loading…
Reference in New Issue
Block a user