Compare commits
10 Commits
7ae332c975
...
3a0e978f76
Author | SHA1 | Date | |
---|---|---|---|
3a0e978f76 | |||
8c10d42d7b | |||
04ec51afbe | |||
fe7a8842ce | |||
66daa5c42c | |||
27fb44937d | |||
7026ed3a65 | |||
fdd3e93778 | |||
def7559457 | |||
7905820d68 |
@ -22,6 +22,7 @@ from flask import Blueprint, render_template
|
|||||||
from accounting.models import BaseAccount
|
from accounting.models import BaseAccount
|
||||||
from accounting.utils.pagination import Pagination
|
from accounting.utils.pagination import Pagination
|
||||||
from accounting.utils.permission import has_permission, can_view
|
from accounting.utils.permission import has_permission, can_view
|
||||||
|
from .queries import get_base_account_query
|
||||||
|
|
||||||
bp: Blueprint = Blueprint("base-account", __name__)
|
bp: Blueprint = Blueprint("base-account", __name__)
|
||||||
"""The view blueprint for the base account management."""
|
"""The view blueprint for the base account management."""
|
||||||
@ -34,7 +35,6 @@ def list_accounts() -> str:
|
|||||||
|
|
||||||
:return: The account list.
|
:return: The account list.
|
||||||
"""
|
"""
|
||||||
from .queries import get_base_account_query
|
|
||||||
accounts: list[BaseAccount] = get_base_account_query()
|
accounts: list[BaseAccount] = get_base_account_query()
|
||||||
pagination: Pagination = Pagination[BaseAccount](accounts)
|
pagination: Pagination = Pagination[BaseAccount](accounts)
|
||||||
return render_template("accounting/base-account/list.html",
|
return render_template("accounting/base-account/list.html",
|
||||||
|
@ -34,6 +34,7 @@ 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.user import get_current_user_pk
|
from accounting.utils.user import get_current_user_pk
|
||||||
from .forms import CurrencyForm
|
from .forms import CurrencyForm
|
||||||
|
from .queries import get_currency_query
|
||||||
|
|
||||||
bp: Blueprint = Blueprint("currency", __name__)
|
bp: Blueprint = Blueprint("currency", __name__)
|
||||||
"""The view blueprint for the currency management."""
|
"""The view blueprint for the currency management."""
|
||||||
@ -48,7 +49,6 @@ def list_currencies() -> str:
|
|||||||
|
|
||||||
:return: The currency list.
|
:return: The currency list.
|
||||||
"""
|
"""
|
||||||
from .queries import get_currency_query
|
|
||||||
currencies: list[Currency] = get_currency_query()
|
currencies: list[Currency] = get_currency_query()
|
||||||
pagination: Pagination = Pagination[Currency](currencies)
|
pagination: Pagination = Pagination[Currency](currencies)
|
||||||
return render_template("accounting/currency/list.html",
|
return render_template("accounting/currency/list.html",
|
||||||
|
@ -23,6 +23,7 @@ from flask import abort
|
|||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
from werkzeug.routing import BaseConverter
|
from werkzeug.routing import BaseConverter
|
||||||
|
|
||||||
|
from accounting import db
|
||||||
from accounting.models import JournalEntry, JournalEntryLineItem
|
from accounting.models import JournalEntry, JournalEntryLineItem
|
||||||
from accounting.utils.journal_entry_types import JournalEntryType
|
from accounting.utils.journal_entry_types import JournalEntryType
|
||||||
|
|
||||||
@ -37,13 +38,7 @@ class JournalEntryConverter(BaseConverter):
|
|||||||
:param value: The journal entry ID.
|
:param value: The journal entry ID.
|
||||||
:return: The corresponding journal entry.
|
:return: The corresponding journal entry.
|
||||||
"""
|
"""
|
||||||
journal_entry: JournalEntry | None = JournalEntry.query\
|
journal_entry: JournalEntry | None = db.session.get(JournalEntry, value)
|
||||||
.join(JournalEntryLineItem)\
|
|
||||||
.filter(JournalEntry.id == value)\
|
|
||||||
.options(selectinload(JournalEntry.line_items)
|
|
||||||
.selectinload(JournalEntryLineItem.offsets)
|
|
||||||
.selectinload(JournalEntryLineItem.journal_entry))\
|
|
||||||
.first()
|
|
||||||
if journal_entry is None:
|
if journal_entry is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
return journal_entry
|
return journal_entry
|
||||||
|
@ -31,7 +31,7 @@ from accounting import db
|
|||||||
from accounting.forms import ACCOUNT_REQUIRED, AccountExists, IsDebitAccount, \
|
from accounting.forms import ACCOUNT_REQUIRED, AccountExists, IsDebitAccount, \
|
||||||
IsCreditAccount
|
IsCreditAccount
|
||||||
from accounting.locale import lazy_gettext
|
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.template_filters import format_amount
|
||||||
from accounting.utils.cast import be
|
from accounting.utils.cast import be
|
||||||
from accounting.utils.random_id import new_id
|
from accounting.utils.random_id import new_id
|
||||||
@ -127,10 +127,8 @@ class KeepAccountWhenHavingOffset:
|
|||||||
assert isinstance(form, LineItemForm)
|
assert isinstance(form, LineItemForm)
|
||||||
if field.data is None or form.id.data is None:
|
if field.data is None or form.id.data is None:
|
||||||
return
|
return
|
||||||
line_item: JournalEntryLineItem | None = db.session\
|
line_item: JournalEntryLineItem | None \
|
||||||
.query(JournalEntryLineItem)\
|
= db.session.get(JournalEntryLineItem, form.id.data)
|
||||||
.filter(JournalEntryLineItem.id == form.id.data)\
|
|
||||||
.options(selectinload(JournalEntryLineItem.offsets)).first()
|
|
||||||
if line_item is None or len(line_item.offsets) == 0:
|
if line_item is None or len(line_item.offsets) == 0:
|
||||||
return
|
return
|
||||||
if field.data != line_item.account_code:
|
if field.data != line_item.account_code:
|
||||||
@ -344,14 +342,13 @@ class LineItemForm(FlaskForm):
|
|||||||
def get_offsets() -> list[JournalEntryLineItem]:
|
def get_offsets() -> list[JournalEntryLineItem]:
|
||||||
if not self.is_need_offset or self.id.data is None:
|
if not self.is_need_offset or self.id.data is None:
|
||||||
return []
|
return []
|
||||||
return JournalEntryLineItem.query\
|
return JournalEntryLineItem.query.join(JournalEntry)\
|
||||||
.filter(JournalEntryLineItem.original_line_item_id
|
.filter(JournalEntryLineItem.original_line_item_id
|
||||||
== self.id.data)\
|
== self.id.data)\
|
||||||
|
.order_by(JournalEntry.date, JournalEntry.no,
|
||||||
|
JournalEntryLineItem.no)\
|
||||||
.options(selectinload(JournalEntryLineItem.journal_entry),
|
.options(selectinload(JournalEntryLineItem.journal_entry),
|
||||||
selectinload(JournalEntryLineItem.account),
|
selectinload(JournalEntryLineItem.account)).all()
|
||||||
selectinload(JournalEntryLineItem.offsets)
|
|
||||||
.selectinload(
|
|
||||||
JournalEntryLineItem.journal_entry)).all()
|
|
||||||
setattr(self, "__offsets", get_offsets())
|
setattr(self, "__offsets", get_offsets())
|
||||||
return getattr(self, "__offsets")
|
return getattr(self, "__offsets")
|
||||||
|
|
||||||
|
@ -660,12 +660,8 @@ class JournalEntryLineItem(db.Model):
|
|||||||
nullable=True)
|
nullable=True)
|
||||||
"""The ID of the original line item."""
|
"""The ID of the original line item."""
|
||||||
original_line_item = db.relationship("JournalEntryLineItem",
|
original_line_item = db.relationship("JournalEntryLineItem",
|
||||||
back_populates="offsets",
|
|
||||||
remote_side=id, passive_deletes=True)
|
remote_side=id, passive_deletes=True)
|
||||||
"""The original line item."""
|
"""The original line item."""
|
||||||
offsets = db.relationship("JournalEntryLineItem",
|
|
||||||
back_populates="original_line_item")
|
|
||||||
"""The offset items."""
|
|
||||||
currency_code = db.Column(db.String,
|
currency_code = db.Column(db.String,
|
||||||
db.ForeignKey(Currency.code, onupdate="CASCADE"),
|
db.ForeignKey(Currency.code, onupdate="CASCADE"),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
@ -758,6 +754,21 @@ class JournalEntryLineItem(db.Model):
|
|||||||
"""
|
"""
|
||||||
setattr(self, "__net_balance", net_balance)
|
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
|
@property
|
||||||
def query_values(self) -> list[str]:
|
def query_values(self) -> list[str]:
|
||||||
"""Returns the values to be queried.
|
"""Returns the values to be queried.
|
||||||
|
@ -77,6 +77,8 @@ class CSVRow(BaseCSVRow):
|
|||||||
"""Constructs a row in the CSV.
|
"""Constructs a row in the CSV.
|
||||||
|
|
||||||
:param journal_entry_date: The journal entry date.
|
:param journal_entry_date: The journal entry date.
|
||||||
|
:param currency: The currency.
|
||||||
|
:param account: The account.
|
||||||
:param description: The description.
|
:param description: The description.
|
||||||
:param debit: The debit amount.
|
:param debit: The debit amount.
|
||||||
:param credit: The credit amount.
|
:param credit: The credit amount.
|
||||||
@ -116,6 +118,7 @@ class PageParams(BasePageParams):
|
|||||||
"""Constructs the HTML page parameters.
|
"""Constructs the HTML page parameters.
|
||||||
|
|
||||||
:param period: The period.
|
:param period: The period.
|
||||||
|
:param pagination: The pagination.
|
||||||
:param line_items: The line items.
|
:param line_items: The line items.
|
||||||
"""
|
"""
|
||||||
self.period: Period = period
|
self.period: Period = period
|
||||||
|
@ -123,7 +123,7 @@ class JournalEntryAccountSelector {
|
|||||||
option.setShown(false);
|
option.setShown(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isAnyMatched) {
|
if (!isAnyMatched && this.#isShowMore) {
|
||||||
this.#optionList.classList.add("d-none");
|
this.#optionList.classList.add("d-none");
|
||||||
this.#queryNoResult.classList.remove("d-none");
|
this.#queryNoResult.classList.remove("d-none");
|
||||||
} else {
|
} else {
|
||||||
|
@ -50,10 +50,10 @@ First written: 2023/3/14
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% if line_item.balance %}
|
{% if line_item.net_balance %}
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div>{{ A_("Net balance") }}</div>
|
<div>{{ A_("Net balance") }}</div>
|
||||||
<div>{{ line_item.balance|accounting_format_amount }}</div>
|
<div>{{ line_item.net_balance|accounting_format_amount }}</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
|
Loading…
Reference in New Issue
Block a user