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 django.conf import settings
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 django.urls import reverse
from django.utils.text import slugify
@ -206,7 +206,7 @@ class UnitOfMeasure(models.TextChoices):
class VatRate(models.Model):
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)
created_at = models.DateTimeField(auto_now_add=True)

View File

@ -2357,7 +2357,6 @@ def dealer_vat_rate_update(request, slug):
redirect("dealer_detail", slug=slug)
return redirect("dealer_detail", slug=slug)
class DealerUpdateView(

View File

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

View File

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

View File

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