699 lines
28 KiB
Python
699 lines
28 KiB
Python
import logging
|
|
from .models import Dealer
|
|
from django.core.exceptions import ImproperlyConfigured,ValidationError
|
|
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
|
|
from django_ledger.forms.bill import (
|
|
BillModelCreateForm,
|
|
BaseBillModelUpdateForm,
|
|
DraftBillModelUpdateForm,
|
|
get_bill_itemtxs_formset_class,
|
|
BillModelConfigureForm,
|
|
InReviewBillModelUpdateForm,
|
|
ApprovedBillModelUpdateForm,
|
|
AccruedAndApprovedBillModelUpdateForm,
|
|
PaidBillModelUpdateForm
|
|
)
|
|
from django.http import HttpResponseForbidden
|
|
from django.utils.html import format_html
|
|
from django.contrib import messages
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import get_object_or_404
|
|
from django.urls import reverse
|
|
from django_ledger.models import ItemTransactionModel
|
|
from django.views.generic.detail import DetailView
|
|
from django_ledger.forms.purchase_order import (ApprovedPurchaseOrderModelUpdateForm,
|
|
BasePurchaseOrderModelUpdateForm,
|
|
DraftPurchaseOrderModelUpdateForm,
|
|
ReviewPurchaseOrderModelUpdateForm,
|
|
get_po_itemtxs_formset_class)
|
|
from django_ledger.views.purchase_order import PurchaseOrderModelModelViewQuerySetMixIn
|
|
from django_ledger.models import PurchaseOrderModel,EstimateModel,BillModel
|
|
from django.views.generic.detail import SingleObjectMixin
|
|
from django.views.generic.edit import UpdateView
|
|
from django.views.generic.base import RedirectView
|
|
from django.views.generic.list import ListView
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
class PurchaseOrderModelUpdateView(LoginRequiredMixin,
|
|
PermissionRequiredMixin,
|
|
UpdateView):
|
|
slug_url_kwarg = 'po_pk'
|
|
slug_field = 'uuid'
|
|
context_object_name = 'po_model'
|
|
template_name = "purchase_orders/po_update.html"
|
|
context_object_name = "po_model"
|
|
permission_required = "django_ledger.change_purchaseordermodel"
|
|
extra_context = {
|
|
'header_subtitle_icon': 'uil:bill'
|
|
}
|
|
action_update_items = False
|
|
queryset = None
|
|
|
|
def get_context_data(self, itemtxs_formset=None, **kwargs):
|
|
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
|
|
context = super().get_context_data(**kwargs)
|
|
context["entity_slug"] = dealer.entity.slug
|
|
po_model: PurchaseOrderModel = self.object
|
|
if not itemtxs_formset:
|
|
itemtxs_qs = self.get_po_itemtxs_qs(po_model)
|
|
itemtxs_qs, itemtxs_agg = po_model.get_itemtxs_data(queryset=itemtxs_qs)
|
|
po_itemtxs_formset_class = get_po_itemtxs_formset_class(po_model)
|
|
itemtxs_formset = po_itemtxs_formset_class(
|
|
entity_slug=dealer.entity.slug,
|
|
user_model=dealer.entity.admin,
|
|
po_model=po_model,
|
|
queryset=itemtxs_qs,
|
|
)
|
|
else:
|
|
itemtxs_qs, itemtxs_agg = po_model.get_itemtxs_data()
|
|
|
|
context["itemtxs_qs"] = itemtxs_qs
|
|
context["itemtxs_formset"] = itemtxs_formset
|
|
return context
|
|
|
|
def get_queryset(self):
|
|
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
|
|
if self.queryset is None:
|
|
self.queryset = PurchaseOrderModel.objects.for_entity(
|
|
entity_slug=self.kwargs['entity_slug'],
|
|
user_model=dealer.entity.admin
|
|
).select_related('entity', 'ce_model')
|
|
return super().get_queryset()
|
|
def get_success_url(self):
|
|
return reverse(
|
|
"purchase_order_update",
|
|
kwargs={
|
|
"dealer_slug": self.kwargs["dealer_slug"],
|
|
"entity_slug": self.kwargs["entity_slug"],
|
|
"po_pk": self.kwargs["po_pk"],
|
|
},
|
|
)
|
|
def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs):
|
|
if self.action_update_items:
|
|
return HttpResponseRedirect(
|
|
redirect_to=reverse(
|
|
"purchase_order_update",
|
|
kwargs={
|
|
"dealer_slug": dealer_slug,
|
|
"entity_slug": entity_slug,
|
|
"po_pk": po_pk,
|
|
},
|
|
)
|
|
)
|
|
return super(PurchaseOrderModelUpdateView, self).get(
|
|
request, dealer_slug, entity_slug, po_pk, *args, **kwargs
|
|
)
|
|
|
|
def post(self, request, dealer_slug, entity_slug, *args, **kwargs):
|
|
if self.action_update_items:
|
|
if not request.user.is_authenticated:
|
|
return HttpResponseForbidden()
|
|
queryset = self.get_queryset()
|
|
po_model: PurchaseOrderModel = self.get_object(queryset=queryset)
|
|
self.object = po_model
|
|
po_itemtxs_formset_class = get_po_itemtxs_formset_class(po_model)
|
|
itemtxs_formset = po_itemtxs_formset_class(
|
|
request.POST,
|
|
user_model=request.dealer.entity.admin,
|
|
po_model=po_model,
|
|
entity_slug=entity_slug,
|
|
)
|
|
|
|
if itemtxs_formset.has_changed():
|
|
if itemtxs_formset.is_valid():
|
|
itemtxs_list = itemtxs_formset.save(commit=False)
|
|
create_bill_uuids = [
|
|
str(i["uuid"].uuid)
|
|
for i in itemtxs_formset.cleaned_data
|
|
if i and i["create_bill"] is True
|
|
]
|
|
|
|
if create_bill_uuids:
|
|
item_uuids = ",".join(create_bill_uuids)
|
|
redirect_url = reverse(
|
|
"bill-create-po",
|
|
kwargs={
|
|
"dealer_slug": self.kwargs["dealer_slug"],
|
|
"entity_slug": self.kwargs["entity_slug"],
|
|
"po_pk": po_model.uuid,
|
|
},
|
|
)
|
|
redirect_url += f"?item_uuids={item_uuids}"
|
|
return HttpResponseRedirect(redirect_url)
|
|
|
|
for itemtxs in itemtxs_list:
|
|
if not itemtxs.po_model_id:
|
|
itemtxs.po_model_id = po_model.uuid
|
|
itemtxs.clean()
|
|
|
|
itemtxs_list = itemtxs_formset.save()
|
|
po_model.update_state()
|
|
po_model.clean()
|
|
po_model.save(
|
|
update_fields=["po_amount", "po_amount_received", "updated"]
|
|
)
|
|
# if valid get saved formset from DB
|
|
messages.add_message(
|
|
request, messages.SUCCESS, "PO items updated successfully."
|
|
)
|
|
return self.render_to_response(context=self.get_context_data())
|
|
# if not valid, return formset with errors...
|
|
return self.render_to_response(
|
|
context=self.get_context_data(itemtxs_formset=itemtxs_formset)
|
|
)
|
|
return super(PurchaseOrderModelUpdateView, self).post(
|
|
request, dealer_slug, entity_slug, *args, **kwargs
|
|
)
|
|
|
|
def get_form(self, form_class=None):
|
|
po_model: PurchaseOrderModel = self.object
|
|
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
|
|
if po_model.is_draft():
|
|
return DraftPurchaseOrderModelUpdateForm(
|
|
entity_slug=self.kwargs["entity_slug"],
|
|
user_model=dealer.entity.admin,
|
|
**self.get_form_kwargs(),
|
|
)
|
|
elif po_model.is_review():
|
|
return ReviewPurchaseOrderModelUpdateForm(
|
|
entity_slug=self.kwargs["entity_slug"],
|
|
user_model=dealer.entity.admin,
|
|
**self.get_form_kwargs(),
|
|
)
|
|
elif po_model.is_approved():
|
|
return ApprovedPurchaseOrderModelUpdateForm(
|
|
entity_slug=self.kwargs["entity_slug"],
|
|
user_model=dealer.entity.admin,
|
|
**self.get_form_kwargs(),
|
|
)
|
|
return BasePurchaseOrderModelUpdateForm(
|
|
entity_slug=self.kwargs["entity_slug"],
|
|
user_model=dealer.entity.admin,
|
|
**self.get_form_kwargs(),
|
|
)
|
|
|
|
def get_form_kwargs(self):
|
|
if self.action_update_items:
|
|
return {
|
|
'initial': self.get_initial(),
|
|
'prefix': self.get_prefix(),
|
|
'instance': self.object
|
|
}
|
|
return super(PurchaseOrderModelUpdateView, self).get_form_kwargs()
|
|
|
|
|
|
def get_po_itemtxs_qs(self, po_model: PurchaseOrderModel):
|
|
return po_model.itemtransactionmodel_set.select_related('bill_model', 'po_model').order_by('created')
|
|
|
|
def form_valid(self, form: BasePurchaseOrderModelUpdateForm):
|
|
po_model: PurchaseOrderModel = form.save(commit=False)
|
|
|
|
if form.has_changed():
|
|
po_items_qs = ItemTransactionModel.objects.for_po(
|
|
entity_slug=self.kwargs['entity_slug'],
|
|
user_model=self.request.admin,
|
|
po_pk=po_model.uuid,
|
|
).select_related('bill_model')
|
|
|
|
if all(['po_status' in form.changed_data,
|
|
po_model.po_status == po_model.PO_STATUS_APPROVED]):
|
|
po_items_qs.update(po_item_status=ItemTransactionModel.STATUS_NOT_ORDERED)
|
|
|
|
if 'fulfilled' in form.changed_data:
|
|
|
|
if not all([i.bill_model for i in po_items_qs]):
|
|
messages.add_message(self.request,
|
|
messages.ERROR,
|
|
f'All PO items must be billed before marking'
|
|
f' PO: {po_model.po_number} as fulfilled.',
|
|
extra_tags='is-danger')
|
|
return self.get(self.request)
|
|
|
|
else:
|
|
if not all([i.bill_model.is_paid() for i in po_items_qs]):
|
|
messages.add_message(self.request,
|
|
messages.SUCCESS,
|
|
f'All bills must be paid before marking'
|
|
f' PO: {po_model.po_number} as fulfilled.',
|
|
extra_tags='is-success')
|
|
return self.get(self.request)
|
|
|
|
po_items_qs.update(po_item_status=ItemTransactionModel.STATUS_RECEIVED)
|
|
|
|
messages.add_message(self.request,
|
|
messages.SUCCESS,
|
|
f'{self.object.po_number} successfully updated.',
|
|
extra_tags='is-success')
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
class BasePurchaseOrderActionActionView(LoginRequiredMixin,
|
|
PermissionRequiredMixin,
|
|
RedirectView,
|
|
SingleObjectMixin):
|
|
http_method_names = ['get']
|
|
pk_url_kwarg = 'po_pk'
|
|
action_name = None
|
|
commit = True
|
|
permission_required = None
|
|
queryset = None
|
|
|
|
def get_queryset(self):
|
|
dealer = get_object_or_404(Dealer, slug=self.kwargs['dealer_slug'])
|
|
if self.queryset is None:
|
|
self.queryset = PurchaseOrderModel.objects.for_entity(
|
|
entity_slug=self.kwargs['entity_slug'],
|
|
user_model=dealer.entity.admin
|
|
).select_related('entity', 'ce_model')
|
|
return super().get_queryset()
|
|
|
|
def get_redirect_url(self, dealer_slug, entity_slug, po_pk, *args, **kwargs):
|
|
return reverse(
|
|
"purchase_order_update",
|
|
kwargs={
|
|
"dealer_slug": dealer_slug,
|
|
"entity_slug": entity_slug,
|
|
"po_pk": po_pk,
|
|
},
|
|
)
|
|
|
|
def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs):
|
|
# kwargs["user_model"] = dealer.entity.admin
|
|
# Get user information for logging
|
|
user_username = request.user.username if request.user.is_authenticated else 'anonymous'
|
|
|
|
dealer = get_object_or_404(Dealer, slug=dealer_slug)
|
|
kwargs["user_model"] = dealer.entity.admin
|
|
if not self.action_name:
|
|
raise ImproperlyConfigured("View attribute action_name is required.")
|
|
response = super(BasePurchaseOrderActionActionView, self).get(
|
|
request, dealer_slug, entity_slug, po_pk, *args, **kwargs
|
|
)
|
|
po_model: PurchaseOrderModel = self.get_object()
|
|
|
|
# Log the attempt to perform the action
|
|
logger.debug(
|
|
f"User {user_username} attempting to call action '{self.action_name}' "
|
|
f"on Purchase Order ID: {po_model.pk} (Entity: {entity_slug})."
|
|
)
|
|
try:
|
|
getattr(po_model, self.action_name)(commit=self.commit, **kwargs)
|
|
# --- Single-line log for successful action ---
|
|
logger.info(
|
|
f"User {user_username} successfully executed action '{self.action_name}' "
|
|
f"on Purchase Order ID: {po_model.pk}."
|
|
)
|
|
messages.add_message(
|
|
request,
|
|
message="PO updated successfully.",
|
|
level=messages.SUCCESS,
|
|
)
|
|
except ValidationError as e:
|
|
# --- Single-line log for ValidationError ---
|
|
print(f"User {user_username} encountered a validation error "
|
|
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
f"Error: {e}")
|
|
logger.warning(
|
|
f"User {user_username} encountered a validation error "
|
|
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
f"Error: {e}"
|
|
)
|
|
except AttributeError as e:
|
|
print(f"User {user_username} encountered an AttributeError "
|
|
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
f"Error: {e}")
|
|
logger.warning(
|
|
f"User {user_username} encountered an AttributeError "
|
|
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
f"Error: {e}"
|
|
)
|
|
return response
|
|
|
|
class BillModelDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
slug_url_kwarg = 'bill_pk'
|
|
slug_field = 'uuid'
|
|
context_object_name = 'bill'
|
|
template_name = "bill/bill_detail.html"
|
|
extra_context = {
|
|
'header_subtitle_icon': 'uil:bill',
|
|
'hide_menu': True
|
|
}
|
|
|
|
def get_context_data(self, *, object_list=None, **kwargs):
|
|
context = super().get_context_data(object_list=object_list, **kwargs)
|
|
context["dealer"] = self.request.dealer
|
|
bill_model: BillModel = self.object
|
|
title = f'Bill {bill_model.bill_number}'
|
|
context['page_title'] = title
|
|
context['header_title'] = title
|
|
|
|
bill_model: BillModel = self.object
|
|
bill_items_qs, item_data = bill_model.get_itemtxs_data()
|
|
context['itemtxs_qs'] = bill_items_qs
|
|
context['total_amount__sum'] = item_data['total_amount__sum']
|
|
|
|
if not bill_model.is_configured():
|
|
link = format_html(f"""
|
|
<a href="{reverse("bill-update", kwargs={
|
|
'dealer_slug': self.kwargs['dealer_slug'],
|
|
'entity_slug': self.kwargs['entity_slug'],
|
|
'bill_pk': bill_model.uuid
|
|
})}">here</a>
|
|
""")
|
|
msg = f'Bill {bill_model.bill_number} has not been fully set up. ' + \
|
|
f'Please update or assign associated accounts {link}.'
|
|
messages.add_message(self.request,
|
|
message=msg,
|
|
level=messages.WARNING,
|
|
extra_tags='is-danger')
|
|
return context
|
|
|
|
|
|
def get_queryset(self):
|
|
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug'])
|
|
if self.queryset is None:
|
|
entity_model = dealer.entity
|
|
qs = entity_model.get_bills()
|
|
self.queryset = qs
|
|
return super().get_queryset()
|
|
|
|
|
|
######################################################3
|
|
#BILL
|
|
|
|
class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
|
slug_url_kwarg = 'bill_pk'
|
|
slug_field = 'uuid'
|
|
context_object_name = 'bill_model'
|
|
template_name = "bill/bill_update.html"
|
|
extra_context = {
|
|
'header_subtitle_icon': 'uil:bill'
|
|
}
|
|
http_method_names = ['get', 'post']
|
|
action_update_items = False
|
|
queryset = None
|
|
|
|
def get_queryset(self):
|
|
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug'])
|
|
if self.queryset is None:
|
|
entity_model = dealer.entity
|
|
qs = entity_model.get_bills()
|
|
self.queryset = qs
|
|
return super().get_queryset().select_related(
|
|
'ledger',
|
|
'ledger__entity',
|
|
'vendor',
|
|
'cash_account',
|
|
'prepaid_account',
|
|
'unearned_account',
|
|
'cash_account__coa_model',
|
|
'prepaid_account__coa_model',
|
|
'unearned_account__coa_model'
|
|
)
|
|
|
|
def get_form(self, form_class=None):
|
|
form_class = self.get_form_class()
|
|
entity_model = self.request.dealer.entity
|
|
if self.request.method == 'POST' and self.action_update_items:
|
|
return form_class(
|
|
entity_model=entity_model,
|
|
user_model=self.request.admin,
|
|
instance=self.object
|
|
)
|
|
form = form_class(
|
|
entity_model=entity_model,
|
|
user_model=self.request.admin,
|
|
**self.get_form_kwargs()
|
|
)
|
|
try:
|
|
form.initial['amount_paid'] = self.object.get_itemtxs_data()[1]["total_amount__sum"]
|
|
except Exception as e:
|
|
print(e)
|
|
return form
|
|
|
|
def get_form_class(self):
|
|
bill_model: BillModel = self.object
|
|
if not bill_model.is_configured():
|
|
return BillModelConfigureForm
|
|
if bill_model.is_draft():
|
|
return DraftBillModelUpdateForm
|
|
elif bill_model.is_review():
|
|
return InReviewBillModelUpdateForm
|
|
elif bill_model.is_approved() and not bill_model.accrue:
|
|
return ApprovedBillModelUpdateForm
|
|
elif bill_model.is_approved() and bill_model.accrue:
|
|
return AccruedAndApprovedBillModelUpdateForm
|
|
elif bill_model.is_paid():
|
|
return PaidBillModelUpdateForm
|
|
return BaseBillModelUpdateForm
|
|
|
|
def get_context_data(self,
|
|
*,
|
|
object_list=None,
|
|
itemtxs_formset=None,
|
|
**kwargs):
|
|
|
|
context = super().get_context_data(object_list=object_list, **kwargs)
|
|
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug'])
|
|
entity_model = dealer.entity
|
|
bill_model: BillModel = self.object
|
|
ledger_model = bill_model.ledger
|
|
|
|
title = f'Bill {bill_model.bill_number}'
|
|
context['page_title'] = title
|
|
context['header_title'] = title
|
|
context['header_subtitle'] = bill_model.get_bill_status_display()
|
|
|
|
if not bill_model.is_configured():
|
|
messages.add_message(
|
|
request=self.request,
|
|
message=f'Bill {bill_model.bill_number} must have all accounts configured.',
|
|
level=messages.ERROR,
|
|
extra_tags='is-danger'
|
|
)
|
|
|
|
if not bill_model.is_paid():
|
|
if ledger_model.locked:
|
|
messages.add_message(self.request,
|
|
messages.ERROR,
|
|
f'Warning! This bill is locked. Must unlock before making any changes.',
|
|
extra_tags='is-danger')
|
|
|
|
if ledger_model.locked:
|
|
messages.add_message(self.request,
|
|
messages.ERROR,
|
|
f'Warning! This bill is locked. Must unlock before making any changes.',
|
|
extra_tags='is-danger')
|
|
|
|
if not ledger_model.is_posted():
|
|
messages.add_message(self.request,
|
|
messages.INFO,
|
|
f'This bill has not been posted. Must post to see ledger changes.',
|
|
extra_tags='is-info')
|
|
|
|
itemtxs_qs = itemtxs_formset.get_queryset() if itemtxs_formset else None
|
|
if not itemtxs_formset:
|
|
itemtxs_formset_class = get_bill_itemtxs_formset_class(bill_model)
|
|
itemtxs_formset = itemtxs_formset_class(entity_model=entity_model, bill_model=bill_model)
|
|
itemtxs_qs, itemtxs_agg = bill_model.get_itemtxs_data(queryset=itemtxs_qs)
|
|
|
|
has_po = any(i.po_model_id for i in itemtxs_qs)
|
|
|
|
if has_po:
|
|
itemtxs_formset.can_delete = False
|
|
itemtxs_formset.has_po = has_po
|
|
|
|
context['itemtxs_formset'] = itemtxs_formset
|
|
context['total_amount__sum'] = itemtxs_agg['total_amount__sum']
|
|
context['has_po'] = has_po
|
|
return context
|
|
|
|
def get_success_url(self):
|
|
return reverse(
|
|
"bill-update",
|
|
kwargs={
|
|
"dealer_slug": self.kwargs["dealer_slug"],
|
|
"entity_slug": self.kwargs["entity_slug"],
|
|
"bill_pk": self.kwargs["bill_pk"],
|
|
},
|
|
)
|
|
def form_valid(self, form):
|
|
form.save(commit=False)
|
|
messages.add_message(self.request,
|
|
messages.SUCCESS,
|
|
f'Bill {self.object.bill_number} successfully updated.',
|
|
extra_tags='is-success')
|
|
return super().form_valid(form)
|
|
|
|
def get(self, request,dealer_slug,entity_slug,bill_pk, *args, **kwargs):
|
|
if self.action_update_items:
|
|
return HttpResponseRedirect(
|
|
redirect_to=reverse('bill-update',
|
|
kwargs={
|
|
'dealer_slug': dealer_slug,
|
|
'entity_slug': entity_slug,
|
|
'bill_pk': bill_pk
|
|
})
|
|
)
|
|
return super(BillModelUpdateView, self).get(request, *args, **kwargs)
|
|
|
|
def post(self, request, dealer_slug, entity_slug, bill_pk, *args, **kwargs):
|
|
if self.action_update_items:
|
|
if not request.user.is_authenticated:
|
|
return HttpResponseForbidden()
|
|
|
|
queryset = self.get_queryset()
|
|
dealer = get_object_or_404(Dealer, slug=dealer_slug)
|
|
entity_model = dealer.entity
|
|
bill_model: BillModel = self.get_object(queryset=queryset)
|
|
bill_pk = bill_model.uuid
|
|
|
|
self.object = bill_model
|
|
|
|
bill_itemtxs_formset_class = get_bill_itemtxs_formset_class(bill_model)
|
|
itemtxs_formset = bill_itemtxs_formset_class(
|
|
request.POST, bill_model=bill_model, entity_model=entity_model
|
|
)
|
|
|
|
if itemtxs_formset.has_changed():
|
|
if itemtxs_formset.is_valid():
|
|
itemtxs_list = itemtxs_formset.save(commit=False)
|
|
|
|
for itemtxs in itemtxs_list:
|
|
itemtxs.bill_model_id = bill_model.uuid
|
|
itemtxs.clean()
|
|
|
|
itemtxs_formset.save()
|
|
itemtxs_qs = bill_model.update_amount_due()
|
|
bill_model.get_state(commit=True)
|
|
bill_model.clean()
|
|
bill_model.save(
|
|
update_fields=[
|
|
"amount_due",
|
|
"amount_receivable",
|
|
"amount_unearned",
|
|
"amount_earned",
|
|
"updated",
|
|
]
|
|
)
|
|
|
|
bill_model.migrate_state(
|
|
entity_slug=self.kwargs["entity_slug"],
|
|
user_model=self.request.user,
|
|
itemtxs_qs=itemtxs_qs,
|
|
raise_exception=False,
|
|
)
|
|
|
|
messages.add_message(
|
|
request,
|
|
message=f"Items for Invoice {bill_model.bill_number} saved.",
|
|
level=messages.SUCCESS,
|
|
)
|
|
|
|
# if valid get saved formset from DB
|
|
return HttpResponseRedirect(
|
|
redirect_to=reverse(
|
|
"bill-update",
|
|
kwargs={
|
|
"dealer_slug": dealer_slug,
|
|
"entity_slug": entity_model.slug,
|
|
"bill_pk": bill_pk,
|
|
},
|
|
)
|
|
)
|
|
context = self.get_context_data(itemtxs_formset=itemtxs_formset)
|
|
return self.render_to_response(context=context)
|
|
return super(BillModelUpdateView, self).post(
|
|
request, dealer_slug, entity_slug, bill_pk, **kwargs
|
|
)
|
|
|
|
|
|
|
|
class BaseBillActionView(LoginRequiredMixin,PermissionRequiredMixin, RedirectView, SingleObjectMixin):
|
|
http_method_names = ['get']
|
|
pk_url_kwarg = 'bill_pk'
|
|
action_name = None
|
|
commit = True
|
|
permission_required = "django_ledger.change_billmodel"
|
|
queryset = None
|
|
|
|
def get_queryset(self):
|
|
if self.queryset is None:
|
|
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
|
|
entity_model = dealer.entity
|
|
qs = entity_model.get_bills()
|
|
self.queryset = qs
|
|
return super().get_queryset()
|
|
|
|
|
|
def get_redirect_url(self, dealer_slug, entity_slug, bill_pk, *args, **kwargs):
|
|
return reverse(
|
|
"bill-update",
|
|
kwargs={
|
|
"dealer_slug": dealer_slug,
|
|
"entity_slug": entity_slug,
|
|
"bill_pk": bill_pk,
|
|
},
|
|
)
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
|
|
kwargs['user_model'] = dealer.entity.admin
|
|
if not self.action_name:
|
|
raise ImproperlyConfigured('View attribute action_name is required.')
|
|
response = super(BaseBillActionView, self).get(request, *args, **kwargs)
|
|
bill_model: BillModel = self.get_object()
|
|
|
|
try:
|
|
getattr(bill_model, self.action_name)(commit=self.commit, **kwargs)
|
|
except ValidationError as e:
|
|
messages.add_message(request,
|
|
message=e.message,
|
|
level=messages.ERROR,
|
|
extra_tags='is-danger')
|
|
return response
|
|
|
|
|
|
class InventoryListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
template_name = 'django_ledger/inventory/inventory_list.html'
|
|
context_object_name = 'inventory_list'
|
|
http_method_names = ['get']
|
|
|
|
def get_context_data(self, *, object_list=None, **kwargs):
|
|
context = super(InventoryListView, self).get_context_data(**kwargs)
|
|
qs = self.get_queryset()
|
|
|
|
# evaluates the queryset...
|
|
context['qs_count'] = qs.count()
|
|
|
|
# ordered inventory...
|
|
ordered_qs = qs.is_ordered()
|
|
context['inventory_ordered'] = ordered_qs
|
|
|
|
# in transit inventory...
|
|
in_transit_qs = qs.in_transit()
|
|
context['inventory_in_transit'] = in_transit_qs
|
|
|
|
# on hand inventory...
|
|
received_qs = qs.is_received()
|
|
context['inventory_received'] = received_qs
|
|
|
|
context['page_title'] = _('Inventory')
|
|
context['header_title'] = _('Inventory Status')
|
|
context['header_subtitle'] = _('Ordered/In Transit/On Hand')
|
|
context['header_subtitle_icon'] = 'ic:round-inventory'
|
|
return context
|
|
|
|
def get_queryset(self):
|
|
if self.queryset is None:
|
|
self.queryset = ItemTransactionModel.objects.inventory_pipeline_aggregate(
|
|
entity_slug=self.kwargs['entity_slug'],
|
|
)
|
|
return super().get_queryset() |