From a6461f34e0c17f10a60ff147e60cf40fb9bdf2d8 Mon Sep 17 00:00:00 2001 From: Faheedkhan Date: Tue, 5 Aug 2025 13:51:05 +0300 Subject: [PATCH] opportunity stage update logic --- inventory/forms.py | 26 ++++++++++ inventory/urls.py | 5 ++ inventory/views.py | 49 ++++++++++++++++++- templates/bill/includes/card_bill.html | 2 +- .../crm/opportunities/opportunity_detail.html | 36 +++++++++++++- templates/header.html | 6 +-- templates/ledger/reports/car_sale_report.html | 2 +- templates/purchase_orders/po_list.html | 14 ++++-- templates/users/user_detail.html | 8 +-- 9 files changed, 132 insertions(+), 16 deletions(-) diff --git a/inventory/forms.py b/inventory/forms.py index e80e6e4a..2232e50b 100644 --- a/inventory/forms.py +++ b/inventory/forms.py @@ -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): """ diff --git a/inventory/urls.py b/inventory/urls.py index 86363bf6..5f5060c7 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -228,6 +228,11 @@ urlpatterns = [ views.OpportunityUpdateView.as_view(), name="update_opportunity", ), + path( + "/crm/opportunities//stage/edit", + views.OpportunityStageUpdateView.as_view(), + name="update_opportunity_stage", + ), path( "/crm/opportunities/", views.OpportunityListView.as_view(), diff --git a/inventory/views.py b/inventory/views.py index 03f16f99..f0f19592 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -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 diff --git a/templates/bill/includes/card_bill.html b/templates/bill/includes/card_bill.html index 3d829e36..88f376f5 100644 --- a/templates/bill/includes/card_bill.html +++ b/templates/bill/includes/card_bill.html @@ -226,7 +226,7 @@ {% endif %} {% endif %} - {% if bill.can_approve and not request.is_manager or not request.is_dealer %} + {% if bill.can_approve and request.is_accountant %} diff --git a/templates/crm/opportunities/opportunity_detail.html b/templates/crm/opportunities/opportunity_detail.html index c09af69e..8de794ef 100644 --- a/templates/crm/opportunities/opportunity_detail.html +++ b/templates/crm/opportunities/opportunity_detail.html @@ -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
  • - Update Stage + Update Stage
  • {% endif %} {% if perms.inventory.delete_opportunity %} @@ -1095,6 +1097,36 @@ + + {% include 'modal/delete_modal.html' %} diff --git a/templates/header.html b/templates/header.html index 6732d11b..17ad6cef 100644 --- a/templates/header.html +++ b/templates/header.html @@ -352,7 +352,7 @@ {% endif %}
    - {% trans 'Car purchase Report'|capfirst %} + {% trans 'Car purchase Report'|capfirst %}
    @@ -363,9 +363,9 @@ {% endif %}
    - {% trans 'Car Sale Report'|capfirst %} + {% trans 'Car Sale Report'|capfirst %}
    -
    + diff --git a/templates/ledger/reports/car_sale_report.html b/templates/ledger/reports/car_sale_report.html index 9b65954b..f3eb846b 100644 --- a/templates/ledger/reports/car_sale_report.html +++ b/templates/ledger/reports/car_sale_report.html @@ -107,7 +107,7 @@
    {% trans 'Total VAT Amount' %}
    -

    {{ total_vat|floatformat:2 }}

    +

    {{ 10000|floatformat:2 }}

    diff --git a/templates/purchase_orders/po_list.html b/templates/purchase_orders/po_list.html index bb51e728..1d760d7b 100644 --- a/templates/purchase_orders/po_list.html +++ b/templates/purchase_orders/po_list.html @@ -1,7 +1,7 @@ {% 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 %} diff --git a/templates/users/user_detail.html b/templates/users/user_detail.html index 9246bfc9..a1a980e8 100644 --- a/templates/users/user_detail.html +++ b/templates/users/user_detail.html @@ -79,12 +79,12 @@