diff --git a/hub/services/urls.py b/hub/services/urls.py index 1295cfc..6ba0c17 100644 --- a/hub/services/urls.py +++ b/hub/services/urls.py @@ -10,7 +10,7 @@ urlpatterns = [ path("partners/", views.partner_list, name="partner_list"), path("service//", views.service_detail, name="service_detail"), path("offering//", views.offering_detail, name="offering_detail"), - path("provider//", views.cloud_provider_detail, name="provider_detail"), + path("provider//", views.provider_detail, name="provider_detail"), path("partner//", views.partner_detail, name="partner_detail"), path("service//interest/", views.create_lead, name="create_lead"), path("service//thank-you/", views.thank_you, name="thank_you"), diff --git a/hub/services/views.py b/hub/services/views.py deleted file mode 100644 index ca552c6..0000000 --- a/hub/services/views.py +++ /dev/null @@ -1,322 +0,0 @@ -import logging -from django.conf import settings -from django.shortcuts import render, get_object_or_404, redirect -from django.contrib import messages -from django.db.models import Q, Prefetch -from .models import ( - Service, - ServiceOffering, - Plan, - ConsultingPartner, - CloudProvider, - Category, - PlanPrice, -) -from .forms import LeadForm -from .odoo import OdooAPI - -logger = logging.getLogger(__name__) - - -def service_list(request): - services = Service.objects.all().prefetch_related( - "categories", - "offerings", - "offerings__cloud_provider", - "offerings__plans", - "offerings__plans__prices", - "consulting_partners", - "external_links", - ) - cloud_providers = CloudProvider.objects.all() - categories = Category.objects.filter(parent=None).prefetch_related("children") - - # Handle category filter - if request.GET.get("category"): - category_id = request.GET.get("category") - category = get_object_or_404(Category, id=category_id) - subcategories = Category.objects.filter(parent=category) - services = services.filter( - Q(categories=category) | Q(categories__in=subcategories) - ).distinct() - - # Handle cloud provider filter - if request.GET.get("cloud_provider"): - provider_id = request.GET.get("cloud_provider") - services = services.filter(offerings__cloud_provider_id=provider_id).distinct() - - # Handle consulting partner filter - if request.GET.get("consulting_partner"): - partner_id = request.GET.get("consulting_partner") - services = services.filter(consulting_partners__id=partner_id).distinct() - - # Handle search - if request.GET.get("search"): - query = request.GET.get("search") - services = services.filter( - Q(name__icontains=query) - | Q(description__icontains=query) - | Q(offerings__description__icontains=query) - ).distinct() - - context = { - "services": services, - "cloud_providers": cloud_providers, - "categories": categories, - "consulting_partners": ConsultingPartner.objects.all(), - } - return render(request, "services/service_list.html", context) - - -def service_detail(request, slug): - service = get_object_or_404( - Service.objects.prefetch_related( - "categories", - "offerings", - "offerings__cloud_provider", - "offerings__plans", - "offerings__plans__prices", - "offerings__plans__prices__currency", - "offerings__plans__prices__term", - "consulting_partners", - "external_links", - ), - slug=slug, - ) - - context = { - "service": service, - } - return render(request, "services/service_detail.html", context) - - -def offering_list(request): - offerings = ( - ServiceOffering.objects.all() - .select_related("service", "cloud_provider") - .prefetch_related( - "service__categories", - "plans", - "plans__prices", - "plans__prices__currency", - "plans__prices__term", - ) - ) - - cloud_providers = CloudProvider.objects.all() - categories = Category.objects.filter(parent=None).prefetch_related("children") - - # Handle cloud provider filter - if request.GET.get("cloud_provider"): - provider_id = request.GET.get("cloud_provider") - offerings = offerings.filter(cloud_provider_id=provider_id) - - # Handle category filter - if request.GET.get("category"): - category_id = request.GET.get("category") - category = get_object_or_404(Category, id=category_id) - subcategories = Category.objects.filter(parent=category) - offerings = offerings.filter( - Q(service__categories=category) | Q(service__categories__in=subcategories) - ).distinct() - - # Handle search - if request.GET.get("search"): - query = request.GET.get("search") - offerings = offerings.filter( - Q(service__name__icontains=query) - | Q(description__icontains=query) - | Q(cloud_provider__name__icontains=query) - ).distinct() - - context = { - "offerings": offerings, - "cloud_providers": cloud_providers, - "categories": categories, - } - return render(request, "services/offering_list.html", context) - - -def offering_detail(request, slug): - offering = get_object_or_404( - ServiceOffering.objects.select_related( - "service", "cloud_provider" - ).prefetch_related( - "plans", "plans__prices", "plans__prices__currency", "plans__prices__term" - ), - slug=slug, - ) - - context = { - "offering": offering, - } - return render(request, "services/offering_detail.html", context) - - -def provider_list(request): - providers = CloudProvider.objects.all().prefetch_related( - "offerings", "consulting_partners" - ) - - # Handle search - if request.GET.get("search"): - query = request.GET.get("search") - providers = providers.filter( - Q(name__icontains=query) | Q(description__icontains=query) - ) - - context = { - "providers": providers, - } - return render(request, "services/provider_list.html", context) - - -def cloud_provider_detail(request, slug): - provider = get_object_or_404( - CloudProvider.objects.prefetch_related( - "offerings", - "offerings__service", - "offerings__plans", - "offerings__plans__prices", - "consulting_partners", - ), - slug=slug, - ) - - # Get all services offered by this provider through offerings - services = ( - Service.objects.filter(offerings__cloud_provider=provider) - .distinct() - .prefetch_related("categories") - ) - - context = { - "provider": provider, - "services": services, - } - return render(request, "services/provider_detail.html", context) - - -def partner_list(request): - partners = ConsultingPartner.objects.all().prefetch_related( - "services", "cloud_providers" - ) - - # Handle cloud provider filter - if request.GET.get("cloud_provider"): - provider_id = request.GET.get("cloud_provider") - partners = partners.filter(cloud_providers__id=provider_id) - - # Handle search - if request.GET.get("search"): - query = request.GET.get("search") - partners = partners.filter( - Q(name__icontains=query) | Q(description__icontains=query) - ) - - context = { - "partners": partners, - "cloud_providers": CloudProvider.objects.all(), - } - return render(request, "services/partner_list.html", context) - - -def partner_detail(request, slug): - partner = get_object_or_404( - ConsultingPartner.objects.prefetch_related( - "services", - "services__categories", - "services__offerings", - "services__offerings__cloud_provider", - "cloud_providers", - ), - slug=slug, - ) - - context = { - "partner": partner, - "services": partner.services.all(), - } - return render(request, "services/partner_detail.html", context) - - -def create_lead(request, slug): - service = get_object_or_404( - Service.objects.prefetch_related("categories"), slug=slug - ) - selected_offering = None - selected_plan = None - - # Get the offering if specified - if request.GET.get("offering"): - selected_offering = get_object_or_404( - ServiceOffering.objects.select_related("cloud_provider").prefetch_related( - "plans" - ), - id=request.GET.get("offering"), - service=service, - ) - - if selected_offering.plans.exists(): - if not request.GET.get("plan"): - # If there's only one plan, automatically select it - if selected_offering.plans.count() == 1: - return redirect( - "services:create_lead", - slug=service.slug, - offering=selected_offering.id, - plan=selected_offering.plans.first().id, - ) - # If there are multiple plans, redirect to offering detail - return redirect("services:offering_detail", slug=selected_offering.slug) - - # Get the selected plan - selected_plan = get_object_or_404( - Plan.objects.prefetch_related( - "prices", "prices__currency", "prices__term" - ), - id=request.GET.get("plan"), - offering=selected_offering, - ) - - if request.method == "POST": - form = LeadForm(request.POST) - if form.is_valid(): - lead = form.save(commit=False) - lead.service = service - lead.offering = selected_offering - lead.plan = selected_plan - - try: - logger.info(f"Attempting to create lead for service: {service.name}") - odoo = OdooAPI() - odoo_lead_id = odoo.create_lead(lead) - lead.odoo_lead_id = odoo_lead_id - lead.save() - - logger.info(f"Successfully created lead with Odoo ID: {odoo_lead_id}") - return redirect("services:thank_you", slug=service.slug) - - except Exception as e: - logger.error(f"Failed to create lead: {str(e)}", exc_info=True) - error_message = "Sorry, there was an error processing your request. Please try again later." - - if settings.DEBUG: - error_message += f" Error: {str(e)}" - - messages.error(request, error_message) - else: - form = LeadForm() - - context = { - "form": form, - "service": service, - "selected_offering": selected_offering, - "selected_plan": selected_plan, - } - return render(request, "services/lead_form.html", context) - - -def thank_you(request, slug): - service = get_object_or_404(Service, slug=slug) - return render(request, "services/thank_you.html", {"service": service}) diff --git a/hub/services/views/__init__.py b/hub/services/views/__init__.py new file mode 100644 index 0000000..b832a41 --- /dev/null +++ b/hub/services/views/__init__.py @@ -0,0 +1,5 @@ +from .leads import * +from .offerings import * +from .partners import * +from .providers import * +from .services import * diff --git a/hub/services/views/leads.py b/hub/services/views/leads.py new file mode 100644 index 0000000..6751ecd --- /dev/null +++ b/hub/services/views/leads.py @@ -0,0 +1,95 @@ +import logging +from django.conf import settings +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib import messages +from services.models import ( + Service, + ServiceOffering, + Plan, +) +from services.forms import LeadForm +from services.odoo import OdooAPI + +logger = logging.getLogger(__name__) + + +def create_lead(request, slug): + service = get_object_or_404( + Service.objects.prefetch_related("categories"), slug=slug + ) + selected_offering = None + selected_plan = None + + # Get the offering if specified + if request.GET.get("offering"): + selected_offering = get_object_or_404( + ServiceOffering.objects.select_related("cloud_provider").prefetch_related( + "plans" + ), + id=request.GET.get("offering"), + service=service, + ) + + if selected_offering.plans.exists(): + if not request.GET.get("plan"): + # If there's only one plan, automatically select it + if selected_offering.plans.count() == 1: + return redirect( + "services:create_lead", + slug=service.slug, + offering=selected_offering.id, + plan=selected_offering.plans.first().id, + ) + # If there are multiple plans, redirect to offering detail + return redirect("services:offering_detail", slug=selected_offering.slug) + + # Get the selected plan + selected_plan = get_object_or_404( + Plan.objects.prefetch_related( + "prices", "prices__currency", "prices__term" + ), + id=request.GET.get("plan"), + offering=selected_offering, + ) + + if request.method == "POST": + form = LeadForm(request.POST) + if form.is_valid(): + lead = form.save(commit=False) + lead.service = service + lead.offering = selected_offering + lead.plan = selected_plan + + try: + logger.info(f"Attempting to create lead for service: {service.name}") + odoo = OdooAPI() + odoo_lead_id = odoo.create_lead(lead) + lead.odoo_lead_id = odoo_lead_id + lead.save() + + logger.info(f"Successfully created lead with Odoo ID: {odoo_lead_id}") + return redirect("services:thank_you", slug=service.slug) + + except Exception as e: + logger.error(f"Failed to create lead: {str(e)}", exc_info=True) + error_message = "Sorry, there was an error processing your request. Please try again later." + + if settings.DEBUG: + error_message += f" Error: {str(e)}" + + messages.error(request, error_message) + else: + form = LeadForm() + + context = { + "form": form, + "service": service, + "selected_offering": selected_offering, + "selected_plan": selected_plan, + } + return render(request, "services/lead_form.html", context) + + +def thank_you(request, slug): + service = get_object_or_404(Service, slug=slug) + return render(request, "services/thank_you.html", {"service": service}) diff --git a/hub/services/views/offerings.py b/hub/services/views/offerings.py new file mode 100644 index 0000000..b6fba84 --- /dev/null +++ b/hub/services/views/offerings.py @@ -0,0 +1,70 @@ +from django.shortcuts import render, get_object_or_404 +from django.db.models import Q +from services.models import ( + ServiceOffering, + CloudProvider, + Category, +) + + +def offering_list(request): + offerings = ( + ServiceOffering.objects.all() + .select_related("service", "cloud_provider") + .prefetch_related( + "service__categories", + "plans", + "plans__prices", + "plans__prices__currency", + "plans__prices__term", + ) + ) + + cloud_providers = CloudProvider.objects.all() + categories = Category.objects.filter(parent=None).prefetch_related("children") + + # Handle cloud provider filter + if request.GET.get("cloud_provider"): + provider_id = request.GET.get("cloud_provider") + offerings = offerings.filter(cloud_provider_id=provider_id) + + # Handle category filter + if request.GET.get("category"): + category_id = request.GET.get("category") + category = get_object_or_404(Category, id=category_id) + subcategories = Category.objects.filter(parent=category) + offerings = offerings.filter( + Q(service__categories=category) | Q(service__categories__in=subcategories) + ).distinct() + + # Handle search + if request.GET.get("search"): + query = request.GET.get("search") + offerings = offerings.filter( + Q(service__name__icontains=query) + | Q(description__icontains=query) + | Q(cloud_provider__name__icontains=query) + ).distinct() + + context = { + "offerings": offerings, + "cloud_providers": cloud_providers, + "categories": categories, + } + return render(request, "services/offering_list.html", context) + + +def offering_detail(request, slug): + offering = get_object_or_404( + ServiceOffering.objects.select_related( + "service", "cloud_provider" + ).prefetch_related( + "plans", "plans__prices", "plans__prices__currency", "plans__prices__term" + ), + slug=slug, + ) + + context = { + "offering": offering, + } + return render(request, "services/offering_detail.html", context) diff --git a/hub/services/views/partners.py b/hub/services/views/partners.py new file mode 100644 index 0000000..1da7b9d --- /dev/null +++ b/hub/services/views/partners.py @@ -0,0 +1,49 @@ +from django.shortcuts import render, get_object_or_404 +from django.db.models import Q +from services.models import ( + ConsultingPartner, + CloudProvider, +) + + +def partner_list(request): + partners = ConsultingPartner.objects.all().prefetch_related( + "services", "cloud_providers" + ) + + # Handle cloud provider filter + if request.GET.get("cloud_provider"): + provider_id = request.GET.get("cloud_provider") + partners = partners.filter(cloud_providers__id=provider_id) + + # Handle search + if request.GET.get("search"): + query = request.GET.get("search") + partners = partners.filter( + Q(name__icontains=query) | Q(description__icontains=query) + ) + + context = { + "partners": partners, + "cloud_providers": CloudProvider.objects.all(), + } + return render(request, "services/partner_list.html", context) + + +def partner_detail(request, slug): + partner = get_object_or_404( + ConsultingPartner.objects.prefetch_related( + "services", + "services__categories", + "services__offerings", + "services__offerings__cloud_provider", + "cloud_providers", + ), + slug=slug, + ) + + context = { + "partner": partner, + "services": partner.services.all(), + } + return render(request, "services/partner_detail.html", context) diff --git a/hub/services/views/providers.py b/hub/services/views/providers.py new file mode 100644 index 0000000..6116501 --- /dev/null +++ b/hub/services/views/providers.py @@ -0,0 +1,50 @@ +from django.shortcuts import render, get_object_or_404 +from django.db.models import Q +from services.models import ( + Service, + CloudProvider, +) + + +def provider_list(request): + providers = CloudProvider.objects.all().prefetch_related( + "offerings", "consulting_partners" + ) + + # Handle search + if request.GET.get("search"): + query = request.GET.get("search") + providers = providers.filter( + Q(name__icontains=query) | Q(description__icontains=query) + ) + + context = { + "providers": providers, + } + return render(request, "services/provider_list.html", context) + + +def provider_detail(request, slug): + provider = get_object_or_404( + CloudProvider.objects.prefetch_related( + "offerings", + "offerings__service", + "offerings__plans", + "offerings__plans__prices", + "consulting_partners", + ), + slug=slug, + ) + + # Get all services offered by this provider through offerings + services = ( + Service.objects.filter(offerings__cloud_provider=provider) + .distinct() + .prefetch_related("categories") + ) + + context = { + "provider": provider, + "services": services, + } + return render(request, "services/provider_detail.html", context) diff --git a/hub/services/views/services.py b/hub/services/views/services.py new file mode 100644 index 0000000..1d2e97c --- /dev/null +++ b/hub/services/views/services.py @@ -0,0 +1,80 @@ +from django.shortcuts import render, get_object_or_404 +from django.db.models import Q +from services.models import ( + Service, + ConsultingPartner, + CloudProvider, + Category, +) + + +def service_list(request): + services = Service.objects.all().prefetch_related( + "categories", + "offerings", + "offerings__cloud_provider", + "offerings__plans", + "offerings__plans__prices", + "consulting_partners", + "external_links", + ) + cloud_providers = CloudProvider.objects.all() + categories = Category.objects.filter(parent=None).prefetch_related("children") + + # Handle category filter + if request.GET.get("category"): + category_id = request.GET.get("category") + category = get_object_or_404(Category, id=category_id) + subcategories = Category.objects.filter(parent=category) + services = services.filter( + Q(categories=category) | Q(categories__in=subcategories) + ).distinct() + + # Handle cloud provider filter + if request.GET.get("cloud_provider"): + provider_id = request.GET.get("cloud_provider") + services = services.filter(offerings__cloud_provider_id=provider_id).distinct() + + # Handle consulting partner filter + if request.GET.get("consulting_partner"): + partner_id = request.GET.get("consulting_partner") + services = services.filter(consulting_partners__id=partner_id).distinct() + + # Handle search + if request.GET.get("search"): + query = request.GET.get("search") + services = services.filter( + Q(name__icontains=query) + | Q(description__icontains=query) + | Q(offerings__description__icontains=query) + ).distinct() + + context = { + "services": services, + "cloud_providers": cloud_providers, + "categories": categories, + "consulting_partners": ConsultingPartner.objects.all(), + } + return render(request, "services/service_list.html", context) + + +def service_detail(request, slug): + service = get_object_or_404( + Service.objects.prefetch_related( + "categories", + "offerings", + "offerings__cloud_provider", + "offerings__plans", + "offerings__plans__prices", + "offerings__plans__prices__currency", + "offerings__plans__prices__term", + "consulting_partners", + "external_links", + ), + slug=slug, + ) + + context = { + "service": service, + } + return render(request, "services/service_detail.html", context)