Replaced the function-based txn_form and txn_store view with the class-based TransactionFormView in the accounting application.
This commit is contained in:
parent
60b3dfa33c
commit
0d38cdd403
@ -152,6 +152,8 @@ class Transaction(DirtyFieldsMixin, models.Model):
|
|||||||
self._records = None
|
self._records = None
|
||||||
self._is_balanced = None
|
self._is_balanced = None
|
||||||
self._has_order_hole = None
|
self._has_order_hole = None
|
||||||
|
self.old_date = None
|
||||||
|
self.current_user = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Returns the string representation of this accounting
|
"""Returns the string representation of this accounting
|
||||||
@ -190,17 +192,16 @@ class Transaction(DirtyFieldsMixin, models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def save(self, current_user=None, old_date: datetime.date = None,
|
def save(self, force_insert=False, force_update=False, using=None,
|
||||||
force_insert=False, force_update=False, using=None,
|
|
||||||
update_fields=None):
|
update_fields=None):
|
||||||
# When the date is changed, the orders of the transactions in the same
|
# When the date is changed, the orders of the transactions in the same
|
||||||
# day need to be reordered
|
# day need to be reordered
|
||||||
txn_to_sort = []
|
txn_to_sort = []
|
||||||
if self.date != old_date:
|
if self.date != self.old_date:
|
||||||
if old_date is not None:
|
if self.old_date is not None:
|
||||||
txn_same_day = list(
|
txn_same_day = list(
|
||||||
Transaction.objects
|
Transaction.objects
|
||||||
.filter(Q(date=old_date), ~Q(pk=self.pk))
|
.filter(Q(date=self.old_date), ~Q(pk=self.pk))
|
||||||
.order_by("ord"))
|
.order_by("ord"))
|
||||||
for i in range(len(txn_same_day)):
|
for i in range(len(txn_same_day)):
|
||||||
if txn_same_day[i].ord != i + 1:
|
if txn_same_day[i].ord != i + 1:
|
||||||
@ -215,18 +216,18 @@ class Transaction(DirtyFieldsMixin, models.Model):
|
|||||||
# Applies the created by and updated by
|
# Applies the created by and updated by
|
||||||
if self.pk is None:
|
if self.pk is None:
|
||||||
self.pk = new_pk(Transaction)
|
self.pk = new_pk(Transaction)
|
||||||
if current_user is not None:
|
if self.current_user is not None:
|
||||||
self.created_by = current_user
|
self.created_by = self.current_user
|
||||||
if current_user is not None:
|
if self.current_user is not None:
|
||||||
self.updated_by = current_user
|
self.updated_by = self.current_user
|
||||||
to_save = [x for x in self.records if x.is_dirty()]
|
to_save = [x for x in self.records if x.is_dirty()]
|
||||||
for record in to_save:
|
for record in to_save:
|
||||||
if record.pk is None:
|
if record.pk is None:
|
||||||
record.pk = new_pk(Record)
|
record.pk = new_pk(Record)
|
||||||
if current_user is not None:
|
if self.current_user is not None:
|
||||||
record.created_by = current_user
|
record.created_by = self.current_user
|
||||||
if current_user is not None:
|
if self.current_user is not None:
|
||||||
record.updated_by = current_user
|
record.updated_by = self.current_user
|
||||||
# Runs the update
|
# Runs the update
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
super().save(force_insert=force_insert, force_update=force_update,
|
super().save(force_insert=force_insert, force_update=force_update,
|
||||||
|
@ -72,7 +72,7 @@ First written: 2020/7/23
|
|||||||
<i class="fas fa-chevron-circle-left"></i>
|
<i class="fas fa-chevron-circle-left"></i>
|
||||||
{{ _("Back")|force_escape }}
|
{{ _("Back")|force_escape }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-primary" role="button" href="{% url "accounting:transactions.edit" "expense" txn as url %}{% url_keep_return url %}">
|
<a class="btn btn-primary" role="button" href="{% url "accounting:transactions.update" "expense" txn as url %}{% url_keep_return url %}">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
{{ _("Edit")|force_escape }}
|
{{ _("Edit")|force_escape }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -72,7 +72,7 @@ First written: 2020/7/23
|
|||||||
<i class="fas fa-chevron-circle-left"></i>
|
<i class="fas fa-chevron-circle-left"></i>
|
||||||
{{ _("Back")|force_escape }}
|
{{ _("Back")|force_escape }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-primary" role="button" href="{% url "accounting:transactions.edit" "income" txn as url %}{% url_keep_return url %}">
|
<a class="btn btn-primary" role="button" href="{% url "accounting:transactions.update" "income" txn as url %}{% url_keep_return url %}">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
{{ _("Edit")|force_escape }}
|
{{ _("Edit")|force_escape }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -72,7 +72,7 @@ First written: 2020/7/23
|
|||||||
<i class="fas fa-chevron-circle-left"></i>
|
<i class="fas fa-chevron-circle-left"></i>
|
||||||
{{ _("Back")|force_escape }}
|
{{ _("Back")|force_escape }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-primary" role="button" href="{% url "accounting:transactions.edit" "transfer" txn as url %}{% url_keep_return url %}">
|
<a class="btn btn-primary" role="button" href="{% url "accounting:transactions.update" "transfer" txn as url %}{% url_keep_return url %}">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
{{ _("Edit")|force_escape }}
|
{{ _("Edit")|force_escape }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -56,7 +56,7 @@ First written: 2020/7/23
|
|||||||
<input id="account-option-url" type="hidden" value="{% url "accounting:api.accounts.options" %}" />
|
<input id="account-option-url" type="hidden" value="{% url "accounting:api.accounts.options" %}" />
|
||||||
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
|
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
|
||||||
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
|
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
|
||||||
<form id="txn-form" action="{% if form.transaction %}{% url "accounting:transactions.update" "expense" form.transaction as url %}{% url_keep_return url %}{% else %}{% url "accounting:transactions.store" "expense" as url %}{% url_keep_return url %}{% endif %}" method="post">
|
<form id="txn-form" action="{% if form.transaction %}{% url "accounting:transactions.update" "expense" form.transaction as url %}{% url_keep_return url %}{% else %}{% url "accounting:transactions.create" "expense" as url %}{% url_keep_return url %}{% endif %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
@ -56,7 +56,7 @@ First written: 2020/7/23
|
|||||||
<input id="account-option-url" type="hidden" value="{% url "accounting:api.accounts.options" %}" />
|
<input id="account-option-url" type="hidden" value="{% url "accounting:api.accounts.options" %}" />
|
||||||
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
|
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
|
||||||
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
|
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
|
||||||
<form id="txn-form" action="{% if form.transaction %}{% url "accounting:transactions.update" "income" form.transaction as url %}{% url_keep_return url %}{% else %}{% url "accounting:transactions.store" "income" as url %}{% url_keep_return url %}{% endif %}" method="post">
|
<form id="txn-form" action="{% if form.transaction %}{% url "accounting:transactions.update" "income" form.transaction as url %}{% url_keep_return url %}{% else %}{% url "accounting:transactions.create" "income" as url %}{% url_keep_return url %}{% endif %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
@ -56,7 +56,7 @@ First written: 2020/7/23
|
|||||||
<input id="account-option-url" type="hidden" value="{% url "accounting:api.accounts.options" %}" />
|
<input id="account-option-url" type="hidden" value="{% url "accounting:api.accounts.options" %}" />
|
||||||
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
|
<input id="summary-categories" type="hidden" value="{{ summary_categories }}" />
|
||||||
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
|
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
|
||||||
<form id="txn-form" action="{% if form.transaction %}{% url "accounting:transactions.update" "transfer" form.transaction as url %}{% url_keep_return url %}{% else %}{% url "accounting:transactions.store" "transfer" as url %}{% url_keep_return url %}{% endif %}" method="post">
|
<form id="txn-form" action="{% if form.transaction %}{% url "accounting:transactions.update" "transfer" form.transaction as url %}{% url_keep_return url %}{% else %}{% url "accounting:transactions.create" "transfer" as url %}{% url_keep_return url %}{% endif %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
@ -76,15 +76,11 @@ urlpatterns = [
|
|||||||
path("search",
|
path("search",
|
||||||
views.search, name="search"),
|
views.search, name="search"),
|
||||||
path("transactions/<txn-type:txn_type>/create",
|
path("transactions/<txn-type:txn_type>/create",
|
||||||
views.txn_form, name="transactions.create"),
|
views.TransactionFormView.as_view(), name="transactions.create"),
|
||||||
path("transactions/<txn-type:txn_type>/store",
|
|
||||||
views.txn_store, name="transactions.store"),
|
|
||||||
path("transactions/<txn-type:txn_type>/<txn:txn>",
|
path("transactions/<txn-type:txn_type>/<txn:txn>",
|
||||||
views.TransactionView.as_view(), name="transactions.detail"),
|
views.TransactionView.as_view(), name="transactions.detail"),
|
||||||
path("transactions/<txn-type:txn_type>/<txn:txn>/edit",
|
|
||||||
views.txn_form, name="transactions.edit"),
|
|
||||||
path("transactions/<txn-type:txn_type>/<txn:txn>/update",
|
path("transactions/<txn-type:txn_type>/<txn:txn>/update",
|
||||||
views.txn_store, name="transactions.update"),
|
views.TransactionFormView.as_view(), name="transactions.update"),
|
||||||
path("transactions/<txn:txn>/delete",
|
path("transactions/<txn:txn>/delete",
|
||||||
views.TransactionDeleteView.as_view(), name="transactions.delete"),
|
views.TransactionDeleteView.as_view(), name="transactions.delete"),
|
||||||
path("transactions/sort/<date:date>",
|
path("transactions/sort/<date:date>",
|
||||||
|
@ -812,84 +812,60 @@ class TransactionView(DetailView):
|
|||||||
% (self.kwargs["txn_type"],)]
|
% (self.kwargs["txn_type"],)]
|
||||||
|
|
||||||
|
|
||||||
@require_GET
|
@method_decorator(login_required, name="dispatch")
|
||||||
@login_required
|
class TransactionFormView(FormView):
|
||||||
def txn_form(request: HttpRequest, txn_type: str,
|
"""The form to create or update an accounting transaction."""
|
||||||
txn: Transaction = None) -> HttpResponse:
|
model = Transaction
|
||||||
"""The view to edit an accounting transaction.
|
form_class = TransactionForm
|
||||||
|
not_modified_message = gettext_noop("This transaction was not modified.")
|
||||||
|
success_message = gettext_noop("This transaction was saved successfully.")
|
||||||
|
|
||||||
Args:
|
def get_context_data(self, **kwargs):
|
||||||
request: The request.
|
"""Returns the context data for the template."""
|
||||||
txn_type: The transaction type.
|
context = super().get_context_data(**kwargs)
|
||||||
txn: The transaction.
|
context["summary_categories"] = utils.get_summary_categories()
|
||||||
|
context["new_record_template"] = self._get_new_record_template_json()
|
||||||
|
return context
|
||||||
|
|
||||||
Returns:
|
def get_template_name(self) -> str:
|
||||||
The response.
|
"""Returns the name of the template."""
|
||||||
"""
|
namespace = self.request.resolver_match.namespace
|
||||||
previous_post = stored_post.get_previous_post(request)
|
model_name = self.model.__name__.lower()
|
||||||
if previous_post is not None:
|
return F"{namespace}/{model_name}_form-{self.txn_type}.html"
|
||||||
form = TransactionForm(previous_post)
|
|
||||||
elif txn is not None:
|
|
||||||
form = utils.make_txn_form_from_model(txn_type, txn)
|
|
||||||
else:
|
|
||||||
form = TransactionForm()
|
|
||||||
form.transaction = txn
|
|
||||||
form.txn_type = txn_type
|
|
||||||
new_record_context = {"record_type": "TTT", "no": "NNN"}
|
|
||||||
if txn_type == "transfer":
|
|
||||||
new_record_template = json.dumps(render_to_string(
|
|
||||||
"accounting/include/record_form-transfer.html",
|
|
||||||
new_record_context))
|
|
||||||
else:
|
|
||||||
new_record_template = json.dumps(render_to_string(
|
|
||||||
"accounting/include/record_form-non-transfer.html",
|
|
||||||
new_record_context))
|
|
||||||
return render(request, F"accounting/transaction_form-{txn_type}.html", {
|
|
||||||
"form": form,
|
|
||||||
"summary_categories": utils.get_summary_categories,
|
|
||||||
"new_record_template": new_record_template,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
def _get_new_record_template_json(self) -> str:
|
||||||
|
context = {"record_type": "TTT", "no": "NNN"}
|
||||||
|
template_name = "accounting/include/record_form-transfer.html"\
|
||||||
|
if self.txn_type == "transfer"\
|
||||||
|
else "accounting/include/record_form-non-transfer.html"
|
||||||
|
return json.dumps(render_to_string(template_name, context))
|
||||||
|
|
||||||
@require_POST
|
def make_form_from_post(self, post: Dict[str, str]) -> TransactionForm:
|
||||||
@login_required
|
"""Creates and returns the form from the POST data."""
|
||||||
def txn_store(request: HttpRequest, txn_type: str,
|
form = TransactionForm(post)
|
||||||
txn: Transaction = None) -> HttpResponseRedirect:
|
form.txn_type = self.txn_type
|
||||||
"""The view to store an accounting transaction.
|
form.transaction = self.get_object()
|
||||||
|
return form
|
||||||
|
|
||||||
Args:
|
def make_form_from_model(self, obj: Transaction) -> TransactionForm:
|
||||||
request: The request.
|
"""Creates and returns the form from a data model."""
|
||||||
txn_type: The transaction type.
|
return utils.make_txn_form_from_model(self.txn_type, obj)
|
||||||
txn: The transaction.
|
|
||||||
|
|
||||||
Returns:
|
def fill_model_from_form(self, obj: Transaction,
|
||||||
The response.
|
form: TransactionForm) -> None:
|
||||||
"""
|
"""Fills in the data model from the form."""
|
||||||
post = request.POST.dict()
|
obj.old_date = obj.date
|
||||||
strip_post(post)
|
utils.fill_txn_from_post(self.txn_type, obj, form.data)
|
||||||
utils.sort_post_txn_records(post)
|
obj.current_user = self.request.user
|
||||||
form = TransactionForm(post)
|
|
||||||
form.transaction = txn
|
def get_object(self) -> Optional[Account]:
|
||||||
form.txn_type = txn_type
|
"""Returns the current object, or None on a create form."""
|
||||||
if not form.is_valid():
|
return self.kwargs.get("txn")
|
||||||
if txn is None:
|
|
||||||
url = reverse("accounting:transactions.create", args=(txn_type,))
|
@property
|
||||||
else:
|
def txn_type(self) -> str:
|
||||||
url = reverse("accounting:transactions.edit", args=(txn_type, txn))
|
"""Returns the transaction type of this form"""
|
||||||
url = str(UrlBuilder(url).query(r=request.GET.get("r")))
|
return self.kwargs["txn_type"]
|
||||||
return stored_post.error_redirect(request, url, post)
|
|
||||||
if txn is None:
|
|
||||||
txn = Transaction()
|
|
||||||
old_date = txn.date
|
|
||||||
utils.fill_txn_from_post(txn_type, txn, post)
|
|
||||||
if not txn.is_dirty(check_relationship=True):
|
|
||||||
message = gettext_noop("This transaction was not modified.")
|
|
||||||
else:
|
|
||||||
txn.save(current_user=request.user, old_date=old_date)
|
|
||||||
message = gettext_noop("This transaction was saved successfully.")
|
|
||||||
messages.success(request, message)
|
|
||||||
url = reverse("accounting:transactions.detail", args=(txn_type, txn))
|
|
||||||
return redirect(str(UrlBuilder(url).query(r=request.GET.get("r"))))
|
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(require_POST, name="dispatch")
|
@method_decorator(require_POST, name="dispatch")
|
||||||
|
Loading…
Reference in New Issue
Block a user