opportunity stage update logic
This commit is contained in:
parent
699b2dfdbd
commit
a6461f34e0
@ -1286,6 +1286,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(),
|
||||
|
||||
@ -6832,7 +6832,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"))
|
||||
@ -6908,6 +6908,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)
|
||||
@ -6930,6 +6931,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):
|
||||
"""
|
||||
@ -6952,7 +6993,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)
|
||||
@ -7024,6 +7065,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
|
||||
|
||||
|
||||
@ -10272,8 +10314,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
|
||||
|
||||
|
||||
|
||||
@ -226,7 +226,7 @@
|
||||
{% endif %}
|
||||
<!-- Mark as Approved -->
|
||||
{% endif %}
|
||||
{% if bill.can_approve and not request.is_manager or not request.is_dealer %}
|
||||
{% 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>
|
||||
|
||||
@ -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 -->
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -107,7 +107,7 @@
|
||||
<div class="card summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{% trans 'Total VAT Amount' %}<i class="fas fa-percent ms-2"></i></h5>
|
||||
<p class="card-text">{{ total_vat|floatformat:2 }}</p>
|
||||
<p class="card-text">{{ 10000|floatformat:2 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -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 %}
|
||||
|
||||
@ -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,9 +92,9 @@
|
||||
{{ _("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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user