add crm dealer slug

This commit is contained in:
ismail 2025-06-25 17:06:38 +03:00
parent a930acfae5
commit 8111dd6378
20 changed files with 188 additions and 171 deletions

View File

@ -86,146 +86,149 @@ urlpatterns = [
# path('dealers/<int:pk>/delete/', views.DealerDeleteView.as_view(), name='dealer_delete'), # path('dealers/<int:pk>/delete/', views.DealerDeleteView.as_view(), name='dealer_delete'),
# CRM URLs # CRM URLs
path( path(
"customers/create/", views.CustomerCreateView.as_view(), name="customer_create" "<slug:dealer_slug>/customers/create/", views.CustomerCreateView.as_view(), name="customer_create"
), ),
path("customers/", views.CustomerListView.as_view(), name="customer_list"), path("<slug:dealer_slug>/customers/", views.CustomerListView.as_view(), name="customer_list"),
path( path(
"customers/<slug:slug>/", "<slug:dealer_slug>/customers/<slug:slug>/",
views.CustomerDetailView.as_view(), views.CustomerDetailView.as_view(),
name="customer_detail", name="customer_detail",
), ),
path( path(
"customers/<slug:slug>/add-note/", "<slug:dealer_slug>/customers/<slug:slug>/add-note/",
views.add_note_to_customer, views.add_note_to_customer,
name="add_note_to_customer", name="add_note_to_customer",
), ),
path( path(
"customers/<slug:slug>/update/", "<slug:dealer_slug>/customers/<slug:slug>/update/",
views.CustomerUpdateView.as_view(), views.CustomerUpdateView.as_view(),
name="customer_update", name="customer_update",
), ),
path( path(
"customers/<slug:slug>/delete/", views.delete_customer, name="customer_delete" "<slug:dealer_slug>/customers/<slug:slug>/delete/", views.delete_customer, name="customer_delete"
), ),
path( path(
"customers/<slug:slug>/opportunities/create/", "<slug:dealer_slug>/customers/<slug:slug>/opportunities/create/",
views.OpportunityCreateView.as_view(), views.OpportunityCreateView.as_view(),
name="create_opportunity", name="create_opportunity",
), ),
path("crm/leads/create/", views.lead_create, name="lead_create"), ########################################
#####Lead
########################################
path("<slug:dealer_slug>/crm/leads/create/", views.lead_create, name="lead_create"),
path( path(
"crm/leads/<slug:slug>/view/", "<slug:dealer_slug>/crm/leads/<slug:slug>/view/",
views.LeadDetailView.as_view(), views.LeadDetailView.as_view(),
name="lead_detail", name="lead_detail",
), ),
path("update-lead-actions/", views.update_lead_actions, name="update_lead_actions"), path("<slug:dealer_slug>/update-lead-actions/", views.update_lead_actions, name="update_lead_actions"),
path("crm/leads/lead_tracking/", views.lead_tracking, name="lead_tracking"), path("<slug:dealer_slug>/crm/leads/lead_tracking/", views.lead_tracking, name="lead_tracking"),
path("crm/leads/lead_view/", views.lead_view, name="lead_view"), path("<slug:dealer_slug>/crm/leads/lead_view/", views.lead_view, name="lead_view"),
path("crm/leads/", views.LeadListView.as_view(), name="lead_list"), path("<slug:dealer_slug>/crm/leads/", views.LeadListView.as_view(), name="lead_list"),
path( path(
"crm/leads/<slug:slug>/update/", "<slug:dealer_slug>/crm/leads/<slug:slug>/update/",
views.LeadUpdateView.as_view(), views.LeadUpdateView.as_view(),
name="lead_update", name="lead_update",
), ),
path("crm/leads/<slug:slug>/delete/", views.LeadDeleteView, name="lead_delete"), path("<slug:dealer_slug>/crm/leads/<slug:slug>/delete/", views.LeadDeleteView, name="lead_delete"),
path( path(
"crm/leads/<slug:slug>/lead-convert/", views.lead_convert, name="lead_convert" "<slug:dealer_slug>/crm/leads/<slug:slug>/lead-convert/", views.lead_convert, name="lead_convert"
), ),
path( path(
"crm/leads/<int:pk>/delete-note/", views.delete_note, name="delete_note_to_lead" "<slug:dealer_slug>/crm/leads/<int:pk>/delete-note/", views.delete_note, name="delete_note_to_lead"
), ),
path( path(
"crm/<int:pk>/update-note/", "<slug:dealer_slug>/crm/<int:pk>/update-note/",
views.update_note, views.update_note,
name="update_note", name="update_note",
), ),
path( path(
"crm/<str:content_type>/<slug:slug>/add-note/", "<slug:dealer_slug>/crm/<str:content_type>/<slug:slug>/add-note/",
views.add_note, views.add_note,
name="add_note", name="add_note",
), ),
path( path(
"crm/<int:pk>/update-task/", "<slug:dealer_slug>/crm/<int:pk>/update-task/",
views.update_task, views.update_task,
name="update_task", name="update_task",
), ),
path( path(
"crm/<str:content_type>/<slug:slug>/add-task/", "<slug:dealer_slug>/crm/<str:content_type>/<slug:slug>/add-task/",
views.add_task, views.add_task,
name="add_task", name="add_task",
), ),
path( path(
"crm/<str:content_type>/<slug:slug>/add-activity/", "<slug:dealer_slug>/crm/<str:content_type>/<slug:slug>/add-activity/",
views.add_activity, views.add_activity,
name="add_activity", name="add_activity",
), ),
path( path(
"crm/leads/<slug:slug>/send_lead_email/", "<slug:dealer_slug>/crm/leads/<slug:slug>/send_lead_email/",
views.send_lead_email, views.send_lead_email,
name="send_lead_email", name="send_lead_email",
), ),
path( path(
"crm/leads/<slug:slug>/send_lead_email/<int:email_pk>", "<slug:dealer_slug>/crm/leads/<slug:slug>/send_lead_email/<int:email_pk>",
views.send_lead_email, views.send_lead_email,
name="send_lead_email_with_template", name="send_lead_email_with_template",
), ),
path( path(
"crm/leads/<slug:slug>/schedule/", "<slug:dealer_slug>/crm/leads/<slug:slug>/schedule/",
views.schedule_lead, views.schedule_lead,
name="schedule_lead", name="schedule_lead",
), ),
path( path(
"crm/leads/schedule/<int:pk>/cancel/", "<slug:dealer_slug>/crm/leads/schedule/<int:pk>/cancel/",
views.schedule_cancel, views.schedule_cancel,
name="schedule_cancel", name="schedule_cancel",
), ),
path( path(
"crm/leads/<slug:slug>/transfer/", "<slug:dealer_slug>/crm/leads/<slug:slug>/transfer/",
views.lead_transfer, views.lead_transfer,
name="lead_transfer", name="lead_transfer",
), ),
path( path(
"crm/opportunities/<slug:slug>/add_note/", "<slug:dealer_slug>/crm/opportunities/<slug:slug>/add_note/",
views.add_note_to_opportunity, views.add_note_to_opportunity,
name="add_note_to_opportunity", name="add_note_to_opportunity",
), ),
path( path(
"crm/opportunities/create/", "<slug:dealer_slug>/crm/opportunities/create/",
views.OpportunityCreateView.as_view(), views.OpportunityCreateView.as_view(),
name="opportunity_create", name="opportunity_create",
), ),
path( path(
"crm/opportunities/<slug:slug>/create/", "<slug:dealer_slug>/crm/opportunities/<slug:slug>/create/",
views.OpportunityCreateView.as_view(), views.OpportunityCreateView.as_view(),
name="lead_opportunity_create", name="lead_opportunity_create",
), ),
path( path(
"crm/opportunities/<slug:slug>/create/", "<slug:dealer_slug>/crm/opportunities/<slug:slug>/create/",
views.OpportunityCreateView.as_view(), views.OpportunityCreateView.as_view(),
name="opportunity_create", name="opportunity_create",
), ),
path( path(
"crm/opportunities/<slug:slug>/", "<slug:dealer_slug>/crm/opportunities/<slug:slug>/",
views.OpportunityDetailView.as_view(), views.OpportunityDetailView.as_view(),
name="opportunity_detail", name="opportunity_detail",
), ),
path( path(
"crm/opportunities/<slug:slug>/edit/", "<slug:dealer_slug>/crm/opportunities/<slug:slug>/edit/",
views.OpportunityUpdateView.as_view(), views.OpportunityUpdateView.as_view(),
name="update_opportunity", name="update_opportunity",
), ),
path( path(
"crm/opportunities/", "<slug:dealer_slug>/crm/opportunities/",
views.OpportunityListView.as_view(), views.OpportunityListView.as_view(),
name="opportunity_list", name="opportunity_list",
), ),
path( path(
"crm/opportunities/<int:pk>/delete/", "<slug:dealer_slug>/crm/opportunities/<int:pk>/delete/",
views.delete_opportunity, views.delete_opportunity,
name="delete_opportunity", name="delete_opportunity",
), ),
path( path(
"crm/opportunities/<slug:slug>/opportunity_update_status/", "<slug:dealer_slug>/crm/opportunities/<slug:slug>/opportunity_update_status/",
views.opportunity_update_status, views.opportunity_update_status,
name="opportunity_update_status", name="opportunity_update_status",
), ),
@ -495,25 +498,25 @@ urlpatterns = [
), ),
# Organization URLs # Organization URLs
path( path(
"organizations/create/", "<slug:dealer_slug>/organizations/create/",
views.OrganizationCreateView.as_view(), views.OrganizationCreateView.as_view(),
name="organization_create", name="organization_create",
), ),
path( path(
"organizations/", views.OrganizationListView.as_view(), name="organization_list" "<slug:dealer_slug>/organizations/", views.OrganizationListView.as_view(), name="organization_list"
), ),
path( path(
"organizations/<slug:slug>/", "<slug:dealer_slug>/organizations/<slug:slug>/",
views.OrganizationDetailView.as_view(), views.OrganizationDetailView.as_view(),
name="organization_detail", name="organization_detail",
), ),
path( path(
"organizations/<slug:slug>/update/", "<slug:dealer_slug>/organizations/<slug:slug>/update/",
views.OrganizationUpdateView.as_view(), views.OrganizationUpdateView.as_view(),
name="organization_update", name="organization_update",
), ),
path( path(
"organizations/<slug:slug>/delete/", "<slug:dealer_slug>/organizations/<slug:slug>/delete/",
views.OrganizationDeleteView, views.OrganizationDeleteView,
name="organization_delete", name="organization_delete",
), ),

View File

@ -2200,7 +2200,7 @@ class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
@login_required @login_required
def add_note_to_customer(request, slug): def add_note_to_customer(request,dealer_slug, slug):
""" """
This function allows authenticated users to add a note to a specific customer. The This function allows authenticated users to add a note to a specific customer. The
note creation is handled by a form, which is validated after submission. If the form note creation is handled by a form, which is validated after submission. If the form
@ -2217,6 +2217,7 @@ def add_note_to_customer(request, slug):
POST request, it renders the note form template with context including POST request, it renders the note form template with context including
the form and customer. the form and customer.
""" """
# get_object_or_404(models.Dealer, slug=dealer_slug)
customer = get_object_or_404(models.Customer, slug=slug) customer = get_object_or_404(models.Customer, slug=slug)
if request.method == "POST": if request.method == "POST":
form = forms.NoteForm(request.POST) form = forms.NoteForm(request.POST)
@ -2226,9 +2227,9 @@ def add_note_to_customer(request, slug):
note.created_by = request.user note.created_by = request.user
note.save() note.save()
return redirect("customer_detail", slug=customer.slug) return redirect("customer_detail", dealer_slug=dealer_slug,slug=customer.slug)
else:
form = forms.NoteForm() form = forms.NoteForm()
return render( return render(
request, "customers/note_form.html", {"form": form, "customer": customer} request, "customers/note_form.html", {"form": form, "customer": customer}
) )
@ -2324,6 +2325,8 @@ class CustomerCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView
form.instance.customer_model = customer form.instance.customer_model = customer
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("customer_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]})
class CustomerUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView): class CustomerUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
@ -2361,10 +2364,11 @@ class CustomerUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView
form.instance.update_user_model() form.instance.update_user_model()
form.instance.update_customer_model() form.instance.update_customer_model()
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("customer_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]})
@login_required @login_required
def delete_customer(request, slug): def delete_customer(request, dealer_slug ,slug):
""" """
Deletes a customer from the system and deactivates the corresponding user account. Deletes a customer from the system and deactivates the corresponding user account.
@ -2383,7 +2387,7 @@ def delete_customer(request, slug):
customer = get_object_or_404(models.Customer, slug=slug) customer = get_object_or_404(models.Customer, slug=slug)
customer.deactivate_account() customer.deactivate_account()
messages.success(request, _("Customer deactivated successfully")) messages.success(request, _("Customer deactivated successfully"))
return redirect("customer_list") return redirect("customer_list", dealer_slug=dealer_slug)
class VendorListView(LoginRequiredMixin, ListView): class VendorListView(LoginRequiredMixin, ListView):
@ -3087,7 +3091,6 @@ class OrganizationDetailView(LoginRequiredMixin, DetailView):
template_name = "organizations/organization_detail.html" template_name = "organizations/organization_detail.html"
context_object_name = "organization" context_object_name = "organization"
class OrganizationCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): class OrganizationCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
""" """
# Handles the creation of a new organization via a web form. This view allows the # Handles the creation of a new organization via a web form. This view allows the
@ -3136,6 +3139,9 @@ class OrganizationCreateView(LoginRequiredMixin, PermissionRequiredMixin, Create
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("organization_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]})
class OrganizationUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView): class OrganizationUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
""" """
@ -3167,9 +3173,11 @@ class OrganizationUpdateView(LoginRequiredMixin, PermissionRequiredMixin, Update
form.instance.update_customer_model() form.instance.update_customer_model()
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("organization_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]})
@login_required @login_required
def OrganizationDeleteView(request, slug): def OrganizationDeleteView(request,dealer_slug, slug):
""" """
Handles the deletion of an organization based on the provided primary key (pk). Looks up Handles the deletion of an organization based on the provided primary key (pk). Looks up
the organization and its corresponding user by email, attempts to delete both, and provides the organization and its corresponding user by email, attempts to delete both, and provides
@ -3186,7 +3194,7 @@ def OrganizationDeleteView(request, slug):
organization = get_object_or_404(models.Organization, slug=slug) organization = get_object_or_404(models.Organization, slug=slug)
organization.deactivate_account() organization.deactivate_account()
messages.success(request, _("Organization Deactivated successfully")) messages.success(request, _("Organization Deactivated successfully"))
return redirect("organization_list") return redirect(reverse_lazy("organization_list", kwargs={"dealer_slug": dealer_slug}))
class RepresentativeListView(LoginRequiredMixin, ListView): class RepresentativeListView(LoginRequiredMixin, ListView):
@ -5130,7 +5138,7 @@ class LeadDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
@login_required @login_required
@permission_required("inventory.add_lead", raise_exception=True) @permission_required("inventory.add_lead", raise_exception=True)
def lead_create(request): def lead_create(request,dealer_slug):
""" """
Handles the creation of a new lead in the inventory system. Handles the creation of a new lead in the inventory system.
@ -5146,7 +5154,7 @@ def lead_create(request):
:return: An HTTP response object rendering the lead creation form or redirecting to the lead list page upon success. :return: An HTTP response object rendering the lead creation form or redirecting to the lead list page upon success.
:rtype: HttpResponse :rtype: HttpResponse
""" """
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
if request.method == "POST": if request.method == "POST":
form = forms.LeadForm(request.POST) form = forms.LeadForm(request.POST)
@ -5201,7 +5209,7 @@ def lead_create(request):
instance.next_action = LeadStatus.NEW instance.next_action = LeadStatus.NEW
instance.save() instance.save()
messages.success(request, _("Lead created successfully")) messages.success(request, _("Lead created successfully"))
return redirect("lead_list") return redirect("lead_list", dealer_slug=dealer.slug)
else: else:
messages.error( messages.error(
request, f"Lead was not created ... : {str(form.errors)}" request, f"Lead was not created ... : {str(form.errors)}"
@ -5234,7 +5242,7 @@ def lead_create(request):
form.fields["staff"].queryset = form.fields["staff"].queryset.filter( form.fields["staff"].queryset = form.fields["staff"].queryset.filter(
dealer=dealer, staff_type="sales" dealer=dealer, staff_type="sales"
) )
print(form.fields["staff"].queryset)
if hasattr(request.user.staffmember, "staff"): if hasattr(request.user.staffmember, "staff"):
form.initial["staff"] = request.user.staffmember.staff form.initial["staff"] = request.user.staffmember.staff
form.fields["staff"].widget.attrs["disabled"] = True form.fields["staff"].widget.attrs["disabled"] = True
@ -5248,8 +5256,8 @@ def lead_create(request):
return render(request, "crm/leads/lead_form.html", {"form": form}) return render(request, "crm/leads/lead_form.html", {"form": form})
def lead_tracking(request): def lead_tracking(request,dealer_slug):
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
new = models.Lead.objects.filter(dealer=dealer, status="new") new = models.Lead.objects.filter(dealer=dealer, status="new")
follow_up = models.Lead.objects.filter( follow_up = models.Lead.objects.filter(
dealer=dealer, next_action__in=["call", "meeting"] dealer=dealer, next_action__in=["call", "meeting"]
@ -5268,7 +5276,7 @@ def lead_tracking(request):
# @require_POST # @require_POST
def update_lead_actions(request): def update_lead_actions(request,dealer_slug):
try: try:
lead_id = request.POST.get("lead_id") lead_id = request.POST.get("lead_id")
current_action = request.POST.get("current_action") current_action = request.POST.get("current_action")
@ -5350,11 +5358,13 @@ class LeadUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
"id_car_model" "id_car_model"
].queryset = form.instance.id_car_make.carmodel_set.all() ].queryset = form.instance.id_car_make.carmodel_set.all()
return form return form
def get_success_url(self):
return reverse_lazy("lead_list",kwargs={"dealer_slug":self.kwargs.get("dealer_slug")})
@login_required @login_required
@permission_required("inventory.delete_lead", raise_exception=True) @permission_required("inventory.delete_lead", raise_exception=True)
def LeadDeleteView(request, slug): def LeadDeleteView(request,dealer_slug, slug):
""" """
Handles the deletion of a Lead along with its associated customer and potentially Handles the deletion of a Lead along with its associated customer and potentially
a related user account in the system. Ensures proper permissions and login a related user account in the system. Ensures proper permissions and login
@ -5373,11 +5383,11 @@ def LeadDeleteView(request, slug):
print(e) print(e)
lead.delete() lead.delete()
messages.success(request, _("Lead deleted successfully")) messages.success(request, _("Lead deleted successfully"))
return redirect("lead_list") return redirect("lead_list",dealer_slug=dealer_slug)
@login_required @login_required
def add_note_to_lead(request, slug): def add_note_to_lead(request,dealer_slug, slug):
""" """
Adds a note to a specific lead. This view is accessible only to authenticated Adds a note to a specific lead. This view is accessible only to authenticated
users. The function handles the POST request to create a new note associated users. The function handles the POST request to create a new note associated
@ -5402,14 +5412,14 @@ def add_note_to_lead(request, slug):
note.created_by = request.user note.created_by = request.user
note.save() note.save()
messages.success(request, _("Note added successfully")) messages.success(request, _("Note added successfully"))
return redirect("lead_detail", slug=lead.slug) return redirect("lead_detail",dealer_slug=dealer_slug, slug=lead.slug)
else: else:
form = forms.NoteForm() form = forms.NoteForm()
return render(request, "crm/note_form.html", {"form": form, "lead": lead}) return render(request, "crm/note_form.html", {"form": form, "lead": lead})
@login_required @login_required
def add_note_to_opportunity(request, slug): def add_note_to_opportunity(request,dealer_slug, slug):
""" """
Add a note to a specific opportunity identified by its primary key. Add a note to a specific opportunity identified by its primary key.
@ -5424,7 +5434,7 @@ def add_note_to_opportunity(request, slug):
:return: A redirect response to the detailed view of the opportunity. :return: A redirect response to the detailed view of the opportunity.
""" """
opportunity = get_object_or_404(models.Opportunity, slug=slug) opportunity = get_object_or_404(models.Opportunity, slug=slug)
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
if request.method == "POST": if request.method == "POST":
notes = request.POST.get("notes") notes = request.POST.get("notes")
if not notes: if not notes:
@ -5437,11 +5447,11 @@ def add_note_to_opportunity(request, slug):
note=notes, note=notes,
) )
messages.success(request, _("Note added successfully")) messages.success(request, _("Note added successfully"))
return redirect("opportunity_detail", slug=opportunity.slug) return redirect("opportunity_detail", dealer_slug=dealer_slug,slug=opportunity.slug)
@login_required @login_required
def delete_note(request, pk): def delete_note(request,dealer_slug, pk):
""" """
Deletes a specific note created by the currently logged-in user and redirects Deletes a specific note created by the currently logged-in user and redirects
to the lead detail page. If the note does not exist or the user is not the creator, to the lead detail page. If the note does not exist or the user is not the creator,
@ -5460,12 +5470,12 @@ def delete_note(request, pk):
lead = models.Lead.objects.get(pk=lead_pk) lead = models.Lead.objects.get(pk=lead_pk)
note.delete() note.delete()
messages.success(request, _("Note deleted successfully.")) messages.success(request, _("Note deleted successfully."))
return redirect("lead_detail", slug=lead.slug) return redirect("lead_detail", dealer_slug=dealer_slug,slug=lead.slug)
@login_required @login_required
@permission_required("inventory.change_lead", raise_exception=True) @permission_required("inventory.change_lead", raise_exception=True)
def lead_convert(request, slug): def lead_convert(request,dealer_slug, slug):
""" """
Converts a lead into a customer and creates a corresponding opportunity. Converts a lead into a customer and creates a corresponding opportunity.
@ -5483,7 +5493,7 @@ def lead_convert(request, slug):
:rtype: HttpResponse :rtype: HttpResponse
""" """
lead = get_object_or_404(models.Lead, slug=slug) lead = get_object_or_404(models.Lead, slug=slug)
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
if hasattr(lead, "opportunity"): if hasattr(lead, "opportunity"):
messages.error(request, _("Lead is already converted to customer")) messages.error(request, _("Lead is already converted to customer"))
else: else:
@ -5497,12 +5507,12 @@ def lead_convert(request, slug):
staff=lead.staff, staff=lead.staff,
) )
messages.success(request, _("Lead converted to customer successfully")) messages.success(request, _("Lead converted to customer successfully"))
return redirect("lead_list") return redirect("lead_list",dealer_slug=dealer_slug)
@login_required @login_required
@permission_required("inventory.add_lead", raise_exception=True) @permission_required("inventory.add_lead", raise_exception=True)
def schedule_lead(request, slug): def schedule_lead(request, dealer_slug,slug):
""" """
Handles the scheduling of a lead for an appointment. Handles the scheduling of a lead for an appointment.
@ -5523,8 +5533,8 @@ def schedule_lead(request, slug):
if not request.is_staff: if not request.is_staff:
messages.error(request, _("You do not have permission to schedule lead")) messages.error(request, _("You do not have permission to schedule lead"))
return redirect("lead_list") return redirect("lead_list", dealer_slug=dealer_slug)
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
lead = get_object_or_404(models.Lead, slug=slug, dealer=dealer) lead = get_object_or_404(models.Lead, slug=slug, dealer=dealer)
if request.method == "POST": if request.method == "POST":
form = forms.ScheduleForm(request.POST) form = forms.ScheduleForm(request.POST)
@ -5547,7 +5557,7 @@ def schedule_lead(request, slug):
) )
except ValidationError as e: except ValidationError as e:
messages.error(request, str(e)) messages.error(request, str(e))
return redirect("schedule_lead", slug=lead.slug) return redirect("schedule_lead", dealer_slug=lead.dealer.slug, slug=lead.slug)
client = get_object_or_404(User, email=lead.email) client = get_object_or_404(User, email=lead.email)
# Create Appointment # Create Appointment
@ -5564,17 +5574,17 @@ def schedule_lead(request, slug):
if lead.opportunity: if lead.opportunity:
return redirect("opportunity_detail", slug=lead.opportunity.slug) return redirect("opportunity_detail", slug=lead.opportunity.slug)
except models.Lead.opportunity.RelatedObjectDoesNotExist: except models.Lead.opportunity.RelatedObjectDoesNotExist:
return redirect("lead_list") return redirect("lead_list", dealer_slug=lead.dealer.slug)
else: else:
messages.error(request, f"Invalid form data: {str(form.errors)}") messages.error(request, f"Invalid form data: {str(form.errors)}")
return redirect("schedule_lead", slug=lead.slug) return redirect("schedule_lead", dealer_slug=dealer_slug,slug=lead.slug)
form = forms.ScheduleForm() form = forms.ScheduleForm()
return render(request, "crm/leads/schedule_lead.html", {"lead": lead, "form": form}) return render(request, "crm/leads/schedule_lead.html", {"lead": lead, "form": form})
@login_required @login_required
@permission_required("inventory.change_lead", raise_exception=True) @permission_required("inventory.change_lead", raise_exception=True)
def lead_transfer(request, slug): def lead_transfer(request,dealer_slug, slug):
""" """
Handles the transfer of a lead to a different staff member. This view is accessible Handles the transfer of a lead to a different staff member. This view is accessible
only to authenticated users with the 'inventory.change_lead' permission. If the only to authenticated users with the 'inventory.change_lead' permission. If the
@ -5586,6 +5596,7 @@ def lead_transfer(request, slug):
:param pk: The primary key of the lead to be transferred. :param pk: The primary key of the lead to be transferred.
:return: An HTTP redirect response to the lead list view. :return: An HTTP redirect response to the lead list view.
""" """
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
lead = get_object_or_404(models.Lead, slug=slug) lead = get_object_or_404(models.Lead, slug=slug)
if request.method == "POST": if request.method == "POST":
form = forms.LeadTransferForm(request.POST) form = forms.LeadTransferForm(request.POST)
@ -5595,11 +5606,11 @@ def lead_transfer(request, slug):
messages.success(request, _("Lead transferred successfully")) messages.success(request, _("Lead transferred successfully"))
else: else:
messages.error(request, f"Invalid form data: {str(form.errors)}") messages.error(request, f"Invalid form data: {str(form.errors)}")
return redirect("lead_list") return redirect("lead_list", dealer_slug=dealer.slug)
@login_required @login_required
def send_lead_email(request, slug, email_pk=None): def send_lead_email(request,dealer_slug, slug, email_pk=None):
""" """
Handles sending emails related to a lead. Supports creating drafts, sending emails, and rendering Handles sending emails related to a lead. Supports creating drafts, sending emails, and rendering
an email composition page. Changes on the lead or email objects, such as marking a lead as contacted an email composition page. Changes on the lead or email objects, such as marking a lead as contacted
@ -5619,9 +5630,9 @@ def send_lead_email(request, slug, email_pk=None):
or email composition rendering, a response object is returned to render the respective page. or email composition rendering, a response object is returned to render the respective page.
Type: HttpResponse Type: HttpResponse
""" """
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
lead = get_object_or_404(models.Lead, slug=slug) lead = get_object_or_404(models.Lead, slug=slug)
status = request.GET.get("status") status = request.GET.get("status")
dealer = get_user_type(request)
if status == "draft": if status == "draft":
models.Email.objects.create( models.Email.objects.create(
content_object=lead, content_object=lead,
@ -5643,17 +5654,17 @@ def send_lead_email(request, slug, email_pk=None):
try: try:
if lead.opportunity: if lead.opportunity:
response = HttpResponse( response = HttpResponse(
redirect("opportunity_detail", slug=lead.opportunity.slug) redirect("opportunity_detail", dealer_slug=dealer_slug,slug=lead.opportunity.slug)
) )
response["HX-Redirect"] = reverse( response["HX-Redirect"] = reverse(
"opportunity_detail", args=[lead.opportunity.slug] "opportunity_detail", args=[lead.opportunity.slug]
) )
else: else:
response = HttpResponse(redirect("lead_detail", slug=lead.slug)) response = HttpResponse(redirect("lead_detail", dealer_slug=dealer_slug,slug=lead.slug))
response["HX-Redirect"] = reverse("lead_detail", args=[lead.slug]) response["HX-Redirect"] = reverse("lead_detail", dealer_slug=dealer_slug,slug=lead.slug)
return response return response
except models.Lead.opportunity.RelatedObjectDoesNotExist: except models.Lead.opportunity.RelatedObjectDoesNotExist:
return redirect("lead_list") return redirect("lead_list",dealer_slug=dealer.slug)
if request.method == "POST": if request.method == "POST":
email_pk = request.POST.get("email_pk") email_pk = request.POST.get("email_pk")
@ -5677,7 +5688,6 @@ def send_lead_email(request, slug, email_pk=None):
request.POST.get("subject"), request.POST.get("subject"),
request.POST.get("message"), request.POST.get("message"),
) )
dealer = get_user_type(request)
models.Activity.objects.create( models.Activity.objects.create(
dealer=dealer, dealer=dealer,
content_object=lead, content_object=lead,
@ -5688,9 +5698,9 @@ def send_lead_email(request, slug, email_pk=None):
messages.success(request, _("Email sent successfully")) messages.success(request, _("Email sent successfully"))
try: try:
if lead.opportunity: if lead.opportunity:
return redirect("opportunity_detail", slug=lead.opportunity.slug) return redirect("opportunity_detail", dealer_slug=dealer_slug,slug=lead.opportunity.slug)
except models.Lead.opportunity.RelatedObjectDoesNotExist: except models.Lead.opportunity.RelatedObjectDoesNotExist:
return redirect("lead_list") return redirect("lead_list",dealer_slug=dealer_slug)
msg = f""" msg = f"""
السلام عليكم السلام عليكم
Dear {lead.full_name}, Dear {lead.full_name},
@ -5784,7 +5794,7 @@ class OpportunityCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin)
def get_initial(self): def get_initial(self):
initial = super().get_initial() initial = super().get_initial()
dealer = get_user_type(self.request) dealer = get_object_or_404(models.Dealer,slug=self.kwargs.get("dealer_slug"))
if self.kwargs.get("slug", None): if self.kwargs.get("slug", None):
lead = models.Lead.objects.get(slug=self.kwargs.get("slug"), dealer=dealer) lead = models.Lead.objects.get(slug=self.kwargs.get("slug"), dealer=dealer)
initial["lead"] = lead initial["lead"] = lead
@ -5792,7 +5802,7 @@ class OpportunityCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin)
return initial return initial
def form_valid(self, form): def form_valid(self, form):
dealer = get_user_type(self.request) dealer = get_object_or_404(models.Dealer,slug=self.kwargs.get("dealer_slug"))
instance = form.save(commit=False) instance = form.save(commit=False)
instance.dealer = dealer instance.dealer = dealer
instance.staff = instance.lead.staff instance.staff = instance.lead.staff
@ -5802,7 +5812,7 @@ class OpportunityCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin)
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self): def get_success_url(self):
return reverse_lazy("opportunity_detail", kwargs={"slug": self.object.slug}) return reverse_lazy("opportunity_detail", kwargs={"dealer_slug":self.kwargs.get("dealer_slug"),"slug": self.object.slug})
class OpportunityUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): class OpportunityUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
@ -5834,7 +5844,7 @@ class OpportunityUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView)
success_message = "Opportunity updated successfully." success_message = "Opportunity updated successfully."
def get_success_url(self): def get_success_url(self):
return reverse_lazy("opportunity_detail", kwargs={"slug": self.object.slug}) return reverse_lazy("opportunity_detail", kwargs={"dealer_slug":self.kwargs.get("dealer_slug"),"slug": self.object.slug})
class OpportunityDetailView(LoginRequiredMixin, DetailView): class OpportunityDetailView(LoginRequiredMixin, DetailView):
@ -5861,7 +5871,7 @@ class OpportunityDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
form = forms.OpportunityStatusForm() form = forms.OpportunityStatusForm()
url = reverse("opportunity_update_status", args=[self.object.slug]) url = reverse("opportunity_update_status", kwargs={"dealer_slug": self.kwargs["dealer_slug"], "slug": self.object.slug})
form.fields["status"].widget.attrs["hx-get"] = url form.fields["status"].widget.attrs["hx-get"] = url
form.fields["stage"].widget.attrs["hx-get"] = url form.fields["stage"].widget.attrs["hx-get"] = url
form.fields["stage"].initial = self.object.stage form.fields["stage"].initial = self.object.stage
@ -5955,7 +5965,7 @@ class OpportunityListView(LoginRequiredMixin, ListView):
@login_required @login_required
def delete_opportunity(request, pk): def delete_opportunity(request,dealer_slug, pk):
""" """
Deletes an opportunity object from the database and redirects to the opportunity Deletes an opportunity object from the database and redirects to the opportunity
list view. If the opportunity with the specified primary key is not found, a 404 list view. If the opportunity with the specified primary key is not found, a 404
@ -5968,14 +5978,15 @@ def delete_opportunity(request, pk):
:return: An HTTP response redirecting to the opportunity list view. :return: An HTTP response redirecting to the opportunity list view.
:rtype: HttpResponse :rtype: HttpResponse
""" """
get_object_or_404(models.Dealer, slug=dealer_slug)
opportunity = get_object_or_404(models.Opportunity, pk=pk) opportunity = get_object_or_404(models.Opportunity, pk=pk)
opportunity.delete() opportunity.delete()
messages.success(request, _("Opportunity deleted successfully")) messages.success(request, _("Opportunity deleted successfully"))
return redirect("opportunity_list") return redirect("opportunity_list",dealer_slug=dealer_slug)
@login_required @login_required
def opportunity_update_status(request, slug): def opportunity_update_status(request,dealer_slug, slug):
""" """
Update the status and/or stage of a specific Opportunity instance. This is a Update the status and/or stage of a specific Opportunity instance. This is a
view function, which is generally tied to a URL endpoint in a Django application. view function, which is generally tied to a URL endpoint in a Django application.
@ -6009,7 +6020,7 @@ def opportunity_update_status(request, slug):
opportunity.stage = stage opportunity.stage = stage
opportunity.save() opportunity.save()
messages.success(request, _("Opportunity status updated successfully")) messages.success(request, _("Opportunity status updated successfully"))
response = HttpResponse(redirect("opportunity_detail", slug=opportunity.slug)) response = HttpResponse(redirect("opportunity_detail",dealer_slug=dealer_slug, slug=opportunity.slug))
response["HX-Refresh"] = "true" response["HX-Refresh"] = "true"
return response return response
@ -8160,7 +8171,7 @@ def DealerSettingsView(request, slug):
@login_required @login_required
def schedule_cancel(request, pk): def schedule_cancel(request,dealer_slug, pk):
""" """
Cancel a schedule by updating its status to "Canceled". The function is protected Cancel a schedule by updating its status to "Canceled". The function is protected
by a login requirement, ensuring only authenticated users can execute it. It by a login requirement, ensuring only authenticated users can execute it. It
@ -8174,6 +8185,7 @@ def schedule_cancel(request, pk):
:return: An HTTP response object with a 200 status code upon successful execution. :return: An HTTP response object with a 200 status code upon successful execution.
:rtype: HttpResponse :rtype: HttpResponse
""" """
get_object_or_404(models.Dealer, slug=dealer_slug)
schedule = get_object_or_404(models.Schedule, pk=pk) schedule = get_object_or_404(models.Schedule, pk=pk)
schedule.status = "Canceled" schedule.status = "Canceled"
schedule.save() schedule.save()
@ -8850,14 +8862,14 @@ def notifications_history(request):
# return render(request, 'activity_history.html') # return render(request, 'activity_history.html')
def add_activity(request, content_type, slug): def add_activity(request,dealer_slug, content_type, slug):
try: try:
model = apps.get_model(f"inventory.{content_type}") model = apps.get_model(f"inventory.{content_type}")
except LookupError: except LookupError:
raise Http404("Model not found") raise Http404("Model not found")
obj = get_object_or_404(model, slug=slug) obj = get_object_or_404(model, slug=slug)
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
if request.method == "POST": if request.method == "POST":
form = forms.ActivityForm(request.POST) form = forms.ActivityForm(request.POST)
if form.is_valid(): if form.is_valid():
@ -8872,17 +8884,17 @@ def add_activity(request, content_type, slug):
messages.success(request, _("Activity added successfully")) messages.success(request, _("Activity added successfully"))
else: else:
messages.error(request, _("Activity form is not valid")) messages.error(request, _("Activity form is not valid"))
return redirect(f"{content_type}_detail", slug=slug) return redirect(f"{content_type}_detail",dealer_slug=dealer_slug, slug=slug)
def add_task(request, content_type, slug): def add_task(request,dealer_slug, content_type, slug):
try: try:
model = apps.get_model(f"inventory.{content_type}") model = apps.get_model(f"inventory.{content_type}")
except LookupError: except LookupError:
raise Http404("Model not found") raise Http404("Model not found")
obj = get_object_or_404(model, slug=slug) obj = get_object_or_404(model, slug=slug)
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
if request.method == "POST": if request.method == "POST":
form = forms.StaffTaskForm(request.POST) form = forms.StaffTaskForm(request.POST)
if form.is_valid(): if form.is_valid():
@ -8895,12 +8907,11 @@ def add_task(request, content_type, slug):
task.save() task.save()
messages.success(request, _("Task added successfully")) messages.success(request, _("Task added successfully"))
else: else:
print(form.errors)
messages.error(request, _("Task form is not valid")) messages.error(request, _("Task form is not valid"))
return redirect(f"{content_type}_detail", slug=slug) return redirect(f"{content_type}_detail",dealer_slug=dealer_slug, slug=slug)
def update_task(request, pk): def update_task(request,dealer_slug, pk):
task = get_object_or_404(models.Tasks, pk=pk) task = get_object_or_404(models.Tasks, pk=pk)
if request.method == "POST": if request.method == "POST":
@ -8912,14 +8923,14 @@ def update_task(request, pk):
return render(request, "partials/task.html", {"task": task}) return render(request, "partials/task.html", {"task": task})
def add_note(request, content_type, slug): def add_note(request,dealer_slug, content_type, slug):
try: try:
model = apps.get_model(f"inventory.{content_type}") model = apps.get_model(f"inventory.{content_type}")
except LookupError: except LookupError:
raise Http404("Model not found") raise Http404("Model not found")
dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
obj = get_object_or_404(model, slug=slug) obj = get_object_or_404(model, slug=slug)
dealer = get_user_type(request)
if request.method == "POST": if request.method == "POST":
form = forms.NoteForm(request.POST) form = forms.NoteForm(request.POST)
if form.is_valid(): if form.is_valid():
@ -8931,20 +8942,19 @@ def add_note(request, content_type, slug):
note.save() note.save()
messages.success(request, _("Note added successfully")) messages.success(request, _("Note added successfully"))
else: else:
print(form.errors)
messages.error(request, _("Note form is not valid")) messages.error(request, _("Note form is not valid"))
return redirect(f"{content_type}_detail", slug=slug) return redirect(f"{content_type}_detail",dealer_slug=dealer_slug, slug=slug)
def update_note(request, pk): def update_note(request,dealer_slug, pk):
note = get_object_or_404(models.Notes, pk=pk) note = get_object_or_404(models.Notes, pk=pk)
lead = get_object_or_404(models.Lead, pk=note.content_object.id) lead = get_object_or_404(models.Lead, pk=note.content_object.id)
dealer = get_user_type(request) dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
if request.method == "POST": if request.method == "POST":
note.note = request.POST.get("note") note.note = request.POST.get("note")
note.save() note.save()
messages.success(request, _("Note updated successfully")) messages.success(request, _("Note updated successfully"))
return redirect("lead_detail", slug=lead.slug) return redirect("lead_detail",dealer_slug=dealer_slug, slug=lead.slug)
else: else:
messages.error(request, _("Note form is not valid")) messages.error(request, _("Note form is not valid"))
notes = models.Notes.objects.filter( notes = models.Notes.objects.filter(

View File

@ -10,7 +10,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_activity' content_type=content_type slug=slug %}" method="post" class="add_activity_form"> <form action="{% url 'add_activity' dealer_slug=request.dealer.slug content_type=content_type slug=slug %}" method="post" class="add_activity_form">
{% csrf_token %} {% csrf_token %}
<div class="mb-2 form-group"> <div class="mb-2 form-group">
<select class="form-select" name="activity_type" id="activity_type"> <select class="form-select" name="activity_type" id="activity_type">

View File

@ -10,7 +10,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_task' content_type slug %}" method="post" class="add_task_form"> <form action="{% url 'add_task' request.dealer.slug content_type slug %}" method="post" class="add_task_form">
{% csrf_token %} {% csrf_token %}
{{ staff_task_form|crispy }} {{ staff_task_form|crispy }}
<button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button>

View File

@ -181,7 +181,7 @@
<div class="modal fade" id="exampleModal" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="exampleModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<form class="modal-content" action="{% url 'lead_transfer' lead.slug %}" method="post"> <form class="modal-content" action="{% url 'lead_transfer' request.dealer.slug lead.slug %}" method="post">
{% csrf_token %} {% csrf_token %}
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Reassign Lead To Another Employee</h5> <h5 class="modal-title" id="exampleModalLabel">Reassign Lead To Another Employee</h5>
@ -252,7 +252,7 @@
<div class="tab-pane fade active show" id="tab-opportunity" role="tabpanel" aria-labelledby="opportunity-tab"> <div class="tab-pane fade active show" id="tab-opportunity" role="tabpanel" aria-labelledby="opportunity-tab">
<div class="mb-1 d-flex justify-content-between align-items-center"> <div class="mb-1 d-flex justify-content-between align-items-center">
<h3 class="mb-4" id="scrollspyTask">{{ _("Opportunities") }} <span class="fw-light fs-7">({{ lead.get_opportunities.count}})</span></h3> <h3 class="mb-4" id="scrollspyTask">{{ _("Opportunities") }} <span class="fw-light fs-7">({{ lead.get_opportunities.count}})</span></h3>
<a href="{% url 'opportunity_create' %}" class="btn btn-phoenix-primary btn-sm" type="button"> <i class="fa-solid fa-plus me-2"></i>{{ _("Add Opportunity") }}</a> <a href="{% url 'lead_opportunity_create' request.dealer.slug lead.slug %}" class="btn btn-phoenix-primary btn-sm" type="button"> <i class="fa-solid fa-plus me-2"></i>{{ _("Add Opportunity") }}</a>
</div> </div>
<div class="border-top border-bottom border-translucent" id="leadDetailsTable"> <div class="border-top border-bottom border-translucent" id="leadDetailsTable">
@ -272,7 +272,7 @@
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{opportunity.car}}</td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{opportunity.car}}</td>
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{opportunity.probability}}</td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{opportunity.probability}}</td>
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{opportunity.priority|capfirst}}</td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{opportunity.priority|capfirst}}</td>
<td class="align-middle text-start fw-bold text-body-tertiary ps-1"><a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' opportunity.slug %}">View</a></td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1"><a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' request.dealer.slug opportunity.slug %}">View</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -316,14 +316,14 @@
class="btn btn-sm btn-phoenix-primary me-2" class="btn btn-sm btn-phoenix-primary me-2"
data-pk="{{ note.pk }}" data-pk="{{ note.pk }}"
data-note="{{ note.note|escapejs }}" data-note="{{ note.note|escapejs }}"
data-url="{% url 'update_note' note.pk %}" data-url="{% url 'update_note' request.dealer.slug note.pk %}"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#noteModal" data-bs-target="#noteModal"
data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>"> data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>">
{{ _("Update") }} {{ _("Update") }}
</a> </a>
<button class="btn btn-phoenix-danger btn-sm delete-btn" <button class="btn btn-phoenix-danger btn-sm delete-btn"
data-url="{% url 'delete_note_to_lead' note.pk %}" data-url="{% url 'delete_note_to_lead' request.dealer.slug note.pk %}"
data-message="Are you sure you want to delete this note?" data-message="Are you sure you want to delete this note?"
data-bs-toggle="modal" data-bs-target="#deleteModal"> data-bs-toggle="modal" data-bs-target="#deleteModal">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>
@ -340,7 +340,7 @@
<div class="tab-pane fade" id="tab-emails" role="tabpanel" aria-labelledby="emails-tab"> <div class="tab-pane fade" id="tab-emails" role="tabpanel" aria-labelledby="emails-tab">
<div class="mb-1 d-flex justify-content-between align-items-center"> <div class="mb-1 d-flex justify-content-between align-items-center">
<h3 class="mb-0" id="scrollspyEmails">{{ _("Emails") }}</h3> <h3 class="mb-0" id="scrollspyEmails">{{ _("Emails") }}</h3>
<a href="{% url 'send_lead_email' lead.slug %}"> <a href="{% url 'send_lead_email' request.dealer.slug lead.slug %}">
<button type="button" class="btn btn-sm btn-phoenix-primary"> <button type="button" class="btn btn-sm btn-phoenix-primary">
<span class="fas fa-plus me-1"></span> <span class="fas fa-plus me-1"></span>
{% trans 'Send Email' %} {% trans 'Send Email' %}
@ -535,7 +535,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_task' 'lead' lead.slug %}" method="post" class="add_task_form"> <form action="{% url 'add_task' request.dealer.slug 'lead' lead.slug %}" method="post" class="add_task_form">
{% csrf_token %} {% csrf_token %}
{{ staff_task_form|crispy }} {{ staff_task_form|crispy }}
<button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button>
@ -555,7 +555,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_note' 'lead' lead.slug %}" method="post" class="add_note_form"> <form action="{% url 'add_note' request.dealer.slug 'lead' lead.slug %}" method="post" class="add_note_form">
{% csrf_token %} {% csrf_token %}
{{ note_form|crispy }} {{ note_form|crispy }}
<button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button>
@ -578,7 +578,7 @@
function reset_form() { function reset_form() {
document.querySelector('#id_note').value = "" document.querySelector('#id_note').value = ""
let form = document.querySelector('.add_note_form') let form = document.querySelector('.add_note_form')
form.action = "{% url 'add_note' 'lead' lead.slug %}" form.action = "{% url 'add_note' request.dealer.slug 'lead' lead.slug %}"
} }
let Toast = Swal.mixin({ let Toast = Swal.mixin({
toast: true, toast: true,
@ -631,7 +631,7 @@
} }
}); });
fetch("{% url 'update_lead_actions' %}", { fetch("{% url 'update_lead_actions' request.dealer.slug %}", {
method: 'POST', method: 'POST',
body: formData, body: formData,
headers: { headers: {

View File

@ -13,7 +13,7 @@
<div class="d-md-flex justify-content-between"> <div class="d-md-flex justify-content-between">
{% if perms.inventory.add_lead %} {% if perms.inventory.add_lead %}
<div> <div>
<a href="{% url 'lead_create' %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{{ _("Add Lead") }}</a> <a href="{% url 'lead_create' request.dealer.slug %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{{ _("Add Lead") }}</a>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -93,7 +93,7 @@
<p>{% trans "Are you sure you want to delete this lead?" %}</p> <p>{% trans "Are you sure you want to delete this lead?" %}</p>
</div> </div>
<div class="modal-footer flex justify-content-center border-top-0"> <div class="modal-footer flex justify-content-center border-top-0">
<a type="button" class="btn btn-sm btn-phoenix-danger w-100" href="{% url 'lead_delete' lead.slug %}"> <a type="button" class="btn btn-sm btn-phoenix-danger w-100" href="{% url 'lead_delete' request.dealer.slug lead.slug %}">
{% trans "Yes" %} {% trans "Yes" %}
</a> </a>
</div> </div>
@ -105,7 +105,7 @@
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="name align-middle white-space-nowrap ps-0"> <td class="name align-middle white-space-nowrap ps-0">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div><a class="fs-8 fw-bold" href="{% url 'lead_detail' lead.slug %}">{{lead.full_name|capfirst}}</a> <div><a class="fs-8 fw-bold" href="{% url 'lead_detail' request.dealer.slug lead.slug %}">{{lead.full_name|capfirst}}</a>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p> <p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p>
{% if lead.status == "new" %} {% if lead.status == "new" %}
@ -210,15 +210,15 @@
</button> </button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
<a href="{% url 'lead_update' lead.slug %}" class="dropdown-item text-success-dark">{% trans "Edit" %}</a> <a href="{% url 'lead_update' request.dealer.slug lead.slug %}" class="dropdown-item text-success-dark">{% trans "Edit" %}</a>
{% endif %} {% endif %}
<button class="dropdown-item text-primary" onclick="openActionModal('{{ lead.pk }}', '{{ lead.action }}', '{{ lead.next_action }}', '{{ lead.next_action_date|date:"Y-m-d\TH:i" }}')"> <button class="dropdown-item text-primary" onclick="openActionModal('{{ lead.pk }}', '{{ lead.action }}', '{{ lead.next_action }}', '{{ lead.next_action_date|date:"Y-m-d\TH:i" }}')">
{% trans "Update Actions" %} {% trans "Update Actions" %}
</button> </button>
<a href="{% url 'send_lead_email' lead.slug %}" class="dropdown-item text-success-dark">{% trans "Send Email" %}</a> <a href="{% url 'send_lead_email' request.dealer.slug lead.slug %}" class="dropdown-item text-success-dark">{% trans "Send Email" %}</a>
<a href="{% url 'schedule_lead' lead.slug %}" class="dropdown-item text-success-dark">{% trans "Schedule Event" %}</a> <a href="{% url 'schedule_lead' request.dealer.slug lead.slug %}" class="dropdown-item text-success-dark">{% trans "Schedule Event" %}</a>
{% if not lead.opportunity %} {% if not lead.opportunity %}
<a href="{% url 'lead_opportunity_create' lead.slug %}" class="dropdown-item text-success-dark">{% trans "Convert to Opportunity" %}</a> <a href="{% url 'lead_opportunity_create' request.dealer.slug lead.slug %}" class="dropdown-item text-success-dark">{% trans "Convert to Opportunity" %}</a>
{% endif %} {% endif %}
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
{% if perms.inventory.delete_lead %} {% if perms.inventory.delete_lead %}
@ -310,7 +310,7 @@
} }
}); });
fetch("{% url 'update_lead_actions' %}", { fetch("{% url 'update_lead_actions' request.dealer.slug %}", {
method: 'POST', method: 'POST',
body: formData, body: formData,
headers: { headers: {

View File

@ -8,7 +8,7 @@
<div class="card email-content"> <div class="card email-content">
<h5 class="card-header">Send Mail</h5> <h5 class="card-header">Send Mail</h5>
<div class="card-body"> <div class="card-body">
<form class="d-flex flex-column h-100" action="{% url 'send_lead_email' lead.slug %}" method="post"> <form class="d-flex flex-column h-100" action="{% url 'send_lead_email' request.dealer.slug lead.slug %}" method="post">
{% csrf_token %} {% csrf_token %}
<div class="row g-3 mb-2"> <div class="row g-3 mb-2">
<div class="col-12"> <div class="col-12">
@ -27,7 +27,7 @@
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div class="d-flex gap-2"> <div class="d-flex gap-2">
<a href="{{ request.META.HTTP_REFERER }}" class="btn btn-phoenix-danger">Discard</a> <a href="{{ request.META.HTTP_REFERER }}" class="btn btn-phoenix-danger">Discard</a>
<a hx-boost="true" hx-push-url='false' hx-include="#message,#subject,#to" href="{% url 'send_lead_email' lead.slug %}?status=draft" class="btn btn-phoenix-success">Save as Draft</a> <a hx-boost="true" hx-push-url='false' hx-include="#message,#subject,#to" href="{% url 'send_lead_email' request.dealer.slug lead.slug %}?status=draft" class="btn btn-phoenix-success">Save as Draft</a>
<button class="btn btn-phoenix-primary fs-10" type="submit">Send<span class="fa-solid fa-paper-plane ms-1"></span></button> <button class="btn btn-phoenix-primary fs-10" type="submit">Send<span class="fa-solid fa-paper-plane ms-1"></span></button>
</div> </div>
</div> </div>

View File

@ -14,7 +14,7 @@
> >
{{ _("Save") }} {{ _("Save") }}
</button> </button>
<a href="{% url 'lead_list' %}" class="btn btn-phoenix-secondary"> <a href="{% url 'lead_list' request.dealer.slug %}" class="btn btn-phoenix-secondary">
{{ _("Cancel") }} {{ _("Cancel") }}
</a> </a>
</form> </form>

View File

@ -6,6 +6,6 @@
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
<button type="submit">Yes, delete</button> <button type="submit">Yes, delete</button>
<a href="{% url 'opportunity_list' %}">Cancel</a> <a href="{% url 'opportunity_list' request.dealer.slug %}">Cancel</a>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -15,11 +15,11 @@
{% if opportunity.estimate %} {% if opportunity.estimate %}
<a class="dropdown-item" href="{% url 'estimate_detail' opportunity.estimate.pk %}">{{ _("View Quotation")}}</a> <a class="dropdown-item" href="{% url 'estimate_detail' opportunity.estimate.pk %}">{{ _("View Quotation")}}</a>
{% else %} {% else %}
<a class="dropdown-item" href="{% url 'estimate_create_from_opportunity' opportunity.slug %}">{{ _("Create Quotation")}}</a> <a class="dropdown-item" href="{% url 'estimate_create_from_opportunity' request.dealer.slug opportunity.slug %}">{{ _("Create Quotation")}}</a>
{% endif %} {% endif %}
</li> </li>
<li><a class="dropdown-item" href="{% url 'update_opportunity' opportunity.slug %}">Update Opportunity</a></li> <li><a class="dropdown-item" href="{% url 'update_opportunity' request.dealer.slug opportunity.slug %}">Update Opportunity</a></li>
<li><a class="dropdown-item" href="{% url 'update_opportunity' opportunity.slug %}">Update Stage</a></li> <li><a class="dropdown-item" href="{% url 'update_opportunity' request.dealer.slug opportunity.slug %}">Update Stage</a></li>
<li><a class="dropdown-item text-danger" href="">Delete Opportunity</a></li> <li><a class="dropdown-item text-danger" href="">Delete Opportunity</a></li>
</ul> </ul>
</div> </div>
@ -392,7 +392,7 @@
</div> </div>
<div class="tab-pane fade" id="tab-notes" role="tabpanel" aria-labelledby="notes-tab"> <div class="tab-pane fade" id="tab-notes" role="tabpanel" aria-labelledby="notes-tab">
<h2 class="mb-4">Notes</h2> <h2 class="mb-4">Notes</h2>
<form action="{% url 'add_note_to_opportunity' opportunity.slug %}" method="post"> <form action="{% url 'add_note_to_opportunity' request.dealer.slug opportunity.slug %}" method="post">
{% csrf_token %} {% csrf_token %}
<textarea class="form-control mb-3" id="notes" rows="4" name="notes" required> </textarea> <textarea class="form-control mb-3" id="notes" rows="4" name="notes" required> </textarea>
<button type="submit" class="btn btn-phoenix-primary mb-3">Add Note</button> <button type="submit" class="btn btn-phoenix-primary mb-3">Add Note</button>
@ -428,7 +428,7 @@
<button class="btn btn-link p-0 ms-3 fs-9 text-primary fw-bold text-decoration-none"><span class="fas fa-sort me-1 fw-extra-bold fs-10"></span>Sorting</button> <button class="btn btn-link p-0 ms-3 fs-9 text-primary fw-bold text-decoration-none"><span class="fas fa-sort me-1 fw-extra-bold fs-10"></span>Sorting</button>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<a href="{% url 'schedule_lead' opportunity.lead.slug %}" class="btn btn-phoenix-primary"><span class="fa-solid fa-plus me-2"></span>Add Meeting </a> <a href="{% url 'schedule_lead' request.dealer.slug opportunity.lead.slug %}" class="btn btn-phoenix-primary"><span class="fa-solid fa-plus me-2"></span>Add Meeting </a>
</div> </div>
</div> </div>
<div class="row g-3"> <div class="row g-3">
@ -456,7 +456,7 @@
</div> </div>
<div class="col-auto"> <div class="col-auto">
<a href="{% url 'schedule_lead' opportunity.lead.slug %}" class="btn btn-phoenix-primary"><span class="fa-solid fa-plus me-2"></span>Add Call</a> <a href="{% url 'schedule_lead' request.dealer.slug opportunity.lead.slug %}" class="btn btn-phoenix-primary"><span class="fa-solid fa-plus me-2"></span>Add Call</a>
</div> </div>
</div> </div>
<pre>{{opportunity.get_all_notes}}</pre> <pre>{{opportunity.get_all_notes}}</pre>
@ -504,7 +504,7 @@
<div class="tab-pane fade" id="tab-emails" role="tabpanel" aria-labelledby="emails-tab"> <div class="tab-pane fade" id="tab-emails" role="tabpanel" aria-labelledby="emails-tab">
<h2 class="mb-4">Emails</h2> <h2 class="mb-4">Emails</h2>
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
<a href="{% url 'send_lead_email' opportunity.lead.slug %}"> <a href="{% url 'send_lead_email' request.dealer.slug opportunity.lead.slug %}">
<button type="button" class="btn btn-sm btn-phoenix-primary"> <button type="button" class="btn btn-sm btn-phoenix-primary">
<span class="fas fa-plus me-1"></span> <span class="fas fa-plus me-1"></span>
{% trans 'Send Email' %} {% trans 'Send Email' %}

View File

@ -21,7 +21,7 @@
</h2> </h2>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<a href="{% url 'opportunity_list' %}" class="btn btn-phoenix-secondary"> <a href="{% url 'opportunity_list' request.dealer.slug %}" class="btn btn-phoenix-secondary">
<span class="fas fa-arrow-left me-2"></span>{% trans "Back to list" %} <span class="fas fa-arrow-left me-2"></span>{% trans "Back to list" %}
</a> </a>
</div> </div>

View File

@ -19,7 +19,7 @@
type="text" type="text"
placeholder="{% trans 'Search opportunities...' %}" placeholder="{% trans 'Search opportunities...' %}"
name="search" name="search"
hx-get="{% url 'opportunity_list' %}" hx-get="{% url 'opportunity_list' request.dealer.slug %}"
hx-trigger="keyup changed delay:500ms" hx-trigger="keyup changed delay:500ms"
hx-target="#opportunities-grid" hx-target="#opportunities-grid"
hx-select="#opportunities-grid" hx-select="#opportunities-grid"
@ -36,7 +36,7 @@
<select <select
class="form-select" class="form-select"
name="stage" name="stage"
hx-get="{% url 'opportunity_list' %}" hx-get="{% url 'opportunity_list' request.dealer.slug %}"
hx-trigger="change" hx-trigger="change"
hx-target="#opportunities-grid" hx-target="#opportunities-grid"
hx-select="#opportunities-grid" hx-select="#opportunities-grid"
@ -57,7 +57,7 @@
<select <select
class="form-select" class="form-select"
name="sort" name="sort"
hx-get="{% url 'opportunity_list' %}" hx-get="{% url 'opportunity_list' request.dealer.slug %}"
hx-trigger="change" hx-trigger="change"
hx-target="#opportunities-grid" hx-target="#opportunities-grid"
hx-select="#opportunities-grid" hx-select="#opportunities-grid"
@ -79,7 +79,7 @@
</div> </div>
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
<a class="btn btn-phoenix-primary btn-sm" href="{% url 'opportunity_create' %}"> <a class="btn btn-phoenix-primary btn-sm" href="{% url 'opportunity_create' request.dealer.slug %}">
<span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }} <span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }}
</a> </a>
</div> </div>

View File

@ -119,10 +119,10 @@
</div> </div>
<div class="d-flex gap-2"> <div class="d-flex gap-2">
<a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' opportunity.slug %}"> <a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' request.dealer.slug opportunity.slug %}">
{{ _("View Details") }} <i class="fa-solid fa-eye ms-2"></i> {{ _("View Details") }} <i class="fa-solid fa-eye ms-2"></i>
</a> </a>
<a class="btn btn-sm btn-phoenix-success" href="{% url 'update_opportunity' opportunity.slug %}"> <a class="btn btn-sm btn-phoenix-success" href="{% url 'update_opportunity' request.dealer.slug opportunity.slug %}">
{{ _("Update") }} <i class="fa-solid fa-pen ms-2"></i> {{ _("Update") }} <i class="fa-solid fa-pen ms-2"></i>
</a> </a>
</div> </div>

View File

@ -12,7 +12,7 @@
<div class="d-md-flex justify-content-between"> <div class="d-md-flex justify-content-between">
{% if perms.django_ledger.add_customermodel %} {% if perms.django_ledger.add_customermodel %}
<div> <div>
<a href="{% url 'customer_create' %}" class="btn btn-sm btn-phoenix-primary me-4"><span class="fas fa-plus me-2"></span>{{ _("Add Customer") }}</a> <a href="{% url 'customer_create' request.dealer.slug %}" class="btn btn-sm btn-phoenix-primary me-4"><span class="fas fa-plus me-2"></span>{{ _("Add Customer") }}</a>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -70,7 +70,7 @@
</td> </td>
<td class="name align-middle white-space-nowrap ps-0"> <td class="name align-middle white-space-nowrap ps-0">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div><a class="fs-8 fw-bold" href="{% url 'customer_detail' customer.slug %}">{{ customer.full_name }}</a> <div><a class="fs-8 fw-bold" href="{% url 'customer_detail' request.dealer.slug customer.slug %}">{{ customer.full_name }}</a>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
</div> </div>
</div> </div>
@ -91,13 +91,13 @@
<td class="date align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 text-body-tertiary">{{ customer.created|date }}</td> <td class="date align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 text-body-tertiary">{{ customer.created|date }}</td>
<td class="align-middle white-space-nowrap text-end pe-0 ps-4"> <td class="align-middle white-space-nowrap text-end pe-0 ps-4">
{% if perms.django_ledger.change_customermodel %} {% if perms.django_ledger.change_customermodel %}
<a href="{% url 'customer_update' customer.slug %}" class="btn btn-sm btn-phoenix-primary me-2" data-url="{% url 'customer_update' customer.slug %}"> <a href="{% url 'customer_update' request.dealer.slug customer.slug %}" class="btn btn-sm btn-phoenix-primary me-2" data-url="{% url 'customer_update' request.dealer.slug customer.slug %}">
<i class="fas fa-pen"></i> <i class="fas fa-pen"></i>
</a> </a>
{% endif %} {% endif %}
{% if perms.django_ledger.delete_customermodel %} {% if perms.django_ledger.delete_customermodel %}
<button class="btn btn-phoenix-danger btn-sm delete-btn" <button class="btn btn-phoenix-danger btn-sm delete-btn"
data-url="{% url 'customer_delete' customer.slug %}" data-url="{% url 'customer_delete' request.dealer.slug customer.slug %}"
data-message="{{ _("Are you sure you want to delete this customer")}}" data-message="{{ _("Are you sure you want to delete this customer")}}"
data-bs-toggle="modal" data-bs-target="#deleteModal"> data-bs-toggle="modal" data-bs-target="#deleteModal">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>

View File

@ -1,6 +1,6 @@
{% load i18n static crispy_forms_filters %} {% load i18n static crispy_forms_filters %}
<form method="post" action="{% url 'add_note_to_customer' customer.slug %}" enctype="multipart/form-data"> <form method="post" action="{% url 'add_note_to_customer' request.dealer.slug customer.slug %}" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" class="btn btn-sm btn-phoenix-success w-100">{{ _("Add") }}</button> <button type="submit" class="btn btn-sm btn-phoenix-success w-100">{{ _("Add") }}</button>

View File

@ -17,7 +17,7 @@
<div class="col-auto"> <div class="col-auto">
{% if perms.django_ledger.delete_customermodel %} {% if perms.django_ledger.delete_customermodel %}
<button class="btn btn-phoenix-danger btn-sm delete-btn" <button class="btn btn-phoenix-danger btn-sm delete-btn"
data-url="{% url 'customer_delete' customer.slug %}" data-url="{% url 'customer_delete' request.dealer.slug customer.slug %}"
data-message="Are you sure you want to delete this customer?" data-message="Are you sure you want to delete this customer?"
data-bs-toggle="modal" data-bs-target="#deleteModal"> data-bs-toggle="modal" data-bs-target="#deleteModal">
<i class="fas fa-trash me-1"> </i>{{ _("Delete") }} <i class="fas fa-trash me-1"> </i>{{ _("Delete") }}
@ -27,7 +27,7 @@
<div class="col-auto"> <div class="col-auto">
{% if perms.django_ledger.change_customermodel %} {% if perms.django_ledger.change_customermodel %}
<a href="{% url 'customer_update' customer.slug %}" class="btn btn-sm btn-phoenix-primary"><span class="fa-solid fa-pen-to-square me-2"></span>{{_("Update")}}</a> <a href="{% url 'customer_update' request.dealer.slug customer.slug %}" class="btn btn-sm btn-phoenix-primary"><span class="fa-solid fa-pen-to-square me-2"></span>{{_("Update")}}</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -85,10 +85,14 @@
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="d-flex align-items-center justify-content-end"> <div class="d-flex align-items-center justify-content-end">
<a id="addBtn" href="#" class="btn btn-sm btn-phoenix-primary mb-3" data-url="{% url 'add_note_to_customer' customer.slug %}" data-bs-toggle="modal" data-bs-target="#noteModal" data-note-title="{{ _("Add") }}<i class='fa fa-plus-circle text-success ms-2'></i>"> <a id="addBtn" href="#" class="btn btn-sm btn-phoenix-primary mb-3" data-url="{% url 'add_note_to_customer' request.dealer.slug customer.slug %}" data-bs-toggle="modal" data-bs-target="#noteModal" data-note-title="{{ _("Add") }}<i class='fa fa-plus-circle text-success ms-2'></i>">
<span class="fas fa-plus me-1"></span> <span class="fas fa-plus me-1"></span>
{% trans 'Add Note' %} {% trans 'Add Note' %}
</a> </a>
{% comment %} <a id="addBtn" class="btn btn-sm btn-phoenix-primary mb-3" hx-get="{% url 'add_note_to_customer' request.dealer.slug customer.slug %}" hx-target=".modal-body" hx-swap="innerHTML" hx-push-url="false" data-bs-toggle="modal" data-bs-target="#noteModal">
<span class="fas fa-plus me-1"></span>
{% trans 'Add Note' %}
</a> {% endcomment %}
</div> </div>
<table class="table fs-9 mb-0 table-responsive"> <table class="table fs-9 mb-0 table-responsive">
<tr> <tr>
@ -208,7 +212,7 @@
const modalBody = noteModal.querySelector(".modal-body"); const modalBody = noteModal.querySelector(".modal-body");
noteModal.addEventListener("show.bs.modal", function (event) { noteModal.addEventListener("", function (event) {
const button = event.relatedTarget; const button = event.relatedTarget;
const url = button.getAttribute("data-url"); const url = button.getAttribute("data-url");
const title = button.getAttribute("data-note-title"); const title = button.getAttribute("data-note-title");

View File

@ -17,12 +17,12 @@
</div> </div>
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 "> <div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 ">
<span class="uil fs-5 lh-1 uil-bolt-alt text-primary"></span> <span class="uil fs-5 lh-1 uil-bolt-alt text-primary"></span>
<a href="{% url 'lead_list' %}"><h4 class="fs-6 pt-3">{{ total_leads }}</h4></a> <a href="{% url 'lead_list' request.dealer.slug %}"><h4 class="fs-6 pt-3">{{ total_leads }}</h4></a>
<p class="fs-9 mb-0">{{ _("Leads")}}</p> <p class="fs-9 mb-0">{{ _("Leads")}}</p>
</div> </div>
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 "> <div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 ">
<span class="uil fs-5 lh-1 uil-user-plus text-warning"></span> <span class="uil fs-5 lh-1 uil-user-plus text-warning"></span>
<a href="{% url 'customer_list' %}"><h4 class="fs-6 pt-3">{{ customers }}</h4></a> <a href="{% url 'customer_list' request.dealer.slug %}"><h4 class="fs-6 pt-3">{{ customers }}</h4></a>
<p class="fs-9 mb-0">{{ _("Customers")}}</p> <p class="fs-9 mb-0">{{ _("Customers")}}</p>
</div> </div>
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 "> <div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 ">

View File

@ -142,21 +142,21 @@
<li class="collapsed-nav-item-title d-none">{% trans 'crm'|upper %}</li> <li class="collapsed-nav-item-title d-none">{% trans 'crm'|upper %}</li>
{% if perms.inventory.view_lead %} {% if perms.inventory.view_lead %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'lead_list' %}"> <a class="nav-link" href="{% url 'lead_list' request.dealer.slug %}">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'leads'|capfirst %}</span> <span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'leads'|capfirst %}</span>
</div> </div>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'lead_tracking' %}"> <a class="nav-link" href="{% url 'lead_tracking' request.dealer.slug %}">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'leads Tracking'|capfirst %}</span> <span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'leads Tracking'|capfirst %}</span>
</div> </div>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'opportunity_list' %}"> <a class="nav-link" href="{% url 'opportunity_list' request.dealer.slug %}">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'Opportunity'|capfirst %}</span> <span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'Opportunity'|capfirst %}</span>
</div> </div>
@ -165,7 +165,7 @@
{% endif %} {% endif %}
{% if perms.django_ledger.view_customermodel %} {% if perms.django_ledger.view_customermodel %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'customer_list' %}"> <a class="nav-link" href="{% url 'customer_list' request.dealer.slug %}">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'customers'|capfirst %}</span> <span class="nav-link-icon"><span data-feather="users"></span></span><span class="nav-link-text">{% trans 'customers'|capfirst %}</span>
</div> </div>
@ -173,7 +173,7 @@
</li> </li>
{% endif %} {% endif %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'organization_list' %}"> <a class="nav-link" href="{% url 'organization_list' request.dealer.slug %}">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-city"></span></span><span class="nav-link-text">{% trans "Organizations"|capfirst %}</span> <span class="nav-link-icon"><span class="fas fa-city"></span></span><span class="nav-link-text">{% trans "Organizations"|capfirst %}</span>
</div> </div>

View File

@ -18,7 +18,7 @@
<div class="d-md-flex justify-content-between"> <div class="d-md-flex justify-content-between">
{% if perms.django_ledger.add_customermodel %} {% if perms.django_ledger.add_customermodel %}
<div> <div>
<a href="{% url 'organization_create' %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{% trans 'add organization'|capfirst %}</a> <a href="{% url 'organization_create' request.dealer.slug %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{% trans 'add organization'|capfirst %}</a>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -85,7 +85,7 @@
{% trans 'Are you sure you want to delete this Organization?' %} {% trans 'Are you sure you want to delete this Organization?' %}
</p> </p>
<button type="button" class="btn btn-phoenix-secondary btn-sm" data-bs-dismiss="modal">{% trans 'No' %}</button> <button type="button" class="btn btn-phoenix-secondary btn-sm" data-bs-dismiss="modal">{% trans 'No' %}</button>
<a type="button" class="btn btn-phoenix-danger btn-sm" href="{% url 'organization_delete' org.slug %}">{% trans 'Yes' %}</a> <a type="button" class="btn btn-phoenix-danger btn-sm" href="{% url 'organization_delete' request.dealer.slug org.slug %}">{% trans 'Yes' %}</a>
</div> </div>
</div> </div>
</div> </div>
@ -94,7 +94,7 @@
<td class="name align-middle white-space-nowrap ps-0 px-1"> <td class="name align-middle white-space-nowrap ps-0 px-1">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div> <div>
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.slug %}">{{ org.name }}</a> <a class="fs-8 fw-bold" href="{% url 'organization_detail' request.dealer.slug org.slug %}">{{ org.name }}</a>
</div> </div>
</div> </div>
</td> </td>
@ -110,7 +110,7 @@
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button> <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'organization_update' org.slug %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a> <a href="{% url 'organization_update' request.dealer.slug org.slug %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
{% if perms.django_ledger.delete_customermodel %} {% if perms.django_ledger.delete_customermodel %}
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans 'Delete' %}</button> <div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans 'Delete' %}</button>
{% endif %} {% endif %}

View File

@ -2,7 +2,7 @@
<tr id="task-{{task.pk}}" class="hover-actions-trigger btn-reveal-trigger position-static {% if task.completed %}completed-task{% endif %}"> <tr id="task-{{task.pk}}" class="hover-actions-trigger btn-reveal-trigger position-static {% if task.completed %}completed-task{% endif %}">
<td class="fs-9 align-middle px-0 py-3"> <td class="fs-9 align-middle px-0 py-3">
<div class="form-check mb-0 fs-8"> <div class="form-check mb-0 fs-8">
<input class="form-check-input" {% if task.completed %}checked{% endif %} type="checkbox" hx-post="{% url 'update_task' task.pk %}" hx-trigger="change" hx-swap="outerHTML" hx-target="#task-{{task.pk}}" /> <input class="form-check-input" {% if task.completed %}checked{% endif %} type="checkbox" hx-post="{% url 'update_task' request.dealer.slug task.pk %}" hx-trigger="change" hx-swap="outerHTML" hx-target="#task-{{task.pk}}" />
</div> </div>
</td> </td>
<td class="subject order align-middle white-space-nowrap py-2 ps-0"><a class="fw-semibold text-primary" href="">{{task.title}}</a> <td class="subject order align-middle white-space-nowrap py-2 ps-0"><a class="fw-semibold text-primary" href="">{{task.title}}</a>