Added _find_imbalanced() and _find_order_holes() methods as shortcuts to tag the accounting records with problems.

This commit is contained in:
依瑪貓 2020-07-16 07:45:16 +08:00
parent 983c2a5533
commit df2c324ce0
3 changed files with 74 additions and 7 deletions

View File

@ -252,6 +252,33 @@ class Record(models.Model):
def balance(self, value): def balance(self, value):
self._balance = value self._balance = value
_is_balanced = None
@property
def is_balanced(self):
"""Whether the transaction of this record is balanced. """
if self._is_balanced is None:
self._is_balanced = self.transaction.is_balanced
return self._is_balanced
@is_balanced.setter
def is_balanced(self, value):
self._is_balanced = value
_has_order_hole = None
@property
def has_order_hole(self):
"""Whether the order of the transactions on this day is not
1, 2, 3, 4, 5..., and should be reordered. """
if self._has_order_hole is None:
self._has_order_hole = self.transaction.has_order_hole
return self._has_order_hole
@has_order_hole.setter
def has_order_hole(self, value):
self._has_order_hole = value
def __str__(self): def __str__(self):
"""Returns the string representation of this accounting """Returns the string representation of this accounting
record.""" record."""

View File

@ -104,15 +104,15 @@ First written: 2020/7/1
</thead> </thead>
<tbody> <tbody>
{% for record in records %} {% for record in records %}
<tr class="{% if not record.transaction.is_balanced or record.transaction.has_order_hole %} table-danger {% endif %}"> <tr class="{% if not record.is_balanced or record.has_order_hole %} table-danger {% endif %}">
<td>{{ record.transaction.date|smart_date }}</td> <td>{{ record.transaction.date|smart_date }}</td>
<td>{{ record.subject.title|title }}</td> <td>{{ record.subject.title|title }}</td>
<td>{{ record.summary|default:"" }}{% if not record.transaction.is_balanced %} <td>{{ record.summary|default:"" }}{% if not record.is_balanced %}
<span class="badge badge-danger badge-pill"> <span class="badge badge-danger badge-pill">
{% trans "Unbalanced" context "Accounting|" as text %} {% trans "Unbalanced" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</span> </span>
{% endif %}{% if record.transaction.has_order_hole %} {% endif %}{% if record.has_order_hole %}
<span class="badge badge-danger badge-pill"> <span class="badge badge-danger badge-pill">
{% trans "Need Reorder" context "Accounting|" as text %} {% trans "Need Reorder" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
@ -137,7 +137,7 @@ First written: 2020/7/1
{# The list for small screens #} {# The list for small screens #}
<ul class="list-group d-md-none"> <ul class="list-group d-md-none">
{% for record in records %} {% for record in records %}
<li class="list-group-item {% if not record.transaction.is_balanced or record.transaction.has_order_hole %} list-group-item-danger {% endif %}"> <li class="list-group-item {% if not record.is_balanced or record.has_order_hole %} list-group-item-danger {% endif %}">
{% if record.sn is not None %} {% if record.sn is not None %}
<a class="list-group-item-action" href="{{ record.transaction.get_absolute_url }}"> <a class="list-group-item-action" href="{{ record.transaction.get_absolute_url }}">
<div class="date-subject-line d-flex justify-content-between align-items-center"> <div class="date-subject-line d-flex justify-content-between align-items-center">
@ -146,13 +146,13 @@ First written: 2020/7/1
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div> <div>
{{ record.summary|default:"" }} {{ record.summary|default:"" }}
{% if not record.transaction.is_balanced %} {% if not record.is_balanced %}
<span class="badge badge-danger badge-pill"> <span class="badge badge-danger badge-pill">
{% trans "Unbalanced" context "Accounting|" as text %} {% trans "Unbalanced" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</span> </span>
{% endif %} {% endif %}
{% if record.transaction.has_order_hole %} {% if record.has_order_hole %}
<span class="badge badge-danger badge-pill"> <span class="badge badge-danger badge-pill">
{% trans "Need Reorder" context "Accounting|" as text %} {% trans "Need Reorder" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}

View File

@ -90,6 +90,43 @@ FROM accounting_subjects AS s
return subjects return subjects
def _find_imbalanced(records):
""""Finds the records with imbalanced transactions, and sets their
is_balanced attribute.
Args:
records (list[Record]): The accounting records.
"""
with connection.cursor() as cursor:
cursor.execute("""SELECT transaction_sn
FROM accounting_records
GROUP BY transaction_sn
HAVING SUM(CASE WHEN is_credit THEN -1 ELSE 1 END * amount) != 0""")
imbalanced = [x[0] for x in cursor.fetchall()]
for record in records:
record.is_balanced = record.transaction.sn not in imbalanced
def _find_order_holes(records):
""""Finds whether the order of the transactions on this day is not
1, 2, 3, 4, 5..., and should be reordered, and sets their
has_order_holes attributes.
Args:
records (list[Record]): The accounting records.
"""
with connection.cursor() as cursor:
cursor.execute("""
SELECT date FROM accounting_transactions
GROUP BY date HAVING COUNT(*)!=MAX(ord)
UNION
SELECT date FROM accounting_transactions
GROUP BY date, ord HAVING COUNT(*) > 1""")
holes = [x[0] for x in cursor.fetchall()]
for record in records:
record.has_order_hole = record.transaction.date in holes
@require_GET @require_GET
@digest_login_required @digest_login_required
def cash(request, subject_code, period_spec): def cash(request, subject_code, period_spec):
@ -221,8 +258,11 @@ ORDER BY
balance=balance_before)) balance=balance_before))
records.append(record_sum) records.append(record_sum)
pagination = Pagination(request, records, True) pagination = Pagination(request, records, True)
records = pagination.records
_find_imbalanced(records)
_find_order_holes(records)
return render(request, "accounting/cash.html", { return render(request, "accounting/cash.html", {
"records": pagination.records, "records": records,
"pagination": pagination, "pagination": pagination,
"current_subject": current_subject, "current_subject": current_subject,
"period": period, "period": period,