update
This commit is contained in:
parent
12d480659e
commit
91ef0da13b
@ -51,9 +51,13 @@ class InjectDealerMiddleware:
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
try:
|
||||
dealer = get_user_type(request)
|
||||
request.user.dealer = dealer
|
||||
try:
|
||||
request.is_dealer = False
|
||||
request.is_staff = False
|
||||
if hasattr(request.user, "dealer"):
|
||||
request.is_dealer = True
|
||||
if hasattr(request.user, "staffmember"):
|
||||
request.is_staff = True
|
||||
except Exception as e:
|
||||
pass
|
||||
response = self.get_response(request)
|
||||
|
||||
14
inventory/migrations/0051_merge_20250226_1654.py
Normal file
14
inventory/migrations/0051_merge_20250226_1654.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Generated by Django 4.2.17 on 2025-02-26 13:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0049_alter_lead_status_alter_leadstatushistory_new_status_and_more'),
|
||||
('inventory', '0050_remove_carreservation_reserved_for'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
@ -955,11 +955,11 @@ class Staff(models.Model, LocalizedNameMixin):
|
||||
objects = StaffUserManager()
|
||||
|
||||
@property
|
||||
def get_user(self):
|
||||
def user(self):
|
||||
return self.staff_member.user
|
||||
|
||||
@property
|
||||
def get_groups(self):
|
||||
def groups(self):
|
||||
return [x.customgroup for x in self.user.groups.all()]
|
||||
|
||||
|
||||
@ -1266,6 +1266,8 @@ class Lead(models.Model):
|
||||
|
||||
def get_latest_schedule(self):
|
||||
return self.schedules.order_by('-scheduled_at').first()
|
||||
def get_latest_schedules(self):
|
||||
return self.schedules.filter(scheduled_at__gt=now()).exclude(status='Canceled').order_by('-scheduled_at')[:5]
|
||||
|
||||
class Schedule(models.Model):
|
||||
PURPOSE_CHOICES = [
|
||||
|
||||
@ -122,6 +122,11 @@ urlpatterns = [
|
||||
views.schedule_lead,
|
||||
name="schedule_lead",
|
||||
),
|
||||
path(
|
||||
"crm/leads/schedule/<int:pk>/cancel/",
|
||||
views.schedule_cancel,
|
||||
name="schedule_cancel",
|
||||
),
|
||||
path(
|
||||
"crm/leads/<int:pk>/transfer/",
|
||||
views.lead_transfer,
|
||||
|
||||
@ -95,13 +95,12 @@ def send_email(from_, to_, subject, message):
|
||||
send_mail(subject, message, from_email, recipient_list)
|
||||
|
||||
|
||||
def get_user_type(request):
|
||||
dealer = ""
|
||||
if hasattr(request.user, "dealer"):
|
||||
dealer = request.user.dealer
|
||||
elif hasattr(request.user, "staffmember"):
|
||||
dealer = request.user.staffmember.staff.dealer
|
||||
return dealer
|
||||
def get_user_type(request):
|
||||
if request.is_dealer:
|
||||
return request.user.dealer
|
||||
elif request.is_staff:
|
||||
return request.user.staffmember.staff.dealer
|
||||
return None
|
||||
|
||||
|
||||
def get_dealer_from_instance(instance):
|
||||
|
||||
@ -2632,12 +2632,11 @@ class LeadListView(ListView):
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
print(dealer)
|
||||
qs = models.Lead.objects.filter(dealer=dealer)
|
||||
if self.request.is_dealer:
|
||||
return qs
|
||||
staffmember = getattr(self.request.user, "staffmember", None)
|
||||
if staffmember:
|
||||
qs = models.Lead.objects.filter(dealer=dealer)
|
||||
if staffmember.staff.staff_type == models.StaffTypes.MANAGER:
|
||||
return qs
|
||||
if staffmember and getattr(staffmember, "staff", None):
|
||||
return qs.filter(staff=staffmember.staff)
|
||||
return models.Lead.objects.none()
|
||||
|
||||
@ -3841,4 +3840,12 @@ def DealerSettingsView(request,pk):
|
||||
form.fields['bill_cash_account'].queryset = dealer.entity.get_all_accounts().filter(role=roles.ASSET_CA_CASH)
|
||||
form.fields['bill_prepaid_account'].queryset = dealer.entity.get_all_accounts().filter(role=roles.ASSET_CA_PREPAID)
|
||||
form.fields['bill_unearned_account'].queryset = dealer.entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE)
|
||||
return render(request, 'account/user_settings.html', {'form': form})
|
||||
return render(request, 'account/user_settings.html', {'form': form})
|
||||
|
||||
def schedule_cancel(request,pk):
|
||||
schedule = get_object_or_404(models.Schedule, pk=pk)
|
||||
schedule.status = "Canceled"
|
||||
schedule.save()
|
||||
response = HttpResponse()
|
||||
response.status_code = 200
|
||||
return response
|
||||
@ -135,7 +135,7 @@
|
||||
<ul class="nav main-tab nav-underline fs-9 deal-details scrollbar flex-nowrap w-100 pb-1 mb-6 justify-content-end" id="myTab" role="tablist" style="overflow-y: hidden;">
|
||||
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link active" id="activity-tab" data-bs-toggle="tab" href="#tab-activity" role="tab" aria-controls="tab-activity" aria-selected="false" tabindex="-1"> <span class="fa-solid fa-chart-line me-2 tab-icon-color fs-8"></span>{{ _("Activity") }}</a></li>
|
||||
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="notes-tab" data-bs-toggle="tab" href="#tab-notes" role="tab" aria-controls="tab-notes" aria-selected="false" tabindex="-1"> <span class="fa-solid fa-clipboard me-2 tab-icon-color fs-8"></span>{{ _("Notes") }}</a></li>
|
||||
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="emails-tab" data-bs-toggle="tab" href="#tab-emails" role="tab" aria-controls="tab-emails" aria-selected="true"> <span class="fa-solid fa-envelope me-2 tab-icon-color fs-8"></span>{{ _("Emails") }}</a></li>
|
||||
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="emails-tab" data-bs-toggle="tab" href="#tab-emails" role="tab" aria-controls="tab-emails" aria-selected="true"> <span class="fa-solid fa-envelope me-2 tab-icon-color fs-8"></span>{{ _("Emails") }}</a></li>
|
||||
<li class="nav-item text-nowrap ml-auto" role="presentation">
|
||||
<button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#exampleModal">Reassign Lead</button>
|
||||
<div class="modal fade" id="exampleModal" tabindex="-1" aria-hidden="true">
|
||||
|
||||
@ -136,22 +136,47 @@
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="">{{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="">{{ lead.email }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="tel:{{ lead.phone_number }}">{{ lead.phone_number }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold">
|
||||
{% if lead.get_latest_schedule %}
|
||||
{{lead.get_latest_schedule.scheduled_type}} at <br>
|
||||
<a href="{% url 'appointment:get_user_appointments' %}">
|
||||
{% if lead.get_latest_schedule.scheduled_type == "Call" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-primary text-primary {% if lead.get_latest_schedule.schedule_past_date %}badge-phoenix-danger text-danger{% endif %} fw-semibold"><span class="text-primary {% if lead.get_latest_schedule.schedule_past_date %}text-danger{% endif %}" data-feather="phone"></span>
|
||||
{{ lead.get_latest_schedule.scheduled_at }}</span>
|
||||
{% elif lead.get_latest_schedule.scheduled_type == "Meeting" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-success text-success fw-semibold"><span class="text-success" data-feather="calendar"></span>
|
||||
{{ lead.get_latest_schedule.scheduled_at }}</span>
|
||||
{% elif lead.get_latest_schedule.scheduled_type == "Email" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-warning text-warning fw-semibold"><span class="text-warning" data-feather="email"></span>
|
||||
{{ lead.get_latest_schedule.scheduled_at }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
<td class="align-middle white-space-nowrap fw-semibold">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingTwo">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||
View Schedules ({{lead.get_latest_schedules.count}})
|
||||
</button>
|
||||
</h2>
|
||||
<div class="accordion-collapse collapse" id="collapseTwo" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body pt-0">
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<table><tbody>
|
||||
{% for schedule in lead.get_latest_schedules %}
|
||||
<tr class="schedule-{{ schedule.pk }}">
|
||||
<td class="align-middle white-space-nowrap">
|
||||
{% if schedule.scheduled_type == "Call" %}
|
||||
<a href="{% url 'appointment:get_user_appointments' %}">
|
||||
<span class="badge badge-phoenix badge-phoenix-primary text-primary {% if schedule.schedule_past_date %}badge-phoenix-danger text-danger{% endif %} fw-semibold"><span class="text-primary {% if schedule.schedule_past_date %}text-danger{% endif %}" data-feather="phone"></span>
|
||||
{{ schedule.scheduled_at }}</span></a>
|
||||
{% elif schedule.scheduled_type == "Meeting" %}
|
||||
<a href="{% url 'appointment:get_user_appointments' %}">
|
||||
<span class="badge badge-phoenix badge-phoenix-success text-success fw-semibold"><span class="text-success" data-feather="calendar"></span>
|
||||
{{ schedule.scheduled_at }}</span></a>
|
||||
{% elif schedule.scheduled_type == "Email" %}
|
||||
<a href="{% url 'appointment:get_user_appointments' %}">
|
||||
<span class="badge badge-phoenix badge-phoenix-warning text-warning fw-semibold"><span class="text-warning" data-feather="email"></span>
|
||||
{{ schedule.scheduled_at }}</span></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a style="cursor: pointer;" hx-delete="{% url 'schedule_cancel' schedule.pk %}" hx-target=".schedule-{{ schedule.pk }}" hx-confirm="Are you sure you want to cancel this schedule?"><i class="fa-solid fa-ban text-danger"></i></a>
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr><td><small><a href="{% url 'appointment:get_user_appointments' %}">View All ...</a></small></td></tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.staff|upper }}</td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold text-body-highlight">{{ lead.source|upper }}</td>
|
||||
@ -179,7 +204,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-end">
|
||||
{% if user == lead.staff.user %}
|
||||
{% if user == lead.staff.user or request.is_dealer %}
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
|
||||
@ -402,14 +402,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% if user.is_authenticated and user.dealer or user.staff %}
|
||||
</li>
|
||||
{% if user.is_authenticated and request.is_dealer or request.is_staff %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link lh-1 pe-0" id="navbarDropdownUser" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-haspopup="true" aria-expanded="false">
|
||||
<div class="avatar avatar-l">
|
||||
{% if user.dealer.logo %}
|
||||
<img class="rounded-circle" src="{{ user.dealer.logo.url }}" alt="" />
|
||||
{% elif user.staff.dealer.logo %}
|
||||
{% elif user.staff.dealer.logo %}
|
||||
<img class="rounded-circle" src="{{ user.staff.dealer.logo.url }}" alt="" />
|
||||
{% else %}
|
||||
<span class="fa fa-user text-body-tertiary" style="width: 32px;"></span>
|
||||
@ -430,16 +430,17 @@
|
||||
<span class="fa fa-user text-body-tertiary" style="width: 32px;"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if user.dealer %}
|
||||
|
||||
{% if request.is_dealer %}
|
||||
<h6 class="mt-2 text-body-emphasis">{{ user.dealer.get_local_name }}</h6>
|
||||
{% else %}
|
||||
<h6 class="mt-2 text-body-emphasis">{{ user.staff.get_local_name }}</h6>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<h6 class="mt-2 text-body-emphasis">{{ user.staffmember.staff.get_local_name }}</h6>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-auto scrollbar" style="height: 10rem;">
|
||||
<ul class="nav d-flex flex-column mb-2 pb-1">
|
||||
{% if user.dealer %}
|
||||
{% if request.is_dealer %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 d-block" href="{% url 'dealer_detail' user.dealer.pk %}"> <span class="me-2 text-body align-bottom" data-feather="user"></span><span>{% translate 'profile'|capfirst %}</span></a>
|
||||
</li>
|
||||
@ -448,7 +449,7 @@
|
||||
<a class="nav-link px-3 d-block" href="{% url 'appointment:user_profile' request.user.id %}"> <span class="me-2 text-body align-bottom" data-feather="user"></span><span>{% translate 'profile'|capfirst %}</span></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if user.dealer %}
|
||||
{% if request.is_dealer %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 d-block" href="{% url 'user_list' %}"><span class="me-2 text-body align-bottom" data-feather="users"></span>{{ _("Staff & Group") }}</a>
|
||||
</li>
|
||||
@ -457,7 +458,7 @@
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
{% if user.dealer %}
|
||||
{% if request.is_dealer %}
|
||||
<a class="nav-link px-3 d-block" href="{% url 'dealer_settings' user.dealer.pk %}"> <span class="me-2 text-body align-bottom" data-feather="settings"></span>Settings & Privacy </a>
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user