Fixed the txn_edit() and txn_store() views to work with cash income and cash expense transactions in the accounting application.

This commit is contained in:
依瑪貓 2020-08-02 14:29:45 +08:00
parent a78cbb2ad8
commit 6f444442b1
2 changed files with 46 additions and 27 deletions

View File

@ -21,6 +21,7 @@
import re import re
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Sum, Case, When, F, Count, Max, Min from django.db.models import Q, Sum, Case, When, F, Count, Max, Min
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
@ -283,11 +284,12 @@ def find_order_holes(records):
record.has_order_hole = record.transaction.date in holes record.has_order_hole = record.transaction.date in holes
def fill_txn_from_post(txn, post): def fill_txn_from_post(txn_type, txn, post):
"""Fills the transaction from the POSTed data. The POSTed data must be """Fills the transaction from the POSTed data. The POSTed data must be
validated and clean at this moment. validated and clean at this moment.
Args: Args:
txn_type (str): The transaction type.
txn (Transaction): The transaction. txn (Transaction): The transaction.
post (dict): The POSTed data. post (dict): The POSTed data.
""" """
@ -297,7 +299,7 @@ def fill_txn_from_post(txn, post):
else: else:
txn.notes = None txn.notes = None
# The records # The records
max_no = _find_max_record_no(post) max_no = _find_max_record_no(txn_type, post)
records = [] records = []
for record_type in max_no.keys(): for record_type in max_no.keys():
for i in range(max_no[record_type]): for i in range(max_no[record_type]):
@ -315,7 +317,18 @@ def fill_txn_from_post(txn, post):
record.summary = post[F"{record_type}-{no}-summary"] record.summary = post[F"{record_type}-{no}-summary"]
else: else:
record.summary = None record.summary = None
record.amount = post[F"{record_type}-{no}-amount"] record.amount = int(post[F"{record_type}-{no}-amount"])
records.append(record)
if txn_type != "transfer":
if txn_type == "expense":
record = txn.credit_records[0]
else:
record = txn.debit_records[0]
record.ord = 1
# TODO: Store 1111 in the settings file
record.account = Account.objects.get(code="1111")
record.summary = None
record.amount = sum([x.amount for x in records])
records.append(record) records.append(record)
txn.records = records txn.records = records
@ -373,12 +386,12 @@ def sort_post_txn_records(post):
post[key] = new_post[key] post[key] = new_post[key]
def make_txn_form_from_model(txn, exists): def make_txn_form_from_model(txn_type, txn):
"""Converts a transaction data model to a transaction form. """Converts a transaction data model to a transaction form.
Args: Args:
txn_type (str): The transaction type.
txn (Transaction): The transaction data model. txn (Transaction): The transaction data model.
exists (bool): Whether the current transaction exists.
Returns: Returns:
TransactionForm: The transaction form. TransactionForm: The transaction form.
@ -386,15 +399,21 @@ def make_txn_form_from_model(txn, exists):
form = TransactionForm( form = TransactionForm(
{x: str(getattr(txn, x)) for x in ["date", "notes"] {x: str(getattr(txn, x)) for x in ["date", "notes"]
if getattr(txn, x) is not None}) if getattr(txn, x) is not None})
form.transaction = txn if exists else None form.transaction = txn if txn.pk is not None else None
for record in txn.records: records = []
if txn_type != "income":
records = records + txn.debit_records
if txn_type != "expense":
records = records + txn.credit_records
for record in records:
data = {x: getattr(record, x) data = {x: getattr(record, x)
for x in ["summary", "amount"] for x in ["summary", "amount"]
if getattr(record, x) is not None} if getattr(record, x) is not None}
if record.pk is not None:
data["id"] = record.pk data["id"] = record.pk
try: try:
data["account"] = record.account.code data["account"] = record.account.code
except AttributeError: except ObjectDoesNotExist:
pass pass
record_form = RecordForm(data) record_form = RecordForm(data)
record_form.transaction = form.transaction record_form.transaction = form.transaction
@ -423,11 +442,7 @@ def make_txn_form_from_post(post, txn_type, txn):
form.transaction = txn form.transaction = txn
form.txn_type = txn_type form.txn_type = txn_type
# The records # The records
max_no = _find_max_record_no(post) max_no = _find_max_record_no(txn_type, post)
if max_no["debit"] == 0:
max_no["debit"] = 1
if max_no["credit"] == 0:
max_no["credit"] = 1
for record_type in max_no.keys(): for record_type in max_no.keys():
records = [] records = []
is_credit = (record_type == "credit") is_credit = (record_type == "credit")
@ -469,26 +484,31 @@ def make_txn_form_from_status(request, txn_type, txn):
status["form"], txn_type, txn) status["form"], txn_type, txn)
def _find_max_record_no(post): def _find_max_record_no(txn_type, post):
"""Finds the max debit and record numbers from the POSTed form. """Finds the max debit and record numbers from the POSTed form.
Args: Args:
txn_type (str): The transaction type.
post (dict[str,str]): The POSTed data. post (dict[str,str]): The POSTed data.
Returns: Returns:
dict[str,int]: The max debit and record numbers from the POSTed form. dict[str,int]: The max debit and record numbers from the POSTed form.
""" """
max_no = { max_no = {}
"debit": 0, if txn_type != "credit":
"credit": 0, max_no["debit"] = 0
} if txn_type != "debit":
max_no["credit"] = 0
for key in post.keys(): for key in post.keys():
m = re.match( m = re.match(
"^(debit|credit)-([1-9][0-9]*)-(id|ord|account|summary|amount)$", "^(debit|credit)-([1-9][0-9]*)-(id|ord|account|summary|amount)$",
key) key)
if m is not None: if m is None:
continue
record_type = m.group(1) record_type = m.group(1)
if record_type not in max_no:
continue
no = int(m.group(2)) no = int(m.group(2))
if max_no[record_type] < no: if max_no[record_type] < no:
max_no[record_type] = no max_no[record_type] = no

View File

@ -825,14 +825,13 @@ def txn_edit(request, txn_type, txn=None):
""" """
form = make_txn_form_from_status(request, txn_type, txn) form = make_txn_form_from_status(request, txn_type, txn)
if form is None: if form is None:
exists = txn is not None
if txn is None: if txn is None:
txn = Transaction(date=timezone.localdate()) txn = Transaction(date=timezone.localdate())
if len(txn.debit_records) == 0: if len(txn.debit_records) == 0:
txn.records.append(Record(ord=1, is_credit=False)) txn.records.append(Record(ord=1, is_credit=False))
if len(txn.credit_records) == 0: if len(txn.credit_records) == 0:
txn.records.append(Record(ord=1, is_credit=True)) txn.records.append(Record(ord=1, is_credit=True))
form = make_txn_form_from_model(txn, exists) form = make_txn_form_from_model(txn_type, txn)
return render(request, F"accounting/transactions/{txn_type}/form.html", { return render(request, F"accounting/transactions/{txn_type}/form.html", {
"item": form, "item": form,
}) })
@ -864,7 +863,7 @@ def txn_store(request, txn_type, txn=None):
return error_redirect(request, url, post) return error_redirect(request, url, post)
if txn is None: if txn is None:
txn = Transaction() txn = Transaction()
fill_txn_from_post(txn, post) fill_txn_from_post(txn_type, txn, post)
if not txn.is_dirty(): if not txn.is_dirty():
url = reverse("accounting:transactions.show", args=(txn_type, txn)) url = reverse("accounting:transactions.show", args=(txn_type, txn))
url = str(UrlBuilder(url).set("r", request.GET.get("r"))) url = str(UrlBuilder(url).set("r", request.GET.get("r")))