diff --git a/accounting/forms.py b/accounting/forms.py index eff5f10..2ebea65 100644 --- a/accounting/forms.py +++ b/accounting/forms.py @@ -34,7 +34,7 @@ class RecordForm(forms.Form): """An accounting record form. 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. """ id = forms.IntegerField( @@ -64,7 +64,7 @@ class RecordForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.transaction = None + self.txn_form = None self.is_credit = None def account_title(self): @@ -109,7 +109,7 @@ class RecordForm(forms.Form): """ if "id" in self.errors: return - if self.transaction is None: + if self.txn_form.transaction is None: if "id" in self.data: raise forms.ValidationError( _("This record is not for this transaction."), @@ -117,7 +117,7 @@ class RecordForm(forms.Form): else: if "id" in self.data: 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( _("This record is not for this transaction."), code="not_belong") @@ -192,10 +192,45 @@ class TransactionForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.txn_type = None - self.transaction = None + # Populates the belonging record forms self.debit_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): """Validates the form globally. diff --git a/accounting/utils.py b/accounting/utils.py index 95adc5b..b3bd107 100644 --- a/accounting/utils.py +++ b/accounting/utils.py @@ -641,7 +641,7 @@ def make_txn_form_from_model(txn_type, txn): except ObjectDoesNotExist: pass record_form = RecordForm(data) - record_form.transaction = form.transaction + record_form.txn_form = form record_form.is_credit = record.is_credit if record.is_credit: form.credit_records.append(record_form) @@ -650,62 +650,6 @@ def make_txn_form_from_model(txn_type, txn): 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): """Finds the max debit and record numbers from the POSTed form. diff --git a/accounting/views.py b/accounting/views.py index 59d59ab..edbc804 100644 --- a/accounting/views.py +++ b/accounting/views.py @@ -820,14 +820,17 @@ def txn_form(request, txn_type, txn=None): Returns: HttpResponse: The response. """ - form = utils.make_txn_form_from_status(request, txn_type, txn) - if form is None: - if txn is None: - form = TransactionForm() - form.debit_records.append(RecordForm()) - form.credit_records.append(RecordForm()) - else: - form = utils.make_txn_form_from_model(txn_type, txn) + previous_post = stored_post.get_previous_post(request) + if previous_post is not None: + form = TransactionForm(previous_post) + elif txn is not None: + form = utils.make_txn_form_from_model(txn_type, txn) + else: + form = TransactionForm() + form.debit_records.append(RecordForm()) + form.credit_records.append(RecordForm()) + form.transaction = txn + form.txn_type = txn_type new_record_context = {"record": RecordForm(), "record_type": "TTT", "no": "NNN", @@ -863,7 +866,10 @@ def txn_store(request, txn_type, txn=None): post = request.POST.dict() strip_post(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 txn is None: url = reverse("accounting:transactions.create", args=(txn_type,))