update in lead and schedule

This commit is contained in:
ismail 2025-05-08 17:00:03 +03:00
parent 90a84934d6
commit f0f3712291
7 changed files with 140 additions and 93 deletions

View File

@ -1014,10 +1014,9 @@ class LeadForm(forms.ModelForm):
id_car_make = forms.ModelChoiceField(
label=_("Make"),
queryset=CarMake.objects.filter(is_sa_import=True),
queryset=CarMake.objects.all(),
widget=forms.Select(
attrs={
"hx-get": "",
"hx-include": "#id_id_car_make",
"hx-select": "#div_id_id_car_model",
@ -1059,13 +1058,15 @@ class LeadForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def filter_qs(self,**kwargs):
dealer = kwargs['dealer']
dealer_make_list = DealersMake.objects.filter(dealer=dealer).values_list("car_make",flat=True)
if "id_car_make" in self.fields:
queryset = self.fields["id_car_make"].queryset.filter(is_sa_import=True)
queryset = self.fields["id_car_make"].queryset.filter(is_sa_import=True,pk__in=dealer_make_list)
self.fields["id_car_make"].choices = [
(obj.id_car_make, obj.get_local_name()) for obj in queryset
]
class ScheduleForm(forms.ModelForm):
"""
Represents a form for scheduling events, extending ModelForm to bind to the

View File

@ -7,6 +7,6 @@ class Command(BaseCommand):
def handle(self, *args, **options):
Service.objects.all().delete()
Service.objects.create(name='Call', price=0,duration=datetime.timedelta(minutes=10),currency='SAR',description='15 min call')
Service.objects.create(name='Meeting', price=0,duration=datetime.timedelta(minutes=30),currency='SAR',description='30 min meeting')
Service.objects.create(name='Visit', price=0,duration=datetime.timedelta(minutes=30),currency='SAR',description='30 min visit')
Service.objects.create(name='call', price=0,duration=datetime.timedelta(minutes=10),currency='SAR',description='15 min call')
Service.objects.create(name='meeting', price=0,duration=datetime.timedelta(minutes=30),currency='SAR',description='30 min meeting')
Service.objects.create(name='email', price=0,duration=datetime.timedelta(minutes=30),currency='SAR',description='30 min visit')

View File

@ -0,0 +1,24 @@
# Generated by Django 5.1.7 on 2025-05-07 14:32
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0010_organization_active'),
]
operations = [
migrations.AddField(
model_name='lead',
name='organization',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organization_leads', to='inventory.organization'),
),
migrations.AlterField(
model_name='lead',
name='customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='customer_leads', to='inventory.customer'),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.7 on 2025-05-08 10:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0011_lead_organization_alter_lead_customer'),
]
operations = [
migrations.AlterField(
model_name='customer',
name='dob',
field=models.DateField(blank=True, null=True, verbose_name='Date of Birth'),
),
migrations.AlterField(
model_name='customer',
name='national_id',
field=models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='National ID'),
),
]

View File

@ -173,7 +173,6 @@ class CarMake(models.Model, LocalizedNameMixin):
class Meta:
verbose_name = _("Make")
class CarModel(models.Model, LocalizedNameMixin):
id_car_model = models.AutoField(primary_key=True)
id_car_make = models.ForeignKey(CarMake, models.DO_NOTHING, db_column="id_car_make")
@ -927,9 +926,10 @@ class Staff(models.Model, LocalizedNameMixin):
def add_group(self,group):
try:
self.user.groups.add(group)
self.add_as_manager()
if self.staff_type in ["accountant","manager"]:
self.add_as_manager()
except Exception as e:
pass
print(e)
def add_as_manager(self):
if self.staff_type in ["accountant","manager"]:
EntityManagementModel.objects.get_or_create(
@ -1049,10 +1049,10 @@ class Customer(models.Model):
max_length=1,
verbose_name=_("Gender"),
)
dob = models.DateField(verbose_name=_("Date of Birth"))
dob = models.DateField(verbose_name=_("Date of Birth"), null=True, blank=True)
email = models.EmailField(unique=True, verbose_name=_("Email"))
national_id = models.CharField(
max_length=10, unique=True, verbose_name=_("National ID")
max_length=10, unique=True, verbose_name=_("National ID"), null=True,blank=True
)
phone_number = PhoneNumberField(
region="SA", unique=True, verbose_name=_("Phone Number")
@ -1095,6 +1095,8 @@ class Customer(models.Model):
except Exception:
pass
customer.save()
self.customer_model = customer
self.save()
return customer
def update_user_model(self):
@ -1127,6 +1129,8 @@ class Customer(models.Model):
)
user.set_password("Tenhal@123")
user.save()
self.user = user
self.save()
return user
def deactivate_account(self):
self.active = False
@ -1184,6 +1188,8 @@ class Organization(models.Model, LocalizedNameMixin):
except Exception:
pass
customer.save()
self.customer_model = customer
self.save()
return customer
def update_user_model(self):
@ -1214,6 +1220,8 @@ class Organization(models.Model, LocalizedNameMixin):
)
user.set_password("Tenhal@123")
user.save()
self.user = user
self.save()
return user
def deactivate_account(self):
@ -1258,12 +1266,13 @@ class Lead(models.Model):
max_length=50, choices=[("customer", _("Customer")), ("organization", _("Organization"))], verbose_name=_("Lead Type")
,default="customer")
customer = models.ForeignKey(
CustomerModel, on_delete=models.CASCADE, related_name="leads",
Customer, on_delete=models.CASCADE, related_name="customer_leads",
null=True,blank=True
)
organization = models.ForeignKey(
Organization, on_delete=models.CASCADE, related_name="organization_leads",
null=True,blank=True
)
# car = models.ForeignKey(
# Car, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("Car")
# )
id_car_make = models.ForeignKey(
CarMake,
on_delete=models.DO_NOTHING,
@ -1347,30 +1356,16 @@ class Lead(models.Model):
@property
def full_name(self):
return f"{self.first_name} {self.last_name}"
def convert_to_customer(self,entity,lead):
customer = entity.get_customers().filter(email=self.email).first()
if entity and not customer:
customer = entity.create_customer(
commit=False,
customer_model_kwargs={
"customer_name": self.full_name,
"address_1": self.address,
"phone": self.phone_number,
"email": self.email,
}
)
customer.additional_info.update({"info":self.to_dict()})
if lead.lead_type == "organization":
customer.additional_info.update({"type":"organization"})
else:
customer.additional_info.update({"type":"customer"})
customer.save()
self.customer = customer
def convert_to_customer(self):
self.status = Status.QUALIFIED
self.save()
return customer
return self.get_customer_model()
def get_customer_model(self):
if self.customer:
return self.customer.customer_model
if self.organization:
return self.organization.customer_model
def get_latest_schedule(self):
return self.schedules.order_by('-scheduled_at').first()
def get_latest_schedules(self):
@ -1378,15 +1373,15 @@ class Lead(models.Model):
def get_all_schedules(self):
return self.schedules.all().order_by('-scheduled_at')
def get_calls(self):
return self.get_all_schedules().filter(scheduled_type='Call')
return self.get_all_schedules().filter(scheduled_type='call')
def get_meetings(self):
return self.get_all_schedules().filter(scheduled_type='Meeting')
return self.get_all_schedules().filter(scheduled_type='meeting')
def get_emails(self):
return Email.objects.filter(content_type__model="lead", object_id=self.id)
return Email.objects.filter(content_type__model="lead", object_id=self.pk)
def get_notes(self):
return Notes.objects.filter(content_type__model="lead", object_id=self.id)
return Notes.objects.filter(content_type__model="lead", object_id=self.pk)
def get_activities(self):
return Activity.objects.filter(content_type__model="lead", object_id=self.id)
return Activity.objects.filter(content_type__model="lead", object_id=self.pk)
class Schedule(models.Model):
PURPOSE_CHOICES = [

View File

@ -150,7 +150,7 @@ from plans.quota import get_user_quota
from django_tables2 import SingleTableView
from django_tables2.export.views import ExportMixin
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
from django.db.models.functions import Lower
from .models import SaleOrder
from .services import (
decodevin,
@ -2494,6 +2494,7 @@ def UserGroupView(request, pk):
if request.method == "POST":
form = forms.UserGroupForm(request.POST)
groups = request.POST.getlist("name")
staff.clear_groups()
for i in groups:
cg = models.CustomGroup.objects.get(id=int(i))
@ -4601,13 +4602,7 @@ def lead_create(request):
:return: An HTTP response object rendering the lead creation form or redirecting to the lead list page upon success.
:rtype: HttpResponse
"""
form = forms.LeadForm()
make = request.GET.get("id_car_make", None)
if make:
form.fields["id_car_model"].queryset = models.CarModel.objects.filter(
id_car_make=int(make)
)
dealer = get_user_type(request)
if request.method == "POST":
form = forms.LeadForm(request.POST)
@ -4620,51 +4615,57 @@ def lead_create(request):
try:
if form.is_valid():
instance = form.save(commit=False)
dealer = get_user_type(request)
instance.dealer = dealer
instance.staff = form.cleaned_data.get("staff")
# creating customer in ledger
customer = (
dealer.entity.get_customers().filter(email=instance.email).first()
)
if not customer:
customer = dealer.entity.create_customer(
commit=False,
customer_model_kwargs={
"customer_name": instance.full_name,
"address_1": instance.address,
"phone": instance.phone_number,
"email": instance.email,
"sales_tax_rate": 0.15,
},
)
customer_info = {
"first_name": instance.first_name,
"last_name": instance.last_name,
"address": instance.address,
"phone_number": str(instance.phone_number),
"email": instance.email,
"crn": form.cleaned_data["crn"],
"vrn": form.cleaned_data["vrn"],
}
customer.additional_info.update({"customer_info": customer_info})
customer.additional_info.update({"type": "lead"})
customer.save()
instance.customer = customer
# try:
# user = User.objects.get(email=customer.email)
# user.first_name = instance.first_name
# user.last_name = instance.last_name
# user.save()
# except Exception as e:
# print(e)
if instance.lead_type == "customer":
customer = models.Customer.objects.filter(email=instance.email)
if not customer:
customer = models.Customer(
dealer=dealer,
address=instance.address,
phone_number=instance.phone_number,
email=instance.email,
first_name=instance.first_name,
last_name=instance.last_name,
)
customer.create_user_model()
customer.create_customer_model()
customer.save()
instance.customer = customer
if instance.lead_type == "organization":
organization = models.Organization.objects.filter(email=instance.email)
if not organization:
organization = models.Organization(
dealer=dealer,
address=instance.address,
phone_number=instance.phone_number,
email=instance.email,
name=instance.first_name + " " + instance.last_name,
)
organization.create_user_model()
organization.create_customer_model()
organization.save()
instance.organization = organization
instance.save()
messages.success(request, _("Lead created successfully"))
return redirect("lead_list")
else:
messages.error(request, f"Lead was not created ... : {str(form.errors)}")
except Exception as e:
messages.error(request, f"Lead was not created ... : {str(e)}")
form = forms.LeadForm()
form.filter_qs(dealer=dealer)
make = request.GET.get("id_car_make", None)
if make:
form.fields["id_car_model"].queryset = models.CarModel.objects.filter(
id_car_make=int(make)
)
return render(request, "crm/leads/lead_form.html", {"form": form})
@ -4870,7 +4871,7 @@ def lead_convert(request, pk):
if hasattr(lead, "opportunity"):
messages.error(request, _("Lead is already converted to customer"))
else:
customer = lead.convert_to_customer(dealer.entity,lead)
customer = lead.convert_to_customer()
models.Opportunity.objects.create(dealer=dealer,customer=customer,lead=lead,probability=50,stage=models.Stage.PROSPECT,staff=lead.staff,status=models.Status.QUALIFIED)
messages.success(request, _("Lead converted to customer successfully"))
return redirect("lead_list")
@ -4896,6 +4897,7 @@ def schedule_lead(request, pk):
method and validity of the form submission.
:rtype: HttpResponse
"""
if not request.is_staff:
messages.error(request, _("You do not have permission to schedule lead"))
return redirect("lead_list")
@ -4907,10 +4909,12 @@ def schedule_lead(request, pk):
instance = form.save(commit=False)
instance.lead = lead
instance.scheduled_by = request.user
instance.customer = lead.customer
instance.customer = lead.get_customer_model()
# Create AppointmentRequest
service,_ = Service.objects.get_or_create(name=instance.scheduled_type,duration=datetime.timedelta(minutes=10),price=0)
# service,_ = Service.objects.get_or_create(name=instance.scheduled_type,duration=datetime.timedelta(minutes=10),price=0)
service = Service.objects.get(name=instance.scheduled_type)
# service = Service.objects.filter(name=instance.scheduled_type).first()
# if not service:
# messages.error(request, "Service not found!")
@ -5008,7 +5012,7 @@ def send_lead_email(request, pk, email_pk=None):
lead.status = models.Status.CONTACTED
lead.save()
# lead.convert_to_customer(dealer.entity)
if request.method == "POST":
email_pk = request.POST.get("email_pk")

View File

@ -153,15 +153,15 @@
{% for schedule in lead.get_latest_schedules %}
<tr class="schedule-{{ schedule.pk }}">
<td class="align-middle white-space-nowrap">
{% if schedule.scheduled_type == "Call" %}
{% 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" %}
{% 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" %}
{% 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>