update
This commit is contained in:
parent
48d70dc084
commit
c4ea8db46e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -35,6 +35,7 @@ admin.site.register(models.Notification)
|
||||
admin.site.register(models.Lead)
|
||||
admin.site.register(models.Activity)
|
||||
admin.site.register(models.Schedule)
|
||||
admin.site.register(models.Notes)
|
||||
|
||||
@admin.register(models.CarMake)
|
||||
class CarMakeAdmin(admin.ModelAdmin):
|
||||
|
||||
@ -737,7 +737,7 @@ class EstimateModelCreateForm(EstimateModelCreateFormBase):
|
||||
'customer': forms.Select(attrs={
|
||||
'id': 'djl-customer-estimate-customer-input',
|
||||
'class': 'input',
|
||||
'label': _('Customer MARWAN'),
|
||||
'label': _('Customer'),
|
||||
}),
|
||||
'terms': forms.Select(attrs={
|
||||
'id': 'djl-customer-estimate-terms-input',
|
||||
|
||||
@ -1224,7 +1224,7 @@ class Schedule(models.Model):
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Scheduled {self.purpose} with {self.customer.customer_name} on {self.scheduled_at}"
|
||||
return f"Scheduled {self.purpose} with {self.lead.full_name} on {self.scheduled_at}"
|
||||
|
||||
def schedule_past_date(self):
|
||||
if self.scheduled_at < timezone.now():
|
||||
|
||||
@ -862,7 +862,7 @@ def create_activity_on_schedule_creation(sender, instance, created, **kwargs):
|
||||
content_object=instance,
|
||||
activity_type='Schedule Created',
|
||||
created_by=instance.scheduled_by.user,
|
||||
notes=f"New schedule created for {instance.purpose} with {instance.customer.customer_name} on {instance.scheduled_at}."
|
||||
notes=f"New schedule created for {instance.purpose} with {instance.lead.full_name} on {instance.scheduled_at}."
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -93,8 +93,10 @@ urlpatterns = [
|
||||
"crm/leads/<int:pk>/update/", views.LeadUpdateView.as_view(), name="lead_update"
|
||||
),
|
||||
path("crm/leads/<int:pk>/delete/", views.LeadDeleteView, name="lead_delete"),
|
||||
path("crm/leads/<int:pk>/add-note/", views.add_note_to_lead, name="add_note"),
|
||||
path("crm/leads/<int:pk>/lead-convert/", views.lead_convert, name="lead_convert"),
|
||||
path("crm/leads/<int:pk>/add-note/", views.add_note_to_lead, name="add_note"),
|
||||
path('crm/leads/<int:pk>/update-note/', views.update_note, name='update_note'),
|
||||
path("crm/leads/<int:pk>/delete-note/", views.delete_note, name="delete_note"),
|
||||
path(
|
||||
"crm/leads/<int:pk>/add-activity/",
|
||||
views.add_activity_to_lead,
|
||||
|
||||
@ -2981,6 +2981,7 @@ def LeadDeleteView(request,pk):
|
||||
return redirect("lead_list")
|
||||
|
||||
|
||||
@login_required
|
||||
def add_note_to_lead(request, pk):
|
||||
lead = get_object_or_404(models.Lead, pk=pk)
|
||||
if request.method == "POST":
|
||||
@ -2988,14 +2989,45 @@ def add_note_to_lead(request, pk):
|
||||
if form.is_valid():
|
||||
note = form.save(commit=False)
|
||||
note.content_object = lead
|
||||
|
||||
note.created_by = request.user
|
||||
note.save()
|
||||
return redirect("lead_detail", pk=pk)
|
||||
messages.success(request, "Note added successfully!")
|
||||
return redirect("lead_detail", pk=lead.pk)
|
||||
else:
|
||||
form = forms.NoteForm()
|
||||
return render(request, "crm/add_note.html", {"form": form, "lead": lead})
|
||||
return render(request, "crm/note_form.html", {"form": form, "lead": lead})
|
||||
|
||||
|
||||
@login_required
|
||||
def update_note(request, pk):
|
||||
note = get_object_or_404(models.Notes, pk=pk, created_by=request.user)
|
||||
lead_pk = note.content_object.pk
|
||||
|
||||
if request.method == "POST":
|
||||
form = forms.NoteForm(request.POST, instance=note)
|
||||
if form.is_valid():
|
||||
updated_note = form.save(commit=False)
|
||||
updated_note.content_object = note.content_object
|
||||
updated_note.created_by = request.user
|
||||
updated_note.save()
|
||||
messages.success(request, "Note updated successfully!")
|
||||
return redirect("lead_detail", pk=lead_pk)
|
||||
else:
|
||||
form = forms.NoteForm(instance=note)
|
||||
|
||||
return render(request, "crm/note_form.html", {"form": form, "note": note})
|
||||
|
||||
|
||||
@login_required
|
||||
def delete_note(request, pk):
|
||||
note = get_object_or_404(models.Notes, pk=pk, created_by=request.user)
|
||||
lead_pk = note.content_object.pk
|
||||
note.delete()
|
||||
messages.success(request, _("Note deleted successfully."))
|
||||
return redirect("lead_detail", pk=lead_pk)
|
||||
|
||||
|
||||
@login_required
|
||||
def lead_convert(request, pk):
|
||||
lead = get_object_or_404(models.Lead, pk=pk)
|
||||
dealer = get_user_type(request)
|
||||
@ -3007,6 +3039,8 @@ def lead_convert(request, pk):
|
||||
messages.success(request, "Lead converted to customer successfully!")
|
||||
return redirect("opportunity_create",pk=lead.pk)
|
||||
|
||||
|
||||
@login_required
|
||||
def schedule_lead(request, pk):
|
||||
lead = get_object_or_404(models.Lead, pk=pk)
|
||||
if request.method == "POST":
|
||||
@ -3026,6 +3060,8 @@ def schedule_lead(request, pk):
|
||||
form = forms.ScheduleForm()
|
||||
return render(request, "crm/leads/schedule_lead.html", {"lead": lead, "form": form})
|
||||
|
||||
|
||||
@login_required
|
||||
def send_lead_email(request, pk):
|
||||
lead = get_object_or_404(models.Lead, pk=pk)
|
||||
dealer = get_user_type(request)
|
||||
@ -3068,6 +3104,8 @@ def send_lead_email(request, pk):
|
||||
{"lead": lead, "message": msg},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def add_activity_to_lead(request, pk):
|
||||
lead = get_object_or_404(models.Lead, pk=pk)
|
||||
if request.method == "POST":
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -63,7 +63,7 @@
|
||||
<!-- Down Payment Field -->
|
||||
<div class="form-floating mb-3">
|
||||
{{ form.down_payment|add_class:"form-control form-control-sm" }}
|
||||
<label for="{{ form.down_payment.id_for_label }}">{{ _("Down Payment<")}}/label>
|
||||
<label for="{{ form.down_payment.id_for_label }}">{{ _("Down Payment")}}</label>
|
||||
{% if form.down_payment.errors %}
|
||||
<div class="alert alert-danger mt-2">
|
||||
{{ form.down_payment.errors }}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static crispy_forms_filters %}
|
||||
{% block content %}
|
||||
<h1>Add Note to {{ lead.first_name }} {{ lead.last_name }}</h1>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-phoenix-primary" type="submit">Add Note</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
{% load i18n static crispy_forms_filters %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% if object %}{{ _("Update") }}{% else %}{{ _("Create") }}{% endif %}</h1>
|
||||
<h3>{% if object %}{{ _("Update") }}{% else %}{{ _("Create") }}{% endif %}</h3>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
17
templates/crm/note_form.html
Normal file
17
templates/crm/note_form.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% load i18n static crispy_forms_filters %}
|
||||
|
||||
{% if form.instance.pk %}
|
||||
<form method="post" action="{% url 'update_note' note.pk %}" enctype="multipart/form-data">
|
||||
{% else %}
|
||||
<form method="post" action="{% url 'add_note' lead.pk %}" enctype="multipart/form-data">
|
||||
{% endif %}
|
||||
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.instance.pk %}
|
||||
<button type="submit" class="btn btn-sm btn-primary w-100">{{ _("Update") }}</button>
|
||||
{% else %}
|
||||
<button type="submit" class="btn btn-sm btn-success w-100">{{ _("Add") }}</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
@ -8,7 +8,7 @@
|
||||
<h2 class="mb-5">{{ _("Opportunities") }}</h2>
|
||||
<div class="d-xl-flex justify-content-between">
|
||||
<div class="mb-3">
|
||||
<a class="btn btn-primary me-4" href="{% url 'opportunity_create' %}"><span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }}</a>
|
||||
<a class="btn btn-sm btn-phoenix-primary me-4" href="{% url 'opportunity_create' %}"><span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -104,16 +104,16 @@
|
||||
<p class="fs-9 mb-1 fw-bold"> {{ _("Probability") }}: %</p>
|
||||
<div class="progress" style="height:16px">
|
||||
{% if opportunity.probability >= 25 and opportunity.probability < 49 %}
|
||||
<div class="progress-bar rounded-pill bg-danger" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bold fs-10 text-sm-end text-secondary me-1">{{ opportunity.probability }}</span>
|
||||
<div class="progress-bar rounded-pill bg-danger-dark" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bolder fs-9 text-sm-end me-1">{{ opportunity.probability }}</span>
|
||||
</div>
|
||||
{% elif opportunity.probability >= 50 and opportunity.probability <= 74 %}
|
||||
<div class="progress-bar rounded-pill bg-warning" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bold fs-10 text-sm-end text-secondary me-1">{{ opportunity.probability }}</span>
|
||||
<div class="progress-bar rounded-pill bg-warning-dark" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bolder fs-9 text-sm-end me-1">{{ opportunity.probability }}</span>
|
||||
</div>
|
||||
{% elif opportunity.probability >= 75 and opportunity.probability <= 100 %}
|
||||
<div class="progress-bar rounded-pill bg-success" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bold fs-10 text-sm-end text-secondary me-1">{{ opportunity.probability }}</span>
|
||||
<div class="progress-bar rounded-pill bg-success-dark" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bolder fs-9 text-sm-end me-1">{{ opportunity.probability }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="col-auto">
|
||||
<div class="d-md-flex justify-content-between">
|
||||
<div>
|
||||
<a href="{% url 'customer_create' %}" class="btn btn-primary me-4"><span class="fas fa-plus me-2"></span>{{ _("Add Customer") }}</a>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -364,7 +364,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Registration Modal -->
|
||||
<div class="modal fade" id="registrationModal" tabindex="-1" aria-labelledby="cregistrationModalLabel" aria-hidden="true">
|
||||
<div class="modal fade" id="registrationModal" tabindex="-1" aria-labelledby="registrationModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
||||
@ -17,38 +17,35 @@
|
||||
{% csrf_token %}
|
||||
{% include 'partials/form_errors.html' %}
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="d-flex flex-column flex-sm-grow-1 p-4">
|
||||
<main class="d-grid gap-4 p-1">
|
||||
<div class="d-flex flex-column flex-sm-grow-1 p-0">
|
||||
|
||||
<div class="row g-4">
|
||||
<h3 class="mb-3">{% trans 'Add Car' %}</h3>
|
||||
|
||||
<!-- VIN -->
|
||||
<div class="col-lg-4 col-xl-6">
|
||||
<div class="card h-100">
|
||||
<div class="card bg-body">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="form-floating">
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
class="form-control form-control-sm"
|
||||
id="{{ form.vin.id_for_label }}" name="{{ form.vin.html_name }}" required/>
|
||||
<label for="{{ form.vin.id_for_label }}">{% trans 'VIN' %}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm my-2">
|
||||
<button type="button"
|
||||
class="btn btn-phoenix-warning fs-8 rounded-start"
|
||||
class="btn btn-warning rounded-start"
|
||||
id="scan-vin-btn"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#scannerModal">
|
||||
<span class="fas fa-camera"></span>
|
||||
<span class="fas fa-camera fs-9"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-phoenix-primary rounded-end" id="decodeVinBtn">
|
||||
{% trans 'Search' %}
|
||||
<button type="button" class="btn btn-sm btn-primary rounded-end ms-1" id="decodeVinBtn">
|
||||
<span class="fas fa-search fs-9 fw-bolder"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="col-6">
|
||||
<div class="form-floating">
|
||||
<span class="text-success fw-bold" id="year-check"></span>
|
||||
@ -70,7 +67,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="row mt-2">
|
||||
<div class="col-6" id="make-row">
|
||||
<div class="form-floating">
|
||||
<span class="text-success fw-bold" id="make-check"></span>
|
||||
@ -89,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="row mt-2">
|
||||
<div class="col-6" id="model-row">
|
||||
<div class="form-floating">
|
||||
<span class="text-success fw-bold" id="model-check"></span>
|
||||
@ -118,18 +115,18 @@
|
||||
disabled>{% trans 'options'|capfirst %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-4 col-xl-6">
|
||||
<div class="row g-3">
|
||||
<div class="row">
|
||||
|
||||
<!--Vendor Field-->
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100">
|
||||
<div class="card bg-body my-1">
|
||||
<div class="card-body">
|
||||
<div class="form-floating">
|
||||
{{ form.vendor|add_class:"form-select form-select-sm" }}
|
||||
@ -142,7 +139,7 @@
|
||||
</div>
|
||||
<!-- Stock Type Card -->
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100">
|
||||
<div class="card bg-body my-1">
|
||||
<div class="card-body">
|
||||
<div class="form-floating">
|
||||
{{ form.stock_type|add_class:"form-select form-select-sm" }}
|
||||
@ -155,7 +152,7 @@
|
||||
</div>
|
||||
<!-- Mileage Card -->
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100">
|
||||
<div class="card bg-body my-1">
|
||||
<div class="card-body">
|
||||
<div class="form-floating">
|
||||
{{ form.mileage|add_class:"form-control form-control-sm" }}
|
||||
@ -167,7 +164,7 @@
|
||||
|
||||
<!-- Receiving Date Field -->
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100 border-1 rounded shadow">
|
||||
<div class="card bg-body my-3">
|
||||
<div class="card-body">
|
||||
<div class="form-floating">
|
||||
{{ form.receiving_date|add_class:"form-control form-control-sm" }}
|
||||
@ -182,7 +179,7 @@
|
||||
|
||||
<!-- Remarks Card -->
|
||||
<div class="col-lg-4 col-xl-8">
|
||||
<div class="card h-100">
|
||||
<div class="card bg-body my-3">
|
||||
<div class="card-body">
|
||||
<div class="form-floating">
|
||||
{{ form.remarks|add_class:"form-control form-control-sm" }}
|
||||
@ -205,10 +202,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<!--Specification Modal-->
|
||||
<div class="modal fade"
|
||||
@ -292,6 +289,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user