lead page ui fix and vat rate validation

This commit is contained in:
Faheed 2025-09-10 03:11:03 +03:00
parent e355953c9b
commit 9c36ef2430
5 changed files with 132 additions and 104 deletions

View File

@ -3,7 +3,7 @@ import uuid
from datetime import datetime from datetime import datetime
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from inventory.validators import SaudiPhoneNumberValidator, vat_rate_validator from inventory.validators import SaudiPhoneNumberValidator
from decimal import Decimal from decimal import Decimal
from django.urls import reverse from django.urls import reverse
from django.utils.text import slugify from django.utils.text import slugify
@ -206,7 +206,7 @@ class UnitOfMeasure(models.TextChoices):
class VatRate(models.Model): class VatRate(models.Model):
dealer = models.ForeignKey("Dealer", on_delete=models.CASCADE) dealer = models.ForeignKey("Dealer", on_delete=models.CASCADE)
rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.15"),validators=[vat_rate_validator]) rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.15"))
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)

View File

@ -2359,7 +2359,6 @@ def dealer_vat_rate_update(request, slug):
return redirect("dealer_detail", slug=slug) return redirect("dealer_detail", slug=slug)
class DealerUpdateView( class DealerUpdateView(
LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, UpdateView LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, UpdateView
): ):

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static widget_tweaks custom_filters %} {% load i18n static widget_tweaks custom_filters %}
{% block title %} {% block title %}
{# Check if an 'object' exists in the context #}
{% if object %} {% if object %}
{% trans 'Update Opportunity' %} {% trans 'Update Opportunity' %}
{% else %} {% else %}
@ -27,99 +26,112 @@
</a> </a>
</div> </div>
</div> </div>
<div class="row g-3"> <div class="row g-3">
<div class="col-lg-8"> <div class="col-lg-8">
<div class="card"> <div class="card">
<div class="card-body p-4 p-sm-5"> <div class="card-body p-4 p-sm-5">
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{% if form.non_field_errors %}<div class="alert alert-danger">{{ form.non_field_errors }}</div>{% endif %} {% if form.non_field_errors %}
<!-- Lead Field --> <div class="alert alert-danger">{{ form.non_field_errors }}</div>
<div class="mb-4"> {% endif %}
<label class="form-label" for="{{ form.lead.id_for_label }}">
{{ form.lead.label }} <h5 class="mb-3 text-dark">{% trans "Main Information" %}</h5>
<span class="text-danger">*</span> <div class="row g-3 mb-5">
</label> <div class="col-md-6">
{{ form.lead|add_class:"form-control" }} <label class="form-label" for="{{ form.lead.id_for_label }}">
{% if form.lead.errors %}<div class="invalid-feedback d-block">{{ form.lead.errors }}</div>{% endif %} {{ form.lead.label }}
</div> <span class="text-danger">*</span>
<!-- Car Field --> </label>
<div class="mb-4"> {{ form.lead|add_class:"form-control form-select" }}
<label class="form-label" for="{{ form.car.id_for_label }}"> {% if form.lead.errors %}<div class="invalid-feedback d-block">{{ form.lead.errors }}</div>{% endif %}
{{ form.car.label }}
<span class="text-danger">*</span>
</label>
{{ form.car|add_class:"form-control" }}
{% if form.car.errors %}<div class="invalid-feedback d-block">{{ form.car.errors }}</div>{% endif %}
</div>
<!-- Stage Field -->
<div class="mb-4">
<label class="form-label" for="{{ form.stage.id_for_label }}">
{{ form.stage.label }}
<span class="text-danger">*</span>
</label>
{{ form.stage|add_class:"form-control" }}
{% if form.stage.errors %}<div class="invalid-feedback d-block">{{ form.stage.errors }}</div>{% endif %}
</div>
<!-- Amount Field -->
{% comment %} <div class="mb-4">
<label class="form-label" for="{{ form.amount.id_for_label }}">
{{ form.amount.label }}
<span class="text-danger">*</span>
</label>
<div class="input-group">
<span class="input-group-text"><span class="icon-saudi_riyal"></span></span>
{{ form.amount|add_class:"form-control" }}
</div> </div>
{% if form.amount.errors %}<div class="invalid-feedback d-block">{{ form.amount.errors }}</div>{% endif %} <div class="col-md-6">
</div> {% endcomment %} <label class="form-label" for="{{ form.car.id_for_label }}">
<!-- Probability Field --> {{ form.car.label }}
{% comment %} <div class="mb-4"> <span class="text-danger">*</span>
<label class="form-label" for="{{ form.probability.id_for_label }}"> </label>
{{ form.probability.label }} {{ form.car|add_class:"form-control form-select" }}
<span class="text-danger">*</span> {% if form.car.errors %}<div class="invalid-feedback d-block">{{ form.car.errors }}</div>{% endif %}
</label> </div>
<div class="d-flex align-items-center gap-3"> <div class="col-md-6">
<input type="range" <label class="form-label" for="{{ form.stage.id_for_label }}">
name="{{ form.probability.name }}" {{ form.stage.label }}
id="{{ form.probability.id_for_label }}" <span class="text-danger">*</span>
min="0" </label>
max="100" {{ form.stage|add_class:"form-control form-select" }}
step="1" {% if form.stage.errors %}<div class="invalid-feedback d-block">{{ form.stage.errors }}</div>{% endif %}
value="{{ form.probability.value|default:'50' }}" </div>
class="form-control form-range" <div class="col-md-6">
oninput="updateProbabilityValue(this.value)"> <label class="form-label" for="{{ form.expected_close_date.id_for_label }}">
<span id="probability-value" {{ form.expected_close_date.label }}
class="badge badge-phoenix fs-6 badge-phoenix-primary"> </label>
{{ form.probability.value|default:'50' }}% <div class="input-group">
</span> {{ form.expected_close_date|add_class:"form-control" }}
<span class="input-group-text"><span class="far fa-calendar"></span></span>
</div>
{% if form.expected_close_date.errors %}
<div class="invalid-feedback d-block">{{ form.expected_close_date.errors }}</div>
{% endif %}
</div> </div>
{% if form.probability.errors %}<div class="invalid-feedback d-block">{{ form.probability.errors }}</div>{% endif %}
</div> </div>
<!-- Expected Revenue --> {% comment %}
<div class="mb-4">
<label class="form-label" for="{{ form.expected_revenue.id_for_label }}">{{ form.expected_revenue.label }}</label>
<div class="input-group">
<span class="input-group-text"><span class="icon-saudi_riyal"></span></span>
{{ form.expected_revenue|add_class:"form-control" }}
</div>
{% if form.expected_revenue.errors %}
<div class="invalid-feedback d-block">{{ form.expected_revenue.errors }}</div>
{% endif %}
</div> {% endcomment %}
<!-- Closing Date -->
<div class="mb-5"> <div class="mb-5">
<label class="form-label" for="{{ form.expected_close_date.id_for_label }}">{{ form.expected_close_date.label }}</label> <h5 class="mb-3 text-dark">{% trans "Financial Information" %}</h5>
<div class="input-group"> <div class="row g-3">
{{ form.expected_close_date|add_class:"form-control" }} <div class="col-md-6">
<span class="input-group-text"><span class="far fa-calendar"></span></span> <label class="form-label" for="{{ form.amount.id_for_label }}">
{{ form.amount.label }}
<span class="text-danger">*</span>
</label>
<div class="input-group input-group-lg">
<span class="input-group-text bg-light border-end-0 text-muted">SAR</span>
{{ form.amount|add_class:"form-control border-start-0" }}
</div>
{% if form.amount.errors %}
<div class="invalid-feedback d-block">{{ form.amount.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.probability.id_for_label }}">
{{ form.probability.label }}
<span class="text-danger">*</span>
</label>
<div class="d-flex align-items-center gap-3">
<input type="range"
name="{{ form.probability.name }}"
id="{{ form.probability.id_for_label }}"
min="0"
max="100"
step="1"
value="{{ form.probability.value|default:'50' }}"
class="form-control form-range"
oninput="updateProbabilityValue(this.value)">
<span id="probability-value" class="badge badge-phoenix fs-6 badge-phoenix-primary">
{{ form.probability.value|default:'50' }}%
</span>
</div>
{% if form.probability.errors %}
<div class="invalid-feedback d-block">{{ form.probability.errors }}</div>
{% endif %}
</div>
<div class="col-12">
<label class="form-label" for="{{ form.expected_revenue.id_for_label }}">
{{ form.expected_revenue.label }}
</label>
<div class="input-group">
<span class="input-group-text">SAR</span>
{{ form.expected_revenue|add_class:"form-control" }}
</div>
{% if form.expected_revenue.errors %}
<div class="invalid-feedback d-block">{{ form.expected_revenue.errors }}</div>
{% endif %}
</div>
</div> </div>
{% if form.expected_close_date.errors %}
<div class="invalid-feedback d-block">{{ form.expected_close_date.errors }}</div>
{% endif %}
</div> </div>
<!-- Form Actions --> {% endcomment %}
<div class="d-flex justify-content-end gap-3"> <div class="d-flex justify-content-end gap-3 mt-4">
<button type="reset" class="btn btn-phoenix-danger px-4"> <button type="reset" class="btn btn-phoenix-danger px-4">
<span class="fas fa-redo me-1"></span>{% trans "Reset" %} <span class="fas fa-redo me-1"></span>{% trans "Reset" %}
</button> </button>
@ -135,17 +147,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<div class="card"> <div class="card">
<div class="card-body p-4"> <div class="card-body p-4">
<h4 class="mb-3">{% trans "Opportunity Guidelines" %}</h4> <h4 class="mb-3">{% trans "Opportunity Guidelines" %}</h4>
<ul class="nav flex-column gap-2 nav-guide"> <ul class="nav flex-column gap-2 nav-guide">
{% comment %}
<li class="nav-item"> <li class="nav-item">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="fas fa-circle text-primary fs-11 me-2"></span> <span class="fas fa-circle text-primary fs-11 me-2"></span>
<span class="text-body-highlight">{% trans "Probability indicates conversion chance" %}</span> <span class="text-body-highlight">{% trans "Probability indicates conversion chance" %}</span>
</div> </div>
</li> </li>
{% endcomment %}
<li class="nav-item"> <li class="nav-item">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="fas fa-circle text-warning fs-11 me-2"></span> <span class="fas fa-circle text-warning fs-11 me-2"></span>
@ -164,29 +179,39 @@
</div> </div>
</div> </div>
</div> </div>
<script> {% endblock %}
{% block customJS %}
<script>
function updateProbabilityValue(value) { function updateProbabilityValue(value) {
const amount = document.getElementById('id_amount'); const amount = document.getElementById('id_amount');
const expectedRevenue = document.getElementById('id_expected_revenue'); const expectedRevenue = document.getElementById('id_expected_revenue');
expectedRevenue.value = (parseFloat(amount.value) * value / 100).toFixed(2);
// Check if amount and expectedRevenue fields exist before using them
if (amount && expectedRevenue) {
expectedRevenue.value = (parseFloat(amount.value) * value / 100).toFixed(2);
}
const badge = document.getElementById('probability-value'); const badge = document.getElementById('probability-value');
badge.textContent = value + '%'; if (badge) {
badge.textContent = value + '%';
// Update badge color based on value // Update badge color based on value
if (value >= 75) { if (value >= 75) {
badge.className = 'badge badge-phoenix fs-6 badge-phoenix-success'; badge.className = 'badge badge-phoenix fs-6 badge-phoenix-success';
} else if (value >= 50) { } else if (value >= 50) {
badge.className = 'badge badge-phoenix fs-6 badge-phoenix-warning'; badge.className = 'badge badge-phoenix fs-6 badge-phoenix-warning';
} else { } else {
badge.className = 'badge badge-phoenix fs-6 badge-phoenix-danger'; badge.className = 'badge badge-phoenix fs-6 badge-phoenix-danger';
}
} }
} }
// Initialize on load // Initialize on load
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const rangeInput = document.getElementById('{{ form.probability.id_for_label }}'); const rangeInput = document.getElementById('{{ form.probability.id_for_label }}');
updateProbabilityValue(rangeInput.value); // Check if rangeInput exists before calling the function
if (rangeInput) {
updateProbabilityValue(rangeInput.value);
}
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -262,7 +262,11 @@
{% if car.marked_price %} {% if car.marked_price %}
<tr> <tr>
<th>{% trans "Cost Price"|capfirst %}</th> <th>{% trans "Cost Price"|capfirst %}</th>
{% if request.is_dealer or request.is_accountant or request.manager%}
<td>{{ car.cost_price|floatformat:2 }}</td> <td>{{ car.cost_price|floatformat:2 }}</td>
{% else %}
<td class="d-none">{{ car.cost_price|floatformat:2 }}</td>
{% endif %}
</tr> </tr>
<tr> <tr>
<th>{% trans "Marked Price"|capfirst %}</th> <th>{% trans "Marked Price"|capfirst %}</th>
@ -270,7 +274,7 @@
</tr> </tr>
<tr> <tr>
{% if perms.django_ledger.view_ledgermodel %} {% if perms.django_ledger.change_ledgermodel %}
<td colspan="2"> <td colspan="2">
{% if not car.get_transfer %} {% if not car.get_transfer %}
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}" <a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"

View File

@ -215,16 +215,16 @@
name="add_another" name="add_another"
value="true" value="true"
class="btn btn-lg btn-phoenix-success md-me-2"> class="btn btn-lg btn-phoenix-success md-me-2">
{% trans "Save and Add Another" %} {% trans "Add to Inventory" %}
</button> </button>
<button type="submit" {% comment %} <button type="submit"
hx-on-before-request="this.setAttribute('disabled','true')" hx-on-before-request="this.setAttribute('disabled','true')"
hx-on-after-request="this.removeAttribute('disabled')" hx-on-after-request="this.removeAttribute('disabled')"
name="go_to_stats" name="go_to_stats"
value="true" value="true"
class="btn btn-lg btn-phoenix-primary"> class="btn btn-lg btn-phoenix-primary">
{% trans "Save and Go to Inventory" %} {% trans "Save and Go to Inventory" %}
</button> </button> {% endcomment %}
</div> </div>
</div> </div>
</div> </div>