update on the appointment and lead and more

This commit is contained in:
gitea 2025-02-18 13:32:40 +00:00
parent 491d60b34f
commit 87cac68e8b
11 changed files with 157 additions and 29 deletions

View File

@ -86,6 +86,11 @@ class StaffForm(forms.ModelForm):
widget=forms.EmailInput(attrs={"class": "form-control form-control-sm"}), widget=forms.EmailInput(attrs={"class": "form-control form-control-sm"}),
) )
service_offered = forms.ModelMultipleChoiceField(
label="Services Offered",
widget=forms.CheckboxSelectMultiple(attrs={"class": "form-check-input"}),
queryset=Service.objects.all(),
required=False,)
class Meta: class Meta:
model = Staff model = Staff
fields = ["name", "arabic_name", "phone_number", "staff_type"] fields = ["name", "arabic_name", "phone_number", "staff_type"]
@ -755,10 +760,9 @@ class ScheduleForm(forms.ModelForm):
scheduled_at = forms.DateTimeField( scheduled_at = forms.DateTimeField(
widget=DateTimeInput(attrs={"type": "datetime-local"}) widget=DateTimeInput(attrs={"type": "datetime-local"})
) )
class Meta: class Meta:
model = Schedule model = Schedule
fields = ["purpose", "scheduled_type", "scheduled_at", "duration", "notes"] fields = ["purpose", "scheduled_type", "scheduled_at", "duration", "notes",]
class NoteForm(forms.ModelForm): class NoteForm(forms.ModelForm):

View File

@ -23,7 +23,6 @@ class LogUserActivityMiddleware:
action=action, action=action,
timestamp=timezone.now() timestamp=timezone.now()
) )
return response return response
def get_client_ip(self, request): def get_client_ip(self, request):
@ -43,12 +42,24 @@ class InjectParamsMiddleware:
request.dealer = get_user_type(request) request.dealer = get_user_type(request)
except Exception as e: except Exception as e:
pass pass
response = self.get_response(request) response = self.get_response(request)
return response return response
class InjectDealerMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
dealer = get_user_type(request)
request.user.dealer = dealer
except Exception as e:
pass
response = self.get_response(request)
return response
# class OTPVerificationMiddleware: # class OTPVerificationMiddleware:
# def __init__(self, get_response): # def __init__(self, get_response):
# self.get_response = get_response # self.get_response = get_response

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.17 on 2025-02-18 09:13
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('appointment', '0001_initial'),
('inventory', '0033_alter_schedule_scheduled_by'),
]
operations = [
migrations.RemoveField(
model_name='staff',
name='user',
),
migrations.AddField(
model_name='staff',
name='staff_member',
field=models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='staff_member', to='appointment.staffmember'),
preserve_default=False,
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.2.17 on 2025-02-18 09:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('appointment', '0001_initial'),
('inventory', '0034_remove_staff_user_staff_staff_member'),
]
operations = [
migrations.AlterField(
model_name='staff',
name='staff_member',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='appointment.staffmember'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-18 13:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0035_alter_staff_staff_member'),
]
operations = [
migrations.AlterField(
model_name='schedule',
name='scheduled_type',
field=models.CharField(choices=[('Call', 'Call'), ('Meeting Service', 'Meeting Service'), ('Email', 'Email')], default='Call', max_length=200),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-18 13:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0036_alter_schedule_scheduled_type'),
]
operations = [
migrations.AlterField(
model_name='schedule',
name='scheduled_type',
field=models.CharField(choices=[('Call', 'Call'), ('Meeting', 'Meeting'), ('Email', 'Email')], default='Call', max_length=200),
),
]

View File

@ -18,7 +18,7 @@ from .mixins import LocalizedNameMixin
from django_ledger.models import EntityModel, ItemModel,EstimateModel,InvoiceModel from django_ledger.models import EntityModel, ItemModel,EstimateModel,InvoiceModel
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from appointment.models import StaffMember
class DealerUserManager(UserManager): class DealerUserManager(UserManager):
def create_user_with_dealer( def create_user_with_dealer(
self, self,
@ -925,7 +925,7 @@ class StaffTypes(models.TextChoices):
class Staff(models.Model, LocalizedNameMixin): class Staff(models.Model, LocalizedNameMixin):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="staff") staff_member = models.OneToOneField(StaffMember, on_delete=models.CASCADE, related_name="staff")
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="staff") dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="staff")
name = models.CharField(max_length=255, verbose_name=_("Name")) name = models.CharField(max_length=255, verbose_name=_("Name"))
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name")) arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))

View File

@ -810,7 +810,7 @@ def track_lead_status_change(sender, instance, **kwargs):
def notify_assigned_staff(sender, instance, created, **kwargs): def notify_assigned_staff(sender, instance, created, **kwargs):
if instance.staff: # Check if the lead is assigned if instance.staff: # Check if the lead is assigned
models.Notification.objects.create( models.Notification.objects.create(
user=instance.staff.user, user=instance.staff.staff_member.user,
message=f"You have been assigned a new lead: {instance.full_name}." message=f"You have been assigned a new lead: {instance.full_name}."
) )

View File

@ -99,8 +99,8 @@ def get_user_type(request):
dealer = "" dealer = ""
if hasattr(request.user, "dealer"): if hasattr(request.user, "dealer"):
dealer = request.user.dealer dealer = request.user.dealer
elif hasattr(request.user, "staff"): elif hasattr(request.user, "staffmember"):
dealer = request.user.staff.dealer dealer = request.user.staffmember.staff.dealer
return dealer return dealer

View File

@ -1879,15 +1879,21 @@ class UserCreateView(
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
email = form.cleaned_data["email"] email = form.cleaned_data["email"]
password = "Tenhal@123" password = "Tenhal@123"
user = User.objects.create_user(username=email, email=email, password=password) user = User.objects.create_user(username=form.cleaned_data["name"], email=email, password=password)
user.is_staff = True
user.save()
staff_member = StaffMember.objects.create(user=user)
services = form.cleaned_data["service_offered"]
if services:
for service in services:
staff_member.services_offered.add(service)
staff = form.save(commit=False) staff = form.save(commit=False)
staff.user = user staff.staff_member = staff_member
staff.dealer = dealer
staff.save() staff.save()
return super().form_valid(form) return super().form_valid(form)
@ -1907,6 +1913,30 @@ class UserUpdateView(
kwargs["instance"] = self.get_object() # Pass the Staff instance to the form kwargs["instance"] = self.get_object() # Pass the Staff instance to the form
return kwargs return kwargs
def get_form(self, form_class = None):
form = super().get_form(form_class)
form.fields['email'].disabled = True
return form
def get_initial(self):
initial = super().get_initial()
initial['service_offered'] = self.object.staff_member.services_offered.all()
initial['email'] = self.object.staff_member.user.email
return initial
def form_valid(self, form):
services = form.cleaned_data["service_offered"]
if not services:
self.object.staff_member.services_offered.clear()
else:
for service in services:
self.object.staff_member.services_offered.add(service)
staff = form.save(commit=False)
staff.name = form.cleaned_data["name"]
staff.arabic_name = form.cleaned_data["arabic_name"]
staff.phone_number = form.cleaned_data["phone_number"]
staff.staff_type = form.cleaned_data["staff_type"]
staff.save()
return super().form_valid(form)
def UserDeleteview(request, pk): def UserDeleteview(request, pk):
user = get_object_or_404(models.Staff, pk=pk) user = get_object_or_404(models.Staff, pk=pk)
@ -3205,8 +3235,8 @@ def lead_create(request):
dealer = get_user_type(request) dealer = get_user_type(request)
instance.dealer = dealer instance.dealer = dealer
staff = None staff = None
if hasattr(request.user, "staff"): if hasattr(request.user, "staffmember"):
staff = request.user.staff staff = request.user.staffmember.staff
instance.staff = staff instance.staff = staff
# creating customer in ledger # creating customer in ledger
@ -3313,7 +3343,7 @@ def delete_note(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: if hasattr(lead, "opportunity"):
messages.error(request, "Lead is already converted to customer.") messages.error(request, "Lead is already converted to customer.")
else: else:
customer = lead.convert_to_customer(dealer.entity) customer = lead.convert_to_customer(dealer.entity)
@ -3323,7 +3353,7 @@ def lead_convert(request, pk):
@login_required @login_required
def schedule_lead(request, pk): def schedule_lead(request, pk):
if not request.user.is_staff: if not hasattr(request.user,"staffmember"):
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 = get_user_type(request) dealer = get_user_type(request)
@ -3342,7 +3372,8 @@ def schedule_lead(request, pk):
if not service: if not service:
messages.error(request, "Service not found!") messages.error(request, "Service not found!")
return redirect("lead_list") return redirect("lead_list")
staff_member = StaffMember.objects.filter(user=request.user).first() # staff_member = StaffMember.objects.filter(user=request.user).first()
staff_member = request.user.staffmember
appointment_request = AppointmentRequest.objects.create( appointment_request = AppointmentRequest.objects.create(
date=instance.scheduled_at.date(), date=instance.scheduled_at.date(),
@ -3389,7 +3420,7 @@ def send_lead_email(request, pk,email_pk=None):
if request.method == "POST": if request.method == "POST":
email_pk = request.POST.get('email_pk') email_pk = request.POST.get('email_pk')
if email_pk != "None" or email_pk != "": if email_pk not in [None,"None",""]:
email = get_object_or_404(models.Email, pk=int(email_pk)) email = get_object_or_404(models.Email, pk=int(email_pk))
email.status = models.EmailStatus.SENT email.status = models.EmailStatus.SENT
email.save() email.save()
@ -3401,7 +3432,8 @@ def send_lead_email(request, pk,email_pk=None):
request.POST.get("subject"), request.POST.get("subject"),
request.POST.get("message"), request.POST.get("message"),
) )
models.Activity.objects.create(content_object=lead, notes="Email sent",created_by=request.user,activity_type=models.ActionChoices.EMAIL) dealer = get_user_type(request)
models.Activity.objects.create(dealer=dealer,content_object=lead, notes="Email sent",created_by=request.user,activity_type=models.ActionChoices.EMAIL)
messages.success(request, _("Email sent successfully!")) messages.success(request, _("Email sent successfully!"))
return redirect("lead_list") return redirect("lead_list")
msg = f""" msg = f"""

View File

@ -201,7 +201,7 @@
<a href="{% url 'lead_update' lead.id %}" class="dropdown-item text-success-dark">{% trans "Edit" %}</a> <a href="{% url 'lead_update' lead.id %}" class="dropdown-item text-success-dark">{% trans "Edit" %}</a>
<a href="{% url 'send_lead_email' lead.id %}" class="dropdown-item text-success-dark">{% trans "Send Email" %}</a> <a href="{% url 'send_lead_email' lead.id %}" class="dropdown-item text-success-dark">{% trans "Send Email" %}</a>
<a href="{% url 'schedule_lead' lead.id %}" class="dropdown-item text-success-dark">{% trans "Set Schedule" %}</a> <a href="{% url 'schedule_lead' lead.id %}" class="dropdown-item text-success-dark">{% trans "Set Schedule" %}</a>
{% if not lead.is_converted %} {% if not lead.opportunity %}
<a href="{% url 'lead_convert' lead.id %}" class="dropdown-item text-success-dark">{% trans "Convert To Opportunity" %}</a> <a href="{% url 'lead_convert' lead.id %}" class="dropdown-item text-success-dark">{% trans "Convert To Opportunity" %}</a>
{% endif %} {% endif %}
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>