This commit is contained in:
Marwan Alwali 2025-02-06 11:42:53 +03:00
parent 1aff58a708
commit 43df77dc7b
4 changed files with 62 additions and 43 deletions

View File

@ -658,9 +658,7 @@ class LeadForm(forms.ModelForm):
'email', 'email',
'phone_number', 'phone_number',
'address', 'address',
'id_car_make', 'car',
'id_car_model',
'year',
'source', 'source',
'channel', 'channel',
'staff', 'staff',

View File

@ -1096,23 +1096,26 @@ class Lead(models.Model):
CustomerModel, on_delete=models.CASCADE, related_name="leads", CustomerModel, on_delete=models.CASCADE, related_name="leads",
null=True,blank=True null=True,blank=True
) )
id_car_make = models.ForeignKey( car = models.ForeignKey(
CarMake, Car, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("Car")
on_delete=models.DO_NOTHING,
blank=True,
null=True,
verbose_name=_("Make"),
)
id_car_model = models.ForeignKey(
CarModel,
on_delete=models.DO_NOTHING,
blank=True,
null=True,
verbose_name=_("Model"),
)
year = models.PositiveSmallIntegerField(
verbose_name=_("Year"), blank=True, null=True
) )
# id_car_make = models.ForeignKey(
# CarMake,
# on_delete=models.DO_NOTHING,
# blank=True,
# null=True,
# verbose_name=_("Make"),
# )
# id_car_model = models.ForeignKey(
# CarModel,
# on_delete=models.DO_NOTHING,
# blank=True,
# null=True,
# verbose_name=_("Model"),
# )
# year = models.PositiveSmallIntegerField(
# verbose_name=_("Year"), blank=True, null=True
# )
source = models.CharField( source = models.CharField(
max_length=50, choices=Sources.choices, verbose_name=_("Source") max_length=50, choices=Sources.choices, verbose_name=_("Source")
) )
@ -1152,28 +1155,26 @@ class Lead(models.Model):
def __str__(self): def __str__(self):
return f"{self.first_name} {self.last_name}" return f"{self.first_name} {self.last_name}"
@property @property
def is_converted(self): def is_converted(self):
return bool(self.customer) return bool(self.customer)
def to_dict(self): def to_dict(self):
return { return {
"first_name": str(self.first_name), "first_name": str(self.first_name),
"last_name": str(self.last_name), "last_name": str(self.last_name),
"email": str(self.email), "email": str(self.email),
"address": str(self.address), "address": str(self.address),
"phone_number": str(self.phone_number), "phone_number": str(self.phone_number),
"id_car_make": str(self.id_car_make.name), "car": self.car.to_dict(),
"id_car_model": str(self.id_car_model.name),
"year": str(self.year),
"created_at": str(self.created.strftime("%Y-%m-%d")), "created_at": str(self.created.strftime("%Y-%m-%d")),
} }
@property @property
def full_name(self): def full_name(self):
return f"{self.first_name} {self.last_name}" return f"{self.first_name} {self.last_name}"
def convert_to_customer(self,entity): def convert_to_customer(self,entity):
if entity and not CustomerModel.objects.filter(email=self.email).exists(): if entity and not entity.get_customers().filter(email=self.email).exists():
customer = entity.create_customer( customer = entity.create_customer(
customer_model_kwargs={ customer_model_kwargs={
"customer_name": self.full_name, "customer_name": self.full_name,
@ -1184,10 +1185,10 @@ class Lead(models.Model):
) )
customer.additional_info = {} customer.additional_info = {}
customer.additional_info.update({"info":self.to_dict()}) customer.additional_info.update({"info":self.to_dict()})
self.customer = customer
customer.save() customer.save()
self.customer = customer
self.save() self.save()
def get_latest_schedule(self): def get_latest_schedule(self):
return self.schedules.order_by('-scheduled_at').first() return self.schedules.order_by('-scheduled_at').first()
@ -1205,27 +1206,33 @@ class Schedule(models.Model):
('Meeting', 'Meeting'), ('Meeting', 'Meeting'),
('Email', 'Email'), ('Email', 'Email'),
] ]
ScheduleStatusChoices = [
('Scheduled', 'Scheduled'),
('Completed', 'Completed'),
('Canceled', 'Canceled'),
]
lead = models.ForeignKey(Lead, on_delete=models.CASCADE, related_name='schedules') lead = models.ForeignKey(Lead, on_delete=models.CASCADE, related_name='schedules')
customer = models.ForeignKey(CustomerModel, on_delete=models.CASCADE, related_name='schedules') customer = models.ForeignKey(CustomerModel, on_delete=models.CASCADE, related_name='schedules',null=True,blank=True)
scheduled_by = models.ForeignKey(Staff, on_delete=models.CASCADE) scheduled_by = models.ForeignKey(Staff, on_delete=models.CASCADE)
purpose = models.CharField(max_length=200, choices=PURPOSE_CHOICES) purpose = models.CharField(max_length=200, choices=PURPOSE_CHOICES)
scheduled_at = models.DateTimeField() scheduled_at = models.DateTimeField()
scheduled_type = models.CharField(max_length=200, choices=ScheduledType,default='Call') scheduled_type = models.CharField(max_length=200, choices=ScheduledType,default='Call')
notes = models.TextField(blank=True, null=True) notes = models.TextField(blank=True, null=True)
status = models.CharField(max_length=200, choices=ScheduleStatusChoices, default='Scheduled')
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
def __str__(self): def __str__(self):
return f"Scheduled {self.purpose} with {self.customer.customer_name} on {self.scheduled_at}" return f"Scheduled {self.purpose} with {self.customer.customer_name} on {self.scheduled_at}"
def schedule_past_date(self): def schedule_past_date(self):
if self.scheduled_at < timezone.now(): if self.scheduled_at < timezone.now():
return True return True
return False return False
class Meta: class Meta:
ordering = ['-scheduled_at'] ordering = ['-scheduled_at']
class LeadStatusHistory(models.Model): class LeadStatusHistory(models.Model):
lead = models.ForeignKey( lead = models.ForeignKey(
@ -1260,7 +1267,7 @@ class Opportunity(models.Model):
Dealer, on_delete=models.CASCADE, related_name="opportunities" Dealer, on_delete=models.CASCADE, related_name="opportunities"
) )
customer = models.ForeignKey( customer = models.ForeignKey(
Customer, on_delete=models.CASCADE, related_name="opportunities" CustomerModel, on_delete=models.CASCADE, related_name="opportunities"
) )
car = models.ForeignKey( car = models.ForeignKey(
Car, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_("Car") Car, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_("Car")

View File

@ -116,6 +116,11 @@ urlpatterns = [
views.OpportunityCreateView.as_view(), views.OpportunityCreateView.as_view(),
name="opportunity_create", name="opportunity_create",
), ),
path(
"crm/opportunities/<int:pk>/create/",
views.OpportunityCreateView.as_view(),
name="opportunity_create",
),
path( path(
"crm/opportunities/<int:pk>/", "crm/opportunities/<int:pk>/",
views.OpportunityDetailView.as_view(), views.OpportunityDetailView.as_view(),

View File

@ -2999,9 +2999,13 @@ def add_note_to_lead(request, pk):
def lead_convert(request, pk): def lead_convert(request, pk):
lead = get_object_or_404(models.Lead, pk=pk) lead = get_object_or_404(models.Lead, pk=pk)
dealer = get_user_type(request) dealer = get_user_type(request)
if lead.is_converted:
messages.error(request, "Lead is already converted to customer.")
return redirect("opportunity_create",pk=lead.pk)
lead.convert_to_customer(dealer.entity) lead.convert_to_customer(dealer.entity)
messages.success(request, "Lead converted to customer successfully!") messages.success(request, "Lead converted to customer successfully!")
return redirect("lead_list") return redirect("opportunity_create",pk=lead.pk)
def schedule_lead(request, pk): def schedule_lead(request, pk):
lead = get_object_or_404(models.Lead, pk=pk) lead = get_object_or_404(models.Lead, pk=pk)
@ -3010,7 +3014,6 @@ def schedule_lead(request, pk):
if form.is_valid(): if form.is_valid():
instance = form.save(commit=False) instance = form.save(commit=False)
instance.lead = lead instance.lead = lead
instance.customer = lead.customer
if hasattr(request.user, "staff"): if hasattr(request.user, "staff"):
instance.scheduled_by = request.user.staff instance.scheduled_by = request.user.staff
instance.save() instance.save()
@ -3019,24 +3022,24 @@ def schedule_lead(request, pk):
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")
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})
def send_lead_email(request, pk): def send_lead_email(request, pk):
lead = get_object_or_404(models.Lead, pk=pk) lead = get_object_or_404(models.Lead, pk=pk)
dealer = get_user_type(request) dealer = get_user_type(request)
lead.convert_to_customer(dealer.entity) lead.convert_to_customer(dealer.entity)
if request.method == "POST": if request.method == "POST":
send_email( send_email(
"manager@tenhal.com", "manager@tenhal.com",
request.POST.get("to"), request.POST.get("to"),
request.POST.get("subject"), request.POST.get("subject"),
request.POST.get("message"), request.POST.get("message"),
) )
messages.success(request, "Email sent successfully!") messages.success(request, "Email sent successfully!")
return redirect("lead_list") return redirect("lead_list")
msg = f""" msg = f"""
السلام عليكم السلام عليكم
Dear {lead.full_name}, Dear {lead.full_name},
@ -3088,10 +3091,16 @@ class OpportunityCreateView(CreateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
dealer = get_user_type(self.request) dealer = get_user_type(self.request)
context["customer"] = models.Customer.objects.filter(dealer=dealer)
context["cars"] = models.Car.objects.filter(dealer=dealer)
return context return context
def get_initial(self):
initial = super().get_initial()
if self.kwargs.get('pk',None):
lead = models.Lead.objects.get(pk=self.kwargs.get('pk'))
initial['customer'] = lead.customer
initial['car'] = lead.car
return initial
def form_valid(self, form): def form_valid(self, form):
dealer = get_user_type(self.request) dealer = get_user_type(self.request)
form.instance.dealer = dealer form.instance.dealer = dealer