diff --git a/inventory/forms.py b/inventory/forms.py index 1d3a1fb4..409c5ad5 100644 --- a/inventory/forms.py +++ b/inventory/forms.py @@ -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 import models as ledger_models 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 = [ @@ -678,7 +686,7 @@ class ScheduleForm(forms.ModelForm): scheduled_at = forms.DateTimeField(widget=DateTimeInput(attrs={'type': 'datetime-local'})) class Meta: model = Schedule - fields = ['purpose','scheduled_type', 'scheduled_at', 'notes'] + fields = ['purpose','scheduled_type', 'scheduled_at','duration', 'notes'] class NoteForm(forms.ModelForm): diff --git a/inventory/migrations/0012_merge_20250206_1308.py b/inventory/migrations/0012_merge_20250206_1308.py new file mode 100644 index 00000000..f185be66 --- /dev/null +++ b/inventory/migrations/0012_merge_20250206_1308.py @@ -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 = [ + ] diff --git a/inventory/migrations/0014_remove_lead_car_lead_id_car_make_lead_id_car_model_and_more.py b/inventory/migrations/0014_remove_lead_car_lead_id_car_make_lead_id_car_model_and_more.py new file mode 100644 index 00000000..fece8a8e --- /dev/null +++ b/inventory/migrations/0014_remove_lead_car_lead_id_car_make_lead_id_car_model_and_more.py @@ -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'), + ), + ] diff --git a/inventory/migrations/0015_merge_20250209_1116.py b/inventory/migrations/0015_merge_20250209_1116.py new file mode 100644 index 00000000..a5a709bd --- /dev/null +++ b/inventory/migrations/0015_merge_20250209_1116.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.17 on 2025-02-09 08:16 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0012_merge_20250206_1308'), + ('inventory', '0014_remove_lead_car_lead_id_car_make_lead_id_car_model_and_more'), + ] + + operations = [ + ] diff --git a/inventory/migrations/0016_schedule_duration.py b/inventory/migrations/0016_schedule_duration.py new file mode 100644 index 00000000..82536c79 --- /dev/null +++ b/inventory/migrations/0016_schedule_duration.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.17 on 2025-02-09 08:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0015_merge_20250209_1116'), + ] + + operations = [ + migrations.AddField( + model_name='schedule', + name='duration', + field=models.DurationField(default=datetime.timedelta(seconds=300)), + ), + ] diff --git a/inventory/migrations/0017_car_hash.py b/inventory/migrations/0017_car_hash.py new file mode 100644 index 00000000..88457273 --- /dev/null +++ b/inventory/migrations/0017_car_hash.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.17 on 2025-02-09 11:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0016_schedule_duration'), + ] + + operations = [ + migrations.AddField( + model_name='car', + name='hash', + field=models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash'), + ), + ] diff --git a/inventory/models.py b/inventory/models.py index 493b3740..e867d83f 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -1,38 +1,21 @@ -# from datetime import timezone -from django.utils import timezone -import itertools -from uuid import uuid4 -from django.conf import settings -from django.db import models, transaction -from django.db.models import Sum, F, Count +from decimal import Decimal +import hashlib +from django.db import models +from datetime import timedelta from django.contrib.auth.models import User, UserManager -from django.db.models.signals import pre_save, post_save -from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ from django_ledger.models import ( VendorModel, EntityModel, - EntityUnitModel, ItemModel, - AccountModel, - ItemModelAbstract, - UnitOfMeasureModel, CustomerModel, - ItemModelQuerySet, ) from django_ledger.io.io_core import get_localdate -from django.db.models import Sum -from decimal import Decimal, InvalidOperation from django.core.exceptions import ValidationError from phonenumber_field.modelfields import PhoneNumberField from django.utils.timezone import now -from sqlalchemy.orm.base import object_state - -from .utilities.financials import get_financial_value, get_total, get_total_financials -from django.db.models import FloatField from .mixins import LocalizedNameMixin from django_ledger.models import EntityModel, ItemModel,EstimateModel,InvoiceModel -from django_countries.fields import CountryField from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType @@ -403,6 +386,11 @@ class Car(models.Model): remarks = models.TextField(blank=True, null=True, verbose_name=_("Remarks")) mileage = models.IntegerField(blank=True, null=True, verbose_name=_("Mileage")) receiving_date = models.DateTimeField(verbose_name=_("Receiving Date")) + hash = models.CharField(max_length=64, blank=True, null=True, verbose_name=_("Hash")) + + def save(self, *args, **kwargs): + self.hash = self.get_hash + super(Car, self).save(*args, **kwargs) class Meta: verbose_name = _("Car") @@ -424,6 +412,12 @@ class Car(models.Model): def get_car_group(self): return f"{self.id_car_make.get_local_name} {self.id_car_model.get_local_name}" + @property + def get_hash(self): + hash_object = hashlib.sha256() + hash_object.update(f"{self.id_car_make.name}{self.id_car_model.name}".encode('utf-8')) + return hash_object.hexdigest() + def to_dict(self): return { "vin": self.vin, @@ -437,6 +431,7 @@ class Car(models.Model): "remarks": self.remarks, "mileage": self.mileage, "receiving_date": self.receiving_date.strftime('%Y-%m-%d %H:%M:%S'), + 'hash': self.get_hash, "id": self.id, } @@ -1097,26 +1092,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") ) @@ -1168,14 +1163,16 @@ 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 def full_name(self): return f"{self.first_name} {self.last_name}" def convert_to_customer(self,entity): - if entity and not entity.get_customers().filter(email=self.email).exists(): + customer = entity.get_customers().filter(email=self.email).first() + if entity and not customer: customer = entity.create_customer( customer_model_kwargs={ "customer_name": self.full_name, @@ -1183,12 +1180,13 @@ class Lead(models.Model): "phone": self.phone_number, "email": self.email, } - ) - customer.additional_info = {} - customer.additional_info.update({"info":self.to_dict()}) - self.customer = customer - customer.save() - self.save() + ) + + customer.additional_info = {} + customer.additional_info.update({"info":self.to_dict()}) + self.customer = customer + customer.save() + self.save() def get_latest_schedule(self): return self.schedules.order_by('-scheduled_at').first() @@ -1218,6 +1216,7 @@ class Schedule(models.Model): purpose = models.CharField(max_length=200, choices=PURPOSE_CHOICES) scheduled_at = models.DateTimeField() scheduled_type = models.CharField(max_length=200, choices=ScheduledType,default='Call') + duration = models.DurationField(default=timedelta(minutes=5)) 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) @@ -1226,8 +1225,9 @@ class Schedule(models.Model): def __str__(self): return f"Scheduled {self.purpose} with {self.lead.full_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 diff --git a/inventory/signals.py b/inventory/signals.py index da7cc19c..e7704cb7 100644 --- a/inventory/signals.py +++ b/inventory/signals.py @@ -694,7 +694,8 @@ def update_item_model_cost(sender, instance, created, **kwargs): product = entity.get_items_all().filter(name=instance.car.vin).first() product.default_amount = instance.selling_price - product.additional_info = {} + if not isinstance(product.additional_info, dict): + product.additional_info = {} product.additional_info.update({"car_finance":instance.to_dict()}) product.additional_info.update({"additional_services": [service.to_dict() for service in instance.additional_services.all()]}) product.save() diff --git a/inventory/templatetags/custom_filters.py b/inventory/templatetags/custom_filters.py index 9629cb29..aa4d1ea6 100644 --- a/inventory/templatetags/custom_filters.py +++ b/inventory/templatetags/custom_filters.py @@ -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) \ No newline at end of file +# @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) \ No newline at end of file diff --git a/inventory/urls.py b/inventory/urls.py index 7c68950b..7d0c6755 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -88,7 +88,7 @@ urlpatterns = [ path( "crm/leads//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//update/", views.LeadUpdateView.as_view(), name="lead_update" ), @@ -196,7 +196,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//add-color/", views.CarColorCreate.as_view(), name="add_color" ), diff --git a/inventory/views.py b/inventory/views.py index e719b421..537b001d 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -1,3 +1,6 @@ +from django.db.models import Func +from appointment.models import Appointment,AppointmentRequest,Service,StaffMember +from datetime import timedelta from calendar import month_name from random import randint from rich import print @@ -115,6 +118,11 @@ logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) + +class Hash(Func): + function = 'get_hash' + + def switch_language(request): language = request.GET.get("language", "en") referer = request.META.get("HTTP_REFERER", "/") @@ -2339,12 +2347,13 @@ def create_estimate(request): items = data.get("item", []) quantities = data.get("quantity", []) - + if not all([items, quantities]): return JsonResponse( {"status": "error", "message": "Items and Quantities are required"}, status=400, - ) + ) + if isinstance(quantities, list): if "0" in quantities: return JsonResponse( @@ -2355,7 +2364,17 @@ def create_estimate(request): return JsonResponse( {"status": "error", "message": "Quantity must be greater than zero"} ) - + if isinstance(items, list): + for item, quantity in zip(items, quantities): + if int(quantity) > models.Car.objects.filter(hash=item).count(): + return JsonResponse( + {"status": "error", "message": "Quantity must be less than or equal to the number of cars in stock"}, + ) + else: + if int(quantities) > models.Car.objects.filter(hash=item).count(): + return JsonResponse( + {"status": "error", "message": "Quantity must be less than or equal to the number of cars in stock"}, + ) estimate = entity.create_estimate( estimate_title=title, customer_model=customer, contract_terms=terms ) @@ -2375,18 +2394,20 @@ def create_estimate(request): ] items_txs = [] for item in items_list: - item_instance = ItemModel.objects.get(pk=item.get("item_id")) - car_instance = models.Car.objects.get(vin=item_instance.name) - items_txs.append( - { - "item_number": item_instance.item_number, - "quantity": Decimal(item.get("quantity")), - "unit_cost": car_instance.finances.selling_price, - "unit_revenue": car_instance.finances.selling_price, - "total_amount": (car_instance.finances.total_vat) - * int(item.get("quantity")), - } - ) + # item_instance = ItemModel.objects.get(pk=item.get("item_id")) + car_instance = ItemModel.objects.filter(additional_info__car_info__hash=item.get("item_id")).all() + + # car_instance = models.Car.objects.get(vin=item_instance.name) + for i in car_instance[:int(quantities[0])]: + items_txs.append( + { + "item_number": i.item_number, + "quantity": 1, + "unit_cost": i.additional_info.get('car_finance').get("selling_price"), + "unit_revenue": i.additional_info.get('car_finance').get("selling_price"), + "total_amount": (i.additional_info.get('car_finance').get("total_vat")) + } + ) estimate_itemtxs = { item.get("item_number"): { @@ -2416,14 +2437,18 @@ def create_estimate(request): ) if isinstance(items, list): - for item in items: - item_instance = ItemModel.objects.get(pk=item) - instance = models.Car.objects.get(vin=item_instance.name) + for item in estimate_itemtxs.keys(): + item_instance = ItemModel.objects.get(item_number=item) + instance = models.Car.objects.get(name=item_instance.name) reserve_car(instance, request) + # for item in items: + # item_instance = ItemModel.objects.filter(additioinal_info__car_info__hash=item).first() + # instance = models.Car.objects.get(hash=item) + # reserve_car(instance, request) else: - item_instance = ItemModel.objects.get(pk=items) - instance = models.Car.objects.get(vin=item_instance.name) + item_instance = ItemModel.objects.get(additioinal_info__car_info__hash=items) + instance = models.Car.objects.get(hash=item) response = reserve_car(instance, request) url = reverse("estimate_detail", kwargs={"pk": estimate.pk}) @@ -2439,22 +2464,21 @@ def create_estimate(request): entity_slug=entity.slug, user_model=entity.admin ) form.fields["customer"].queryset = entity.get_customers().filter(active=True) - car_list = models.Car.objects.filter( - dealer=dealer, finances__selling_price__gt=0 - ).exclude(status="reserved") + car_list = models.Car.objects.filter(dealer=dealer).exclude(status="reserved").values_list( + 'id_car_make__name', 'id_car_model__name','hash').distinct() + context = { "form": form, "items": [ { - "car": x, - "product": entity.get_items_all() - .filter(item_role=ItemModel.ITEM_ROLE_PRODUCT, name=x.vin) - .first(), + 'make':x[0], + 'model':x[1], + 'hash': x[2] } for x in car_list ], } - + return render(request, "sales/estimates/estimate_form.html", context) @@ -2940,28 +2964,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 @@ -2969,6 +2990,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) @@ -3030,12 +3055,14 @@ def lead_convert(request, pk): if lead.is_converted: messages.error(request, "Lead is already converted to customer.") return redirect("opportunity_create",pk=lead.pk) + if not models.Car.objects.filter(id_car_make=lead.id_car_make,id_car_model=lead.id_car_model).first(): + messages.error(request, "Cannot convert lead to customer. Car model not found.") + return redirect("lead_list") lead.convert_to_customer(dealer.entity) 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) @@ -3046,8 +3073,33 @@ def schedule_lead(request, pk): instance.lead = lead if hasattr(request.user, "staff"): instance.scheduled_by = request.user.staff + + # Save the Schedule instance instance.save() - messages.success(request, "Lead scheduled successfully!") + + # Create AppointmentRequest + service = Service.objects.filter(name=instance.scheduled_type).first() + if not service: + messages.error(request, "Service not found!") + return redirect("lead_list") + + appointment_request = AppointmentRequest.objects.create( + date=instance.scheduled_at.date(), + start_time=instance.scheduled_at.time(), + end_time=(instance.scheduled_at + instance.duration).time(), + service=service, + staff_member=StaffMember.objects.first() + ) + + # Create Appointment + Appointment.objects.create( + client=request.user, # Replace with the appropriate client + appointment_request=appointment_request, + phone="123-456-7890", # Replace with actual phone number + address="123 Main St", # Replace with actual address + ) + + messages.success(request, "Lead scheduled and appointment created successfully!") return redirect("lead_list") else: messages.error(request, f"Invalid form data: {str(form.errors)}") @@ -3130,9 +3182,9 @@ class OpportunityCreateView(CreateView): def get_initial(self): initial = super().get_initial() if self.kwargs.get('pk',None): - lead = models.Lead.objects.get(pk=self.kwargs.get('pk')) + 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): diff --git a/scripts/run.py b/scripts/run.py index fba9a050..aeb1622e 100644 --- a/scripts/run.py +++ b/scripts/run.py @@ -1,52 +1,96 @@ from django_ledger.models.invoice import InvoiceModel from django_ledger.utils import accruable_net_summary from decimal import Decimal -from django_ledger.models import EstimateModel,EntityModel +from django_ledger.models import EstimateModel,EntityModel,ItemModel from rich import print from datetime import date -from inventory.models import VatRate +from inventory.models import Car, Dealer, 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 +from django.utils import timezone +import hashlib +User = get_user_model() -def run(): - # estimate = EstimateModel.objects.first() - # calculator = CarFinanceCalculator(estimate) - # finance_data = calculator.get_finance_data() +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", + # ) + # now = timezone.now() + # end_time = now + timedelta(minutes=10) + # service = Service.objects.first() + # appointment_request = AppointmentRequest.objects.create( + # date=now.date(), + # start_time=now.time(), + # end_time=end_time.time(), + # 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)) \ No newline at end of file + # appointment = Appointment.objects.create( + # client=User.objects.first(), + # appointment_request=appointment_request, + # phone="123-456-7890", + # address="123 Main St", + # ) + dealer = Dealer.objects.get(user__email="ismail.mosa.ibrahim@gmail.com") + entity = dealer.entity + + car_list = Car.objects.filter(dealer=dealer).all() + # context = { + # "items": [ + # { + # "car": x, + # "product": entity.get_items_all() + # .filter(item_role=ItemModel.ITEM_ROLE_PRODUCT, name=x.vin) + # .first(), + # } + # for x in car_list + # ], + # } + + for i in car_list: + hash_object = hashlib.sha256() + hash_object.update(f"{i.id_car_make.name}{i.id_car_model.name}".encode('utf-8')) + print(hash_object.hexdigest() , i.id_car_make.name, i.id_car_model.name) + + \ No newline at end of file diff --git a/templates/crm/leads/lead_list.html b/templates/crm/leads/lead_list.html index ed393ade..e1154868 100644 --- a/templates/crm/leads/lead_list.html +++ b/templates/crm/leads/lead_list.html @@ -135,13 +135,14 @@ - {{ lead.car.id_car_make.get_local_name }} - {{ lead.car.id_car_model.get_local_name }} {{ lead.year }} + {{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }} {{ lead.email }} {{ lead.phone_number }} {% if lead.get_latest_schedule %} + {% if lead.get_latest_schedule.scheduled_type == "Call" %} - + {{ lead.get_latest_schedule.scheduled_at }} {% elif lead.get_latest_schedule.scheduled_type == "Meeting" %} @@ -150,6 +151,7 @@ {{ lead.get_latest_schedule.scheduled_at }} {% endif %} + {% endif %} {{ lead.staff|upper }} diff --git a/templates/sales/estimates/estimate_form.html b/templates/sales/estimates/estimate_form.html index dfd3d0f6..c71daf7e 100644 --- a/templates/sales/estimates/estimate_form.html +++ b/templates/sales/estimates/estimate_form.html @@ -18,7 +18,7 @@