Moved the format_amount and format_date template filters from the "accounting.transaction.template_filters" module to the "accounting.template_filters" module, and rename the filters from "accounting_txn_format_amount" and "accounting_txn_format_date" to "accounting_format_amount" and "accounting_format_date", respectively. They will not only be used in the transaction management, but also the reports.
This commit is contained in:
parent
9065686cc5
commit
cc958a39b3
@ -58,6 +58,10 @@ def init_app(app: Flask, user_utils: AbstractUserUtils,
|
|||||||
template_folder="templates",
|
template_folder="templates",
|
||||||
static_folder="static")
|
static_folder="static")
|
||||||
|
|
||||||
|
from .template_filters import format_amount, format_date
|
||||||
|
bp.add_app_template_filter(format_amount, "accounting_format_amount")
|
||||||
|
bp.add_app_template_filter(format_date, "accounting_format_date")
|
||||||
|
|
||||||
from . import locale
|
from . import locale
|
||||||
locale.init_app(app, bp)
|
locale.init_app(app, bp)
|
||||||
|
|
||||||
|
68
src/accounting/template_filters.py
Normal file
68
src/accounting/template_filters.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# The Mia! Accounting Flask Project.
|
||||||
|
# Author: imacat@mail.imacat.idv.tw (imacat), 2023/2/25
|
||||||
|
|
||||||
|
# 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 template filters.
|
||||||
|
|
||||||
|
"""
|
||||||
|
from decimal import Decimal
|
||||||
|
from datetime import date, timedelta
|
||||||
|
|
||||||
|
from flask_babel import get_locale
|
||||||
|
|
||||||
|
from accounting.locale import gettext
|
||||||
|
|
||||||
|
|
||||||
|
def format_amount(value: Decimal | None) -> str:
|
||||||
|
"""Formats an amount for readability.
|
||||||
|
|
||||||
|
:param value: The amount.
|
||||||
|
:return: The formatted amount text.
|
||||||
|
"""
|
||||||
|
if value is None or value == 0:
|
||||||
|
return "-"
|
||||||
|
whole: int = int(value)
|
||||||
|
frac: Decimal = (value - whole).normalize()
|
||||||
|
return "{:,}".format(whole) + str(frac)[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def format_date(value: date) -> str:
|
||||||
|
"""Formats a date to be human-friendly.
|
||||||
|
|
||||||
|
:param value: The date.
|
||||||
|
:return: The human-friendly date text.
|
||||||
|
"""
|
||||||
|
today: date = date.today()
|
||||||
|
if value == today:
|
||||||
|
return gettext("Today")
|
||||||
|
if value == today - timedelta(days=1):
|
||||||
|
return gettext("Yesterday")
|
||||||
|
if value == today + timedelta(days=1):
|
||||||
|
return gettext("Tomorrow")
|
||||||
|
locale = str(get_locale())
|
||||||
|
if locale == "zh" or locale.startswith("zh_"):
|
||||||
|
if value == today - timedelta(days=2):
|
||||||
|
return gettext("The day before yesterday")
|
||||||
|
if value == today + timedelta(days=2):
|
||||||
|
return gettext("The day after tomorrow")
|
||||||
|
if locale == "zh" or locale.startswith("zh_"):
|
||||||
|
weekdays = ["一", "二", "三", "四", "五", "六", "日"]
|
||||||
|
weekday = weekdays[value.weekday()]
|
||||||
|
else:
|
||||||
|
weekday = value.strftime("%a")
|
||||||
|
if value.year != today.year:
|
||||||
|
return "{}/{}/{}({})".format(
|
||||||
|
value.year, value.month, value.day, weekday)
|
||||||
|
return "{}/{}({})".format(value.month, value.day, weekday)
|
@ -44,14 +44,14 @@ First written: 2023/2/26
|
|||||||
<div>{{ entry.summary }}</div>
|
<div>{{ entry.summary }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ entry.amount|accounting_txn_format_amount }}</div>
|
<div>{{ entry.amount|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div>{{ A_("Total") }}</div>
|
<div>{{ A_("Total") }}</div>
|
||||||
<div>{{ currency.debit_total|accounting_txn_format_amount }}</div>
|
<div>{{ currency.debit_total|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -57,7 +57,7 @@ First written: 2023/2/25
|
|||||||
summary_errors = entry_form.summary.errors,
|
summary_errors = entry_form.summary.errors,
|
||||||
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
||||||
amount_errors = entry_form.amount.errors,
|
amount_errors = entry_form.amount.errors,
|
||||||
amount_text = entry_form.amount.data|accounting_txn_format_amount,
|
amount_text = entry_form.amount.data|accounting_format_amount,
|
||||||
entry_errors = entry_form.all_errors %}
|
entry_errors = entry_form.all_errors %}
|
||||||
{% include "accounting/transaction/include/form-entry-item.html" %}
|
{% include "accounting/transaction/include/form-entry-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
@ -31,7 +31,7 @@ First written: 2023/2/25
|
|||||||
currency_code_errors = currency_form.code.errors,
|
currency_code_errors = currency_form.code.errors,
|
||||||
debit_forms = currency_form.debit,
|
debit_forms = currency_form.debit,
|
||||||
debit_errors = currency_form.debit_errors,
|
debit_errors = currency_form.debit_errors,
|
||||||
debit_total = currency_form.form.debit_total|accounting_txn_format_amount %}
|
debit_total = currency_form.form.debit_total|accounting_format_amount %}
|
||||||
{% include "accounting/transaction/expense/include/form-currency-item.html" %}
|
{% include "accounting/transaction/expense/include/form-currency-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -89,7 +89,7 @@ First written: 2023/2/26
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
{{ obj.date|accounting_txn_format_date }}
|
{{ obj.date|accounting_format_date }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% block transaction_currencies %}{% endblock %}
|
{% block transaction_currencies %}{% endblock %}
|
||||||
|
@ -44,14 +44,14 @@ First written: 2023/2/26
|
|||||||
<div>{{ entry.summary }}</div>
|
<div>{{ entry.summary }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ entry.amount|accounting_txn_format_amount }}</div>
|
<div>{{ entry.amount|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div>{{ A_("Total") }}</div>
|
<div>{{ A_("Total") }}</div>
|
||||||
<div>{{ currency.debit_total|accounting_txn_format_amount }}</div>
|
<div>{{ currency.debit_total|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -57,7 +57,7 @@ First written: 2023/2/25
|
|||||||
summary_errors = entry_form.summary.errors,
|
summary_errors = entry_form.summary.errors,
|
||||||
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
||||||
amount_errors = entry_form.amount.errors,
|
amount_errors = entry_form.amount.errors,
|
||||||
amount_text = entry_form.amount.data|accounting_txn_format_amount,
|
amount_text = entry_form.amount.data|accounting_format_amount,
|
||||||
entry_errors = entry_form.all_errors %}
|
entry_errors = entry_form.all_errors %}
|
||||||
{% include "accounting/transaction/include/form-entry-item.html" %}
|
{% include "accounting/transaction/include/form-entry-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
@ -31,7 +31,7 @@ First written: 2023/2/25
|
|||||||
currency_code_errors = currency_form.code.errors,
|
currency_code_errors = currency_form.code.errors,
|
||||||
credit_forms = currency_form.credit,
|
credit_forms = currency_form.credit,
|
||||||
credit_errors = currency_form.credit_errors,
|
credit_errors = currency_form.credit_errors,
|
||||||
credit_total = currency_form.form.credit_total|accounting_txn_format_amount %}
|
credit_total = currency_form.form.credit_total|accounting_format_amount %}
|
||||||
{% include "accounting/transaction/income/include/form-currency-item.html" %}
|
{% include "accounting/transaction/income/include/form-currency-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -85,7 +85,7 @@ First written: 2023/2/18
|
|||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
{% for item in list %}
|
{% for item in list %}
|
||||||
<a class="list-group-item list-group-item-action" href="{{ url_for("accounting.transaction.detail", txn=item)|accounting_append_next }}">
|
<a class="list-group-item list-group-item-action" href="{{ url_for("accounting.transaction.detail", txn=item)|accounting_append_next }}">
|
||||||
{{ item.date|accounting_txn_format_date }} {{ item }}
|
{{ item.date|accounting_format_date }} {{ item }}
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,14 +40,14 @@ First written: 2023/2/26
|
|||||||
<div>{{ entry.summary }}</div>
|
<div>{{ entry.summary }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ entry.amount|accounting_txn_format_amount }}</div>
|
<div>{{ entry.amount|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div>{{ A_("Total") }}</div>
|
<div>{{ A_("Total") }}</div>
|
||||||
<div>{{ currency.debit_total|accounting_txn_format_amount }}</div>
|
<div>{{ currency.debit_total|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -66,14 +66,14 @@ First written: 2023/2/26
|
|||||||
<div>{{ entry.summary }}</div>
|
<div>{{ entry.summary }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ entry.amount|accounting_txn_format_amount }}</div>
|
<div>{{ entry.amount|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
<li class="list-group-item accounting-transaction-entry accounting-transaction-entry-total">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div>{{ A_("Total") }}</div>
|
<div>{{ A_("Total") }}</div>
|
||||||
<div>{{ currency.debit_total|accounting_txn_format_amount }}</div>
|
<div>{{ currency.debit_total|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -59,7 +59,7 @@ First written: 2023/2/25
|
|||||||
summary_errors = entry_form.summary.errors,
|
summary_errors = entry_form.summary.errors,
|
||||||
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
||||||
amount_errors = entry_form.amount.errors,
|
amount_errors = entry_form.amount.errors,
|
||||||
amount_text = entry_form.amount.data|accounting_txn_format_amount,
|
amount_text = entry_form.amount.data|accounting_format_amount,
|
||||||
entry_errors = entry_form.all_errors %}
|
entry_errors = entry_form.all_errors %}
|
||||||
{% include "accounting/transaction/include/form-entry-item.html" %}
|
{% include "accounting/transaction/include/form-entry-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
@ -99,7 +99,7 @@ First written: 2023/2/25
|
|||||||
summary_errors = entry_form.summary.errors,
|
summary_errors = entry_form.summary.errors,
|
||||||
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
amount_data = "" if entry_form.amount.data is none else entry_form.amount.data|accounting_txn_format_amount_input,
|
||||||
amount_errors = entry_form.amount.errors,
|
amount_errors = entry_form.amount.errors,
|
||||||
amount_text = entry_form.amount.data|accounting_txn_format_amount,
|
amount_text = entry_form.amount.data|accounting_format_amount,
|
||||||
entry_errors = entry_form.all_errors %}
|
entry_errors = entry_form.all_errors %}
|
||||||
{% include "accounting/transaction/include/form-entry-item.html" %}
|
{% include "accounting/transaction/include/form-entry-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
@ -31,10 +31,10 @@ First written: 2023/2/25
|
|||||||
currency_code_errors = currency_form.code.errors,
|
currency_code_errors = currency_form.code.errors,
|
||||||
debit_forms = currency_form.debit,
|
debit_forms = currency_form.debit,
|
||||||
debit_errors = currency_form.debit_errors,
|
debit_errors = currency_form.debit_errors,
|
||||||
debit_total = currency_form.form.debit_total|accounting_txn_format_amount,
|
debit_total = currency_form.form.debit_total|accounting_format_amount,
|
||||||
credit_forms = currency_form.credit,
|
credit_forms = currency_form.credit,
|
||||||
credit_errors = currency_form.credit_errors,
|
credit_errors = currency_form.credit_errors,
|
||||||
credit_total = currency_form.form.credit_total|accounting_txn_format_amount %}
|
credit_total = currency_form.form.credit_total|accounting_format_amount %}
|
||||||
{% include "accounting/transaction/transfer/include/form-currency-item.html" %}
|
{% include "accounting/transaction/transfer/include/form-currency-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -17,16 +17,12 @@
|
|||||||
"""The template filters for the transaction management.
|
"""The template filters for the transaction management.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from datetime import date, timedelta
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from html import escape
|
from html import escape
|
||||||
from urllib.parse import ParseResult, urlparse, parse_qsl, urlencode, \
|
from urllib.parse import ParseResult, urlparse, parse_qsl, urlencode, \
|
||||||
urlunparse
|
urlunparse
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask_babel import get_locale
|
|
||||||
|
|
||||||
from accounting.locale import gettext
|
|
||||||
|
|
||||||
|
|
||||||
def with_type(uri: str) -> str:
|
def with_type(uri: str) -> str:
|
||||||
@ -61,19 +57,6 @@ def to_transfer(uri: str) -> str:
|
|||||||
return urlunparse(parts)
|
return urlunparse(parts)
|
||||||
|
|
||||||
|
|
||||||
def format_amount(value: Decimal | None) -> str:
|
|
||||||
"""Formats an amount for readability.
|
|
||||||
|
|
||||||
:param value: The amount.
|
|
||||||
:return: The formatted amount text.
|
|
||||||
"""
|
|
||||||
if value is None or value == 0:
|
|
||||||
return "-"
|
|
||||||
whole: int = int(value)
|
|
||||||
frac: Decimal = (value - whole).normalize()
|
|
||||||
return "{:,}".format(whole) + str(frac)[1:]
|
|
||||||
|
|
||||||
|
|
||||||
def format_amount_input(value: Decimal) -> str:
|
def format_amount_input(value: Decimal) -> str:
|
||||||
"""Format an amount for an input value.
|
"""Format an amount for an input value.
|
||||||
|
|
||||||
@ -85,36 +68,6 @@ def format_amount_input(value: Decimal) -> str:
|
|||||||
return str(whole) + str(frac)[1:]
|
return str(whole) + str(frac)[1:]
|
||||||
|
|
||||||
|
|
||||||
def format_date(value: date) -> str:
|
|
||||||
"""Formats a date to be human-friendly.
|
|
||||||
|
|
||||||
:param value: The date.
|
|
||||||
:return: The human-friendly date text.
|
|
||||||
"""
|
|
||||||
today: date = date.today()
|
|
||||||
if value == today:
|
|
||||||
return gettext("Today")
|
|
||||||
if value == today - timedelta(days=1):
|
|
||||||
return gettext("Yesterday")
|
|
||||||
if value == today + timedelta(days=1):
|
|
||||||
return gettext("Tomorrow")
|
|
||||||
locale = str(get_locale())
|
|
||||||
if locale == "zh" or locale.startswith("zh_"):
|
|
||||||
if value == today - timedelta(days=2):
|
|
||||||
return gettext("The day before yesterday")
|
|
||||||
if value == today + timedelta(days=2):
|
|
||||||
return gettext("The day after tomorrow")
|
|
||||||
if locale == "zh" or locale.startswith("zh_"):
|
|
||||||
weekdays = ["一", "二", "三", "四", "五", "六", "日"]
|
|
||||||
weekday = weekdays[value.weekday()]
|
|
||||||
else:
|
|
||||||
weekday = value.strftime("%a")
|
|
||||||
if value.year != today.year:
|
|
||||||
return "{}/{}/{}({})".format(
|
|
||||||
value.year, value.month, value.day, weekday)
|
|
||||||
return "{}/{}({})".format(value.month, value.day, weekday)
|
|
||||||
|
|
||||||
|
|
||||||
def text2html(value: str) -> str:
|
def text2html(value: str) -> str:
|
||||||
"""Converts plain text into HTML.
|
"""Converts plain text into HTML.
|
||||||
|
|
||||||
|
@ -36,18 +36,16 @@ from accounting.utils.user import get_current_user_pk
|
|||||||
from .dispatcher import TransactionType, get_txn_type, TXN_TYPE_OBJ
|
from .dispatcher import TransactionType, get_txn_type, TXN_TYPE_OBJ
|
||||||
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, \
|
from .template_filters import with_type, to_transfer, format_amount_input, \
|
||||||
format_amount_input, format_date, text2html
|
text2html
|
||||||
from .template_globals import currency_options, default_currency_code
|
from .template_globals import currency_options, default_currency_code
|
||||||
|
|
||||||
bp: Blueprint = Blueprint("transaction", __name__)
|
bp: Blueprint = Blueprint("transaction", __name__)
|
||||||
"""The view blueprint for the transaction management."""
|
"""The view blueprint for the transaction management."""
|
||||||
bp.add_app_template_filter(with_type, "accounting_txn_with_type")
|
bp.add_app_template_filter(with_type, "accounting_txn_with_type")
|
||||||
bp.add_app_template_filter(to_transfer, "accounting_txn_to_transfer")
|
bp.add_app_template_filter(to_transfer, "accounting_txn_to_transfer")
|
||||||
bp.add_app_template_filter(format_amount, "accounting_txn_format_amount")
|
|
||||||
bp.add_app_template_filter(format_amount_input,
|
bp.add_app_template_filter(format_amount_input,
|
||||||
"accounting_txn_format_amount_input")
|
"accounting_txn_format_amount_input")
|
||||||
bp.add_app_template_filter(format_date, "accounting_txn_format_date")
|
|
||||||
bp.add_app_template_filter(text2html, "accounting_txn_text2html")
|
bp.add_app_template_filter(text2html, "accounting_txn_text2html")
|
||||||
bp.add_app_template_global(currency_options, "accounting_txn_currency_options")
|
bp.add_app_template_global(currency_options, "accounting_txn_currency_options")
|
||||||
bp.add_app_template_global(default_currency_code,
|
bp.add_app_template_global(default_currency_code,
|
||||||
|
Loading…
Reference in New Issue
Block a user