update
This commit is contained in:
parent
99f0165603
commit
01d0515b32
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -110,7 +110,7 @@ class CustomerForm(forms.ModelForm, AddClassMixin):
|
||||
"dob",
|
||||
"email",
|
||||
"national_id",
|
||||
"city",
|
||||
|
||||
"phone_number",
|
||||
"address",
|
||||
]
|
||||
@ -583,20 +583,14 @@ class EmailForm(forms.Form):
|
||||
class LeadForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Lead
|
||||
fields = ['title',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'phone_number',
|
||||
fields = ['customer',
|
||||
'city',
|
||||
'salary',
|
||||
'obligations',
|
||||
'id_car_make',
|
||||
'id_car_model',
|
||||
'year',
|
||||
'source',
|
||||
'channel',
|
||||
'assigned',
|
||||
'staff',
|
||||
'priority',
|
||||
]
|
||||
|
||||
@ -624,7 +618,7 @@ class ActivityForm(forms.ModelForm):
|
||||
class OpportunityForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Opportunity
|
||||
fields = ['customer', 'car', 'stage', 'probability', 'closing_date']
|
||||
fields = ['customer', 'car', 'stage', 'probability', 'staff', 'closing_date']
|
||||
|
||||
|
||||
class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
# Generated by Django 5.1.4 on 2025-01-17 00:20
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0003_alter_carmake_car_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='lead',
|
||||
old_name='assigned',
|
||||
new_name='staff',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='customer',
|
||||
name='city',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='customer',
|
||||
name='lead',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='customer',
|
||||
name='staff',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='address',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='email',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='first_name',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='last_name',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='obligations',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='phone_number',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='salary',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='lead',
|
||||
name='title',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organization',
|
||||
name='created_at',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lead',
|
||||
name='customer',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.customer'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='created',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='Created'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='updated',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='Updated'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='representative',
|
||||
name='id_number',
|
||||
field=models.CharField(max_length=10, unique=True, verbose_name='ID Number'),
|
||||
),
|
||||
]
|
||||
@ -780,23 +780,82 @@ class Priority(models.TextChoices):
|
||||
MEDIUM = "medium", _("Medium")
|
||||
HIGH = "high", _("High")
|
||||
|
||||
|
||||
class Customer(models.Model):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE,related_name="customers")
|
||||
title = models.CharField(choices=Title.choices, default=Title.NA, max_length=10, verbose_name=_("Title"))
|
||||
first_name = models.CharField(max_length=50, verbose_name=_("First Name"))
|
||||
middle_name = models.CharField(max_length=50, blank=True, null=True, verbose_name=_("Middle Name"))
|
||||
last_name = models.CharField(max_length=50, verbose_name=_("Last Name"))
|
||||
gender = models.CharField(choices=[('m', _('Male')), ('f', _('Female'))], max_length=1, verbose_name=_("Gender"))
|
||||
dob = models.DateField(verbose_name=_("Date of Birth"))
|
||||
email = models.EmailField(unique=True, verbose_name=_("Email"))
|
||||
national_id = models.CharField(max_length=10, unique=True, verbose_name=_("National ID"))
|
||||
phone_number = PhoneNumberField(region="SA", unique=True, verbose_name=_("Phone Number"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
||||
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Customer")
|
||||
verbose_name_plural = _("Customers")
|
||||
|
||||
def __str__(self):
|
||||
middle = f" {self.middle_name}" if self.middle_name else ""
|
||||
return f"{self.first_name}{middle} {self.last_name}"
|
||||
|
||||
@property
|
||||
def get_full_name(self):
|
||||
return f"{self.first_name} {self.middle_name} {self.last_name}"
|
||||
|
||||
|
||||
class Organization(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='organizations')
|
||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
crn = models.CharField(max_length=15, verbose_name=_("Commercial Registration Number"))
|
||||
vrn = models.CharField(max_length=15, verbose_name=_("VAT Registration Number"))
|
||||
phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
logo = models.ImageField(upload_to="logos", blank=True, null=True, verbose_name=_("Logo"))
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
||||
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Organization")
|
||||
verbose_name_plural = _("Organizations")
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Representative(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='representatives')
|
||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
id_number = models.CharField(max_length=10, unique=True, verbose_name=_("ID Number"))
|
||||
phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
|
||||
email = models.EmailField(max_length=255, verbose_name=_("Email Address"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
organization = models.ManyToManyField(Organization, related_name='representatives')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Representative")
|
||||
verbose_name_plural = _("Representatives")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Lead(models.Model):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="leads")
|
||||
title = models.CharField(max_length=20, choices=Title.choices, verbose_name=_("Title"))
|
||||
first_name = models.CharField(max_length=50, verbose_name=_("First Name"))
|
||||
last_name = models.CharField(max_length=50, verbose_name=_("Last Name"))
|
||||
email = models.EmailField(unique=True, verbose_name=_("Email"), db_index=True)
|
||||
phone_number = PhoneNumberField(region="SA", verbose_name=_("Phone Number"))
|
||||
salary = models.PositiveIntegerField(blank=True, null=True, verbose_name=_("Salary"))
|
||||
obligations = models.PositiveIntegerField(blank=True, null=True, verbose_name=_("Obligations"))
|
||||
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="leads")
|
||||
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"))
|
||||
channel = models.CharField(max_length=50, choices=Channel.choices, verbose_name=_("Channel"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
city = models.CharField(max_length=50, verbose_name=_("City"))
|
||||
assigned = models.ForeignKey(Staff, on_delete=models.SET_NULL, blank=True, null=True, related_name="assigned", verbose_name=_("Assigned"))
|
||||
staff = models.ForeignKey(Staff, on_delete=models.SET_NULL, blank=True, null=True, related_name="assigned", verbose_name=_("Assigned"))
|
||||
priority = models.CharField(max_length=10, choices=Priority.choices, default=Priority.MEDIUM,
|
||||
verbose_name=_("Priority"))
|
||||
status = models.CharField(max_length=50, choices=Status.choices, verbose_name=_("Status"), db_index=True, default=Status.NEW)
|
||||
@ -826,38 +885,6 @@ class LeadStatusHistory(models.Model):
|
||||
return f"{self.lead}: {self.old_status} → {self.new_status}"
|
||||
|
||||
|
||||
class Customer(models.Model):
|
||||
lead = models.OneToOneField(Lead, on_delete=models.SET_NULL, null=True, blank=True,
|
||||
related_name="converted", verbose_name=_("Lead"))
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE,related_name="customers")
|
||||
staff = models.ForeignKey(Staff, on_delete=models.SET_NULL, null=True, related_name="customer_staff",
|
||||
verbose_name=_("Staff"))
|
||||
title = models.CharField(choices=Title.choices, default=Title.NA, max_length=10, verbose_name=_("Title"))
|
||||
first_name = models.CharField(max_length=50, verbose_name=_("First Name"))
|
||||
middle_name = models.CharField(max_length=50, blank=True, null=True, verbose_name=_("Middle Name"))
|
||||
last_name = models.CharField(max_length=50, verbose_name=_("Last Name"))
|
||||
gender = models.CharField(choices=[('m', _('Male')), ('f', _('Female'))], max_length=1, verbose_name=_("Gender"))
|
||||
dob = models.DateField(verbose_name=_("Date of Birth"))
|
||||
email = models.EmailField(unique=True, verbose_name=_("Email"))
|
||||
national_id = models.CharField(max_length=10, unique=True, verbose_name=_("National ID"))
|
||||
phone_number = PhoneNumberField(region="SA", unique=True, verbose_name=_("Phone Number"))
|
||||
city = models.CharField(max_length=255, blank=True, verbose_name=_("City"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
||||
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Customer")
|
||||
verbose_name_plural = _("Customers")
|
||||
|
||||
def __str__(self):
|
||||
middle = f" {self.middle_name}" if self.middle_name else ""
|
||||
return f"{self.first_name}{middle} {self.last_name}"
|
||||
|
||||
@property
|
||||
def get_full_name(self):
|
||||
return f"{self.first_name} {self.middle_name} {self.last_name}"
|
||||
|
||||
def validate_probability(value):
|
||||
if value < 0 or value > 100:
|
||||
raise ValidationError(_("Probability must be between 0 and 100."))
|
||||
@ -963,41 +990,6 @@ class Vendor(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
|
||||
class Organization(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='organizations')
|
||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
crn = models.CharField(max_length=15, verbose_name=_("Commercial Registration Number"))
|
||||
vrn = models.CharField(max_length=15, verbose_name=_("VAT Registration Number"))
|
||||
phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
logo = models.ImageField(upload_to="logos", blank=True, null=True, verbose_name=_("Logo"))
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Organization")
|
||||
verbose_name_plural = _("Organizations")
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Representative(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='representatives')
|
||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
id_number = models.CharField(max_length=10, verbose_name=_("ID Number"))
|
||||
phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
|
||||
email = models.EmailField(max_length=255, verbose_name=_("Email Address"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
organization = models.ManyToManyField(Organization, related_name='representatives')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Representative")
|
||||
verbose_name_plural = _("Representatives")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class SaleQuotation(models.Model):
|
||||
quotation_number = models.CharField(max_length=10, unique=True)
|
||||
|
||||
@ -805,7 +805,7 @@ def track_lead_status_change(sender, instance, **kwargs):
|
||||
lead=instance,
|
||||
old_status=old_lead.status,
|
||||
new_status=instance.status,
|
||||
changed_by=instance.assigned # Assuming the assigned staff made the change
|
||||
changed_by=instance.staff # Assuming the assigned staff made the change
|
||||
)
|
||||
except models.Lead.DoesNotExist:
|
||||
pass # Ignore if the lead doesn't exist (e.g., during initial creation)
|
||||
@ -813,10 +813,10 @@ def track_lead_status_change(sender, instance, **kwargs):
|
||||
|
||||
@receiver(post_save, sender=models.Lead)
|
||||
def notify_assigned_staff(sender, instance, created, **kwargs):
|
||||
if instance.assigned: # Check if the lead is assigned
|
||||
if instance.staff: # Check if the lead is assigned
|
||||
models.Notification.objects.create(
|
||||
user=instance.assigned.user,
|
||||
message=f"You have been assigned a new lead: {instance.first_name} {instance.last_name}."
|
||||
user=instance.staff.user,
|
||||
message=f"You have been assigned a new lead: {instance.customer.get_full_name}."
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -884,6 +884,7 @@ class CustomerListView(LoginRequiredMixin, ListView):
|
||||
context_object_name = "customers"
|
||||
paginate_by = 10
|
||||
template_name = "customers/customer_list.html"
|
||||
ordering = ["-created"]
|
||||
|
||||
def get_queryset(self):
|
||||
query = self.request.GET.get("q")
|
||||
@ -1001,6 +1002,11 @@ class VendorListView(LoginRequiredMixin, ListView):
|
||||
context_object_name = "vendors"
|
||||
paginate_by = 10
|
||||
template_name = "vendors/vendors_list.html"
|
||||
ordering = ["-created"]
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
return models.Vendor.objects.filter(dealer=dealer)
|
||||
|
||||
|
||||
class VendorDetailView(LoginRequiredMixin, DetailView):
|
||||
@ -1430,8 +1436,7 @@ class UserListView(LoginRequiredMixin, ListView):
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
staff = models.Staff.objects.filter(dealer=dealer).all()
|
||||
return staff
|
||||
return models.Staff.objects.filter(dealer=dealer).all()
|
||||
|
||||
|
||||
class UserDetailView(LoginRequiredMixin, DetailView):
|
||||
@ -1514,8 +1519,7 @@ class OrganizationListView(LoginRequiredMixin, ListView):
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
data = models.Organization.objects.filter(dealer=dealer).all()
|
||||
return data
|
||||
return models.Organization.objects.filter(dealer=dealer).all()
|
||||
|
||||
|
||||
class OrganizationDetailView(DetailView):
|
||||
@ -1559,11 +1563,11 @@ class RepresentativeListView(LoginRequiredMixin, ListView):
|
||||
model = models.Representative
|
||||
template_name = "representatives/representative_list.html"
|
||||
context_object_name = "representatives"
|
||||
paginate_by = 10
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
data = models.Representative.objects.filter(dealer=dealer).all()
|
||||
return data
|
||||
return models.Representative.objects.filter(dealer=dealer).all()
|
||||
|
||||
|
||||
class RepresentativeDetailView(DetailView):
|
||||
@ -1785,6 +1789,7 @@ class BankAccountListView(LoginRequiredMixin, ListView):
|
||||
model = BankAccountModel
|
||||
template_name = "ledger/bank_accounts/bank_account_list.html"
|
||||
context_object_name = "bank_accounts"
|
||||
paginate_by = 10
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
@ -1860,11 +1865,7 @@ class AccountListView(LoginRequiredMixin, ListView):
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
entity = dealer.entity
|
||||
qs = entity.get_all_accounts()
|
||||
paginator = Paginator(qs, 20)
|
||||
page_number = self.request.GET.get("page", 1) # Default to page 1
|
||||
page_obj = paginator.get_page(page_number)
|
||||
return page_obj
|
||||
return entity.get_all_accounts()
|
||||
|
||||
|
||||
class AccountCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
|
||||
@ -2222,6 +2223,7 @@ class InvoiceListView(LoginRequiredMixin, ListView):
|
||||
model = InvoiceModel
|
||||
template_name = "sales/invoices/invoice_list.html"
|
||||
context_object_name = "invoices"
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
@ -2583,7 +2585,7 @@ class UserActivityLogListView(ListView):
|
||||
model = models.UserActivityLog
|
||||
template_name = "dealers/activity_log.html"
|
||||
context_object_name = "logs"
|
||||
paginate_by = 10
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
@ -2601,8 +2603,7 @@ class LeadListView(ListView):
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
leads = models.Lead.objects.filter(dealer=dealer).all()
|
||||
return leads
|
||||
return models.Lead.objects.filter(dealer=dealer).all()
|
||||
|
||||
|
||||
class LeadDetailView(DetailView):
|
||||
@ -2706,10 +2707,10 @@ class OpportunityCreateView(CreateView):
|
||||
def form_valid(self, form):
|
||||
dealer = get_user_type(self.request)
|
||||
form.instance.dealer = dealer
|
||||
staff = self.request.user.staff
|
||||
# staff = dealer.staff
|
||||
print(dealer)
|
||||
print(staff)
|
||||
form.instance.staff = staff
|
||||
# print(staff)
|
||||
# form.instance.staff = staff
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
@ -2735,11 +2736,11 @@ class OpportunityListView(ListView):
|
||||
model = models.Opportunity
|
||||
template_name = "crm/opportunities/opportunity_list.html"
|
||||
context_object_name = "opportunities"
|
||||
paginate_by = 10
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
data = models.Opportunity.objects.filter(dealer=dealer).all()
|
||||
return data
|
||||
return models.Opportunity.objects.filter(dealer=dealer).all()
|
||||
|
||||
|
||||
@login_required
|
||||
@ -2771,12 +2772,11 @@ class NotificationListView(LoginRequiredMixin, ListView):
|
||||
model = models.Notification
|
||||
template_name = "crm/notifications_history.html"
|
||||
context_object_name = "notifications"
|
||||
paginate_by = 10
|
||||
paginate_by = 20
|
||||
ordering = "-created"
|
||||
|
||||
def get_queryset(self):
|
||||
return models.Notification.objects.filter(user=self.request.user).order_by(
|
||||
"-created"
|
||||
)
|
||||
return models.Notification.objects.filter(user=self.request.user)
|
||||
|
||||
|
||||
@login_required
|
||||
@ -2840,11 +2840,11 @@ class ItemServiceListView(ListView):
|
||||
model = models.AdditionalServices
|
||||
template_name = "items/service/service_list.html"
|
||||
context_object_name = "services"
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
items = models.AdditionalServices.objects.filter(dealer=dealer).all()
|
||||
return items
|
||||
return models.AdditionalServices.objects.filter(dealer=dealer).all()
|
||||
|
||||
|
||||
class ItemExpenseCreateView(CreateView):
|
||||
@ -2889,22 +2889,22 @@ class ItemExpenseListView(ListView):
|
||||
model = ItemModel
|
||||
template_name = "items/expenses/expenses_list.html"
|
||||
context_object_name = "expenses"
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
items = dealer.entity.get_items_expenses()
|
||||
return items
|
||||
return dealer.entity.get_items_expenses()
|
||||
|
||||
|
||||
class BillListView(ListView):
|
||||
model = ItemModel
|
||||
template_name = "ledger/bills/bill_list.html"
|
||||
context_object_name = "bills"
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_user_type(self.request)
|
||||
items = dealer.entity.get_bills()
|
||||
return items
|
||||
return dealer.entity.get_bills()
|
||||
|
||||
|
||||
class BillCreateView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
|
||||
|
||||
BIN
static/images/.DS_Store
vendored
BIN
static/images/.DS_Store
vendored
Binary file not shown.
BIN
static/images/car_make/maserati_Fw9s7lU.png
Normal file
BIN
static/images/car_make/maserati_Fw9s7lU.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
static/images/spot-illustrations/.DS_Store
vendored
BIN
static/images/spot-illustrations/.DS_Store
vendored
Binary file not shown.
BIN
templates/crm/.DS_Store
vendored
BIN
templates/crm/.DS_Store
vendored
Binary file not shown.
@ -119,11 +119,11 @@
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold">
|
||||
<div class="d-flex align-items-center">
|
||||
<a class="fs-8 fw-bold" href="{% url 'lead_detail' lead.pk %}">{{ lead.first_name }} {{ lead.last_name }}</a>
|
||||
<a class="fs-8 fw-bold" href="{% url 'lead_detail' lead.pk %}">{{ lead.customer.get_full_name }}</a>
|
||||
</div>
|
||||
</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"><a class="text-body-highlight" href="">{{ lead.customer.email }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="tel:{{ lead.customer.phone_number }}">{{ lead.customer.phone_number }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold text-body-highlight">{{ lead.source|upper }}</td>
|
||||
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.channel|upper }}</td>
|
||||
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 text-body-tertiary">{{ lead.created|date }}</td>
|
||||
|
||||
BIN
templates/crm/opportunities/.DS_Store
vendored
Normal file
BIN
templates/crm/opportunities/.DS_Store
vendored
Normal file
Binary file not shown.
@ -60,6 +60,19 @@
|
||||
</div>
|
||||
|
||||
<!-- Staff -->
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<select class="form-control" id="{{ form.staff.id_for_label }}" name="{{ form.staff.name }}">
|
||||
{% for value, label in form.staff.field.choices %}
|
||||
<option value="{{ value }}" {% if form.staff.value == value %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label for="{{ form.staff.id_for_label }}">{{ _("Staff") }}</label>
|
||||
</div>
|
||||
{{ form.staff.errors }}
|
||||
</div>
|
||||
|
||||
<!-- closing date-->
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="date" class="form-control" id="{{ form.closing_date.id_for_label }}" name="{{ form.closing_date.name }}" value="{{ form.closing_date.value|date:'Y-m-d' }}">
|
||||
|
||||
504
templates/crm/opportunities/opportunity_list copy.html
Normal file
504
templates/crm/opportunities/opportunity_list copy.html
Normal file
@ -0,0 +1,504 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="px-4 px-lg-6">
|
||||
<h2 class="mb-5">{{ _("Opportunities") }}</h2>
|
||||
<div class="d-xl-flex justify-content-between">
|
||||
<div class="mb-3">
|
||||
<a class="btn btn-primary me-4" href="{% url 'opportunity_create' %}"><span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-4 px-lg-6 scrollbar">
|
||||
<div class="deals">
|
||||
{% for opportunity in opportunities %}
|
||||
<div class="deals-col col-sm-6 me-4 mt-4">
|
||||
<div class="d-flex align-items-center justify-content-between position-sticky top-0 z-1 bg-body">
|
||||
<div>
|
||||
<h5 class="mb-2 ms-4">{{ opportunity.car.id_car_make.get_local_name }} - {{ opportunity.car.id_car_model.get_local_name }} - {{ opportunity.car.year }}</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-3">
|
||||
<button class="btn p-0" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><a class="dropdown-item" href="{% url 'update_opportunity' pk=opportunity.pk %}">{{ _("Edit") }}</a></li>
|
||||
<li><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" deals-items-row">
|
||||
<div class="w-100 min-vh-50" >
|
||||
<div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<a class="dropdown-indicator-icon position-absolute text-body-tertiary text-end"
|
||||
href="#collapseWidthDeals-1"
|
||||
role="button"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseWidthDeals-1">
|
||||
<span class="fa-solid fa-angle-down text-end"></span>
|
||||
</a>
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div class="d-flex gap-3">
|
||||
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<span class="me-2" data-feather="clock" style="stroke-width:2;"></span>
|
||||
<p class="mb-0 fs-9 fw-semibold text-body-tertiary date">{{ opportunity.created|date }}<span class="text-body-quaternary"> . {{ opportunity.created|time}}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="deals-items-head d-flex align-items-center mb-2">
|
||||
<a class="text-primary fw-bold line-clamp-1 me-3 mb-0 fs-9" href="{% url 'opportunity_detail' opportunity.pk %}">{{ _("View") }}</a>
|
||||
<p class="fs-10 mb-0 mt-1 d-none"><span class="me-1 text-body-quaternary" data-feather="grid" style="stroke-width:2; height: 12px; width: 12px"></span>{{ opportunity.get_stage_display }}</p>
|
||||
<p class="ms-auto fs-9 text-body-emphasis fw-semibold mb-0 deals-revenue">{{ opportunity.car.finances.total }}</p>
|
||||
</div>
|
||||
<div class="deals-company-agent d-flex flex-between-center">
|
||||
<div class="d-flex align-items-center"><span class="uil uil-user me-2"></span>
|
||||
<p class="text-body-secondary fw-bold fs-10 mb-0">{{ opportunity.customer.get_full_name }}</p>
|
||||
</div>
|
||||
<div class="d-flex align-items-center"><span class="uil uil-headphones me-2"></span>
|
||||
<p class="text-body-secondary fw-bold fs-10 mb-0">{{ opportunity.staff.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapseWidthDeals-1">
|
||||
<div class="d-flex gap-2 mb-5"><span class="badge badge-phoenix fs-10 badge-phoenix-info">{{ opportunity.get_stage_display }}</span><span class="badge badge-phoenix fs-10 badge-phoenix-danger">{{ opportunity.get_status_display }}</span></div>
|
||||
<table class="mb-4 w-100 table-stats table-stats">
|
||||
<tr>
|
||||
<th>{{ _("Details") }}</th>
|
||||
<th>:</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-1">
|
||||
<div class="d-flex align-items-center"><span class="me-2 text-body-tertiary" data-feather="dollar-sign"></span>
|
||||
<p class="fw-semibold fs-9 mb-0 text-body-tertiary">{{ _("Expected Revenue")}}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="d-none d-sm-block pe-sm-2">:</td>
|
||||
<td class="py-1">
|
||||
<p class="ps-6 ps-sm-0 fw-semibold fs-9 mb-0 mb-0 pb-3 pb-sm-0 text-body-emphasis">{{ opportunity.car.finances.total }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-1">
|
||||
<div class="d-flex align-items-center"><span class="me-2 text-body-tertiary" data-feather="user" style="width:16px; height:16px"></span>
|
||||
<p class="fw-semibold fs-9 mb-0 text-body-tertiary">{{ _("Contact") }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class=" d-none d-sm-block pe-sm-2">:</td>
|
||||
<td class="py-1">
|
||||
<p class="fw-semibold fs-9 mb-0 mb-0 pb-3 pb-sm-0 text-body-emphasis d-flex align-items-center gap-2"><a href=""> <span class="fa-solid fa-square-phone text-body-tertiary"></span></a><a href=""> <span class="fa-solid fa-square-envelope text-body-tertiary"></span></a><a href=""> <span class="fab fa-whatsapp-square text-body-tertiary"></span></a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-1">
|
||||
<div class="d-flex align-items-center"><span class="me-2 text-body-tertiary" data-feather="calendar" style="width:16px; height:16px"></span>
|
||||
<p class="fw-semibold fs-9 mb-0 text-body-tertiary">{{ _("Closing Date")}}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class=" d-none d-sm-block pe-sm-2">:</td>
|
||||
<td class="py-1">
|
||||
<p class="fw-semibold fs-9 mb-0 mb-0 pb-3 pb-sm-0 text-body-emphasis">{{ opportunity.closing_date }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<p class="fs-9 mb-1 fw-bold"> {{ _("Probability") }}: %</p>
|
||||
<div class="progress" style="height:16px">
|
||||
{% if opportunity.probability >= 25 and opportunity.probability < 49 %}
|
||||
<div class="progress-bar rounded-pill bg-danger" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bold fs-10 text-sm-end text-secondary me-1">{{ opportunity.probability }}</span>
|
||||
</div>
|
||||
{% elif opportunity.probability >= 50 and opportunity.probability <= 74 %}
|
||||
<div class="progress-bar rounded-pill bg-warning" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bold fs-10 text-sm-end text-secondary me-1">{{ opportunity.probability }}</span>
|
||||
</div>
|
||||
{% elif opportunity.probability >= 75 and opportunity.probability <= 100 %}
|
||||
<div class="progress-bar rounded-pill bg-success" role="progressbar" style="width: {{ opportunity.probability }}%" aria-valuenow="{{ opportunity.probability }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span class="fw-bold fs-10 text-sm-end text-secondary me-1">{{ opportunity.probability }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="deleteModal"
|
||||
data-bs-backdrop="static"
|
||||
data-bs-keyboard="false"
|
||||
tabindex="-1"
|
||||
aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
|
||||
{% trans "Delete Opportunity" %}
|
||||
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p class="mb-0 text-danger fw-bold">
|
||||
{% trans "Are you sure you want to delete this opportunity?" %}
|
||||
</p>
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">
|
||||
{% trans "No" %}
|
||||
</button>
|
||||
<a type="button" class="btn btn-danger btn-sm" href="{% url 'delete_opportunity' opportunity.pk %}">
|
||||
{% trans "Yes" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="addOpportunityModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="addOpportunityModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content bg-body-highlight p-6">
|
||||
<div class="modal-header justify-content-between border-0 p-0 mb-2">
|
||||
<h3 class="mb-0">Opportunity Information</h3>
|
||||
<button class="btn btn-sm btn-phoenix-secondary" data-bs-dismiss="modal" aria-label="Close"><span class="fas fa-times text-danger"></span></button>
|
||||
</div>
|
||||
<div class="modal-body px-0">
|
||||
<form method="post" class="form" action="{% url 'create_opportunity' opportunity.customer.pk %}">
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-6">
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Owner</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Ally Aagaard</option>
|
||||
<option>Aida Moen</option>
|
||||
<option>Niko Koss</option>
|
||||
<option>Alec Haag</option>
|
||||
<option>Lonnie Kub</option>
|
||||
<option>Ola Smith</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Name</label>
|
||||
<input class="form-control" type="text" placeholder="Enter deal name" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-6 col-lg-12 col-xl-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Amount</label>
|
||||
<div class="row g-2">
|
||||
<div class="col">
|
||||
<input class="form-control" type="number" placeholder="$ Enter amount" />
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select class="form-select">
|
||||
<option>USD</option>
|
||||
<option>GBP</option>
|
||||
<option>EUR</option>
|
||||
<option>JPY</option>
|
||||
<option>CAD</option>
|
||||
<option>AUD</option>
|
||||
<option>CNY</option>
|
||||
<option>CHF</option>
|
||||
<option>ZAR</option>
|
||||
<option>BRL</option>
|
||||
<option>RUB</option>
|
||||
<option>INR</option>
|
||||
<option>MXN</option>
|
||||
<option>NZD</option>
|
||||
<option>SGD</option>
|
||||
<option>HKD</option>
|
||||
<option>KRW</option>
|
||||
<option>SEK</option>
|
||||
<option>NOK</option>
|
||||
<option>TRY</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Code</label>
|
||||
<input class="form-control" type="text" placeholder="Enter deals code" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Type
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Buy One Get One Free</option>
|
||||
<option>Clearance sale</option>
|
||||
<option>Bundle deals</option>
|
||||
<option>Free shipping</option>
|
||||
<option>Loyalty programs</option>
|
||||
<option>Limited-time offers</option>
|
||||
<option>Refer-a-friend discounts</option>
|
||||
<option>Seasonal sales</option>
|
||||
<option>Membership discounts</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Category
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Financial</option>
|
||||
<option>Marketplace</option>
|
||||
<option>Travel</option>
|
||||
<option>E-commerce</option>
|
||||
<option>Cloud Computing</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Probability (%)</label>
|
||||
<input class="form-control" type="text" placeholder="Enter value" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Expected Revenue</label>
|
||||
<div class="row g-2">
|
||||
<div class="col">
|
||||
<input class="form-control" type="number" placeholder="$ Enter amount" />
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select class="form-select">
|
||||
<option>USD</option>
|
||||
<option>GBP</option>
|
||||
<option>EUR</option>
|
||||
<option>JPY</option>
|
||||
<option>CAD</option>
|
||||
<option>AUD</option>
|
||||
<option>CNY</option>
|
||||
<option>CHF</option>
|
||||
<option>ZAR</option>
|
||||
<option>BRL</option>
|
||||
<option>RUB</option>
|
||||
<option>INR</option>
|
||||
<option>MXN</option>
|
||||
<option>NZD</option>
|
||||
<option>SGD</option>
|
||||
<option>HKD</option>
|
||||
<option>KRW</option>
|
||||
<option>SEK</option>
|
||||
<option>NOK</option>
|
||||
<option>TRY</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Contact Name</label>
|
||||
<input class="form-control" type="text" placeholder="Enter contact name" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Phone Number</label>
|
||||
<input class="form-control" type="text" placeholder="Enter phone number" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Email Address</label>
|
||||
<input class="form-control" type="text" placeholder="Enter email address" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Lead Source
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Referrals</option>
|
||||
<option>Former Clients</option>
|
||||
<option>Competitors</option>
|
||||
<option>Business & sales</option>
|
||||
<option>Google resources</option>
|
||||
<option>Linkedin</option>
|
||||
<option>Marketing</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Campaign Source
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Online Campaign</option>
|
||||
<option>Offline Campaign</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Time Zone</label>
|
||||
<select class="form-select">
|
||||
<option>GMT-12:00 Etc/GMT-12</option>
|
||||
<option>GMT-11:00 Etc/GMT-11</option>
|
||||
<option>GMT-11:00 Pacific/Midway</option>
|
||||
<option>GMT-10:00 America/Adak</option>
|
||||
<option>GMT-09:00 America/Anchorage</option>
|
||||
<option>GMT-09:00 Pacific/Gambier</option>
|
||||
<option>GMT-08:00 America/Dawson_Creek</option>
|
||||
<option>GMT-08:00 America/Ensenada</option>
|
||||
<option>GMT-08:00 America/Los_Angeles</option>
|
||||
<option>GMT-07:00 America/Chihuahua</option>
|
||||
<option>GMT-07:00 America/Denver</option>
|
||||
<option>GMT-06:00 America/Belize</option>
|
||||
<option>GMT-06:00 America/Cancun</option>
|
||||
<option>GMT-06:00 America/Chicago</option>
|
||||
<option>GMT-06:00 Chile/EasterIsland</option>
|
||||
<option>GMT-05:00 America/Bogota</option>
|
||||
<option>GMT-05:00 America/Havana</option>
|
||||
<option>GMT-05:00 America/New_York</option>
|
||||
<option>GMT-04:30 America/Caracas</option>
|
||||
<option>GMT-04:00 America/Campo_Grande</option>
|
||||
<option>GMT-04:00 America/Glace_Bay</option>
|
||||
<option>GMT-04:00 America/Goose_Bay</option>
|
||||
<option>GMT-04:00 America/Santiago</option>
|
||||
<option>GMT-04:00 America/La_Paz</option>
|
||||
<option>GMT-03:00 America/Argentina/Buenos_Aires</option>
|
||||
<option>GMT-03:00 America/Montevideo</option>
|
||||
<option>GMT-03:00 America/Araguaina</option>
|
||||
<option>GMT-03:00 America/Godthab</option>
|
||||
<option>GMT-03:00 America/Miquelon</option>
|
||||
<option>GMT-03:00 America/Sao_Paulo</option>
|
||||
<option>GMT-03:30 America/St_Johns</option>
|
||||
<option>GMT-02:00 America/Noronha</option>
|
||||
<option>GMT-01:00 Atlantic/Cape_Verde</option>
|
||||
<option>GMT Europe/Belfast</option>
|
||||
<option>GMT Africa/Abidjan</option>
|
||||
<option>GMT Europe/Dublin</option>
|
||||
<option>GMT Europe/Lisbon</option>
|
||||
<option>GMT Europe/London</option>
|
||||
<option>UTC UTC</option>
|
||||
<option>GMT+01:00 Africa/Algiers</option>
|
||||
<option>GMT+01:00 Africa/Windhoek</option>
|
||||
<option>GMT+01:00 Atlantic/Azores</option>
|
||||
<option>GMT+01:00 Atlantic/Stanley</option>
|
||||
<option>GMT+01:00 Europe/Amsterdam</option>
|
||||
<option>GMT+01:00 Europe/Belgrade</option>
|
||||
<option>GMT+01:00 Europe/Brussels</option>
|
||||
<option>GMT+02:00 Africa/Cairo</option>
|
||||
<option>GMT+02:00 Africa/Blantyre</option>
|
||||
<option>GMT+02:00 Asia/Beirut</option>
|
||||
<option>GMT+02:00 Asia/Damascus</option>
|
||||
<option>GMT+02:00 Asia/Gaza</option>
|
||||
<option>GMT+02:00 Asia/Jerusalem</option>
|
||||
<option>GMT+03:00 Africa/Addis_Ababa</option>
|
||||
<option>GMT+03:00 Asia/Riyadh89</option>
|
||||
<option>GMT+03:00 Europe/Minsk</option>
|
||||
<option>GMT+03:30 Asia/Tehran</option>
|
||||
<option>GMT+04:00 Asia/Dubai</option>
|
||||
<option>GMT+04:00 Asia/Yerevan</option>
|
||||
<option>GMT+04:00 Europe/Moscow</option>
|
||||
<option>GMT+04:30 Asia/Kabul</option>
|
||||
<option>GMT+05:00 Asia/Tashkent</option>
|
||||
<option>GMT+05:30 Asia/Kolkata</option>
|
||||
<option>GMT+05:45 Asia/Katmandu</option>
|
||||
<option>GMT+06:00 Asia/Dhaka</option>
|
||||
<option>GMT+06:00 Asia/Yekaterinburg</option>
|
||||
<option>GMT+06:30 Asia/Rangoon</option>
|
||||
<option>GMT+07:00 Asia/Bangkok</option>
|
||||
<option>GMT+07:00 Asia/Novosibirsk</option>
|
||||
<option>GMT+08:00 Etc/GMT+8</option>
|
||||
<option>GMT+08:00 Asia/Hong_Kong</option>
|
||||
<option>GMT+08:00 Asia/Krasnoyarsk</option>
|
||||
<option>GMT+08:00 Australia/Perth</option>
|
||||
<option>GMT+08:45 Australia/Eucla</option>
|
||||
<option>GMT+09:00 Asia/Irkutsk</option>
|
||||
<option>GMT+09:00 Asia/Seoul</option>
|
||||
<option>GMT+09:00 Asia/Tokyo</option>
|
||||
<option>GMT+09:30 Australia/Adelaide</option>
|
||||
<option>GMT+09:30 Australia/Darwin</option>
|
||||
<option>GMT+09:30 Pacific/Marquesas</option>
|
||||
<option>GMT+10:00 Etc/GMT+10</option>
|
||||
<option>GMT+10:00 Australia/Brisbane</option>
|
||||
<option>GMT+10:00 Australia/Hobart</option>
|
||||
<option>GMT+10:00 Asia/Yakutsk</option>
|
||||
<option>GMT+10:30 Australia/Lord_Howe</option>
|
||||
<option>GMT+11:00 Asia/Vladivostok</option>
|
||||
<option>GMT+11:30 Pacific/Norfolk</option>
|
||||
<option>GMT+12:00 Etc/GMT+12</option>
|
||||
<option>GMT+12:00 Asia/Anadyr</option>
|
||||
<option>GMT+12:00 Asia/Magadan</option>
|
||||
<option>GMT+12:00 Pacific/Auckland</option>
|
||||
<option>GMT+12:45 Pacific/Chatham</option>
|
||||
<option>GMT+13:00 Pacific/Tongatapu</option>
|
||||
<option>GMT+14:00 Pacific/Kiritimati</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Create Date</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="dd / mm / yyyy" data-options='{"disableMobile":true}' />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Start Time</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="H:i" data-options='{"enableTime":true,"noCalendar":true,"dateFormat":"H:i","disableMobile":true}' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Closing Date</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="dd / mm / yyyy" data-options='{"disableMobile":true}' />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Closing Time</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="H:i" data-options='{"enableTime":true,"noCalendar":true,"dateFormat":"H:i","disableMobile":true}' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Stage</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>New</option>
|
||||
<option>In Progress</option>
|
||||
<option>Pending</option>
|
||||
<option>Canceled</option>
|
||||
<option>Completed</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Priority</label>
|
||||
<select class="form-select">
|
||||
<option>Urgent</option>
|
||||
<option>High</option>
|
||||
<option>Medium</option>
|
||||
<option>Low</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer border-0 pt-6 px-0 pb-0">
|
||||
<button class="btn btn-link text-danger px-3 my-0" data-bs-dismiss="modal" aria-label="Close">Cancel</button>
|
||||
|
||||
<button class="btn btn-primary my-0">Create Deal</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="px-4 px-lg-6">
|
||||
<div class="row g-3">
|
||||
<h2 class="mb-5">{{ _("Opportunities") }}</h2>
|
||||
<div class="d-xl-flex justify-content-between">
|
||||
<div class="mb-3">
|
||||
@ -12,34 +12,28 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="px-4 px-lg-6 ">
|
||||
<div class="deals-items-container">
|
||||
<div class="deals scrollbar">
|
||||
<div class="deals-col me-4">
|
||||
|
||||
<div class="w-100 min-vh-50">
|
||||
|
||||
<div class="px-4 px-lg-6 scrollbar">
|
||||
<div class="deals">
|
||||
{% for opportunity in opportunities %}
|
||||
<div class="deals-col col-sm-6 me-4 mt-4">
|
||||
<div class="d-flex align-items-center justify-content-between position-sticky top-0 z-1 bg-body">
|
||||
<div>
|
||||
<h5 class="mb-2 ms-4">{{ opportunity.car.id_car_make.get_local_name }} - {{ opportunity.car.id_car_model.get_local_name }} - {{ opportunity.car.year }}</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-3">
|
||||
<button class="btn p-0" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><a class="dropdown-item" href="{% url 'update_opportunity' pk=opportunity.pk %}">{{ _("Edit") }}</a></li>
|
||||
<li><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" deals-items-row">
|
||||
<div class="w-100 min-vh-50" >
|
||||
<div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h5 class="mb-2 ms-4">{{ opportunity.car.id_car_make.get_local_name }} - {{ opportunity.car.id_car_model.get_local_name }} - {{ opportunity.car.year }}</h5>
|
||||
<a class="dropdown-indicator-icon position-absolute text-body-tertiary text-end"
|
||||
href="#collapseWidthDeals-1"
|
||||
href="#collapseWidthDeals-{{ opportunity.pk }}"
|
||||
role="button"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseWidthDeals-1">
|
||||
aria-controls="collapseWidthDeals-{{ opportunity.pk }}">
|
||||
<span class="fa-solid fa-angle-down text-end"></span>
|
||||
</a>
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
@ -64,7 +58,7 @@
|
||||
<p class="text-body-secondary fw-bold fs-10 mb-0">{{ opportunity.staff.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapseWidthDeals-1">
|
||||
<div class="collapse" id="collapseWidthDeals-{{ opportunity.pk }}">
|
||||
<div class="d-flex gap-2 mb-5"><span class="badge badge-phoenix fs-10 badge-phoenix-info">{{ opportunity.get_stage_display }}</span><span class="badge badge-phoenix fs-10 badge-phoenix-danger">{{ opportunity.get_status_display }}</span></div>
|
||||
<table class="mb-4 w-100 table-stats table-stats">
|
||||
<tr>
|
||||
@ -123,381 +117,17 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="deleteModal"
|
||||
data-bs-backdrop="static"
|
||||
data-bs-keyboard="false"
|
||||
tabindex="-1"
|
||||
aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
|
||||
{% trans "Delete Opportunity" %}
|
||||
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p class="mb-0 text-danger fw-bold">
|
||||
{% trans "Are you sure you want to delete this opportunity?" %}
|
||||
</p>
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">
|
||||
{% trans "No" %}
|
||||
</button>
|
||||
<a type="button" class="btn btn-danger btn-sm" href="{% url 'delete_opportunity' opportunity.pk %}">
|
||||
{% trans "Yes" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="addOpportunityModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="addOpportunityModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content bg-body-highlight p-6">
|
||||
<div class="modal-header justify-content-between border-0 p-0 mb-2">
|
||||
<h3 class="mb-0">Opportunity Information</h3>
|
||||
<button class="btn btn-sm btn-phoenix-secondary" data-bs-dismiss="modal" aria-label="Close"><span class="fas fa-times text-danger"></span></button>
|
||||
</div>
|
||||
<div class="modal-body px-0">
|
||||
<form method="post" class="form" action="{% url 'create_opportunity' opportunity.customer.pk %}">
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-6">
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Owner</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Ally Aagaard</option>
|
||||
<option>Aida Moen</option>
|
||||
<option>Niko Koss</option>
|
||||
<option>Alec Haag</option>
|
||||
<option>Lonnie Kub</option>
|
||||
<option>Ola Smith</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Name</label>
|
||||
<input class="form-control" type="text" placeholder="Enter deal name" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-6 col-lg-12 col-xl-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Amount</label>
|
||||
<div class="row g-2">
|
||||
<div class="col">
|
||||
<input class="form-control" type="number" placeholder="$ Enter amount" />
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select class="form-select">
|
||||
<option>USD</option>
|
||||
<option>GBP</option>
|
||||
<option>EUR</option>
|
||||
<option>JPY</option>
|
||||
<option>CAD</option>
|
||||
<option>AUD</option>
|
||||
<option>CNY</option>
|
||||
<option>CHF</option>
|
||||
<option>ZAR</option>
|
||||
<option>BRL</option>
|
||||
<option>RUB</option>
|
||||
<option>INR</option>
|
||||
<option>MXN</option>
|
||||
<option>NZD</option>
|
||||
<option>SGD</option>
|
||||
<option>HKD</option>
|
||||
<option>KRW</option>
|
||||
<option>SEK</option>
|
||||
<option>NOK</option>
|
||||
<option>TRY</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Code</label>
|
||||
<input class="form-control" type="text" placeholder="Enter deals code" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Opportunity Type
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Buy One Get One Free</option>
|
||||
<option>Clearance sale</option>
|
||||
<option>Bundle deals</option>
|
||||
<option>Free shipping</option>
|
||||
<option>Loyalty programs</option>
|
||||
<option>Limited-time offers</option>
|
||||
<option>Refer-a-friend discounts</option>
|
||||
<option>Seasonal sales</option>
|
||||
<option>Membership discounts</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Category
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Financial</option>
|
||||
<option>Marketplace</option>
|
||||
<option>Travel</option>
|
||||
<option>E-commerce</option>
|
||||
<option>Cloud Computing</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Probability (%)</label>
|
||||
<input class="form-control" type="text" placeholder="Enter value" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Expected Revenue</label>
|
||||
<div class="row g-2">
|
||||
<div class="col">
|
||||
<input class="form-control" type="number" placeholder="$ Enter amount" />
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select class="form-select">
|
||||
<option>USD</option>
|
||||
<option>GBP</option>
|
||||
<option>EUR</option>
|
||||
<option>JPY</option>
|
||||
<option>CAD</option>
|
||||
<option>AUD</option>
|
||||
<option>CNY</option>
|
||||
<option>CHF</option>
|
||||
<option>ZAR</option>
|
||||
<option>BRL</option>
|
||||
<option>RUB</option>
|
||||
<option>INR</option>
|
||||
<option>MXN</option>
|
||||
<option>NZD</option>
|
||||
<option>SGD</option>
|
||||
<option>HKD</option>
|
||||
<option>KRW</option>
|
||||
<option>SEK</option>
|
||||
<option>NOK</option>
|
||||
<option>TRY</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Contact Name</label>
|
||||
<input class="form-control" type="text" placeholder="Enter contact name" />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Phone Number</label>
|
||||
<input class="form-control" type="text" placeholder="Enter phone number" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Email Address</label>
|
||||
<input class="form-control" type="text" placeholder="Enter email address" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Lead Source
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Referrals</option>
|
||||
<option>Former Clients</option>
|
||||
<option>Competitors</option>
|
||||
<option>Business & sales</option>
|
||||
<option>Google resources</option>
|
||||
<option>Linkedin</option>
|
||||
<option>Marketing</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Campaign Source
|
||||
<button class="btn btn-link p-0 ms-3"><span class="fa-solid fa-plus me-1"></span><span>Add new</span></button>
|
||||
</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>Online Campaign</option>
|
||||
<option>Offline Campaign</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="text-body-highlight fw-bold mb-2">Time Zone</label>
|
||||
<select class="form-select">
|
||||
<option>GMT-12:00 Etc/GMT-12</option>
|
||||
<option>GMT-11:00 Etc/GMT-11</option>
|
||||
<option>GMT-11:00 Pacific/Midway</option>
|
||||
<option>GMT-10:00 America/Adak</option>
|
||||
<option>GMT-09:00 America/Anchorage</option>
|
||||
<option>GMT-09:00 Pacific/Gambier</option>
|
||||
<option>GMT-08:00 America/Dawson_Creek</option>
|
||||
<option>GMT-08:00 America/Ensenada</option>
|
||||
<option>GMT-08:00 America/Los_Angeles</option>
|
||||
<option>GMT-07:00 America/Chihuahua</option>
|
||||
<option>GMT-07:00 America/Denver</option>
|
||||
<option>GMT-06:00 America/Belize</option>
|
||||
<option>GMT-06:00 America/Cancun</option>
|
||||
<option>GMT-06:00 America/Chicago</option>
|
||||
<option>GMT-06:00 Chile/EasterIsland</option>
|
||||
<option>GMT-05:00 America/Bogota</option>
|
||||
<option>GMT-05:00 America/Havana</option>
|
||||
<option>GMT-05:00 America/New_York</option>
|
||||
<option>GMT-04:30 America/Caracas</option>
|
||||
<option>GMT-04:00 America/Campo_Grande</option>
|
||||
<option>GMT-04:00 America/Glace_Bay</option>
|
||||
<option>GMT-04:00 America/Goose_Bay</option>
|
||||
<option>GMT-04:00 America/Santiago</option>
|
||||
<option>GMT-04:00 America/La_Paz</option>
|
||||
<option>GMT-03:00 America/Argentina/Buenos_Aires</option>
|
||||
<option>GMT-03:00 America/Montevideo</option>
|
||||
<option>GMT-03:00 America/Araguaina</option>
|
||||
<option>GMT-03:00 America/Godthab</option>
|
||||
<option>GMT-03:00 America/Miquelon</option>
|
||||
<option>GMT-03:00 America/Sao_Paulo</option>
|
||||
<option>GMT-03:30 America/St_Johns</option>
|
||||
<option>GMT-02:00 America/Noronha</option>
|
||||
<option>GMT-01:00 Atlantic/Cape_Verde</option>
|
||||
<option>GMT Europe/Belfast</option>
|
||||
<option>GMT Africa/Abidjan</option>
|
||||
<option>GMT Europe/Dublin</option>
|
||||
<option>GMT Europe/Lisbon</option>
|
||||
<option>GMT Europe/London</option>
|
||||
<option>UTC UTC</option>
|
||||
<option>GMT+01:00 Africa/Algiers</option>
|
||||
<option>GMT+01:00 Africa/Windhoek</option>
|
||||
<option>GMT+01:00 Atlantic/Azores</option>
|
||||
<option>GMT+01:00 Atlantic/Stanley</option>
|
||||
<option>GMT+01:00 Europe/Amsterdam</option>
|
||||
<option>GMT+01:00 Europe/Belgrade</option>
|
||||
<option>GMT+01:00 Europe/Brussels</option>
|
||||
<option>GMT+02:00 Africa/Cairo</option>
|
||||
<option>GMT+02:00 Africa/Blantyre</option>
|
||||
<option>GMT+02:00 Asia/Beirut</option>
|
||||
<option>GMT+02:00 Asia/Damascus</option>
|
||||
<option>GMT+02:00 Asia/Gaza</option>
|
||||
<option>GMT+02:00 Asia/Jerusalem</option>
|
||||
<option>GMT+03:00 Africa/Addis_Ababa</option>
|
||||
<option>GMT+03:00 Asia/Riyadh89</option>
|
||||
<option>GMT+03:00 Europe/Minsk</option>
|
||||
<option>GMT+03:30 Asia/Tehran</option>
|
||||
<option>GMT+04:00 Asia/Dubai</option>
|
||||
<option>GMT+04:00 Asia/Yerevan</option>
|
||||
<option>GMT+04:00 Europe/Moscow</option>
|
||||
<option>GMT+04:30 Asia/Kabul</option>
|
||||
<option>GMT+05:00 Asia/Tashkent</option>
|
||||
<option>GMT+05:30 Asia/Kolkata</option>
|
||||
<option>GMT+05:45 Asia/Katmandu</option>
|
||||
<option>GMT+06:00 Asia/Dhaka</option>
|
||||
<option>GMT+06:00 Asia/Yekaterinburg</option>
|
||||
<option>GMT+06:30 Asia/Rangoon</option>
|
||||
<option>GMT+07:00 Asia/Bangkok</option>
|
||||
<option>GMT+07:00 Asia/Novosibirsk</option>
|
||||
<option>GMT+08:00 Etc/GMT+8</option>
|
||||
<option>GMT+08:00 Asia/Hong_Kong</option>
|
||||
<option>GMT+08:00 Asia/Krasnoyarsk</option>
|
||||
<option>GMT+08:00 Australia/Perth</option>
|
||||
<option>GMT+08:45 Australia/Eucla</option>
|
||||
<option>GMT+09:00 Asia/Irkutsk</option>
|
||||
<option>GMT+09:00 Asia/Seoul</option>
|
||||
<option>GMT+09:00 Asia/Tokyo</option>
|
||||
<option>GMT+09:30 Australia/Adelaide</option>
|
||||
<option>GMT+09:30 Australia/Darwin</option>
|
||||
<option>GMT+09:30 Pacific/Marquesas</option>
|
||||
<option>GMT+10:00 Etc/GMT+10</option>
|
||||
<option>GMT+10:00 Australia/Brisbane</option>
|
||||
<option>GMT+10:00 Australia/Hobart</option>
|
||||
<option>GMT+10:00 Asia/Yakutsk</option>
|
||||
<option>GMT+10:30 Australia/Lord_Howe</option>
|
||||
<option>GMT+11:00 Asia/Vladivostok</option>
|
||||
<option>GMT+11:30 Pacific/Norfolk</option>
|
||||
<option>GMT+12:00 Etc/GMT+12</option>
|
||||
<option>GMT+12:00 Asia/Anadyr</option>
|
||||
<option>GMT+12:00 Asia/Magadan</option>
|
||||
<option>GMT+12:00 Pacific/Auckland</option>
|
||||
<option>GMT+12:45 Pacific/Chatham</option>
|
||||
<option>GMT+13:00 Pacific/Tongatapu</option>
|
||||
<option>GMT+14:00 Pacific/Kiritimati</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Create Date</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="dd / mm / yyyy" data-options='{"disableMobile":true}' />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Start Time</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="H:i" data-options='{"enableTime":true,"noCalendar":true,"dateFormat":"H:i","disableMobile":true}' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Closing Date</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="dd / mm / yyyy" data-options='{"disableMobile":true}' />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Closing Time</label>
|
||||
<input class="form-control datetimepicker" type="text" placeholder="H:i" data-options='{"enableTime":true,"noCalendar":true,"dateFormat":"H:i","disableMobile":true}' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Stage</label>
|
||||
<select class="form-select">
|
||||
<option>Select</option>
|
||||
<option>New</option>
|
||||
<option>In Progress</option>
|
||||
<option>Pending</option>
|
||||
<option>Canceled</option>
|
||||
<option>Completed</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="text-body-highlight fw-bold mb-2">Priority</label>
|
||||
<select class="form-select">
|
||||
<option>Urgent</option>
|
||||
<option>High</option>
|
||||
<option>Medium</option>
|
||||
<option>Low</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer border-0 pt-6 px-0 pb-0">
|
||||
<button class="btn btn-link text-danger px-3 my-0" data-bs-dismiss="modal" aria-label="Close">Cancel</button>
|
||||
|
||||
<button class="btn btn-primary my-0">Create Deal</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@ -22,27 +22,27 @@
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-6 col-md-8">
|
||||
<form class="row g-3" method="post" class="form" novalidate>
|
||||
<form method="post" class="form row g-3 needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="{{ form.first_name.id_for_label }}" name="{{ form.first_name.name }}" value="{{ form.first_name.value|default:'' }}" placeholder="{{ _("First Name")}}">
|
||||
<input type="text" class="form-control" id="{{ form.first_name.id_for_label }}" name="{{ form.first_name.name }}" value="" placeholder="{{ _("First Name")}}" required>
|
||||
<label for="{{ form.first_name.id_for_label }}">{{ _("First Name")}}</label>
|
||||
{{ form.first_name.errors }}
|
||||
<div class="invalid-feedback mt-0">{{ form.first_name.errors|striptags }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="{{ form.middle_name.id_for_label }}" name="{{ form.middle_name.name }}" value="{{ form.middle_name.value|default:'' }}" placeholder="{{ _("Middle Name")}}">
|
||||
<input type="text" class="form-control" id="{{ form.middle_name.id_for_label }}" name="{{ form.middle_name.name }}" value="" placeholder="{{ _("Middle Name")}}" required>
|
||||
<label for="{{ form.middle_name.id_for_label }}">{{ _("Middle Name")}}</label>
|
||||
{{ form.middle_name.errors }}
|
||||
<div class="invalid-feedback mt-0">{{ form.middle_name.errors }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="{{ form.last_name.id_for_label }}" name="{{ form.last_name.name }}" value="{{ form.last_name.value|default:'' }}" placeholder="{{ _("Last Name")}}">
|
||||
<input type="text" class="form-control" id="{{ form.last_name.id_for_label }}" name="{{ form.last_name.name }}" value="" placeholder="{{ _("Last Name")}}" required>
|
||||
<label for="{{ form.last_name.id_for_label }}">{{ _("Last Name")}}</label>
|
||||
{{ form.last_name.errors }}
|
||||
<div class="invalid-feedback mt-0">{{ form.last_name.errors }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-2">
|
||||
@ -76,25 +76,18 @@
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="email" class="form-control" id="{{ form.email.id_for_label }}" name="{{ form.email.name }}" value="{{ form.email.value|default:'' }}" placeholder="{{ _("Email") }}">
|
||||
<input type="email" class="form-control" id="{{ form.email.id_for_label }}" name="{{ form.email.name }}" value="" placeholder="{{ _("Email") }}" required>
|
||||
<label for="{{ form.email.id_for_label }}">{{ _("Email") }}</label>
|
||||
{{ form.email.errors }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="{{ form.national_id.id_for_label }}" name="{{ form.national_id.name }}" value="{{ form.national_id.value|default:'' }}" placeholder="{{ _("Enter national ID")}}">
|
||||
<input type="text" class="form-control" id="{{ form.national_id.id_for_label }}" name="{{ form.national_id.name }}" value="" placeholder="{{ _("Enter national ID")}}" required>
|
||||
<label for="{{ form.national_id.id_for_label }}">{{ _("National ID")}}</label>
|
||||
{{ form.national_id.errors }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="{{ form.city.id_for_label }}" name="{{ form.city.name }}" value="{{ form.city.value|default:'' }}" placeholder="{{ _("City")}}">
|
||||
<label for="{{ form.city.id_for_label }}">{{ _("City") }}</label>
|
||||
{{ form.country.errors }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<input type="tel" class="form-control" id="{{ form.phone_number.id_for_label }}" name="{{ form.phone_number.name }}" value="{{ form.phone_number.value|default:'' }}" placeholder="phone">
|
||||
@ -103,7 +96,7 @@
|
||||
{{ form.phone_number.errors }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-12">
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="form-floating">
|
||||
<textarea class="form-control" id="{{ form.address.id_for_label }}" name="{{ form.address.name }}" placeholder="Enter address">{{ form.address.value|default:'' }}</textarea>
|
||||
<label for="{{ form.address.id_for_label }}">{{ _("Address") }}</label>
|
||||
@ -112,10 +105,11 @@
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="d-flex mb-3">
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary me-2 px-6">{% trans "cancel"|capfirst %}</a>
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<button class="btn btn-primary me-2 px-6" type="submit">
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary">{% trans "cancel"|capfirst %}</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -86,11 +86,11 @@
|
||||
<span class="fa-solid fa-money-bill-trend-up fs-5 text-warning-light dark__text-opacity-75" data-bs-theme="light"></span>
|
||||
<div class="d-flex d-md-block gap-2 align-items-center mt-1 mt-md-0">
|
||||
<p class="fs-9 mb-0 mb-md-2 text-body-tertiary text-nowrap">{% trans "Profits"|upper %}</p>
|
||||
<h4 class="text-body-highlight mb-0">{{ total_profit }} {% trans 'SAR' %}</h4>
|
||||
<h4 class="text-body-highlight mb-0">{{ total_profit|floatformat }} {% trans 'SAR' %}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 mt-md-0">
|
||||
<h3 class="text-body-highlight mb-2">{{ total_selling_price }} {% trans 'SAR' %}</h3>
|
||||
<h3 class="text-body-highlight mb-2">{{ total_selling_price|floatformat }} {% trans 'SAR' %}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.modal-dialog {
|
||||
max-width: 95%;
|
||||
}
|
||||
|
||||
</style>
|
||||
{% include 'partials/form_errors.html' %}
|
||||
|
||||
@ -22,15 +20,23 @@
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="d-flex flex-column flex-sm-grow-1 p-4">
|
||||
<main class="d-grid gap-4 p-1">
|
||||
|
||||
<div class="row g-4">
|
||||
<h3 class="mb-3">{% trans 'Add Car' %}</h3>
|
||||
<!-- VIN -->
|
||||
<div class="col-lg-12 col-xl-12">
|
||||
<div class="card h-100 border-1 rounded shadow">
|
||||
<div class="col-lg-4 col-xl-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<label class="form-label" for="{{ form.vin.id_for_label }}">
|
||||
{% trans 'VIN' %}:
|
||||
</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="form-floating">
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
id="{{ form.vin.id_for_label }}" name="{{ form.vin.html_name }}" />
|
||||
<label for="{{ form.vin.id_for_label }}">{% trans 'VIN' %}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm my-2">
|
||||
<button type="button"
|
||||
class="btn btn-phoenix-warning fs-8 rounded-start"
|
||||
id="scan-vin-btn"
|
||||
@ -38,130 +44,106 @@
|
||||
data-bs-target="#scannerModal">
|
||||
<span class="fas fa-camera"></span>
|
||||
</button>
|
||||
<input type="text"
|
||||
class="form-control form-control-sm"
|
||||
id="{{ form.vin.id_for_label }}" name="{{ form.vin.html_name }}" />
|
||||
<button type="button" class="btn btn-sm btn-phoenix-primary rounded-end" id="decodeVinBtn">
|
||||
{% trans 'Search' %}
|
||||
</button>
|
||||
</div>
|
||||
{% if form.vin.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.vin.errors|striptags }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Year Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body" id="year-row">
|
||||
<label class="form-label" for="{{ form.year.id_for_label }}">
|
||||
{% trans 'Year' %}:
|
||||
</label>
|
||||
<span class="text-success fw-bold" id="year-check"></span>
|
||||
<input type="number"
|
||||
class="form-control form-control-sm"
|
||||
id="{{ form.year.id_for_label }}"
|
||||
name="{{ form.year.html_name }}" />
|
||||
{% if form.year.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.year.errors|striptags }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Makes Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100">
|
||||
<div id="make-row" class="card-body">
|
||||
<div class="status"></div>
|
||||
<label class="form-label" for="{{ form.id_car_make.id_for_label }}">
|
||||
{% trans 'make'|capfirst %}:
|
||||
</label>
|
||||
<span class="text-success fw-bold" id="make-check"></span>
|
||||
{{ form.id_car_make|add_class:"form-select form-select-sm" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="col-6">
|
||||
<div class="form-floating">
|
||||
<span class="text-success fw-bold" id="year-check"></span>
|
||||
<input type="number"
|
||||
class="form-control form-control-sm"
|
||||
id="{{ form.year.id_for_label }}"
|
||||
name="{{ form.year.html_name }}" />
|
||||
<label for="{{ form.year.id_for_label }}">{% trans 'Year' %}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="serie-row" class="col-6">
|
||||
|
||||
<!-- Models Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100">
|
||||
<div id="model-row" class="card-body">
|
||||
<label class="form-label" for="{{ form.id_car_model.id_for_label }}">
|
||||
{% trans 'model'|capfirst %}:
|
||||
</label>
|
||||
<span class="text-success fw-bold" id="model-check"></span>
|
||||
<select class="form-select form-select-sm"
|
||||
id="{{ form.id_car_model.id_for_label }}"
|
||||
name="{{ form.id_car_model.html_name }}">
|
||||
<option value="">{% trans 'Select' %}</option>
|
||||
</select>
|
||||
<div class="badge badge-phoenix fs-11 badge-phoenix-success m-1" id="generation-div"></div>
|
||||
<div class="form-floating">
|
||||
<select class="form-select form-select-sm"
|
||||
id="{{ form.id_car_serie.id_for_label }}"
|
||||
name="{{ form.id_car_serie.html_name }}">
|
||||
<option value="">{% trans 'Select' %}</option>
|
||||
</select>
|
||||
<label for="{{ form.id_car_serie.id_for_label }}">{% trans 'Series' %}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="col-6" id="make-row">
|
||||
<div class="form-floating">
|
||||
<span class="text-success fw-bold" id="make-check"></span>
|
||||
{{ form.id_car_make|add_class:"form-select form-select-sm" }}
|
||||
<label for="{{ form.id_car_make.id_for_label }}">{% trans 'make'|capfirst %}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6" id="trim-row">
|
||||
<div class="form-floating">
|
||||
|
||||
<!-- Series Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body" id="serie-row">
|
||||
<label class="form-label" for="{{ form.id_car_serie.id_for_label }}">
|
||||
{% trans 'Series' %}:
|
||||
</label>
|
||||
<select class="form-select form-select-sm"
|
||||
id="{{ form.id_car_serie.id_for_label }}"
|
||||
name="{{ form.id_car_serie.html_name }}">
|
||||
<option value="">{% trans 'Select' %}</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trims Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body" id="trim-row">
|
||||
<label class="form-label" for="{{ form.id_car_trim.id_for_label }}">
|
||||
{% trans 'trim'|capfirst %}:
|
||||
</label>
|
||||
<select class="form-select form-select-sm"
|
||||
id="{{ form.id_car_trim.id_for_label }}"
|
||||
name="{{ form.id_car_trim.html_name }}">
|
||||
<option value="">{% trans 'Select' %}</option>
|
||||
</select>
|
||||
<label for="{{ form.id_car_trim.id_for_label }}">{% trans 'trim'|capfirst %}</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row my-3">
|
||||
<div class="col-6" id="model-row">
|
||||
<div class="form-floating">
|
||||
<span class="text-success fw-bold" id="model-check"></span>
|
||||
<select class="form-select form-select-sm"
|
||||
id="{{ form.id_car_model.id_for_label }}"
|
||||
name="{{ form.id_car_model.html_name }}">
|
||||
<option value="">{% trans 'Select' %}</option>
|
||||
</select>
|
||||
<label for="{{ form.id_car_model.id_for_label }}">{% trans 'model'|capfirst %}</label>
|
||||
</div>
|
||||
<div class="badge badge-phoenix fs-11 badge-phoenix-success m-1" id="generation-div"></div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="btn-group btn-group-sm justify-content-between align-items-center my-2">
|
||||
<button type="button"
|
||||
class="btn btn-phoenix-primary m-1"
|
||||
class="btn btn-sm btn-phoenix-primary rounded-start"
|
||||
id="specification-btn"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#specificationsModal"
|
||||
disabled>{% trans 'specifications'|capfirst %}
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-phoenix-warning m-1"
|
||||
class="btn btn-sm btn-phoenix-warning rounded-end"
|
||||
id="options-btn"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#equipmentOptionsModal"
|
||||
disabled>{% trans 'options'|capfirst %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-4 col-xl-6">
|
||||
<div class="row g-3">
|
||||
<!-- Vendor Field -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.vendor.id_for_label }}" class="form-label">
|
||||
{% trans 'Vendor' %}:
|
||||
</label>
|
||||
<div class="form-floating">
|
||||
{{ form.vendor|add_class:"form-select form-select-sm" }}
|
||||
<label for="{{ form.vendor.id_for_label }}" class="form-label">
|
||||
{% trans 'Vendor' %}
|
||||
</label>
|
||||
</div>
|
||||
{% if form.vendor.errors %}
|
||||
<div class="text-danger small">
|
||||
@ -173,13 +155,17 @@
|
||||
</div>
|
||||
|
||||
<!-- Stock Type Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<label class="form-label" for="{{ form.stock_type.id_for_label }}">
|
||||
{% trans 'Stock Type'|capfirst %}:
|
||||
<div class="form-floating">
|
||||
{{ form.stock_type|add_class:"form-select form-select-sm" }}
|
||||
<label for="{{ form.stock_type.id_for_label }}">
|
||||
{% trans 'Stock Type'|capfirst %}
|
||||
</label>
|
||||
{{ form.stock_type|add_class:"form-select form-select-sm" }} {% if form.stock_type.errors %}
|
||||
</div>
|
||||
|
||||
{% if form.stock_type.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.stock_type.errors|striptags }}
|
||||
</div>
|
||||
@ -188,13 +174,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mileage Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<label class="form-label" for="{{ form.mileage.id_for_label }}">
|
||||
{% trans 'Mileage'|capfirst %}:
|
||||
</label>
|
||||
{{ form.mileage|add_class:"form-control form-control-sm" }} {% if form.mileage.errors %}
|
||||
<div class="form-floating">
|
||||
{{ form.mileage|add_class:"form-control form-control-sm" }}
|
||||
<label for="{{ form.mileage.id_for_label }}">{% trans 'Mileage'|capfirst %}</label>
|
||||
</div>
|
||||
{% if form.mileage.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.mileage.errors|striptags }}
|
||||
</div>
|
||||
@ -204,33 +191,37 @@
|
||||
</div>
|
||||
|
||||
<!-- Receiving Date Field -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100 border-1 rounded shadow">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.receiving_date.id_for_label }}"
|
||||
class="form-label">
|
||||
{% trans 'Receiving Date' %}:
|
||||
</label>
|
||||
{{ form.receiving_date|add_class:"form-control form-control-sm" }}
|
||||
{% if form.receiving_date.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.receiving_date.errors|striptags }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-xl-4">
|
||||
<div class="card h-100 border-1 rounded shadow">
|
||||
<div class="card-body">
|
||||
<div class="form-floating">
|
||||
{{ form.receiving_date|add_class:"form-control form-control-sm" }}
|
||||
<label for="{{ form.receiving_date.id_for_label }}"
|
||||
class="form-label">
|
||||
{% trans 'Receiving Date' %}:
|
||||
</label>
|
||||
</div>
|
||||
{% if form.receiving_date.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.receiving_date.errors|striptags }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Remarks Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="col-lg-4 col-xl-8">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<label class="label" for="{{ form.remarks.id_for_label }}">
|
||||
<div class="form-floating">
|
||||
<label for="{{ form.remarks.id_for_label }}">
|
||||
{% trans 'Remarks'|capfirst %}:
|
||||
</label>
|
||||
{{ form.remarks|add_class:"form-control form-control-sm" }} {% if form.remarks.errors %}
|
||||
{{ form.remarks|add_class:"form-control form-control-sm" }}
|
||||
</div>
|
||||
{% if form.remarks.errors %}
|
||||
<div class="text-danger small">
|
||||
{{ form.remarks.errors|striptags }}
|
||||
</div>
|
||||
@ -238,33 +229,45 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Specifications Buttons -->
|
||||
<div class="row g-1">
|
||||
<div class="btn-group">
|
||||
|
||||
<button type="submit" name="add_another" value="true" class="btn btn-sm btn-success me-1">
|
||||
<div class="btn-group mt-3">
|
||||
|
||||
<button type="submit" name="add_another" value="true" class="btn btn-sm btn-phoenix-success me-1">
|
||||
{% trans "Save and Add Another" %}
|
||||
</button>
|
||||
<button type="submit" name="go_to_stats" value="true" class="btn btn-sm btn-primary">
|
||||
<button type="submit" name="go_to_stats" value="true" class="btn btn-sm btn-phoenix-primary">
|
||||
{% trans "Save and Go to Inventory" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<!-- Specification Modal -->
|
||||
<div class="modal fade" id="specificationsModal" tabindex="-1" aria-labelledby="specificationsModalLabel">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content rounded-top-2">
|
||||
<div class="modal-header">
|
||||
|
||||
<!--Specification Modal-->
|
||||
<div class="modal fade"
|
||||
id="specificationsModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="specificationsModalLabel"
|
||||
aria-modal="true"
|
||||
role="dialog">
|
||||
<div class="modal-dialog modal-md">
|
||||
<div class="modal-content overflow-hidden">
|
||||
<div class="modal-header position-relative">
|
||||
<h5 class="modal-title" id="specificationsModalLabel">
|
||||
{% trans 'specifications'|capfirst %}
|
||||
<span class="ms-3 my-5">{% trans 'specifications'|capfirst %}</span><span class="ms-1 fw-light">{{ _("Details") }}</span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Close' %}"></button>
|
||||
|
||||
<button class="btn btn-circle project-modal-btn position-absolute end-0 top-0 mt-3 me-3 bg-body-emphasis" data-bs-dismiss="modal">
|
||||
<span class="fa-solid fa-xmark text-body dark__text-gray-100"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="specificationsContent"></div>
|
||||
@ -276,11 +279,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- equipments and options Modal -->
|
||||
<div class="modal fade" id="equipmentOptionsModal" tabindex="-1" aria-labelledby="equipmentOptionsModalLabel">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content rounded-top-2">
|
||||
<div class="modal-header">
|
||||
<!--equipments and options Modal-->
|
||||
<div class="modal fade"
|
||||
id="equipmentOptionsModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="equipmentOptionsModalLabel"
|
||||
aria-modal="true"
|
||||
role="dialog">
|
||||
<div class="modal-dialog modal-md">
|
||||
<div class="modal-content overflow-hidden">
|
||||
<div class="modal-header position-relative">
|
||||
<h5 class="modal-title" id="equipmentOptionsModalLabel">
|
||||
{% trans 'Options'|capfirst %}
|
||||
</h5>
|
||||
|
||||
@ -70,7 +70,7 @@
|
||||
<span class="badge badge-phoenix badge-phoenix-info"><span class="badge-label">{{_("Used")}}</span></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-start"><a class="fs-8 fw-bold" href="{% url 'car_detail' car.pk %}">{{ car.vin }}</a></td>
|
||||
<td class="align-middle white-space-nowrap text-start"><a class="fs-9 fw-bold" href="{% url 'car_detail' car.pk %}">{{ car.vin }}</a></td>
|
||||
<td class="align-middle white-space-nowrap text-center fw-bold">{{ car.year }}</td>
|
||||
{% if car.colors.exists %}
|
||||
<td class="align-middle white-space-nowrap text-body fs-9 text-start">
|
||||
|
||||
@ -27,8 +27,8 @@
|
||||
<tbody class="list">
|
||||
{% for service in services %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
<td class="align-middle product white-space-nowrap py-0">{{ service.item.item_number }}</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ service.name }}</td>
|
||||
<td class="align-middle product white-space-nowrap py-0">{{ service.pk }}</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ service.get_local_name }}</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ service.uom }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if service.taxable %}
|
||||
|
||||
@ -4,12 +4,15 @@
|
||||
{% block title %}{{ _("Invoices") }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="d-flex flex-column flex-sm-grow-1 ms-sm-14 p-4">
|
||||
<main class="d-grid gap-4 p-1">
|
||||
<div class="row mt-4">
|
||||
<h3 class="text-center">{% trans "Invoices" %}</h3>
|
||||
<div class="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-7 border-y">
|
||||
<div class="mx-n4 px-4 mx-lg-n6 px-lg-6 pt-7 border-y">
|
||||
|
||||
<div class="table-responsive mx-n1 px-1 scrollbar">
|
||||
<table class="table fs-9 mb-0 border-top border-translucent">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm fs-9 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Invoice Number" %}</th>
|
||||
@ -76,4 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Loading…
x
Reference in New Issue
Block a user