changes
This commit is contained in:
parent
1f2cf5a7ec
commit
778a41aa47
@ -1,3 +1,4 @@
|
||||
from django.urls import reverse
|
||||
from django_countries.widgets import CountrySelectWidget
|
||||
from phonenumber_field.formfields import PhoneNumberField
|
||||
from django.core.validators import MinLengthValidator
|
||||
@ -35,8 +36,7 @@ from .models import (
|
||||
# SaleQuotationCar,
|
||||
AdditionalServices,
|
||||
Staff,
|
||||
Opportunity, Priority, Sources, Lead, Activity, Notes, CarModel,
|
||||
SaleOrder
|
||||
Opportunity, Priority, Sources, Lead, Activity, Notes, CarModel,SaleOrder,CarMake
|
||||
)
|
||||
from django_ledger.models import ItemModel, InvoiceModel, BillModel,VendorModel
|
||||
from django.forms import ModelMultipleChoiceField, ValidationError, DateInput,DateTimeInput
|
||||
@ -650,6 +650,12 @@ class EmailForm(forms.Form):
|
||||
|
||||
|
||||
class LeadForm(forms.ModelForm):
|
||||
id_car_make = forms.ModelChoiceField(label="Make",
|
||||
queryset=CarMake.objects.filter(is_sa_import=True),
|
||||
widget=forms.Select(attrs={"class": "form-control form-control-sm","hx-get":"","hx-include":"#id_id_car_make","hx-select":"#div_id_id_car_model","hx-target":"#div_id_id_car_model","hx-swap":"outerHTML"}),
|
||||
required=True
|
||||
)
|
||||
id_car_model = forms.ModelChoiceField(label="Model", queryset=CarModel.objects.none(),widget=forms.Select(attrs={"class": "form-control form-control-sm"}),required=True)
|
||||
class Meta:
|
||||
model = Lead
|
||||
fields = [
|
||||
@ -658,7 +664,9 @@ class LeadForm(forms.ModelForm):
|
||||
'email',
|
||||
'phone_number',
|
||||
'address',
|
||||
'car',
|
||||
'id_car_make',
|
||||
'id_car_model',
|
||||
'year',
|
||||
'source',
|
||||
'channel',
|
||||
'staff',
|
||||
@ -666,8 +674,8 @@ class LeadForm(forms.ModelForm):
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if "id_car_make" in self.fields:
|
||||
queryset = self.fields["id_car_make"].queryset.filter(is_sa_import=True)
|
||||
self.fields["id_car_make"].choices = [
|
||||
|
||||
14
inventory/migrations/0012_merge_20250206_1308.py
Normal file
14
inventory/migrations/0012_merge_20250206_1308.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Generated by Django 4.2.17 on 2025-02-06 10:08
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0002_alter_carregistration_car'),
|
||||
('inventory', '0011_remove_lead_year_alter_schedule_customer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.17 on 2025-02-06 11:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0012_merge_20250206_1308'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='carregistration',
|
||||
name='text2',
|
||||
field=models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 2'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='carregistration',
|
||||
name='text3',
|
||||
field=models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 3'),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.2.17 on 2025-02-06 12:07
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0013_alter_carregistration_text2_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='car',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lead',
|
||||
name='id_car_make',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lead',
|
||||
name='id_car_model',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lead',
|
||||
name='year',
|
||||
field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Year'),
|
||||
),
|
||||
]
|
||||
@ -1096,26 +1096,26 @@ class Lead(models.Model):
|
||||
CustomerModel, on_delete=models.CASCADE, related_name="leads",
|
||||
null=True,blank=True
|
||||
)
|
||||
car = models.ForeignKey(
|
||||
Car, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("Car")
|
||||
# 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,
|
||||
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(
|
||||
max_length=50, choices=Sources.choices, verbose_name=_("Source")
|
||||
)
|
||||
@ -1167,7 +1167,8 @@ class Lead(models.Model):
|
||||
"email": str(self.email),
|
||||
"address": str(self.address),
|
||||
"phone_number": str(self.phone_number),
|
||||
"car": self.car.to_dict(),
|
||||
"make": str(self.id_car_make.name),
|
||||
"model": str(self.id_car_model.name),
|
||||
"created_at": str(self.created.strftime("%Y-%m-%d")),
|
||||
}
|
||||
@property
|
||||
@ -1225,8 +1226,9 @@ class Schedule(models.Model):
|
||||
def __str__(self):
|
||||
return f"Scheduled {self.purpose} with {self.customer.customer_name} on {self.scheduled_at}"
|
||||
|
||||
@property
|
||||
def schedule_past_date(self):
|
||||
if self.scheduled_at < timezone.now():
|
||||
if self.scheduled_at < now():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@ -319,10 +319,10 @@ def number_to_words_arabic(number):
|
||||
|
||||
return ' '.join(words)
|
||||
|
||||
@register.filter(name='num2words')
|
||||
def num2words(number, language='en'):
|
||||
"""Template filter to convert a number to words in the specified language."""
|
||||
if language == 'ar':
|
||||
return number_to_words_arabic(number)
|
||||
else:
|
||||
return number_to_words_english(number)
|
||||
# @register.filter(name='num2words')
|
||||
# def num2words(number, language='en'):
|
||||
# """Template filter to convert a number to words in the specified language."""
|
||||
# if language == 'ar':
|
||||
# return number_to_words_arabic(number)
|
||||
# else:
|
||||
# return number_to_words_english(number)
|
||||
@ -88,7 +88,7 @@ urlpatterns = [
|
||||
path(
|
||||
"crm/leads/<int:pk>/view/", views.LeadDetailView.as_view(), name="lead_detail"
|
||||
),
|
||||
path("crm/leads/create/", views.LeadCreateView.as_view(), name="lead_create"),
|
||||
path("crm/leads/create/", views.lead_create, name="lead_create"),
|
||||
path(
|
||||
"crm/leads/<int:pk>/update/", views.LeadUpdateView.as_view(), name="lead_update"
|
||||
),
|
||||
@ -194,7 +194,6 @@ urlpatterns = [
|
||||
),
|
||||
path("cars/add/", views.CarCreateView.as_view(), name="car_add"),
|
||||
path("ajax/", views.AjaxHandlerView.as_view(), name="ajax_handler"),
|
||||
path("cars/get-car-models/", views.get_car_models, name="get_car_models"),
|
||||
path(
|
||||
"cars/<int:car_pk>/add-color/", views.CarColorCreate.as_view(), name="add_color"
|
||||
),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from appointment.models import Appointment
|
||||
from calendar import month_name
|
||||
from random import randint
|
||||
from rich import print
|
||||
@ -2944,28 +2945,25 @@ class LeadDetailView(DetailView):
|
||||
return context
|
||||
|
||||
|
||||
class LeadCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin):
|
||||
model = models.Lead
|
||||
form_class = forms.LeadForm
|
||||
template_name = "crm/leads/lead_form.html"
|
||||
success_message = "Lead created successfully!"
|
||||
success_url = reverse_lazy("lead_list")
|
||||
|
||||
def form_valid(self, form):
|
||||
dealer = get_user_type(self.request)
|
||||
form.instance.dealer = dealer
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
def get_car_models(request):
|
||||
make_id = request.GET.get("id_car_make")
|
||||
if make_id:
|
||||
car_models = models.CarModel.objects.filter(id_car_make=make_id).values(
|
||||
"id_car_model", "name", "arabic_name"
|
||||
)
|
||||
return JsonResponse(list(car_models), safe=False)
|
||||
return JsonResponse([], safe=False)
|
||||
def lead_create(request):
|
||||
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))
|
||||
if request.method == "POST":
|
||||
form = forms.LeadForm(request.POST)
|
||||
form.fields['id_car_model'].queryset = models.CarModel.objects.filter(id_car_make=int(request.POST['id_car_make']))
|
||||
if form.is_valid():
|
||||
instance = form.save(commit=False)
|
||||
dealer = get_user_type(request)
|
||||
instance = form.save(commit=False)
|
||||
instance.dealer = dealer
|
||||
instance.save()
|
||||
|
||||
messages.success(request, "Lead created successfully!")
|
||||
return redirect("lead_list")
|
||||
|
||||
return render(request, "crm/leads/lead_form.html", {"form": form})
|
||||
|
||||
class LeadUpdateView(UpdateView):
|
||||
model = models.Lead
|
||||
@ -2973,6 +2971,10 @@ class LeadUpdateView(UpdateView):
|
||||
template_name = "crm/leads/lead_form.html"
|
||||
success_url = reverse_lazy("lead_list")
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
form.fields["id_car_model"].queryset = form.instance.id_car_make.carmodel_set.all()
|
||||
return form
|
||||
|
||||
def LeadDeleteView(request,pk):
|
||||
lead = get_object_or_404(models.Lead, pk=pk)
|
||||
|
||||
@ -4,49 +4,68 @@ from decimal import Decimal
|
||||
from django_ledger.models import EstimateModel,EntityModel
|
||||
from rich import print
|
||||
from datetime import date
|
||||
from inventory.models import VatRate
|
||||
from inventory.models import VatRate,Lead,CarMake,CarModel,Schedule
|
||||
from inventory.utils import CarFinanceCalculator
|
||||
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
def run():
|
||||
# estimate = EstimateModel.objects.first()
|
||||
# calculator = CarFinanceCalculator(estimate)
|
||||
# finance_data = calculator.get_finance_data()
|
||||
User = get_user_model()
|
||||
|
||||
def run():
|
||||
# print(Service.objects.first().pk)
|
||||
# print(Appointment.objects.first().client)
|
||||
|
||||
# print(finance_data)
|
||||
# entity = EntityModel.objects.get(name="ismail")
|
||||
# bs_report = entity.get_balance_sheet_statement(
|
||||
# to_date=date(2025, 1, 1),
|
||||
# save_pdf=False,
|
||||
# filepath='./'
|
||||
# )
|
||||
|
||||
# ic_report = entity.get_income_statement(
|
||||
# from_date=date(2022, 1, 1),
|
||||
# to_date=date(2022, 12, 31),
|
||||
# save_pdf=False,
|
||||
# filepath='./'
|
||||
# appointment = Appointment.objects.create(
|
||||
# client_name="John Doe",
|
||||
# client_email="john@example.com",
|
||||
# service="Haircut",
|
||||
# date_time="2023-10-15 10:00:00",
|
||||
# status="pending")
|
||||
make = CarMake.objects.first()
|
||||
# Lead.objects.create(
|
||||
# first_name="John",
|
||||
# last_name="Doe",
|
||||
# email="john@example.com",
|
||||
# phone_number="123-456-7890",
|
||||
# address="123 Main St",
|
||||
# id_car_make=make,
|
||||
# id_car_model=make.carmodel_set.first(),
|
||||
# year="2022",
|
||||
# source="website",
|
||||
# channel="online",
|
||||
# staff="John Doe",
|
||||
# priority="high",
|
||||
# )
|
||||
|
||||
# # print(bs_report)
|
||||
# print(ic_report.get_report_data())
|
||||
# estimate = EstimateModel.objects.first()
|
||||
# calculator = CarFinanceCalculator(estimate)
|
||||
# finance_data = calculator.get_finance_data()
|
||||
# schedult = Schedule.objects.create(
|
||||
# name="John Doe",
|
||||
# email="john@example.com",
|
||||
# phone_number="123-456-7890",
|
||||
# address="123 Main St",
|
||||
# id_car_make=make,
|
||||
# id_car_model=make.carmodel_set.first(),
|
||||
# year="2022",
|
||||
# source="website",
|
||||
# channel="online",
|
||||
# staff="John Doe",
|
||||
# priority="high",
|
||||
# )
|
||||
service = Service.objects.first()
|
||||
appointment_request = AppointmentRequest.objects.create(
|
||||
date=get_localdate(),
|
||||
start_time=datetime.now().strftime("%H:%M:%S"),
|
||||
end_time=datetime.time(datetime.now() + timedelta(minutes=30)).strftime("%H:%M:%S"),
|
||||
service=service,
|
||||
staff_member=StaffMember.objects.first(),
|
||||
)
|
||||
|
||||
|
||||
# invoice_itemtxs = {
|
||||
# i.get("item_number"): {
|
||||
# "unit_cost": i.get("total_price"),
|
||||
# "quantity": i.get("quantity"),
|
||||
# "total_amount": i.get("total_vat"),
|
||||
# }
|
||||
# for i in finance_data.get("cars")
|
||||
# }
|
||||
# invoice = InvoiceModel.objects.first()
|
||||
entity = EntityModel.objects.filter(name="ismail").first()
|
||||
invoice_qs = InvoiceModel.objects.for_entity(
|
||||
entity_slug=entity.slug,
|
||||
user_model=entity.admin,
|
||||
).unpaid()
|
||||
print(accruable_net_summary(invoice_qs))
|
||||
appointment = Appointment.objects.create(
|
||||
client=User.objects.first(),
|
||||
appointment_request=appointment_request,
|
||||
phone="123-456-7890",
|
||||
address="123 Main St",
|
||||
)
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
<div class="d-flex align-items-center bg-info-subtle rounded me-2"><span class="text-info-dark" data-feather="database"></span></div>
|
||||
<span>{{ _("Source")|capfirst }}</span>
|
||||
</div>
|
||||
</th>``
|
||||
</th>
|
||||
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 10%;">
|
||||
<div class="d-inline-flex flex-center">
|
||||
<div class="d-flex align-items-center bg-warning-subtle rounded me-2"><span class="text-warning-dark" data-feather="grid"></span></div>
|
||||
@ -135,13 +135,13 @@
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="">{{ lead.car.id_car_make.get_local_name }} - {{ lead.car.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.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 %}
|
||||
{% if lead.get_latest_schedule.scheduled_type == "Call" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-primary text-primary fw-semibold"><span class="text-primary" data-feather="phone"></span>
|
||||
<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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user