Moved the logic in the make_txn_form_from_post() utility to the constructor of the transaction form, and moved the logic in the make_txn_form_from_status() utility to the txn_form view, and applied the standardized control flow to the txn_form view in the accounting application.

This commit is contained in:
依瑪貓 2020-08-12 20:42:31 +08:00
parent 5e8e8e815e
commit 0996fa59f8
3 changed files with 57 additions and 72 deletions

View File

@ -34,7 +34,7 @@ class RecordForm(forms.Form):
"""An accounting record form. """An accounting record form.
Attributes: Attributes:
transaction (Transaction|None): The current transaction or None. txn_form (TransactionForm): The parent transaction form.
is_credit (bool): Whether this is a credit record. is_credit (bool): Whether this is a credit record.
""" """
id = forms.IntegerField( id = forms.IntegerField(
@ -64,7 +64,7 @@ class RecordForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.transaction = None self.txn_form = None
self.is_credit = None self.is_credit = None
def account_title(self): def account_title(self):
@ -109,7 +109,7 @@ class RecordForm(forms.Form):
""" """
if "id" in self.errors: if "id" in self.errors:
return return
if self.transaction is None: if self.txn_form.transaction is None:
if "id" in self.data: if "id" in self.data:
raise forms.ValidationError( raise forms.ValidationError(
_("This record is not for this transaction."), _("This record is not for this transaction."),
@ -117,7 +117,7 @@ class RecordForm(forms.Form):
else: else:
if "id" in self.data: if "id" in self.data:
record = Record.objects.get(pk=self.data["id"]) record = Record.objects.get(pk=self.data["id"])
if record.transaction.pk != self.transaction.pk: if record.transaction.pk != self.txn_form.transaction.pk:
raise forms.ValidationError( raise forms.ValidationError(
_("This record is not for this transaction."), _("This record is not for this transaction."),
code="not_belong") code="not_belong")
@ -192,10 +192,45 @@ class TransactionForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.txn_type = None # Populates the belonging record forms
self.transaction = None
self.debit_records = [] self.debit_records = []
self.credit_records = [] self.credit_records = []
if len(args) > 0 and isinstance(args[0], dict):
by_rec_id = {}
for key in args[0].keys():
m = re.match(
("^((debit|credit)-([1-9][0-9]*))-"
"(id|ord|account|summary|amount)$"),
key)
if m is None:
continue
rec_id = m.group(1)
column = m.group(4)
if rec_id not in by_rec_id:
by_rec_id[rec_id] = {
"is_credit": m.group(2) == "credit",
"no": int(m.group(3)),
"data": {},
}
by_rec_id[rec_id]["data"][column] = args[0][key]
debit_data_list = [x for x in by_rec_id.values()
if not x["is_credit"]]
debit_data_list.sort(key=lambda x: x["no"])
for x in debit_data_list:
record_form = RecordForm(x["data"])
record_form.txn_form = self
record_form.is_credit = False
self.debit_records.append(record_form)
credit_data_list = [x for x in by_rec_id.values()
if x["is_credit"]]
credit_data_list.sort(key=lambda x: x["no"])
for x in credit_data_list:
record_form = RecordForm(x["data"])
record_form.txn_form = self
record_form.is_credit = True
self.credit_records.append(record_form)
self.txn_type = None
self.transaction = None
def clean(self): def clean(self):
"""Validates the form globally. """Validates the form globally.

View File

@ -641,7 +641,7 @@ def make_txn_form_from_model(txn_type, txn):
except ObjectDoesNotExist: except ObjectDoesNotExist:
pass pass
record_form = RecordForm(data) record_form = RecordForm(data)
record_form.transaction = form.transaction record_form.txn_form = form
record_form.is_credit = record.is_credit record_form.is_credit = record.is_credit
if record.is_credit: if record.is_credit:
form.credit_records.append(record_form) form.credit_records.append(record_form)
@ -650,62 +650,6 @@ def make_txn_form_from_model(txn_type, txn):
return form return form
def make_txn_form_from_post(post, txn_type, txn):
"""Converts the POSTed data to a transaction form.
Args:
post (dict[str]): The POSTed data.
txn_type (str): The transaction type.
txn (Transaction|None): The current transaction, or None
if there is no current transaction.
Returns:
TransactionForm: The transaction form.
"""
form = TransactionForm(
{x: post[x] for x in ("date", "notes") if x in post})
form.transaction = txn
form.txn_type = txn_type
# The records
max_no = _find_max_record_no(txn_type, post)
for record_type in max_no.keys():
records = []
is_credit = (record_type == "credit")
for i in range(max_no[record_type]):
no = i + 1
record_form = RecordForm(
{x: post[F"{record_type}-{no}-{x}"]
for x in ["id", "account", "summary", "amount"]
if F"{record_type}-{no}-{x}" in post})
record_form.transaction = form.transaction
record_form.is_credit = is_credit
records.append(record_form)
if record_type == "debit":
form.debit_records = records
else:
form.credit_records = records
return form
def make_txn_form_from_status(request, txn_type, txn):
"""Converts the previously-stored status to a transaction form.
Args:
request (HttpRequest): The request.
txn_type (str): The transaction type.
txn (Transaction|None): The current transaction, or None
if there is no current transaction.
Returns:
TransactionForm: The transaction form, or None if there is no
previously-stored status.
"""
form = stored_post.get_previous_post(request)
if form is None:
return None
return make_txn_form_from_post(form, txn_type, txn)
def _find_max_record_no(txn_type, 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.

View File

@ -820,14 +820,17 @@ def txn_form(request, txn_type, txn=None):
Returns: Returns:
HttpResponse: The response. HttpResponse: The response.
""" """
form = utils.make_txn_form_from_status(request, txn_type, txn) previous_post = stored_post.get_previous_post(request)
if form is None: if previous_post is not None:
if txn is None: form = TransactionForm(previous_post)
elif txn is not None:
form = utils.make_txn_form_from_model(txn_type, txn)
else:
form = TransactionForm() form = TransactionForm()
form.debit_records.append(RecordForm()) form.debit_records.append(RecordForm())
form.credit_records.append(RecordForm()) form.credit_records.append(RecordForm())
else: form.transaction = txn
form = utils.make_txn_form_from_model(txn_type, txn) form.txn_type = txn_type
new_record_context = {"record": RecordForm(), new_record_context = {"record": RecordForm(),
"record_type": "TTT", "record_type": "TTT",
"no": "NNN", "no": "NNN",
@ -863,7 +866,10 @@ def txn_store(request, txn_type, txn=None):
post = request.POST.dict() post = request.POST.dict()
strip_post(post) strip_post(post)
utils.sort_post_txn_records(post) utils.sort_post_txn_records(post)
form = utils.make_txn_form_from_post(post, txn_type, txn) form = TransactionForm(post)
form.transaction = txn
form.txn_type = txn_type
#form = utils.make_txn_form_from_post(post, txn_type, txn)
if not form.is_valid(): if not form.is_valid():
if txn is None: if txn is None:
url = reverse("accounting:transactions.create", args=(txn_type,)) url = reverse("accounting:transactions.create", args=(txn_type,))