11 Commits

Author SHA1 Message Date
3a0e978f76 Removed an unused import from the "accounting.journal_entry.forms.line_item" module. 2023-04-08 00:44:13 +08:00
8c10d42d7b Added documentation to the currency and account parameters of the CSVRow class, and the pagination parameter of the PageParams class in the "accounting.report.reports.journal" module. 2023-04-08 00:44:13 +08:00
04ec51afbe Changed the "offsets" relationship to a pseudo property, to apply the correct but complex ordering rules. 2023-04-07 16:04:54 +08:00
fe7a8842ce Fixed the query in the JournalEntryConverter converter. 2023-04-07 15:31:06 +08:00
66daa5c42c Fixed the query in the KeepAccountWhenHavingOffset validator. 2023-04-07 15:29:17 +08:00
27fb44937d Fixed the incorrect query in the "offsets" pseudo property of the LineItemForm form. 2023-04-07 15:11:04 +08:00
7026ed3a65 Fixed the order of the items in the "offsets" pseudo property of the LineItemForm form. 2023-04-07 15:01:22 +08:00
fdd3e93778 Fixed the net balance in the line items in the journal entry detail. 2023-04-07 14:57:24 +08:00
def7559457 Fixed the #filterOptions in the JavaScript JournalEntryAccountSelector to show the "more" option when there is no matches, but it is not showing all the accounts. 2023-04-07 12:34:24 +08:00
7905820d68 Revised the imports in the "accounting.base_account.views" and "accounting.currency.views" modules. 2023-04-06 16:09:36 +08:00
7ae332c975 Moved the "Test Site and Live Demonstration" section to the front of the documentation. 2023-04-06 10:00:24 +08:00
10 changed files with 60 additions and 58 deletions

View File

@ -17,8 +17,6 @@ accounting reports:
In addition, *Mia! Accounting* tracks offsets for unpaid payables and
receivables.
You may try the `live demonstration`_.
Installation
============
@ -33,6 +31,18 @@ You may also download the from the `PyPI project page`_ or the
`release page`_ on the `Git repository`_.
Test Site and Live Demonstration
================================
You may find a working example in the `test site`_ in the
`source distribution`_. It is the simplest website that works with
*Mia! Accounting*. It is used in the automatic tests. It is the same
code run for `live demonstration`_.
If you do not have a running Flask application or do not know how to
start one, you may start with the test site.
Prerequisites
=============
@ -157,18 +167,6 @@ base template:
Check your Flask application and see how it works.
Test Site and Live Demonstration
================================
You may find a working example in the `test site`_ in the
`source distribution`_. It is the simplest website that works with
*Mia! Accounting*. It is used in the automatic tests. It is the same
code run for `live demonstration`_.
If you do not have a running Flask application, you may start with the
test site.
Documentation
=============
@ -203,6 +201,8 @@ Authors
.. _Flask: https://flask.palletsprojects.com
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
.. _source distribution: https://pypi.org/project/mia-accounting/#files
.. _live demonstration: https://accounting.imacat.idv.tw
.. _PyPI project page: https://pypi.org/project/mia-accounting
.. _release page: https://github.com/imacat/mia-accounting/releases
@ -216,6 +216,4 @@ Authors
.. _init_app: https://mia-accounting.readthedocs.io/en/latest/accounting.html#accounting.init_app
.. _flask_sqlalchemy.SQLAlchemy.create_all: https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/api/#flask_sqlalchemy.SQLAlchemy.create_all
.. _Bootstrap navigation bar: https://getbootstrap.com/docs/5.3/components/navbar/
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
.. _source distribution: https://pypi.org/project/mia-accounting/#files
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io

View File

@ -12,8 +12,6 @@ accounting reports:
In addition, *Mia! Accounting* tracks offsets for unpaid payables and
receivables.
You may try the `live demonstration`_.
Installation
------------
@ -28,6 +26,18 @@ You may also download the from the `PyPI project page`_ or the
`release page`_ on the `Git repository`_.
Test Site and Live Demonstration
--------------------------------
You may find a working example in the `test site`_ in the
`source distribution`_. It is the simplest website that works with
*Mia! Accounting*. It is used in the automatic tests. It is the same
code run for `live demonstration`_.
If you do not have a running Flask application or do not know how to
start one, you may start with the test site.
Prerequisites
-------------
@ -102,18 +112,6 @@ base template:
Check your Flask application and see how it works.
Test Site and Live Demonstration
--------------------------------
You may find a working example in the `test site`_ in the
`source distribution`_. It is the simplest website that works with
*Mia! Accounting*. It is used in the automatic tests. It is the same
code run for `live demonstration`_.
If you do not have a running Flask application, you may start with the
test site.
Documentation
-------------
@ -122,6 +120,8 @@ Refer to the `documentation on Read the Docs`_.
.. _Flask: https://flask.palletsprojects.com
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
.. _source distribution: https://pypi.org/project/mia-accounting/#files
.. _live demonstration: https://accounting.imacat.idv.tw
.. _PyPI project page: https://pypi.org/project/mia-accounting
.. _release page: https://github.com/imacat/mia-accounting/releases
@ -133,6 +133,4 @@ Refer to the `documentation on Read the Docs`_.
.. _Tempus-Dominus: https://getdatepicker.com
.. _flask_sqlalchemy.SQLAlchemy.create_all: https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/api/#flask_sqlalchemy.SQLAlchemy.create_all
.. _Bootstrap navigation bar: https://getbootstrap.com/docs/5.3/components/navbar/
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
.. _source distribution: https://pypi.org/project/mia-accounting/#files
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io

View File

@ -22,6 +22,7 @@ from flask import Blueprint, render_template
from accounting.models import BaseAccount
from accounting.utils.pagination import Pagination
from accounting.utils.permission import has_permission, can_view
from .queries import get_base_account_query
bp: Blueprint = Blueprint("base-account", __name__)
"""The view blueprint for the base account management."""
@ -34,7 +35,6 @@ def list_accounts() -> str:
:return: The account list.
"""
from .queries import get_base_account_query
accounts: list[BaseAccount] = get_base_account_query()
pagination: Pagination = Pagination[BaseAccount](accounts)
return render_template("accounting/base-account/list.html",

View File

@ -34,6 +34,7 @@ from accounting.utils.pagination import Pagination
from accounting.utils.permission import has_permission, can_view, can_edit
from accounting.utils.user import get_current_user_pk
from .forms import CurrencyForm
from .queries import get_currency_query
bp: Blueprint = Blueprint("currency", __name__)
"""The view blueprint for the currency management."""
@ -48,7 +49,6 @@ def list_currencies() -> str:
:return: The currency list.
"""
from .queries import get_currency_query
currencies: list[Currency] = get_currency_query()
pagination: Pagination = Pagination[Currency](currencies)
return render_template("accounting/currency/list.html",

View File

@ -23,6 +23,7 @@ from flask import abort
from sqlalchemy.orm import selectinload
from werkzeug.routing import BaseConverter
from accounting import db
from accounting.models import JournalEntry, JournalEntryLineItem
from accounting.utils.journal_entry_types import JournalEntryType
@ -37,13 +38,7 @@ class JournalEntryConverter(BaseConverter):
:param value: The journal entry ID.
:return: The corresponding journal entry.
"""
journal_entry: JournalEntry | None = JournalEntry.query\
.join(JournalEntryLineItem)\
.filter(JournalEntry.id == value)\
.options(selectinload(JournalEntry.line_items)
.selectinload(JournalEntryLineItem.offsets)
.selectinload(JournalEntryLineItem.journal_entry))\
.first()
journal_entry: JournalEntry | None = db.session.get(JournalEntry, value)
if journal_entry is None:
abort(404)
return journal_entry

View File

@ -31,7 +31,7 @@ from accounting import db
from accounting.forms import ACCOUNT_REQUIRED, AccountExists, IsDebitAccount, \
IsCreditAccount
from accounting.locale import lazy_gettext
from accounting.models import Account, JournalEntryLineItem
from accounting.models import Account, JournalEntry, JournalEntryLineItem
from accounting.template_filters import format_amount
from accounting.utils.cast import be
from accounting.utils.random_id import new_id
@ -127,10 +127,8 @@ class KeepAccountWhenHavingOffset:
assert isinstance(form, LineItemForm)
if field.data is None or form.id.data is None:
return
line_item: JournalEntryLineItem | None = db.session\
.query(JournalEntryLineItem)\
.filter(JournalEntryLineItem.id == form.id.data)\
.options(selectinload(JournalEntryLineItem.offsets)).first()
line_item: JournalEntryLineItem | None \
= db.session.get(JournalEntryLineItem, form.id.data)
if line_item is None or len(line_item.offsets) == 0:
return
if field.data != line_item.account_code:
@ -344,14 +342,13 @@ class LineItemForm(FlaskForm):
def get_offsets() -> list[JournalEntryLineItem]:
if not self.is_need_offset or self.id.data is None:
return []
return JournalEntryLineItem.query\
return JournalEntryLineItem.query.join(JournalEntry)\
.filter(JournalEntryLineItem.original_line_item_id
== self.id.data)\
.order_by(JournalEntry.date, JournalEntry.no,
JournalEntryLineItem.no)\
.options(selectinload(JournalEntryLineItem.journal_entry),
selectinload(JournalEntryLineItem.account),
selectinload(JournalEntryLineItem.offsets)
.selectinload(
JournalEntryLineItem.journal_entry)).all()
selectinload(JournalEntryLineItem.account)).all()
setattr(self, "__offsets", get_offsets())
return getattr(self, "__offsets")

View File

@ -660,12 +660,8 @@ class JournalEntryLineItem(db.Model):
nullable=True)
"""The ID of the original line item."""
original_line_item = db.relationship("JournalEntryLineItem",
back_populates="offsets",
remote_side=id, passive_deletes=True)
"""The original line item."""
offsets = db.relationship("JournalEntryLineItem",
back_populates="original_line_item")
"""The offset items."""
currency_code = db.Column(db.String,
db.ForeignKey(Currency.code, onupdate="CASCADE"),
nullable=False)
@ -758,6 +754,21 @@ class JournalEntryLineItem(db.Model):
"""
setattr(self, "__net_balance", net_balance)
@property
def offsets(self) -> list[t.Self]:
"""Returns the offset items.
:return: The offset items.
"""
if not hasattr(self, "__offsets"):
cls: t.Type[t.Self] = self.__class__
offsets: list[t.Self] = cls.query.join(JournalEntry)\
.filter(JournalEntryLineItem.original_line_item_id == self.id)\
.order_by(JournalEntry.date, JournalEntry.no,
cls.is_debit, cls.no).all()
setattr(self, "__offsets", offsets)
return getattr(self, "__offsets")
@property
def query_values(self) -> list[str]:
"""Returns the values to be queried.

View File

@ -77,6 +77,8 @@ class CSVRow(BaseCSVRow):
"""Constructs a row in the CSV.
:param journal_entry_date: The journal entry date.
:param currency: The currency.
:param account: The account.
:param description: The description.
:param debit: The debit amount.
:param credit: The credit amount.
@ -116,6 +118,7 @@ class PageParams(BasePageParams):
"""Constructs the HTML page parameters.
:param period: The period.
:param pagination: The pagination.
:param line_items: The line items.
"""
self.period: Period = period

View File

@ -123,7 +123,7 @@ class JournalEntryAccountSelector {
option.setShown(false);
}
}
if (!isAnyMatched) {
if (!isAnyMatched && this.#isShowMore) {
this.#optionList.classList.add("d-none");
this.#queryNoResult.classList.remove("d-none");
} else {

View File

@ -50,10 +50,10 @@ First written: 2023/3/14
{% endfor %}
</ul>
</div>
{% if line_item.balance %}
{% if line_item.net_balance %}
<div class="d-flex justify-content-between">
<div>{{ A_("Net balance") }}</div>
<div>{{ line_item.balance|accounting_format_amount }}</div>
<div>{{ line_item.net_balance|accounting_format_amount }}</div>
</div>
{% else %}
<div class="d-flex justify-content-between">