Customer View changed #170
@ -1288,6 +1288,32 @@ class OpportunityForm(forms.ModelForm):
|
||||
if self.instance and self.instance.pk:
|
||||
self.fields["probability"].initial = self.instance.probability
|
||||
|
||||
class OpportunityStageForm(forms.ModelForm):
|
||||
"""
|
||||
Represents a form for creating or editing Opportunity instances.
|
||||
|
||||
This class is a Django ModelForm designed to simplify the process of
|
||||
validating and persisting data for Opportunity model instances. It
|
||||
maps fields from the Opportunity model to form fields, making it
|
||||
convenient to handle user input for operations such as creating and
|
||||
updating opportunities.
|
||||
|
||||
:ivar Meta.model: The model associated with the form.
|
||||
:type Meta.model: type
|
||||
:ivar Meta.fields: List of fields from the model included in the form.
|
||||
:type Meta.fields: list
|
||||
"""
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Opportunity
|
||||
fields = [
|
||||
"stage",
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
|
||||
"""
|
||||
|
||||
@ -228,6 +228,11 @@ urlpatterns = [
|
||||
views.OpportunityUpdateView.as_view(),
|
||||
name="update_opportunity",
|
||||
),
|
||||
path(
|
||||
"<slug:dealer_slug>/crm/opportunities/<slug:slug>/stage/edit",
|
||||
views.OpportunityStageUpdateView.as_view(),
|
||||
name="update_opportunity_stage",
|
||||
),
|
||||
path(
|
||||
"<slug:dealer_slug>/crm/opportunities/",
|
||||
views.OpportunityListView.as_view(),
|
||||
@ -928,6 +933,7 @@ urlpatterns = [
|
||||
views.ItemServiceUpdateView.as_view(),
|
||||
name="item_service_update",
|
||||
),
|
||||
|
||||
# Expanese
|
||||
path(
|
||||
"<slug:dealer_slug>/items/expeneses/",
|
||||
@ -1284,6 +1290,10 @@ urlpatterns = [
|
||||
|
||||
path('<slug:dealer_slug>/schedules/calendar/', views.schedule_calendar, name='schedule_calendar'),
|
||||
|
||||
# staff profile
|
||||
path('<slug:dealer_slug>/staff/<slug:slug>detail/', views.StaffDetailView.as_view(), name='staff_detail'),
|
||||
|
||||
|
||||
]
|
||||
|
||||
handler404 = "inventory.views.custom_page_not_found_view"
|
||||
|
||||
@ -2197,6 +2197,35 @@ class DealerUpdateView(
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("dealer_detail", kwargs={"slug": self.object.slug})
|
||||
|
||||
class StaffDetailView(LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
Represents a detailed view for a Dealer model.
|
||||
|
||||
This class extends Django's `DetailView` to provide a detailed view of a dealer.
|
||||
It includes additional context data such as the count of staff members, cars
|
||||
associated with the dealer, available car makes, and dynamically fetched quotas.
|
||||
The class also ensures that users must be logged in to access the detailed view.
|
||||
|
||||
:ivar model: The model associated with this view (Dealer model).
|
||||
:type model: django.db.models.Model
|
||||
:ivar template_name: Path to the template used to render the view.
|
||||
:type template_name: str
|
||||
:ivar context_object_name: The name used to refer to the object in the template context.
|
||||
:type context_object_name: str
|
||||
"""
|
||||
|
||||
model = models.Staff
|
||||
template_name = "staff/staff_detail.html"
|
||||
context_object_name = "staff"
|
||||
|
||||
|
||||
|
||||
def dealer_vat_rate_update(request, slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=slug)
|
||||
models.VatRate.objects.filter(dealer=dealer).update(rate=request.POST.get("rate"))
|
||||
messages.success(request, _("VAT rate updated successfully"))
|
||||
return redirect("dealer_detail", slug=slug)
|
||||
|
||||
|
||||
class CustomerListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
@ -6791,27 +6820,37 @@ def send_lead_email(request, dealer_slug, slug, email_pk=None):
|
||||
# return response
|
||||
# return redirect("lead_list", dealer_slug=dealer_slug)
|
||||
msg = f"""
|
||||
السلام عليكم
|
||||
Dear {lead.full_name},
|
||||
السلام عليكم {lead.full_name},
|
||||
|
||||
أود أن أشارككم تقدير المشروع الذي ناقشناه. يرجى العثور على الوثيقة التفصيلية للمقترح المرفقة.
|
||||
شكراً لزيارتك لـ {lead.dealer.name}! لقد كان من دواعي سرورنا مساعدتك اليوم.
|
||||
|
||||
I hope this email finds you well. I wanted to share with you the estimate for the project we discussed. Please find the detailed estimate document attached.
|
||||
لقد أنشأنا ملفاً شخصياً لك في نظامنا لتتبع تفضيلاتك والسيارات التي تهتم بها. سنتواصل معك قريباً للمتابعة والإجابة على أي أسئلة أخرى قد تكون لديك.
|
||||
|
||||
يرجى مراجعة المقترح وإعلامي إذا كانت لديك أي أسئلة أو مخاوف. إذا كانت كل شيء يبدو جيدًا، يمكننا المضي قدمًا في المشروع.
|
||||
في هذه الأثناء، لا تتردد في الاتصال بنا مباشرة على {lead.dealer.phone_number} أو زيارتنا مرة أخرى في أي وقت يناسبك.
|
||||
|
||||
Please review the estimate and let me know if you have any questions or concerns. If everything looks good, we can proceed with the project.
|
||||
نتطلع إلى مساعدتك في العثور على سيارتك القادمة!
|
||||
|
||||
شكراً لاهتمامكم بهذا الأمر.
|
||||
Thank you for your attention to this matter.
|
||||
تحياتي،
|
||||
{lead.dealer.arabic_name}
|
||||
{lead.dealer.address}
|
||||
{lead.dealer.phone_number}
|
||||
-----
|
||||
Dear {lead.full_name},
|
||||
|
||||
تحياتي,
|
||||
Best regards,
|
||||
[Your Name]
|
||||
[Your Position]
|
||||
[Your Company]
|
||||
[Your Contact Information]
|
||||
"""
|
||||
Thank you for visiting {lead.dealer.name}! It was a pleasure to assist you today.
|
||||
|
||||
We've created a profile for you in our system to keep track of your preferences and the vehicles you're interested in. We'll be in touch shortly to follow up and answer any further questions you may have.
|
||||
|
||||
In the meantime, feel free to contact us directly at {lead.dealer.phone_number} or visit us again at your convenience.
|
||||
|
||||
We look forward to helping you find your next car!
|
||||
|
||||
Best regards,
|
||||
{lead.dealer.name}
|
||||
{lead.dealer.address}
|
||||
{lead.dealer.phone_number}
|
||||
|
||||
"""
|
||||
subject = ""
|
||||
if email_pk:
|
||||
email = get_object_or_404(models.Email, pk=email_pk)
|
||||
@ -6851,7 +6890,7 @@ class OpportunityCreateView(
|
||||
template_name = "crm/opportunities/opportunity_form.html"
|
||||
success_message = _("Opportunity created successfully.")
|
||||
permission_required = ["inventory.add_opportunity"]
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
initial = super().get_initial()
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs.get("dealer_slug"))
|
||||
@ -6927,6 +6966,7 @@ class OpportunityUpdateView(
|
||||
template_name = "crm/opportunities/opportunity_form.html"
|
||||
success_message = _("Opportunity updated successfully.")
|
||||
permission_required = ["inventory.change_opportunity"]
|
||||
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
@ -6949,6 +6989,46 @@ class OpportunityUpdateView(
|
||||
},
|
||||
)
|
||||
|
||||
class OpportunityStageUpdateView(
|
||||
LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, UpdateView
|
||||
):
|
||||
"""
|
||||
Handles the update functionality for Opportunity objects.
|
||||
|
||||
This class-based view is responsible for handling the update of existing
|
||||
Opportunity instances. It uses a Django form that is specified by the
|
||||
`form_class` attribute and renders a template to display and process the
|
||||
update form. Access to this view is restricted to authenticated users, as
|
||||
it inherits from `LoginRequiredMixin`.
|
||||
|
||||
It defines the model to be updated and the form template to be used. Upon
|
||||
successful update, it redirects the user to the detail page of the updated
|
||||
opportunity instance.
|
||||
|
||||
:ivar model: The model associated with this view. Represents the Opportunity model.
|
||||
:type model: django.db.models.Model
|
||||
:ivar form_class: The form class used to manage the Opportunity update process.
|
||||
:type form_class: django.forms.ModelForm
|
||||
:ivar template_name: The path to the template used to render the opportunity
|
||||
update form.
|
||||
:type template_name: str
|
||||
"""
|
||||
|
||||
model = models.Opportunity
|
||||
form_class = forms.OpportunityStageForm
|
||||
success_message = _("Opportunity Stage updated successfully.")
|
||||
permission_required = ["inventory.change_opportunity"]
|
||||
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy(
|
||||
"opportunity_detail",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs.get("dealer_slug"),
|
||||
"slug": self.object.slug,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class OpportunityDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
||||
"""
|
||||
@ -6971,7 +7051,7 @@ class OpportunityDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailV
|
||||
template_name = "crm/opportunities/opportunity_detail.html"
|
||||
context_object_name = "opportunity"
|
||||
permission_required = ["inventory.view_opportunity"]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs.get("dealer_slug"))
|
||||
context = super().get_context_data(**kwargs)
|
||||
@ -7043,6 +7123,7 @@ class OpportunityDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailV
|
||||
"schedules": qs.filter(scheduled_at__gt=timezone.now())[:5],
|
||||
}
|
||||
context["schedule_form"] = forms.ScheduleForm()
|
||||
context["stage_form"] = forms.OpportunityStageForm()
|
||||
return context
|
||||
|
||||
|
||||
@ -7063,17 +7144,11 @@ class OpportunityListView(LoginRequiredMixin, PermissionRequiredMixin, ListView)
|
||||
staff = self.request.staff
|
||||
queryset = models.Opportunity.objects.filter(dealer=dealer, lead__staff=staff)
|
||||
|
||||
# Search filter
|
||||
search = self.request.GET.get("q")
|
||||
if search:
|
||||
queryset = queryset.filter(
|
||||
Q(customer__first_name__icontains=search)
|
||||
| Q(customer__last_name__icontains=search)
|
||||
| Q(customer__email__icontains=search)
|
||||
)
|
||||
|
||||
|
||||
# Stage filter
|
||||
stage = self.request.GET.get("stage")
|
||||
print(stage)
|
||||
if stage:
|
||||
queryset = queryset.filter(stage=stage)
|
||||
|
||||
@ -7084,7 +7159,16 @@ class OpportunityListView(LoginRequiredMixin, PermissionRequiredMixin, ListView)
|
||||
elif sort == "highest":
|
||||
queryset = queryset.order_by("-expected_revenue")
|
||||
elif sort == "closing":
|
||||
queryset = queryset.order_by("closing_date")
|
||||
queryset = queryset.order_by("expected_close_date")
|
||||
|
||||
# Search filter
|
||||
search = self.request.GET.get("q")
|
||||
if search:
|
||||
queryset = queryset.filter(
|
||||
Q(customer__first_name__icontains=search)
|
||||
| Q(customer__last_name__icontains=search)
|
||||
| Q(customer__email__icontains=search)
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
@ -7332,10 +7416,15 @@ class ItemServiceListView(LoginRequiredMixin, PermissionRequiredMixin, ListView)
|
||||
query = self.request.GET.get("q")
|
||||
qs = models.AdditionalServices.objects.filter(dealer=dealer).all()
|
||||
if query:
|
||||
qs = apply_search_filters(qs, query)
|
||||
qs = qs.filter(Q(name__icontains=query)|
|
||||
Q(id__icontains=query)|
|
||||
Q(uom__icontains=query)
|
||||
)
|
||||
return qs
|
||||
|
||||
|
||||
|
||||
|
||||
class ItemExpenseCreateView(LoginRequiredMixin, PermissionRequiredMixin,SuccessMessageMixin, CreateView):
|
||||
"""
|
||||
Represents a view for creating item expense entries.
|
||||
@ -7427,6 +7516,9 @@ class ItemExpenseUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateV
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ItemExpenseListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
"""
|
||||
Handles the display of a list of item expenses.
|
||||
@ -7828,27 +7920,44 @@ def send_email_view(request, dealer_slug, pk):
|
||||
)
|
||||
|
||||
msg = f"""
|
||||
السلام عليكم
|
||||
Dear {estimate.customer.customer_name},
|
||||
السلام عليكم،
|
||||
|
||||
أود أن أشارككم عرض السعر.
|
||||
عزيزي {estimate.customer.customer_name}،
|
||||
|
||||
I wanted to share with you the quotation.
|
||||
يسعدني أن أشارككم عرض السعر الذي طلبتموه. يرجى الاطلاع على التفاصيل الكاملة والأسعار من خلال الرابط أدناه.
|
||||
|
||||
يرجى مراجعة عرض السعر وإعلامي إذا كانت لديك أي استفسارات أو ملاحظات. إذا كان كل شيء على ما يرام، يمكننا المتابعة في الإجراءات.
|
||||
حرصنا على أن يكون عرضنا مناسباً وشفافاً. إذا كانت لديكم أي استفسارات أو ملاحظات، فلا تترددوا في التواصل معنا.
|
||||
|
||||
Please review the quotation and let me know if you have any questions or concerns. If everything looks good, we can proceed with the process.
|
||||
رابط عرض السعر:
|
||||
{link}
|
||||
|
||||
رابط عرض السعر:
|
||||
{link}
|
||||
نأمل أن ينال العرض إعجابكم ونتطلع إلى بدء العمل قريباً!
|
||||
|
||||
تحياتي،
|
||||
|
||||
تحياتي,
|
||||
Best regards,
|
||||
{dealer.get_local_name}
|
||||
{dealer.phone_number}
|
||||
هيكل | Haikal
|
||||
"""
|
||||
{dealer.get_local_name}
|
||||
{dealer.phone_number}
|
||||
Haikal | هيكل
|
||||
-----
|
||||
Dear {estimate.customer.customer_name},
|
||||
|
||||
I hope this email finds you well.
|
||||
|
||||
Following up on our conversation, I'm excited to share the quotation for your review. Please find the detailed pricing and information by clicking on the link below.
|
||||
|
||||
We've done our best to provide you with a fair and competitive offer. If you have any questions or would like to discuss it further, please don't hesitate to reach out.
|
||||
|
||||
Quotation Link:
|
||||
{link}
|
||||
|
||||
We look forward to hearing from you and hopefully moving forward with your project!
|
||||
|
||||
Best regards,
|
||||
|
||||
{dealer.get_local_name}
|
||||
{dealer.phone_number}
|
||||
Haikal
|
||||
"""
|
||||
# subject = _("Quotation")
|
||||
|
||||
send_email(
|
||||
@ -9387,10 +9496,12 @@ def submit_plan(request, dealer_slug):
|
||||
tax=15,
|
||||
status=1,
|
||||
)
|
||||
logger.info(f"order created {order}")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
logger.error(e)
|
||||
if not order:
|
||||
messages.error(request, _("Error creating order"))
|
||||
logger.error("unable to create order")
|
||||
return redirect("pricing_page", dealer_slug=dealer_slug)
|
||||
transaction_url = handle_payment(request, order)
|
||||
return redirect(transaction_url)
|
||||
@ -9404,9 +9515,13 @@ def payment_callback(request, dealer_slug):
|
||||
payment_id = request.GET.get("id")
|
||||
history = models.PaymentHistory.objects.filter(transaction_id=payment_id).first()
|
||||
payment_status = request.GET.get("status")
|
||||
logger.info(f"Received payment callback for dealer_slug: {dealer_slug}, payment_id: {payment_id}, status: {payment_status}")
|
||||
order = Order.objects.filter(user=dealer.user, status=1).first() # Status 1 = NEW
|
||||
|
||||
print(order)
|
||||
if payment_status == "paid":
|
||||
logger.info(f"Payment successful for transaction ID {payment_id}. Processing order completion.")
|
||||
|
||||
billing_info, created = BillingInfo.objects.get_or_create(
|
||||
user=dealer.user,
|
||||
defaults={
|
||||
@ -9418,12 +9533,20 @@ def payment_callback(request, dealer_slug):
|
||||
'country': dealer.entity.country or " ",
|
||||
}
|
||||
)
|
||||
if created:
|
||||
logger.info(f"Created new billing info for user {dealer.user}.")
|
||||
else:
|
||||
logger.debug(f"Billing info already exists for user {dealer.user}.")
|
||||
|
||||
if not hasattr(order.user, 'userplan'):
|
||||
UserPlan.objects.create(
|
||||
user=order.user,
|
||||
plan=order.plan,
|
||||
expire=datetime.now().date() + timedelta(days=order.get_plan_pricing().pricing.period)
|
||||
)
|
||||
logger.info(f"Created new UserPlan for user {order.user} with plan {order.plan}.")
|
||||
else:
|
||||
logger.info(f"UserPlan already exists for user {order.user}.")
|
||||
|
||||
try:
|
||||
|
||||
@ -9441,7 +9564,7 @@ def payment_callback(request, dealer_slug):
|
||||
order.complete_order()
|
||||
history.status = "paid"
|
||||
history.save()
|
||||
|
||||
logger.info(f"Order {order.id} for user {order.user} completed successfully. Payment history updated.")
|
||||
invoice = order.get_invoices().first()
|
||||
return render(
|
||||
request,
|
||||
@ -9450,12 +9573,14 @@ def payment_callback(request, dealer_slug):
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"Error completing order {order.id} for user {order.user}: {e}")
|
||||
logger.error(f"Plan activation failed: {str(e)}")
|
||||
history.status = "failed"
|
||||
history.save()
|
||||
return render(request, "payment_failed.html", {"message": "Plan activation error"})
|
||||
|
||||
elif payment_status == "failed":
|
||||
logger.warning(f"Payment failed for transaction ID {payment_id}. Message: {message}")
|
||||
history.status = "failed"
|
||||
history.save()
|
||||
return render(request, "payment_failed.html", {"message": message})
|
||||
@ -10271,8 +10396,11 @@ class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListVie
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
dealer = get_user_type(self.request)
|
||||
vendors=models.Vendor.objects.filter(dealer=dealer)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["entity_slug"] = dealer.entity.slug
|
||||
context["vendors"] = vendors
|
||||
|
||||
return context
|
||||
|
||||
|
||||
@ -10716,13 +10844,69 @@ def purchase_report_csv_export(request,dealer_slug):
|
||||
])
|
||||
return response
|
||||
|
||||
# @login_required
|
||||
# def car_sale_report_view(request,dealer_slug):
|
||||
# dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
# cars_sold = models.Car.objects.filter(dealer=dealer,status='sold')
|
||||
# current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
# context={'cars_sold':cars_sold,'current_time':current_time }
|
||||
# return render(request,'ledger/reports/car_sale_report.html',context)
|
||||
|
||||
|
||||
@login_required
|
||||
def car_sale_report_view(request,dealer_slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
cars_sold = models.Car.objects.filter(dealer=dealer,status='sold')
|
||||
current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
context={'cars_sold':cars_sold,'current_time':current_time }
|
||||
return render(request,'ledger/reports/car_sale_report.html',context)
|
||||
def car_sale_report_view(request, dealer_slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
cars_sold = models.Car.objects.filter(dealer=dealer, status='sold')
|
||||
|
||||
# Get filter parameters from the request
|
||||
selected_make = request.GET.get('make')
|
||||
selected_model = request.GET.get('model')
|
||||
selected_serie = request.GET.get('serie')
|
||||
selected_year = request.GET.get('year')
|
||||
|
||||
# Apply filters to the queryset
|
||||
if selected_make:
|
||||
cars_sold = cars_sold.filter(id_car_make__name=selected_make)
|
||||
if selected_model:
|
||||
cars_sold = cars_sold.filter(id_car_model__name=selected_model)
|
||||
if selected_serie:
|
||||
cars_sold = cars_sold.filter(id_car_serie__name=selected_serie)
|
||||
if selected_year:
|
||||
cars_sold = cars_sold.filter(year=selected_year)
|
||||
|
||||
# Get distinct values for filter dropdowns
|
||||
makes = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_make__name', flat=True).distinct()
|
||||
models_qs = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_model__name', flat=True).distinct()
|
||||
series = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_serie__name', flat=True).distinct()
|
||||
years = models.Car.objects.filter(dealer=dealer, status='sold').values_list('year', flat=True).distinct().order_by('-year')
|
||||
|
||||
# # Calculate summary data for the filtered results
|
||||
|
||||
total_revenue = cars_sold.aggregate(total_revenue=Sum('finances__marked_price'))['total_revenue'] or 0
|
||||
# total_vat = cars_sold.aggregate(total_vat=Sum('finances__vat_amount'))['total_vat'] or 0
|
||||
total_discount = cars_sold.aggregate(total_discount=Sum('finances__discount_amount'))['total_discount'] or 0
|
||||
|
||||
current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
context = {
|
||||
'cars_sold': cars_sold,
|
||||
'current_time': current_time,
|
||||
'dealer': dealer,
|
||||
'total_revenue': total_revenue,
|
||||
# 'total_vat': total_vat,
|
||||
'total_discount': total_discount,
|
||||
'makes': makes,
|
||||
'models': models_qs,
|
||||
'series': series,
|
||||
'years': years,
|
||||
'selected_make': selected_make,
|
||||
'selected_model': selected_model,
|
||||
'selected_serie': selected_serie,
|
||||
'selected_year': selected_year,
|
||||
}
|
||||
|
||||
return render(request, 'ledger/reports/car_sale_report.html', context)
|
||||
|
||||
|
||||
|
||||
def car_sale_report_csv_export(request,dealer_slug):
|
||||
@ -10766,10 +10950,10 @@ def car_sale_report_csv_export(request,dealer_slug):
|
||||
car.year,
|
||||
car.id_car_serie.name,
|
||||
car.id_car_trim.name,
|
||||
car.mileage,
|
||||
car.mileage if car.mileage else '0',
|
||||
car.stock_type,
|
||||
car.created_at.strftime("%Y-%m-%d %H:%M:%S") if car.created_at else '',
|
||||
car.sold_date.strftime("%Y-%m-%d %H:%M:%S") if car.created_at else '',
|
||||
car.sold_date.strftime("%Y-%m-%d %H:%M:%S") if car.sold_date else '',
|
||||
car.finances.cost_price,
|
||||
car.finances.marked_price,
|
||||
car.finances.discount_amount,
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
105
staticfiles/css/calendar_dark.css
Normal file
105
staticfiles/css/calendar_dark.css
Normal file
@ -0,0 +1,105 @@
|
||||
|
||||
/* Card and container styling */
|
||||
.card {
|
||||
background-color: #2d3748;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid #4a5568;
|
||||
}
|
||||
|
||||
/* FullCalendar header */
|
||||
.fc .fc-toolbar.fc-header-toolbar {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.fc .fc-toolbar-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: #edf2f7;
|
||||
}
|
||||
|
||||
/* Calendar buttons */
|
||||
.fc .fc-button-group > .fc-button {
|
||||
background-color: #4a5568;
|
||||
border-color: #4a5568;
|
||||
color: #e2e8f0;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.fc .fc-button-group > .fc-button:hover {
|
||||
background-color: #64748b;
|
||||
}
|
||||
|
||||
.fc .fc-button-primary:not(:disabled).fc-button-active,
|
||||
.fc .fc-button-primary:not(:disabled):active {
|
||||
background-color: #4299e1;
|
||||
border-color: #4299e1;
|
||||
color: #fff;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Day cells */
|
||||
.fc-daygrid-day {
|
||||
background-color: #2d3748;
|
||||
border: 1px solid #4a5568;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.fc-day-other {
|
||||
background-color: #202c3c !important;
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
.fc-day-today {
|
||||
background-color: #38a169 !important;
|
||||
border-color: #38a169 !important;
|
||||
}
|
||||
|
||||
.fc-daygrid-day-number {
|
||||
font-weight: 500;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
/* Event styling */
|
||||
.fc-event {
|
||||
border-radius: 4px;
|
||||
padding: 3px 6px;
|
||||
font-size: 12px;
|
||||
color: #ffffff !important;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Event colors (you can adjust these in your Django template) */
|
||||
/* .fc-event-completed { background-color: #38a169; border-color: #38a169; } */
|
||||
/* .fc-event-canceled { background-color: #e53e3e; border-color: #e53e3e; } */
|
||||
/* .fc-event-scheduled { background-color: #4299e1; border-color: #4299e1; } */
|
||||
|
||||
|
||||
/* List group styling */
|
||||
.list-group-item {
|
||||
border-color: #4a5568;
|
||||
background-color: #2d3748;
|
||||
color: #e2e8f0;
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.list-group-item:hover {
|
||||
background-color: #4a5568;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #2d3748;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.modal-header .close {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 767.98px) {
|
||||
.fc .fc-toolbar-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
99
staticfiles/css/calendar_light.css
Normal file
99
staticfiles/css/calendar_light.css
Normal file
@ -0,0 +1,99 @@
|
||||
/* static/css/light_theme.css */
|
||||
|
||||
/* Card and container styling */
|
||||
.card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #e0e6ed;
|
||||
}
|
||||
|
||||
/* FullCalendar header */
|
||||
.fc .fc-toolbar.fc-header-toolbar {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.fc .fc-toolbar-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
/* Calendar buttons */
|
||||
.fc .fc-button-group > .fc-button {
|
||||
background-color: #e9ecef;
|
||||
border-color: #e9ecef;
|
||||
color: #495057;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.fc .fc-button-group > .fc-button:hover {
|
||||
background-color: #e2e6ea;
|
||||
}
|
||||
|
||||
.fc .fc-button-primary:not(:disabled).fc-button-active,
|
||||
.fc .fc-button-primary:not(:disabled):active {
|
||||
background-color: #007bff;
|
||||
border-color: #007bff;
|
||||
color: #fff;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Day cells */
|
||||
.fc-daygrid-day {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e0e6ed;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.fc-day-other {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #ced4da;
|
||||
}
|
||||
|
||||
.fc-day-today {
|
||||
background-color: #fff3cd !important;
|
||||
border-color: #ffeeba !important;
|
||||
}
|
||||
|
||||
.fc-daygrid-day-number {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Event styling */
|
||||
.fc-event {
|
||||
border-radius: 4px;
|
||||
padding: 3px 6px;
|
||||
font-size: 12px;
|
||||
color: #ffffff !important;
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* List group styling */
|
||||
.list-group-item {
|
||||
border-color: #e0e6ed;
|
||||
background-color: #ffffff;
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.list-group-item:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #ffffff;
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
.modal-header .close {
|
||||
color: #adb5bd;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 767.98px) {
|
||||
.fc .fc-toolbar-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
staticfiles/images/logos/vendors/logo1.jpg
vendored
Normal file
BIN
staticfiles/images/logos/vendors/logo1.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@ -3,6 +3,7 @@
|
||||
{% block title %}
|
||||
{% trans 'Admin Management' %} {% endblock %}
|
||||
{% block content %}
|
||||
<h3 class="my-4">{% trans "Admin Management" %}<li class="fa fa-user-cog ms-2 text-primary"></li></h3>
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-4 g-4 mt-10">
|
||||
<div class="col">
|
||||
<a href="{% url 'user_management' request.dealer.slug %}">
|
||||
|
||||
@ -203,7 +203,7 @@
|
||||
{% if perms.django_ledger.change_billmodel %}
|
||||
{% if "update" not in request.path %}
|
||||
<a hx-boost="true" href="{% url 'bill-update' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill.uuid %}">
|
||||
<button class="btn btn-phoenix-primary"
|
||||
<button class="btn btn-phoenix-primary">
|
||||
<i class="fas fa-edit me-2"></i>{% trans 'Update' %}
|
||||
</button>
|
||||
</a>
|
||||
@ -225,16 +225,18 @@
|
||||
</button>
|
||||
{% endif %}
|
||||
<!-- Mark as Approved -->
|
||||
{% if bill.can_approve and perms.django_ledger.can_approve_billmodel %}
|
||||
<button class="btn btn-phoenix-success"
|
||||
onclick="showPOModal('Mark as Approved', '{% url 'bill-action-mark-as-approved' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Approved')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Approved' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if bill.can_approve and not request.is_manager %}
|
||||
{% endif %}
|
||||
{% if bill.can_approve and request.is_accountant %}
|
||||
<button class="btn btn-phoenix-warning" disabled>
|
||||
<i class="fas fa-hourglass-start me-2"></i><span class="text-warning">{% trans 'Waiting for Manager Approval' %}</span>
|
||||
</button>
|
||||
{% else %}
|
||||
{% if bill.can_approve and perms.django_ledger.can_approve_billmodel %}
|
||||
<button class="btn btn-phoenix-success"
|
||||
onclick="showPOModal('Mark as Approved', '{% url 'bill-action-mark-as-approved' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Approved')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Approved' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<!-- Mark as Paid -->
|
||||
{% if bill.can_pay %}
|
||||
|
||||
@ -30,19 +30,11 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<span class="step-links">
|
||||
{% if notifications.has_previous %}
|
||||
<a href="?page=1">« first</a>
|
||||
<a href="?page={{ notifications.previous_page_number }}">previous</a>
|
||||
{% endif %}
|
||||
<span class="current">Page {{ notifications.number }} of {{ notifications.paginator.num_pages }}.</span>
|
||||
{% if notifications.has_next %}
|
||||
<a href="?page={{ notifications.next_page_number }}">next</a>
|
||||
<a href="?page={{ notifications.paginator.num_pages }}">last »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">{% include 'partials/pagination.html' %}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>No notifications found.</p>
|
||||
{% endif %}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static humanize %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block title %}
|
||||
{{ _("Opportunity Detail") }}
|
||||
{% endblock title %}
|
||||
@ -39,8 +40,9 @@
|
||||
href="{% url 'update_opportunity' request.dealer.slug opportunity.slug %}">Update Opportunity</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item"
|
||||
href="{% url 'update_opportunity' request.dealer.slug opportunity.slug %}">Update Stage</a>
|
||||
<a class="dropdown-item" type="button"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#updateStageModal">Update Stage</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if perms.inventory.delete_opportunity %}
|
||||
@ -1095,6 +1097,36 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="updateStageModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="post"
|
||||
action="{% url 'update_opportunity_stage' request.dealer.slug opportunity.slug %}"
|
||||
hx-post="{% url 'update_opportunity_stage' request.dealer.slug opportunity.slug %}"
|
||||
hx-swap="none"
|
||||
hx-on::after-request="location.reload()">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="updateStageModalLabel">{{ _("Update Opportunity Stage") }}</h5>
|
||||
<button class="btn btn-close p-1"
|
||||
type="button"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ stage_form|crispy }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-phoenix-primary" type="submit">{{ _("Save") }}</button>
|
||||
<button class="btn btn-phoenix-secondary"
|
||||
type="button"
|
||||
data-bs-dismiss="modal">{{ _("Cancel") }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% include 'modal/delete_modal.html' %}
|
||||
<!-- email Modal -->
|
||||
|
||||
@ -5,13 +5,28 @@
|
||||
{{ _("Opportunities") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
{% if opportunities or request.GET.q%}
|
||||
<div class="row g-3 mt-4">
|
||||
<div class="col-12">
|
||||
<h2 class="mb-3">
|
||||
{{ _("Opportunities") }}
|
||||
<li class="fas fas fa-rocket text-primary ms-2"></li>
|
||||
</h2>
|
||||
<div class="row g-3 justify-content-between mb-4">
|
||||
<div class="col-auto">
|
||||
<div class="d-md-flex justify-content-between">
|
||||
<h2 class="mb-3">
|
||||
{{ _("Opportunities") }}
|
||||
<li class="fas fas fa-rocket text-primary ms-2"></li>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
{% if perms.inventory.add_opportunity %}
|
||||
<div class="d-flex justify-content-between">
|
||||
<a class="btn btn-phoenix-primary btn-sm"
|
||||
href="{% url 'opportunity_create' request.dealer.slug %}">
|
||||
<span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3 mb-4">
|
||||
@ -19,29 +34,38 @@
|
||||
<div class="d-flex flex-column flex-lg-row align-items-start align-items-lg-center gap-3 w-100"
|
||||
id="filter-container">
|
||||
<!-- Search Input - Wider and properly aligned -->
|
||||
<div class="search-box position-relative flex-grow-1 me-2"
|
||||
style="min-width: 200px">
|
||||
<form class="position-relative show" id="search-form">
|
||||
<input name="q"
|
||||
id="search-input"
|
||||
class="form-control form-control-sm search-input search"
|
||||
type="search"
|
||||
aria-label="Search"
|
||||
placeholder="{{ _("Search") }}"
|
||||
value="{{ request.GET.q }}" />
|
||||
<span class="fa fa-magnifying-glass search-box-icon"></span>
|
||||
{% if request.GET.q %}
|
||||
<button type="button"
|
||||
class="btn-close position-absolute end-0 top-50 translate-middle cursor-pointer shadow-none"
|
||||
id="clear-search"
|
||||
aria-label="Close"></button>
|
||||
{% endif %}
|
||||
</form>
|
||||
<div class="search-box position-relative flex-grow-1 me-2" style="min-width: 200px">
|
||||
<form class="position-relative show" id="search-form"
|
||||
hx-get=""
|
||||
hx-boost="false"
|
||||
hx-trigger="keyup changed delay:500ms, search">
|
||||
|
||||
<input name="q"
|
||||
id="search-input"
|
||||
class="form-control form-control-sm search-input search"
|
||||
type="search"
|
||||
aria-label="Search"
|
||||
placeholder="{{ _("Search") }}..."
|
||||
value="{{ request.GET.q}}" />
|
||||
|
||||
<span class="fa fa-magnifying-glass search-box-icon"></span>
|
||||
|
||||
{% if request.GET.q %}
|
||||
<button type="button"
|
||||
class="btn-close position-absolute end-0 top-50 translate-middle cursor-pointer shadow-none"
|
||||
id="clear-search"
|
||||
aria-label="Clear Search"></button>
|
||||
{% endif %}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Filter Dropdowns - Aligned in a row -->
|
||||
<div class="d-flex flex-column flex-sm-row gap-3 w-100"
|
||||
style="max-width: 400px">
|
||||
<!-- Stage Filter -->
|
||||
<!-- Stage Filter -->
|
||||
|
||||
<div class="flex-grow-1">
|
||||
<select class="form-select"
|
||||
name="stage"
|
||||
@ -78,14 +102,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if perms.inventory.add_opportunity %}
|
||||
<div class="d-flex justify-content-between">
|
||||
<a class="btn btn-phoenix-primary btn-sm"
|
||||
href="{% url 'opportunity_create' request.dealer.slug %}">
|
||||
<span class="fas fa-plus me-2"></span>{{ _("Add Opportunity") }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -103,22 +120,21 @@
|
||||
{% include "empty-illustration-page.html" with value="opportunity" url=create_opportunity_url %}
|
||||
{% endif %}
|
||||
{% block customJS %}
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const searchInput = document.getElementById("search-input");
|
||||
const clearButton = document.getElementById("clear-search");
|
||||
const searchForm = document.getElementById("search-form");
|
||||
|
||||
if (clearButton) {
|
||||
clearButton.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
searchInput.value = ""; // Clear input field
|
||||
// Remove query parameter without reloading the page
|
||||
const newUrl = window.location.pathname;
|
||||
history.replaceState(null, "", newUrl);
|
||||
window.location.reload();
|
||||
});
|
||||
clearButton.addEventListener("click", function() {
|
||||
searchInput.value = "";
|
||||
// This clears the search and triggers the htmx search
|
||||
// by submitting the form with an empty query.
|
||||
searchForm.submit();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@ -5,223 +5,222 @@
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
{% include 'modal/delete_modal.html' %}
|
||||
{% include 'components/note_modal.html' with content_type="customer" slug=customer.slug %}
|
||||
|
||||
<!---->
|
||||
<div class="mt-4">
|
||||
<!--heading -->
|
||||
<div class="row align-items-center justify-content-between g-3 mb-4">
|
||||
<div class="col-auto">
|
||||
<h3 class="mb-0">{% trans 'Customer details' %}<li class="fas fa-user ms-2 text-primary"></li></h3>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="row g-3">
|
||||
<div class="col-auto">
|
||||
{% if perms.inventory.change_customer %}
|
||||
<a href="{% url 'customer_update' request.dealer.slug customer.slug %}"
|
||||
class="btn btn-sm btn-phoenix-primary"><span class="fa-solid fa-pen-to-square me-2"></span>{{ _("Update") }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if perms.inventory.delete_customer %}
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn"
|
||||
data-url="{% url 'customer_delete' request.dealer.slug customer.slug %}"
|
||||
data-message="Are you sure you want to delete this customer?"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#deleteModal">
|
||||
<i class="fas fa-trash me-1"> </i>{{ _("Delete") }}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<h3 class="mb-0">{% trans 'Customer details' %}<i class="fas fa-user ms-2 text-primary"></i></h3>
|
||||
</div>
|
||||
<div class="col-auto d-flex gap-2">
|
||||
{% if perms.inventory.change_customer %}
|
||||
<a href="{% url 'customer_update' request.dealer.slug customer.slug %}"
|
||||
class="btn btn-sm btn-phoenix-primary">
|
||||
<span class="fa-solid fa-pen-to-square me-2"></span>{{ _("Edit") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.inventory.delete_customer %}
|
||||
<button class="btn btn-sm btn-phoenix-danger delete-btn"
|
||||
data-url="{% url 'customer_delete' request.dealer.slug customer.slug %}"
|
||||
data-message="{% trans 'Are you sure you want to delete this customer?' %}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#deleteModal">
|
||||
<i class="fas fa-trash me-1"></i>{{ _("Delete") }}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!--cards-->
|
||||
<div class="row">
|
||||
|
||||
<div class="col m-2">
|
||||
<div class="card h-100">
|
||||
<div class="card-body d-flex flex-column justify-content-between pb-3">
|
||||
<div class="row align-items-center g-5 mb-3 text-center text-sm-start">
|
||||
<div class="col-12 col-sm-auto mb-sm-2">
|
||||
<div class="avatar avatar-5xl">
|
||||
{% if customer.image %}<img class="rounded-circle" src="{{ customer.image.url }}" alt="" />{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-auto flex-1">
|
||||
<h3>{{ customer.full_name }}</h3>
|
||||
<p class="text-body-secondary">{{ customer.created|timesince }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between border-top border-dashed pt-4">
|
||||
<div>
|
||||
<h6>{% trans 'Invoices' %}</h6>
|
||||
<p class="fs-7 text-body-secondary mb-0">{{ invoices.count }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h6>{% trans 'Quotations' %}</h6>
|
||||
<p class="fs-7 text-body-secondary mb-0">{{ estimates.count }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col m-2">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<h3 class="me-1">{% trans 'Default Address' %}</h3>
|
||||
<button class="btn btn-link p-0">
|
||||
<span class="fas fa-pen fs-8 ms-3 text-body-quaternary"></span>
|
||||
</button>
|
||||
</div>
|
||||
<h5 class="text-body-secondary">{{ _("Address") }}</h5>
|
||||
<p class="text-body-secondary">{{ customer.address }}</p>
|
||||
<div class="mb-3">
|
||||
<h5 class="text-body-secondary">{% trans 'Email' %}</h5>
|
||||
<a href="{{ customer.email }}">{{ customer.email }}</a>
|
||||
</div>
|
||||
<h5 class="text-body-secondary">{% trans 'Phone Number' %}</h5>
|
||||
<a class="text-body-secondary" href="#">{{ customer.phone_number }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col m-2">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
{% if perms.inventory.change_customer %}
|
||||
<div class="d-flex align-items-center justify-content-end">
|
||||
{% if perms.inventory.change_lead %}
|
||||
<button class="btn btn-phoenix-primary btn-sm"
|
||||
type="button"
|
||||
onclick=""
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#noteModal">
|
||||
<span class="fas fa-plus me-1"></span>{{ _("Add Note") }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="card h-100 shadow-sm">
|
||||
<div class="card-body d-flex flex-column justify-content-between pb-3">
|
||||
<div class="row align-items-center g-5 mb-3 text-center text-sm-start">
|
||||
<div class="col-12 col-sm-auto mb-sm-2">
|
||||
<div class="avatar avatar-5xl">
|
||||
{% if customer.image %}
|
||||
<img class="rounded-circle border border-2 border-primary" src="{{ customer.image.url }}" alt="{{ customer.full_name }}"/>
|
||||
{% else %}
|
||||
<div class="avatar-text rounded-circle bg-secondary text-white border border-2 border-primary">
|
||||
<span class="fs-4">{{ customer.full_name|first|default:"?" }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<table class="table fs-9 mb-0 table-responsive">
|
||||
<tr>
|
||||
<th class="align-middle pe-6 text-start" scope="col">{{ _("Note") }}</th>
|
||||
<th class="align-middle pe-6 text-start" scope="col">{{ _("Date") }}</th>
|
||||
</tr>
|
||||
<tbody id="notesTable">
|
||||
{% for note in notes %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ note.note }}</td>
|
||||
<td class="align-middle text-body-tertiary text-start white-space-nowrap">{{ note.created }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 mt-3">
|
||||
<div class="mb-6">
|
||||
|
||||
|
||||
<div>
|
||||
<div class="table-responsive scrollbar">
|
||||
<table class="table table-sm fs-9 mb-0">
|
||||
<thead class="bg-body-highlight">
|
||||
<tr>
|
||||
<th class="sort align-middle" scope="col" >{% trans 'Leads'|upper %}</th>
|
||||
<th class="sort align-middle " scope="col" >{% trans 'Opportunities'|upper %}</th>
|
||||
<th class="sort align-middle " scope="col">{% trans 'Estimates'|upper %}</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="customer-order-table-body">
|
||||
{% for lead in leads %}
|
||||
<tr>
|
||||
<td><a href="{% url 'lead_detail' request.dealer.slug lead.slug%}">{{lead}} ({{ forloop.counter }})<a></td>
|
||||
<td><a href="{% url 'opportunity_detail' request.dealer.slug lead.opportunity.slug%}">{{lead.opportunity}} ({{ forloop.counter }})</a></td>
|
||||
|
||||
<td>
|
||||
{% for estimate in lead.customer.customer_model.estimatemodel_set.all %}
|
||||
<h4 class="me-2 my-1"><a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}"><span class="me-2">#{{forloop.counter }}</span>{{estimate}}</a></h4>
|
||||
|
||||
|
||||
|
||||
<table class="table table-sm">
|
||||
<thead class="bg-body-highlight">
|
||||
<tr>
|
||||
<th class="sort align-middle " scope="col">{% trans 'Sale orders'|upper %}</th>
|
||||
<th class="sort align-middle " scope="col">{% trans 'Invoices'|upper %}</th>
|
||||
<th class="sort align-middle " scope="col">{% trans 'Car VIN'|upper %}</th>
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
{% for sale_order in estimate.sale_orders.all %}
|
||||
|
||||
<div><a href={% url 'order_detail' request.dealer.slug sale_order.pk%}>{{estimate.sale_orders.first}}</a></div>
|
||||
{% endfor %}
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{% for invoice in estimate.invoicemodel_set.all %}
|
||||
|
||||
{% if invoice.is_paid %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-success">
|
||||
<div><a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug invoice.pk %}">{{invoice}}</a></div>
|
||||
</span>
|
||||
{%else%}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-info">
|
||||
<div><a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug invoice.pk %}">{{invoice}}</a></div>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endfor %}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
<div><a href="#">{{estimate.itemtransactionmodel_set.first.item_model.name}}</a></div>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="col-12 col-sm-auto flex-1">
|
||||
<h3>{{ customer.full_name }}</h3>
|
||||
<p class="text-body-secondary">{% trans "Member since:" %} {{ customer.created|date:"d M Y" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between border-top border-dashed pt-4 mt-auto">
|
||||
<div class="text-center">
|
||||
<h6 class="mb-1 text-uppercase text-body-secondary fs-8">{% trans 'Invoices' %}</h6>
|
||||
<p class="fs-6 fw-bold mb-0">{{ invoices.count }}</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h6 class="mb-1 text-uppercase text-body-secondary fs-8">{% trans 'Quotations' %}</h6>
|
||||
<p class="fs-6 fw-bold mb-0">{{ estimates.count }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="card h-100 shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="card-title mb-0">{% trans 'Default Information' %}</h5>
|
||||
</div>
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li class="mb-2">
|
||||
<strong class="text-body-secondary d-block">{% trans 'Address' %}:</strong>
|
||||
<p class="mb-0">{{ customer.address|default:_("N/A") }}</p>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<strong class="text-body-secondary d-block">{% trans 'Email' %}:</strong>
|
||||
<a href="mailto:{{ customer.email|default:"" }}" class="text-decoration-none">{{ customer.email|default:_("N/A") }}</a>
|
||||
</li>
|
||||
<li class="mb-0">
|
||||
<strong class="text-body-secondary d-block">{% trans 'Phone Number' %}:</strong>
|
||||
<a href="tel:{{ customer.phone_number|default:"" }}" class="text-decoration-none">{{ customer.phone_number|default:_("N/A") }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="card-title mb-0">{% trans 'Notes' %}</h5>
|
||||
{% if perms.inventory.change_customer %}
|
||||
<button class="btn btn-phoenix-primary btn-sm d-flex align-items-center"
|
||||
type="button"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#noteModal">
|
||||
<i class="fas fa-plus me-1"></i>{{ _("Add Note") }}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-striped mb-0">
|
||||
<thead class="bg-body-tertiary">
|
||||
<tr>
|
||||
<th scope="col" style="width: 60%;">{% trans 'Note' %}</th>
|
||||
<th scope="col" style="width: 15%;">{% trans 'Date' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for note in notes %}
|
||||
<tr class="align-middle">
|
||||
<td class="text-body-secondary">{{ note.note|default_if_none:""|linebreaksbr }}</td>
|
||||
<td class="text-body-secondary text-nowrap">{{ note.created|date:"d M Y" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-body-secondary">
|
||||
<i class="fas fa-info-circle me-2"></i>{% trans 'No notes found for this customer.' %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<h5 class="card-title mb-3">{% trans 'Sales History' %}</h5>
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item me-6" role="presentation">
|
||||
<button class="nav-link active" id="leads-tab" data-bs-toggle="tab" data-bs-target="#leads-tab-pane" type="button" role="tab" aria-controls="leads-tab-pane" aria-selected="true">{% trans 'Leads' %}</button>
|
||||
</li>
|
||||
<li class="nav-item me-6" role="presentation">
|
||||
<button class="nav-link" id="opportunities-tab" data-bs-toggle="tab" data-bs-target="#opportunities-tab-pane" type="button" role="tab" aria-controls="opportunities-tab-pane" aria-selected="false">{% trans 'Opportunities' %}</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="estimates-tab" data-bs-toggle="tab" data-bs-target="#estimates-tab-pane" type="button" role="tab" aria-controls="estimates-tab-pane" aria-selected="false">{% trans 'Estimates' %}</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content pt-3" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="leads-tab-pane" role="tabpanel" aria-labelledby="leads-tab" tabindex="0">
|
||||
{% for lead in leads %}
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="fas fa-handshake me-2 text-primary"></i>
|
||||
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}" class="fw-bold">{{ lead }}</a>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p class="text-body-secondary">{% trans 'No leads found for this customer.' %}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="opportunities-tab-pane" role="tabpanel" aria-labelledby="opportunities-tab" tabindex="0">
|
||||
{% for lead in leads %}
|
||||
{% if lead.opportunity %}
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="fas fa-chart-line me-2 text-success"></i>
|
||||
<a href="{% url 'opportunity_detail' request.dealer.slug lead.opportunity.slug %}" class="fw-bold">{{ lead.opportunity }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
<p class="text-body-secondary">{% trans 'No opportunities found for this customer.' %}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="estimates-tab-pane" role="tabpanel" aria-labelledby="estimates-tab" tabindex="0">
|
||||
{% for estimate in estimates %}
|
||||
<div class="card mb-3 shadow-sm">
|
||||
<div class="card-body p-3">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<h6 class="mb-0">
|
||||
<i class="fas fa-file-invoice me-2 text-info"></i>
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}" class="text-decoration-none">{{ estimate }}</a>
|
||||
</h6>
|
||||
<span class="badge bg-success">{{ estimate.created|date:"d M Y" }}</span>
|
||||
</div>
|
||||
<ul class="list-unstyled mb-0 ms-5">
|
||||
{% for sale_order in estimate.sale_orders.all %}
|
||||
<li class="mb-2">
|
||||
<i class="fas fa-truck-moving me-2 text-success"></i>
|
||||
<a href="{% url 'order_detail' request.dealer.slug sale_order.pk %}">{{ sale_order }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% for invoice in estimate.invoicemodel_set.all %}
|
||||
<li class="mb-2">
|
||||
<i class="fas fa-receipt me-2 {% if invoice.is_paid %}text-success{% else %}text-warning{% endif %}"></i>
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug invoice.pk %}" class="text-decoration-none">{{ invoice }}</a>
|
||||
<span class="badge rounded-pill {% if invoice.is_paid %}bg-success{% else %}bg-warning{% endif %} ms-2">{% if invoice.is_paid %}{% trans "Paid" %}{% else %}{% trans "Unpaid" %}{% endif %}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% for item in estimate.itemtransactionmodel_set.all %}
|
||||
<li>
|
||||
<i class="fas fa-car me-2 text-primary"></i>
|
||||
<a href="{% url 'car_detail' request.dealer.slug item.item_model.car.slug %}">{{ item.item_model.car.vin}} | {{item.item_model.car.id_car_make.name}} | {{item.item_model.car.id_car_model.name}}</a>
|
||||
</li>
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p class="text-body-secondary">{% trans 'No estimates found for this customer.' %}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "components/note_modal.html" with content_type="customer" slug=customer.slug %}
|
||||
|
||||
|
||||
@ -254,4 +253,5 @@
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
@ -56,8 +56,8 @@
|
||||
border-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
<h2>{{ _("Select Car Makes You Sell") }}</h2>
|
||||
<form method="post"
|
||||
<h2 class="text-center text-primary">{{ _("Select Car Makes You Sell") }}</h2>
|
||||
<form method="post" class="mb-3"
|
||||
action="{% url 'assign_car_makes' request.dealer.slug %}">
|
||||
{% csrf_token %}
|
||||
<div class="car-makes-grid">
|
||||
@ -83,7 +83,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button class="btn btn-phoenix-primary btn-lg" type="submit">
|
||||
<button class="btn btn-outline-primary btn-lg" type="submit">
|
||||
<i class="fa fa-save me-2"></i>{{ _("Save") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -21,8 +21,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post" novalidate>
|
||||
<div>
|
||||
<form method="post" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row mb-4">
|
||||
|
||||
@ -352,7 +352,7 @@
|
||||
<a class="nav-link" href="#">
|
||||
{% endif %}
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-shopping-cart"></i><span class="nav-link-text">{% trans 'Car purchase Report'|capfirst %}</span>
|
||||
<i class="fas fa-chart-pie"></i><span class="nav-link-text">{% trans 'Car purchase Report'|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -363,9 +363,9 @@
|
||||
<a class="nav-link" href="#">
|
||||
{% endif %}
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-car"></i><span class="nav-link-text">{% trans 'Car Sale Report'|capfirst %}</span>
|
||||
<i class="fas fa-chart-pie"></i><span class="nav-link-text">{% trans 'Car Sale Report'|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
@ -445,8 +445,8 @@
|
||||
<li class="nav-item">
|
||||
<div class="theme-control-toggle fa-icon-wait">
|
||||
<input class="form-check-input ms-0 theme-control-toggle-input" type="checkbox" data-theme-control="phoenixTheme" value="dark" id="themeControlToggleSm" />
|
||||
<label class="mb-0 theme-control-toggle-label theme-control-toggle-light" for="themeControlToggleSm" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title='{{ _("Switch theme")}}' style="height:32px;width:32px;"><span class="icon" data-feather="moon"></span></label>
|
||||
<label class="mb-0 theme-control-toggle-label theme-control-toggle-dark" for="themeControlToggleSm" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title='{{ _("Switch theme")}}' style="height:32px;width:32px;"><span class="icon" data-feather="sun"></span></label>
|
||||
<label class="mb-0 theme-control-toggle-label theme-control-toggle-light" for="themeControlToggleSm" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{ _("Switch theme")}}" style="height:32px;width:32px;"><span class="icon" data-feather="moon"></span></label>
|
||||
<label class="mb-0 theme-control-toggle-label theme-control-toggle-dark" for="themeControlToggleSm" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{{ _("Switch theme")}}" style="height:32px;width:32px;"><span class="icon" data-feather="sun"></span></label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
@ -462,7 +462,7 @@
|
||||
{% include "notifications.html" %}
|
||||
{% endif %}
|
||||
|
||||
{% if user.is_authenticated%}
|
||||
{% if user.is_authenticated and request.is_dealer or request.is_staff %}
|
||||
<li class="nav-item dropdown">
|
||||
<a hx-boost="false" class="nav-link lh-1 pe-0" id="navbarDropdownUser" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-haspopup="true" aria-expanded="false">
|
||||
<div class="avatar avatar-l text-center align-middle">
|
||||
@ -492,7 +492,7 @@
|
||||
{% if request.is_dealer %}
|
||||
<h6 class="mt-2 text-body-emphasis">{{ user.dealer.get_local_name }}</h6>
|
||||
{% else %}
|
||||
<h6 class="mt-2 text-body-emphasis">{{ user.staff.get_local_name }}</h6>
|
||||
<h6 class="mt-2 text-body-emphasis">{{ user.staffmember.staff.get_local_name }}</h6>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -504,7 +504,7 @@
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a hx-boost="false" class="nav-link px-3 d-block" href="{% url 'appointment:user_profile' request.user.id %}"> <span class="me-2 text-body align-bottom" data-feather="user"></span><span>{% translate 'profile'|capfirst %}</span></a>
|
||||
<a hx-boost="false" class="nav-link px-3 d-block" href="{% url 'staff_detail' request.dealer.slug request.staff.slug %}"> <span class="me-2 text-body align-bottom" data-feather="user"></span><span>{% translate 'profile'|capfirst %}</span></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if request.is_dealer %}
|
||||
@ -530,7 +530,7 @@
|
||||
</li>
|
||||
{% if request.is_staff %}
|
||||
<li class="nav-item">
|
||||
<a hx-boost="false" class="nav-link px-3 d-block" href="{% url 'schedule_calendar' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="calendar"></span>{{ _("My Calendar") }}</a>
|
||||
<a hx-boost="false" class="nav-link px-3 d-block" href="{% url 'schedule_calendar' request.dealer.slug%}"> <span class="me-2 text-body align-bottom" data-feather="calendar"></span>{{ _("My Calendar") }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<!--<li class="nav-item"><a class="nav-link px-3 d-block" href=""> Language</a></li>-->
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
{% include "partials/search_box.html" %}
|
||||
{% if page_obj.object_list or request.GET.q%}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<table class="table align-items-center">
|
||||
<thead class="bg-body-highlight">
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Item Number" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Name" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Unit of Measure" %}</th>
|
||||
@ -35,12 +35,12 @@
|
||||
<td class="align-middle product white-space-nowrap">{{ expense.uom }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if perms.django_ledger.change_itemmodel %}
|
||||
|
||||
<a href="{% url 'item_expense_update' request.dealer.slug expense.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">{% trans "Update" %}</a>
|
||||
class="btn btn-sm btn-phoenix-primary"><li class="fa fa-edit me-1"></li>{% trans "Update" %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap"></td>
|
||||
<td class="align-middle white-space-nowrap text-start"></td>
|
||||
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
|
||||
@ -16,10 +16,10 @@
|
||||
</div>
|
||||
{% include "partials/search_box.html" %}
|
||||
{% if page_obj.object_list or request.GET.q %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center">
|
||||
<thead class="bg-body-highlight">
|
||||
<tr >
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Item Number" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Name" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Unit of Measure" %}</th>
|
||||
@ -39,7 +39,7 @@
|
||||
<td class="align-middle white-space-nowrap text-start">
|
||||
{% if perms.inventory.add_additionalservices %}
|
||||
<a href="{% url 'item_service_update' request.dealer.slug service.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">{% trans "Update" %}</a>
|
||||
class="btn btn-sm btn-phoenix-primary"><li class="fa fa-edit me-1"></li>{% trans "Update" %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -7,38 +7,123 @@
|
||||
|
||||
{% block content%}
|
||||
|
||||
<style>
|
||||
|
||||
.summary-card {
|
||||
border: 1px solid var(--card-border);
|
||||
border-radius: .5rem;
|
||||
box-shadow: var(--card-shadow);
|
||||
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
.summary-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
|
||||
}
|
||||
.summary-card .card-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.summary-card .card-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: var(--secondary-color) !important;
|
||||
}
|
||||
.summary-card .card-text {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid report-container">
|
||||
<header class="report-header text-center">
|
||||
<h1 class="display-4">{% trans 'Car Sale Report' %} <span class="fas fa-car mx-2 text-primary"></span><span class="fas fa-money-bill mx-2 text-primary"></span></h1>
|
||||
<h1 class="display-4">{% trans 'Car Sale Report' %} <span class="fas fa-chart-line mx-2 text-primary"></span></h1>
|
||||
<p class="lead text-muted"><strong>{{dealer}}</strong></p>
|
||||
<p class="text-muted">{% trans 'Report Date' %}: {{current_time}}</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section id="summary" class="mb-1">
|
||||
<h2 class="section-heading mb-2">{% trans 'Report Summary' %}</h2>
|
||||
<div class="row ">
|
||||
<div class="col-md-6 col-lg-4 mb-2">
|
||||
<section id="filters" class="mb-5 p-4 rounded border border-primary">
|
||||
<h2 class="section-heading mb-4">{% trans 'Filters' %} <i class="fas fa-sliders-h ms-2"></i></h2>
|
||||
<form method="GET" class="row g-3 align-items-end">
|
||||
<div class="col-md-3">
|
||||
<label for="make-select" class="form-label">{% trans 'Make' %}</label>
|
||||
<select id="make-select" name="make" class="form-select">
|
||||
<option value="">{% trans 'All Makes' %}</option>
|
||||
{% for make in makes %}
|
||||
<option value="{{ make }}" {% if make == selected_make %}selected{% endif %}>{{ make }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="model-select" class="form-label">{% trans 'Model' %}</label>
|
||||
<select id="model-select" name="model" class="form-select">
|
||||
<option value="">{% trans 'All Models' %}</option>
|
||||
{% for model in models %}
|
||||
<option value="{{ model }}" {% if model == selected_model %}selected{% endif %}>{{ model }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="serie-select" class="form-label">{% trans 'Serie' %}</label>
|
||||
<select id="serie-select" name="serie" class="form-select">
|
||||
<option value="">{% trans 'All Series' %}</option>
|
||||
{% for serie in series %}
|
||||
<option value="{{ serie }}" {% if serie == selected_serie %}selected{% endif %}>{{ serie }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="year-select" class="form-label">{% trans 'Year' %}</label>
|
||||
<select id="year-select" name="year" class="form-select">
|
||||
<option value="">{% trans 'All Years' %}</option>
|
||||
{% for year in years %}
|
||||
<option value="{{ year }}" {% if year|stringformat:"s" == selected_year %}selected{% endif %}>{{ year }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="submit" class="btn btn-primary w-100"><i class="fas fa-filter me-2"></i>{% trans 'Filter' %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section id="summary" class="mb-5">
|
||||
<h2 class="section-heading mb-4 border-start border-5 border-primary p-2">{% trans 'Report Summary' %}</h2>
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary">{% trans 'Total Revenue Amount' %}<span class="fas fa-solid fa-dollar-sign mx-1"></span><span class="fas fa-car"></span></h5>
|
||||
<p class="card-text fs-4 fw-bold">120000000</p>
|
||||
<h5 class="card-title">{% trans 'Total Revenue' %}<i class="fas fa-dollar-sign ms-2"></i></h5>
|
||||
<p class="card-text">{{ total_revenue|floatformat:2 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 mb-2">
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary">{% trans 'Total Vat Amount' %}<span class="fas fa-solid fa-percent mx-1"></span><span class="fas fa-car"></span></h5>
|
||||
<p class="card-text fs-4 fw-bold">12000</p>
|
||||
<h5 class="card-title">{% trans 'Total VAT Amount' %}<i class="fas fa-percent ms-2"></i></h5>
|
||||
<p class="card-text">{{ 10000|floatformat:2 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 mb-2">
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary">{% trans 'Total Discount Amount' %} <span class="fas fa-solid fa-tag mx-1"></span><span class="fas fa-car"></span></h5>
|
||||
<p class="card-text fs-4 fw-bold">12000</p>
|
||||
<h5 class="card-title">{% trans 'Total Discount Amount' %}<i class="fas fa-tag ms-2"></i></h5>
|
||||
<p class="card-text">{{ total_discount|floatformat:2 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{% trans 'Total Cars Sold' %}<i class="fas fa-car ms-2"></i></h5>
|
||||
<p class="card-text">{{ cars_sold|length }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -49,13 +134,12 @@
|
||||
|
||||
</section>
|
||||
|
||||
<section id="purchase-details" class="mb-3">
|
||||
<h2 class="section-heading">{% trans 'Detailed Purchase List' %}</h2>
|
||||
|
||||
<section id="sale-details" class="mb-3">
|
||||
<h2 class="section-heading border-start border-5 border-primary p-2">{% trans 'Detailed Sale List' %}</h2>
|
||||
<div class="d-flex justify-content-end mb-3 d-print-none">
|
||||
<a href="{% url 'car-sale-report-csv-export' request.dealer.slug %}" class="btn btn-phoenix-primary">
|
||||
<i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %}
|
||||
</a>
|
||||
<a href="{% url 'car-sale-report-csv-export' dealer.slug %}" class="btn btn-phoenix-primary">
|
||||
<i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %}
|
||||
</a>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-bordered table-sm">
|
||||
@ -108,4 +192,4 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -8,73 +8,114 @@
|
||||
|
||||
{% block content%}
|
||||
|
||||
<style>
|
||||
|
||||
.summary-card {
|
||||
border: 1px solid var(--card-border);
|
||||
border-radius: .5rem;
|
||||
box-shadow: var(--card-shadow);
|
||||
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
.summary-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
|
||||
}
|
||||
.summary-card .card-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.summary-card .card-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: var(--secondary-color) !important;
|
||||
}
|
||||
.summary-card .card-text {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid report-container">
|
||||
<header class="report-header text-center">
|
||||
<h1 class="display-4">{% trans 'Car Purchase Report' %} <span class="fas fa-car mx-2 text-primary"></span><span class="fas fa-chart-bar mx-2 text-primary"></span></h1>
|
||||
<h1 class="display-4">{% trans 'Car Purchase Report' %}<i class="fas fa-chart-pie ms-2 text-primary"></i></h1>
|
||||
<p class="lead text-muted"><strong>{{dealer}}</strong></p>
|
||||
<p class="text-muted">Report Date: {{current_time}}</p>
|
||||
<p class="text-muted">{% trans "Report Date" %}: {{current_time}}</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section id="summary" class="mb-1">
|
||||
<h2 class="section-heading mb-2">{% trans 'Report Summary' %}</h2>
|
||||
<div class="row ">
|
||||
<div class="col-md-6 col-lg-4 mb-2">
|
||||
<section id="summary" class="mb-5">
|
||||
<h2 class="section-heading mb-4 border-start border-3 border-primary p-2">{% trans 'Report Summary' %}</h2>
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary">{% trans 'Total Purchase Amount' %}<span class="fas fa-money-bill ms-1"><span></h5>
|
||||
<p class="card-text fs-4 fw-bold">{{total_po_amount}}</p>
|
||||
<h5 class="card-title">{% trans 'Total Purchase Amount' %}<span class="fas fa-money-bill ms-2"></span></h5>
|
||||
<p class="card-text">{{total_po_amount}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4 mb-2">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary">{% trans 'Total Cars Purchased' %}<span class="fas fa-shopping-bag mx-1"></span><span class="fas fa-car"></span></h5>
|
||||
<p class="card-text fs-4 fw-bold">{{total_po_cars}}</p>
|
||||
<h5 class="card-title">{% trans 'Total Cars Purchased' %}<span class="fas fa-car ms-2"></span></h5>
|
||||
<p class="card-text">{{total_po_cars}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{% trans 'Total Purchase Orders' %}<span class="fas fa-file-invoice ms-2"></span></h5>
|
||||
<p class="card-text">{{data|length}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="purchase-details" class="mb-3">
|
||||
<h2 class="section-heading">{% trans 'Detailed Purchase List' %}</h2>
|
||||
<h2 class="section-heading border-start border-3 border-primary p-2">{% trans 'Detailed Purchase List' %}</h2>
|
||||
|
||||
<div class="d-flex justify-content-end mb-3 d-print-none">
|
||||
<a href="{% url 'purchase-report-csv-export' request.dealer.slug %}" class="btn btn-phoenix-primary">
|
||||
<i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %}
|
||||
</a>
|
||||
<i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-bordered table-sm">
|
||||
<thead>
|
||||
<table class="table table-striped table-hover">
|
||||
<thead class="bg-body-highlight">
|
||||
<tr>
|
||||
<th>{% trans 'Purchase ID' %}</th>
|
||||
<th>{% trans 'Date Created' %}</th>
|
||||
<th>{% trans 'Status' %}</th>
|
||||
<th>{% trans 'PO Amount' %}</th>
|
||||
<th>{% trans 'Date Fulfilled' %}</th>
|
||||
<th>{% trans 'Created By' %}</th>
|
||||
<th>{% trans 'Cars Purchased' %}</th>
|
||||
<th>{% trans 'Vendor' %}</th>
|
||||
<th scope="col">{% trans 'Purchase ID' %}</th>
|
||||
<th scope="col">{% trans 'Date Created' %}</th>
|
||||
<th scope="col">{% trans 'Status' %}</th>
|
||||
<th scope="col">{% trans 'PO Amount' %}</th>
|
||||
<th scope="col">{% trans 'Date Fulfilled' %}</th>
|
||||
<th scope="col">{% trans 'Created By' %}</th>
|
||||
<th scope="col">{% trans 'Cars Purchased' %}</th>
|
||||
<th scope="col">{% trans 'Vendor' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for po in data %}
|
||||
<tr>
|
||||
<td class="ps-1">{{po.po_number}}</td>
|
||||
<td>{{po.po_number}}</td>
|
||||
<td>{{po.po_created|date}}</td>
|
||||
<td>{{po.po_status}}</td>
|
||||
<td>{{po.po_amount}}</td>
|
||||
<td>{{po.po_fulfilled_date}}</td>
|
||||
<td>staff</td>
|
||||
<td>
|
||||
{% if po.po_fulfilled_date%}
|
||||
{{po.po_fulfilled_date}}
|
||||
{%else%}
|
||||
{% trans 'Not fulfilled'%}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% firstof po.created_by.get_full_name 'staff' %}</td>
|
||||
<td>{{po.po_quantity}}</td>
|
||||
<td>
|
||||
{{po.vendors_str}}
|
||||
@ -82,16 +123,10 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" class="text-end fw-bold">{% trans 'Total Purchase'%}:</td>
|
||||
<td class="fw-bold text-primary">{{total_po_amount}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -7,9 +7,4 @@
|
||||
http://{{ site_domain }}{% url 'current_plan' %}
|
||||
|
||||
{% blocktrans %}or you can upgrade your plan here:{% endblocktrans %}
|
||||
http://{{ site_domain }}{% url 'upgrade_plan' %}
|
||||
|
||||
{% trans "Thank you" %}
|
||||
--
|
||||
{% blocktrans %}The Team at {{ site_name }}{% endblocktrans %}
|
||||
{% endautoescape %}
|
||||
http://{{ site_domain }}{% url 'upgrade_plan' %}
|
||||
@ -1,7 +1,7 @@
|
||||
<!-- po_list.html -->
|
||||
{% extends "base.html" %}
|
||||
{% load i18n static %}
|
||||
{% block title %}Purchase Orders - {{ block.super }}{% endblock %}
|
||||
{% block title %}Purchase Orders{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
@ -123,7 +123,15 @@
|
||||
{% include 'modal/delete_modal.html' %}
|
||||
|
||||
{% else %}
|
||||
{% url "purchase_order_create" request.dealer.slug request.dealer.entity.slug as create_purchase_url %}
|
||||
{% include "empty-illustration-page.html" with value="purchase order" url=create_purchase_url %}
|
||||
{% if vendors %}
|
||||
{% url "purchase_order_create" request.dealer.slug request.dealer.entity.slug as create_purchase_url %}
|
||||
{% include "empty-illustration-page.html" with value="purchase order" url=create_purchase_url %}
|
||||
{% else %}
|
||||
|
||||
{% url "vendor_create" request.dealer.slug as vendor_create_url %}
|
||||
{% include "message-illustration.html" with value1=_("You don't have a Vendor, Please add a Vendor before creating a Purchase Order.") value2=_("Create New Vendor") url=vendor_create_url %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
107
templates/staff/staff_detail.html
Normal file
107
templates/staff/staff_detail.html
Normal file
@ -0,0 +1,107 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static custom_filters crispy_forms_filters %}
|
||||
{% block title %}
|
||||
{% trans 'Profile' %} {% endblock %}
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<div class="row align-items-center justify-content-between g-3 mb-4">
|
||||
<div class="col-auto">
|
||||
<h2 class="mb-0">{% trans 'Profile' %}</h2>
|
||||
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="row g-2 g-sm-3">
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-phoenix-primary"
|
||||
href="{% url 'user_update' request.dealer.slug request.staff.slug %}"><span class="fas fa-edit me-2 text-primary"></span>{{ _("Edit") }} </a>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a href="{% url 'staff_password_reset' request.dealer.slug staff.user.pk %}" 'staff_password_reset' request.dealer.slug user_.pk
|
||||
class="btn btn-phoenix-danger"><span class="fas fa-key me-2"></span>{{ _("Change Password") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="border-bottom border-dashed pb-4">
|
||||
<div class="row align-items-center g-3 g-sm-5 text-center text-sm-start">
|
||||
<div class="col-12 col-sm-auto">
|
||||
<input class="d-none" id="avatarFile" type="file" />
|
||||
<label class="cursor-pointer avatar avatar-5xl" for="avatarFile">
|
||||
{% if staff.logo %}
|
||||
<img src="{{ staff.logo.url }}"
|
||||
alt="{{ staff.get_local_name }}"
|
||||
class="rounded-circle"
|
||||
style="max-width: 150px" />
|
||||
{% else %}
|
||||
<span class="rounded-circle feather feather-user text-body-tertiary"
|
||||
style="max-width: 150px"></span>
|
||||
<img src="{% static 'images/logos/logo.png' %}"
|
||||
alt="{{ staff.get_local_name }}"
|
||||
class=""
|
||||
style="max-width: 150px" />
|
||||
{% endif %}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-auto flex-1">
|
||||
<h3>{{ staff.get_local_name }}</h3>
|
||||
<p class="text-body-secondary">{{staff.user.groups.name}}</p>
|
||||
<p class="text-body-secondary">{% trans 'Joined' %} {{ staff.created|timesince }} {% trans 'ago' %}</p>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-between-center pt-4">
|
||||
<div>
|
||||
<h6 class="mb-2 text-body-secondary">{% trans 'last login'|capfirst %}</h6>
|
||||
<h4 class="fs-7 text-body-highlight mb-0">{{ staff.user.last_login|date:"D M d, Y H:i" }}</h4>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="border-bottom border-dashed">
|
||||
<h4 class="mb-3">{% trans 'Default Address' %}</h4>
|
||||
</div>
|
||||
<div class="pt-4 mb-7 mb-lg-4 mb-xl-7">
|
||||
<div class="row justify-content-between">
|
||||
<div class="col-auto">
|
||||
<h5 class="text-body-highlight">{% trans 'Address' %}</h5>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<p class="text-body-secondary">{{ staff.address }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-top border-dashed pt-4">
|
||||
<div class="row flex-between-center mb-2">
|
||||
<div class="col-auto">
|
||||
<h5 class="text-body-highlight mb-0">{% trans 'Email' %}</h5>
|
||||
</div>
|
||||
<div class="col-auto">{{ staff.user.email }}</div>
|
||||
</div>
|
||||
<div class="row flex-between-center">
|
||||
<div class="col-auto">
|
||||
<h5 class="text-body-highlight mb-0">{% trans 'Phone' %}</h5>
|
||||
</div>
|
||||
<div class="col-auto" dir="ltr">{{ staff.phone_number }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@ -79,12 +79,12 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer d-flex ">
|
||||
<a class="btn btn-sm btn-phoenix-primary me-1"
|
||||
<a class="btn btn-sm btn-phoenix-primary me-3"
|
||||
href="{% url 'user_update' request.dealer.slug user_.slug %}">
|
||||
{{ _("Edit") }}
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn me-1"
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn me-3"
|
||||
data-url="{% url 'user_delete' request.dealer.slug user_.slug %}"
|
||||
data-message='{{ _("Are you sure you want to delete this user?") }}'
|
||||
data-bs-toggle="modal"
|
||||
@ -92,13 +92,13 @@
|
||||
{{ _("Delete") }}
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
<a class="btn btn-sm btn-phoenix-secondary me-1"
|
||||
<a class="btn btn-sm btn-phoenix-secondary me-3"
|
||||
href="{% url 'user_list' request.dealer.slug %}">
|
||||
{{ _("Back to List") }}
|
||||
{{ _("Back to Staffs List") }}
|
||||
<i class="fa-regular fa-circle-left"></i>
|
||||
</a>
|
||||
<a class="btn btn-sm btn-phoenix-secondary"
|
||||
href="{% url 'staff_password_reset' request.dealer.slug user_.pk %}">
|
||||
href="{% url 'staff_password_reset' request.dealer.slug %}">
|
||||
{{ _("Reset Password") }}
|
||||
<i class="fa-solid fa-key"></i>
|
||||
</a>
|
||||
|
||||
@ -88,7 +88,7 @@
|
||||
|
||||
{% else %}
|
||||
{% url "pricing_page" request.dealer.slug as pricing_page_url %}
|
||||
{% include "message-illustration.html" with value1="No Active Plan, please create your subscription plan." value2="Buy Plan" url=pricing_page_url %}
|
||||
{% include "message-illustration.html" with value1=_("No active plan, Please create a subscription plan.") value2=_("Buy Plan") url=pricing_page_url %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user