This commit is contained in:
Faheedkhan 2025-07-06 13:47:09 +03:00
commit e29f520d6c
4 changed files with 40 additions and 33 deletions

View File

@ -465,9 +465,9 @@ urlpatterns = [
views.RepresentativeDeleteView.as_view(), views.RepresentativeDeleteView.as_view(),
name="representative_delete", name="representative_delete",
), ),
path("<slug:dealer_slug>/ledgers/", views.LedgerModelListView.as_view(), name="ledger_list"), path("<slug:dealer_slug>/ledgers/<slug:entity_slug>/", views.LedgerModelListView.as_view(), name="ledger_list"),
path( path(
"<slug:dealer_slug>/ledgers/create/", views.LedgerModelCreateView.as_view(), name="ledger_create" "<slug:dealer_slug>/ledgers/<slug:entity_slug>/create/", views.LedgerModelCreateView.as_view(), name="ledger_create"
), ),
path( path(
"<slug:dealer_slug>/ledgers/<slug:entity_slug>/detail/<uuid:pk>/", "<slug:dealer_slug>/ledgers/<slug:entity_slug>/detail/<uuid:pk>/",

View File

@ -1232,7 +1232,7 @@ def inventory_stats_view(request, dealer_slug):
"trims": {}, "trims": {},
} }
try: try:
logger.debug(f"Attempting to update inventory for Car ID: {car.id}, Make: {make.name} ({make.id_car_make}), " logger.debug(f"Attempting to update inventory for Car ID: {car.id}, Make: {make.name} ({make.id_car_make}), "
f"Model: {model.name} ({model.id_car_model}).") f"Model: {model.name} ({model.id_car_model}).")
inventory[make.id_car_make]["models"][model.id_car_model]["total_cars"] += 1 inventory[make.id_car_make]["models"][model.id_car_model]["total_cars"] += 1
@ -1260,7 +1260,7 @@ def inventory_stats_view(request, dealer_slug):
f"Error updating inventory counts for car ID {getattr(car, 'id', 'N/A')}. " f"Error updating inventory counts for car ID {getattr(car, 'id', 'N/A')}. "
f"Make ID: {getattr(make, 'id_car_make', 'N/A')}, Model ID: {getattr(model, 'id_car_model', 'N/A')}, " f"Make ID: {getattr(make, 'id_car_make', 'N/A')}, Model ID: {getattr(model, 'id_car_model', 'N/A')}, "
f"Trim ID: {getattr(trim, 'id_car_trim', 'N/A')}. Error: {e}", f"Trim ID: {getattr(trim, 'id_car_trim', 'N/A')}. Error: {e}",
exc_info=True exc_info=True
) )
print(e) print(e)
result = { result = {
@ -2922,7 +2922,7 @@ def GroupPermissionView(request, dealer_slug, pk):
("inventory", "notes"), ("inventory", "notes"),
("inventory", "tasks"), ("inventory", "tasks"),
("inventory", "activity"), ("inventory", "activity"),
("django_ledger", "purchaseordermodel"), ("django_ledger", "purchaseordermodel"),
("django_ledger", "bankaccountmodel"), ("django_ledger", "bankaccountmodel"),
@ -2972,7 +2972,7 @@ def GroupPermissionView(request, dealer_slug, pk):
group.permissions.clear() group.permissions.clear()
if valid_perms.exists(): if valid_perms.exists():
group.permissions.add(*valid_perms) group.permissions.add(*valid_perms)
# --- Logging for successful permission update --- # --- Logging for successful permission update ---
logger.info( logger.info(
f"Permissions for Group '{group.name}' (ID: {group.id}) " f"Permissions for Group '{group.name}' (ID: {group.id}) "
@ -4654,7 +4654,7 @@ def create_sale_order(request, dealer_slug, pk):
item.item_model.additional_info["car_info"]["status"] = "sold" item.item_model.additional_info["car_info"]["status"] = "sold"
item.item_model.save() item.item_model.save()
logger.debug(f"Car status updated to 'sold' for item.item_model PK: {getattr(item.item_model, 'pk', 'N/A')}.") logger.debug(f"Car status updated to 'sold' for item.item_model PK: {getattr(item.item_model, 'pk', 'N/A')}.")
except KeyError: except KeyError:
logger.warning(f"KeyError: 'car_info' or 'status' key missing when attempting to update status to 'sold' for item.item_model PK: {getattr(item.item_model, 'pk', 'N/A')}.") logger.warning(f"KeyError: 'car_info' or 'status' key missing when attempting to update status to 'sold' for item.item_model PK: {getattr(item.item_model, 'pk', 'N/A')}.")
pass pass
@ -4887,7 +4887,7 @@ def estimate_mark_as(request, dealer_slug, pk):
except Exception as e: except Exception as e:
logger.error(f"Failed to update car status to 'available' for Estimate ID: {getattr(estimate, 'pk', 'N/A')}. " logger.error(f"Failed to update car status to 'available' for Estimate ID: {getattr(estimate, 'pk', 'N/A')}. "
f"Attempted VIN: '{car.vin}'. Error: {e}",exc_info=True ) f"Attempted VIN: '{car.vin}'. Error: {e}",exc_info=True )
messages.success(request, _("Quotation canceled successfully")) messages.success(request, _("Quotation canceled successfully"))
estimate.save() estimate.save()
messages.success(request, _("Quotation marked as ") + mark.upper()) messages.success(request, _("Quotation marked as ") + mark.upper())
@ -5336,7 +5336,7 @@ def PaymentCreateView(request, dealer_slug, pk):
elif bill: elif bill:
set_bill_payment(dealer, entity, bill, amount, payment_method) set_bill_payment(dealer, entity, bill, amount, payment_method)
logger.info(f"User {user_username} (ID: {user_id}) successfully processed payment for Bill ID: {bill.pk} (Dealer: {dealer.slug}) Amount: {amount}, Method: {payment_method}.") logger.info(f"User {user_username} (ID: {user_id}) successfully processed payment for Bill ID: {bill.pk} (Dealer: {dealer.slug}) Amount: {amount}, Method: {payment_method}.")
messages.success(request, _("Payment created successfully")) messages.success(request, _("Payment created successfully"))
return redirect(redirect_url, dealer_slug=dealer.slug, pk=model.pk) return redirect(redirect_url, dealer_slug=dealer.slug, pk=model.pk)
except Exception as e: except Exception as e:
@ -5344,7 +5344,7 @@ def PaymentCreateView(request, dealer_slug, pk):
f"User {user_username} (ID: {user_id}) encountered error creating payment " f"User {user_username} (ID: {user_id}) encountered error creating payment "
f"for (Dealer: {dealer.slug}). " f"for (Dealer: {dealer.slug}). "
f"Attempted Amount: {amount}, Method: {payment_method}. Error: {e}", f"Attempted Amount: {amount}, Method: {payment_method}. Error: {e}",
exc_info=True exc_info=True
) )
messages.error(request, f"Error creating payment: {str(e)}") messages.error(request, f"Error creating payment: {str(e)}")
else: else:
@ -5652,9 +5652,9 @@ def lead_create(request,dealer_slug):
user_username = request.user.username if request.user.is_authenticated else 'anonymous' user_username = request.user.username if request.user.is_authenticated else 'anonymous'
# Log intent before trying to mark as paid # Log intent before trying to mark as paid
form = forms.LeadForm(request.POST) form = forms.LeadForm(request.POST)
# Filter car models based on the selected make (for POST requests) # Filter car models based on the selected make (for POST requests)
if "id_car_make" in request.POST: if "id_car_make" in request.POST:
form.fields["id_car_model"].queryset = models.CarModel.objects.filter( form.fields["id_car_model"].queryset = models.CarModel.objects.filter(
@ -5859,7 +5859,7 @@ def update_lead_actions(request,dealer_slug):
) )
return JsonResponse({"success": False, "message": "Lead not found"}, status=404) return JsonResponse({"success": False, "message": "Lead not found"}, status=404)
except Exception as e: except Exception as e:
involved_lead_id = request.POST.get("lead_id", "N/A") involved_lead_id = request.POST.get("lead_id", "N/A")
logger.error( logger.error(
f"User {user_username} encountered an unexpected error while updating Lead ID: '{involved_lead_id}' " f"User {user_username} encountered an unexpected error while updating Lead ID: '{involved_lead_id}' "
f"for dealer '{dealer_slug}'. Error: {e}", f"for dealer '{dealer_slug}'. Error: {e}",
@ -5927,14 +5927,14 @@ def LeadDeleteView(request,dealer_slug, slug):
""" """
# get the user info for logging # get the user info for logging
user_username = request.user.username if request.user.is_authenticated else 'anonymous' user_username = request.user.username if request.user.is_authenticated else 'anonymous'
lead = get_object_or_404(models.Lead, slug=slug) lead = get_object_or_404(models.Lead, slug=slug)
# Log intent before attempting deletion # Log intent before attempting deletion
logger.debug( logger.debug(
f"User {user_username} attempting to delete Lead ID: {lead.id} ('{lead.name}') " f"User {user_username} attempting to delete Lead ID: {lead.id} ('{lead.name}') "
f"and its associated customer/user for dealer '{dealer_slug}'." f"and its associated customer/user for dealer '{dealer_slug}'."
) )
try: try:
@ -5951,7 +5951,7 @@ def LeadDeleteView(request,dealer_slug, slug):
f"User {user_username} encountered an error deleting associated user/customer " f"User {user_username} encountered an error deleting associated user/customer "
f"for Lead ID: {lead.id} ('{lead.name}') (Email: {getattr(lead.customer, 'email', 'N/A')}). " # Safely get email f"for Lead ID: {lead.id} ('{lead.name}') (Email: {getattr(lead.customer, 'email', 'N/A')}). " # Safely get email
f"Error: {e}", f"Error: {e}",
exc_info=True exc_info=True
) )
print(e) print(e)
lead_id_final = lead.id # Capture before deletion lead_id_final = lead.id # Capture before deletion
@ -7049,9 +7049,9 @@ class BillModelCreateView(LoginRequiredMixin,PermissionRequiredMixin,CreateView)
for_purchase_order = False for_purchase_order = False
for_estimate = False for_estimate = False
permission_required = "django_ledger.add_billmodel" permission_required = "django_ledger.add_billmodel"
# Get user info for logging # Get user info for logging
def get(self, request, dealer_slug, **kwargs): def get(self, request, dealer_slug, **kwargs):
user_username = request.user.username if request.user.is_authenticated else 'anonymous' user_username = request.user.username if request.user.is_authenticated else 'anonymous'
@ -7082,7 +7082,7 @@ class BillModelCreateView(LoginRequiredMixin,PermissionRequiredMixin,CreateView)
context = super(BillModelCreateView, self).get_context_data(**kwargs) context = super(BillModelCreateView, self).get_context_data(**kwargs)
user_username = self.request.user.username if self.request.user.is_authenticated else 'anonymous' user_username = self.request.user.username if self.request.user.is_authenticated else 'anonymous'
if self.for_purchase_order: if self.for_purchase_order:
po_pk = self.kwargs["po_pk"] po_pk = self.kwargs["po_pk"]
po_item_uuids_qry_param = self.request.GET.get("item_uuids") po_item_uuids_qry_param = self.request.GET.get("item_uuids")
@ -7191,7 +7191,7 @@ class BillModelCreateView(LoginRequiredMixin,PermissionRequiredMixin,CreateView)
entity_slug=self.kwargs["entity_slug"], user_model=self.request.user entity_slug=self.kwargs["entity_slug"], user_model=self.request.user
) )
po_model: PurchaseOrderModel = get_object_or_404(po_qs, uuid__exact=po_pk) po_model: PurchaseOrderModel = get_object_or_404(po_qs, uuid__exact=po_pk)
user_username = self.request.user.username if self.request.user.is_authenticated else 'anonymous' user_username = self.request.user.username if self.request.user.is_authenticated else 'anonymous'
try: try:
bill_model.can_bind_po(po_model, raise_exception=True) bill_model.can_bind_po(po_model, raise_exception=True)
@ -8717,7 +8717,10 @@ class LedgerModelCreateView(LedgerModelCreateViewBase):
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self): def get_success_url(self):
return reverse("ledger_list") return reverse("ledger_list", kwargs={
"dealer_slug": self.kwargs["dealer_slug"],
"entity_slug": self.kwargs["entity_slug"]
})
class LedgerModelModelActionView(LedgerModelModelActionViewBase): class LedgerModelModelActionView(LedgerModelModelActionViewBase):
@ -8735,7 +8738,10 @@ class LedgerModelModelActionView(LedgerModelModelActionViewBase):
""" """
def get_redirect_url(self, *args, **kwargs): def get_redirect_url(self, *args, **kwargs):
return reverse("ledger_list", args=[self.kwargs["dealer_slug"]]) return reverse("ledger_list", kwargs={
"dealer_slug": self.kwargs["dealer_slug"],
"entity_slug": self.kwargs["entity_slug"]
})
class LedgerModelDeleteView(LedgerModelDeleteViewBase, SuccessMessageMixin): class LedgerModelDeleteView(LedgerModelDeleteViewBase, SuccessMessageMixin):
@ -8759,7 +8765,10 @@ class LedgerModelDeleteView(LedgerModelDeleteViewBase, SuccessMessageMixin):
permission_required = ["django_ledger.delete_ledgermodel"] permission_required = ["django_ledger.delete_ledgermodel"]
def get_success_url(self): def get_success_url(self):
return reverse("ledger_list", args=[self.kwargs["dealer_slug"]]) return reverse("ledger_list", kwargs={
"dealer_slug": self.kwargs["dealer_slug"],
"entity_slug": self.kwargs["entity_slug"]
})
# class LedgerModelCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView): # class LedgerModelCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView):
@ -9388,7 +9397,7 @@ def add_note(request,dealer_slug, content_type, slug):
logger.info( logger.info(
f"User {user_username} successfully added a note " f"User {user_username} successfully added a note "
f"for {content_type} ID: {obj.slug} (Dealer: {dealer_slug}). " f"for {content_type} ID: {obj.slug} (Dealer: {dealer_slug}). "
f"Note: '{note.notes[:50]}...'." f"Note: '{note.notes[:50]}...'."
) )
messages.success(request, _("Note added successfully")) messages.success(request, _("Note added successfully"))
else: else:
@ -9607,7 +9616,7 @@ def activate_account(request,dealer_slug, content_type, slug):
# --- Single-line log for successful account activation --- # --- Single-line log for successful account activation ---
logger.info( logger.info(
f"User {user_username} successfully activated account " f"User {user_username} successfully activated account "
f"for {content_type} ID: {obj.slug} ('{obj.name if hasattr(obj, 'name') else obj}') " f"for {content_type} ID: {obj.slug} ('{obj.name if hasattr(obj, 'name') else obj}') "
f"on dealer '{dealer_slug}'." f"on dealer '{dealer_slug}'."
) )
messages.success(request, _("Account activated successfully")) messages.success(request, _("Account activated successfully"))
@ -9669,7 +9678,7 @@ def permenant_delete_account(request,dealer_slug, content_type, slug):
f"User {user_username} encountered an unexpected error " f"User {user_username} encountered an unexpected error "
f"while permanently deleting account for {content_type} ID: {obj.slug} " f"while permanently deleting account for {content_type} ID: {obj.slug} "
f"('{obj.name if hasattr(obj, 'name') else obj}') on dealer '{dealer_slug}'. Error: {e}", f"('{obj.name if hasattr(obj, 'name') else obj}') on dealer '{dealer_slug}'. Error: {e}",
exc_info=True exc_info=True
) )
messages.error(request, _(f"Error deleting account: {e}")) messages.error(request, _(f"Error deleting account: {e}"))
return redirect("user_management", dealer_slug=dealer_slug) return redirect("user_management", dealer_slug=dealer_slug)
@ -9685,7 +9694,7 @@ def permenant_delete_account(request,dealer_slug, content_type, slug):
def PurchaseOrderCreateView(request, dealer_slug,entity_slug): def PurchaseOrderCreateView(request, dealer_slug,entity_slug):
dealer = get_object_or_404(models.Dealer, slug=dealer_slug) dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
entity = dealer.entity entity = dealer.entity
# Get user information for logging # Get user information for logging
user_username = request.user.username if request.user.is_authenticated else 'anonymous' user_username = request.user.username if request.user.is_authenticated else 'anonymous'
@ -10102,7 +10111,7 @@ class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase):
request, dealer_slug, entity_slug, po_pk, *args, **kwargs request, dealer_slug, entity_slug, po_pk, *args, **kwargs
) )
po_model: PurchaseOrderModel = self.get_object() po_model: PurchaseOrderModel = self.get_object()
# Log the attempt to perform the action # Log the attempt to perform the action
logger.debug( logger.debug(
f"User {user_username} attempting to call action '{self.action_name}' " f"User {user_username} attempting to call action '{self.action_name}' "
@ -10311,7 +10320,7 @@ def upload_cars(request, dealer_slug, pk=None):
logger.error( logger.error(
f"User {user_username} encountered an error while preparing car data " f"User {user_username} encountered an error while preparing car data "
f"for upload (Item PK: {pk if pk else 'N/A'}, Dealer: {dealer_slug}). Error: {e}", f"for upload (Item PK: {pk if pk else 'N/A'}, Dealer: {dealer_slug}). Error: {e}",
exc_info=True exc_info=True
) )
messages.error(request, f"Error processing CSV: {str(e)}") messages.error(request, f"Error processing CSV: {str(e)}")
return response return response

View File

@ -230,7 +230,7 @@
{% if perms.django_ledger.view_journalentrymodel %} {% if perms.django_ledger.view_journalentrymodel %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'ledger_list' request.dealer.slug %}"> <a class="nav-link" href="{% url 'ledger_list' request.dealer.slug request.dealer.entity.slug %}">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-book"></span></span><span class="nav-link-text">{% trans "Ledgers"|capfirst %}</span> <span class="nav-link-icon"><span class="fas fa-book"></span></span><span class="nav-link-text">{% trans "Ledgers"|capfirst %}</span>
</div> </div>

View File

@ -10,9 +10,7 @@
<div class="d-flex justify-content-between mb-2"> <div class="d-flex justify-content-between mb-2">
<h3 class="">{% trans "Ledger" %}</h3> <h3 class="">{% trans "Ledger" %}</h3>
{% if perms.django_ledger.add_ledgermodel%} <a href="{% url 'ledger_create' request.dealer.slug request.dealer.entity.slug %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'Create Ledger' %}</a>
<a href="{% url 'ledger_create' request.dealer.slug %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'Create Ledger' %}</a>
{% endif %}
</div> </div>
<div class="table-responsive px-1 scrollbar mt-3"> <div class="table-responsive px-1 scrollbar mt-3">
<table class="table align-items-center table-flush"> <table class="table align-items-center table-flush">