Replaced the function-based account_form and account_store views with the class-based AccountFormView in the accounting application.

This commit is contained in:
依瑪貓 2020-08-14 00:36:29 +08:00
parent 95b6a6a4ea
commit f82c4afbfe
3 changed files with 48 additions and 71 deletions

View File

@ -63,21 +63,22 @@ class Account(DirtyFieldsMixin, models.Model):
self.is_for_credit = None self.is_for_credit = None
self._is_in_use = None self._is_in_use = None
self._is_parent_and_in_use = None self._is_parent_and_in_use = None
self.current_user = None
def __str__(self): def __str__(self):
"""Returns the string representation of this account.""" """Returns the string representation of this account."""
return self.code.__str__() + " " + self.title return self.code.__str__() + " " + self.title
def save(self, current_user=None, force_insert=False, force_update=False, def save(self, force_insert=False, force_update=False, using=None,
using=None, update_fields=None): update_fields=None):
self.parent = None if len(self.code) == 1\ self.parent = None if len(self.code) == 1\
else Account.objects.get(code=self.code[:-1]) else Account.objects.get(code=self.code[:-1])
if self.pk is None: if self.pk is None:
self.pk = new_pk(Account) self.pk = new_pk(Account)
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
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,
using=using, update_fields=update_fields) using=using, update_fields=update_fields)

View File

@ -92,9 +92,9 @@ urlpatterns = [
path("accounts", path("accounts",
views.AccountListView.as_view(), name="accounts"), views.AccountListView.as_view(), name="accounts"),
path("accounts/create", path("accounts/create",
views.account_form, name="accounts.create"), views.AccountFormView.as_view(), name="accounts.create"),
path("accounts/store", path("accounts/store",
views.account_store, name="accounts.store"), views.AccountFormView.as_view(), name="accounts.store"),
path("api/accounts", path("api/accounts",
views.api_account_list, name="api.accounts"), views.api_account_list, name="api.accounts"),
path("api/accounts/options", path("api/accounts/options",
@ -102,9 +102,9 @@ urlpatterns = [
path("accounts/<account:account>", path("accounts/<account:account>",
views.AccountView.as_view(), name="accounts.detail"), views.AccountView.as_view(), name="accounts.detail"),
path("accounts/<account:account>/edit", path("accounts/<account:account>/edit",
views.account_form, name="accounts.edit"), views.AccountFormView.as_view(), name="accounts.edit"),
path("accounts/<account:account>/update", path("accounts/<account:account>/update",
views.account_store, name="accounts.update"), views.AccountFormView.as_view(), name="accounts.update"),
path("accounts/<account:account>/delete", path("accounts/<account:account>/delete",
views.account_delete, name="accounts.delete"), views.account_delete, name="accounts.delete"),
] ]

View File

@ -21,11 +21,12 @@
import datetime import datetime
import json import json
import re import re
from typing import Dict, Optional
from django.contrib import messages from django.contrib import messages
from django.db import transaction from django.db import transaction
from django.db.models import Sum, Case, When, F, Q, Count, BooleanField, \ from django.db.models import Sum, Case, When, F, Q, Count, BooleanField, \
ExpressionWrapper ExpressionWrapper, Exists, OuterRef
from django.db.models.functions import TruncMonth, Coalesce from django.db.models.functions import TruncMonth, Coalesce
from django.http import JsonResponse, HttpResponseRedirect, Http404, \ from django.http import JsonResponse, HttpResponseRedirect, Http404, \
HttpRequest, HttpResponse HttpRequest, HttpResponse
@ -43,7 +44,7 @@ from mia_core.digest_auth import login_required
from mia_core.period import Period from mia_core.period import Period
from mia_core.utils import Pagination, get_multi_lingual_search, UrlBuilder, \ from mia_core.utils import Pagination, get_multi_lingual_search, UrlBuilder, \
strip_post, PaginationException strip_post, PaginationException
from mia_core.views import DeleteView from mia_core.views import DeleteView, FormView
from . import utils from . import utils
from .forms import AccountForm, TransactionForm from .forms import AccountForm, TransactionForm
from .models import Record, Transaction, Account from .models import Record, Transaction, Account
@ -965,10 +966,9 @@ def txn_sort(request: HttpRequest, date: datetime.date) -> HttpResponse:
class AccountListView(ListView): class AccountListView(ListView):
"""The view to list the accounts.""" """The view to list the accounts."""
queryset = Account.objects\ queryset = Account.objects\
.annotate(child_count=Count("child_set"),
record_count=Count("record"))\
.annotate(is_parent_and_in_use=ExpressionWrapper( .annotate(is_parent_and_in_use=ExpressionWrapper(
Q(child_count__gt=0) & Q(record_count__gt=0), Exists(Account.objects.filter(parent=OuterRef("pk")))
& Exists(Record.objects.filter(account=OuterRef("pk"))),
output_field=BooleanField()))\ output_field=BooleanField()))\
.order_by("code") .order_by("code")
@ -981,69 +981,45 @@ class AccountView(DetailView):
return self.request.resolver_match.kwargs["account"] return self.request.resolver_match.kwargs["account"]
@require_GET @method_decorator(login_required, name="dispatch")
@login_required class AccountFormView(FormView):
def account_form(request: HttpRequest, model = Account
account: Account = None) -> HttpResponse: form = AccountForm
"""The view to edit an accounting transaction. not_modified_message = gettext_noop("This account was not modified.")
success_message = gettext_noop("This account was saved successfully.")
Args: def make_form_from_post(self, post: Dict[str, str]) -> AccountForm:
request: The request. """Creates and returns the form from the POST data."""
account: The account. form = AccountForm(post)
form.account = self.get_current_object()
return form
Returns: def make_form_from_model(self, obj: Account) -> AccountForm:
The response. """Creates and returns the form from a data model."""
"""
previous_post = stored_post.get_previous_post(request)
if previous_post is not None:
form = AccountForm(previous_post)
elif account is not None:
form = AccountForm({ form = AccountForm({
"code": account.code, "code": obj.code,
"title": account.title, "title": obj.title,
}) })
else: form.account = obj
form = AccountForm() return form
form.account = account
return render(request, "accounting/account_form.html", {
"form": form,
})
def fill_model_from_form(self, obj: Account, form: AccountForm) -> None:
"""Fills in the data model from the form."""
obj.code = form["code"].value()
obj.title = form["title"].value()
obj.current_user = self.request.user
@require_POST def get_error_url(self) -> str:
@login_required """Returns the URL on error."""
def account_store(request: HttpRequest, user = self.get_current_object()
account: Account = None) -> HttpResponseRedirect: return reverse("accounting:accounts.create") if user is None\
"""The view to store an account. else reverse("accounting:accounts.edit", args=(user,))
Args: def get_current_object(self) -> Optional[Account]:
request: The request. """Returns the current object, or None on a create form."""
account: The account. if "account" in self.kwargs:
return self.kwargs["account"]
Returns: return None
The response.
"""
post = request.POST.dict()
strip_post(post)
form = AccountForm(post)
form.account = account
if not form.is_valid():
if account is None:
url = reverse("accounting:accounts.create")
else:
url = reverse("accounting:accounts.edit", args=(account,))
return stored_post.error_redirect(request, url, post)
if account is None:
account = Account()
account.code = form["code"].value()
account.title = form["title"].value()
if not account.is_dirty():
message = gettext_noop("This account was not modified.")
else:
account.save(current_user=request.user)
message = gettext_noop("This account was saved successfully.")
messages.success(request, message)
return redirect("accounting:accounts.detail", account)
@require_POST @require_POST