improve initial page load filter selection
This commit is contained in:
parent
19d9dff83e
commit
381f2f09e6
2 changed files with 220 additions and 100 deletions
|
@ -226,16 +226,18 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form method="get" class="row g-3" id="filter-form">
|
<form method="get" class="row g-3" id="filter-form">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="cloud_provider" class="form-label">Cloud Provider</label>
|
<label for="cloud_provider" class="form-label">Cloud Provider <span class="text-danger">*</span></label>
|
||||||
<select name="cloud_provider" id="cloud_provider" class="form-select filter-select">
|
<select name="cloud_provider" id="cloud_provider" class="form-select filter-select">
|
||||||
|
<option value="">-- Select Cloud Provider --</option>
|
||||||
{% for provider in all_cloud_providers %}
|
{% for provider in all_cloud_providers %}
|
||||||
<option value="{{ provider }}" {% if provider == filter_cloud_provider %}selected{% endif %}>{{ provider }}</option>
|
<option value="{{ provider }}" {% if provider == filter_cloud_provider %}selected{% endif %}>{{ provider }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="service" class="form-label">Service</label>
|
<label for="service" class="form-label">Service <span class="text-danger">*</span></label>
|
||||||
<select name="service" id="service" class="form-select filter-select">
|
<select name="service" id="service" class="form-select filter-select">
|
||||||
|
<option value="">-- Select Service --</option>
|
||||||
{% for service in all_services %}
|
{% for service in all_services %}
|
||||||
<option value="{{ service }}" {% if service == filter_service %}selected{% endif %}>{{ service }}</option>
|
<option value="{{ service }}" {% if service == filter_service %}selected{% endif %}>{{ service }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -772,7 +774,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
<h4>No pricing data available</h4>
|
<h4>No pricing data available</h4>
|
||||||
<p>{% if filter_cloud_provider or filter_service or filter_compute_plan_group or filter_service_level %}No data matches the selected filters. Try adjusting your filter criteria.{% else %}Please ensure you have active compute plans with prices and VSHNAppCat price configurations.{% endif %}</p>
|
<p>{% if not filter_cloud_provider and not filter_service %}Please select both a <strong>Cloud Provider</strong> and <strong>Service</strong> from the filters above to view pricing data.{% elif not filter_cloud_provider %}Please select a <strong>Cloud Provider</strong> from the filters above.{% elif not filter_service %}Please select a <strong>Service</strong> from the filters above.{% elif filter_cloud_provider or filter_service or filter_compute_plan_group or filter_service_level %}No data matches the selected filters. Try adjusting your filter criteria.{% else %}Please ensure you have active compute plans with prices and VSHNAppCat price configurations.{% endif %}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,14 +2,19 @@ import re
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from hub.services.models.pricing import ComputePlan, StoragePlan, ExternalPricePlans, VSHNAppCatPrice
|
from hub.services.models.pricing import (
|
||||||
|
ComputePlan,
|
||||||
|
StoragePlan,
|
||||||
|
ExternalPricePlans,
|
||||||
|
VSHNAppCatPrice,
|
||||||
|
)
|
||||||
from django.contrib.admin.views.decorators import staff_member_required
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
def natural_sort_key(obj):
|
def natural_sort_key(obj):
|
||||||
"""Extract numeric parts for natural sorting (works for any plan name)"""
|
"""Extract numeric parts for natural sorting (works for any plan name)"""
|
||||||
name = obj.name if hasattr(obj, 'name') else str(obj)
|
name = obj.name if hasattr(obj, "name") else str(obj)
|
||||||
parts = re.split(r"(\d+)", name)
|
parts = re.split(r"(\d+)", name)
|
||||||
return [int(part) if part.isdigit() else part for part in parts]
|
return [int(part) if part.isdigit() else part for part in parts]
|
||||||
|
|
||||||
|
@ -130,18 +135,61 @@ def pricelist(request):
|
||||||
filter_compute_plan_group = request.GET.get("compute_plan_group", "")
|
filter_compute_plan_group = request.GET.get("compute_plan_group", "")
|
||||||
filter_service_level = request.GET.get("service_level", "")
|
filter_service_level = request.GET.get("service_level", "")
|
||||||
|
|
||||||
|
# Get filter options for dropdowns first (needed for initial page load)
|
||||||
|
all_cloud_providers = (
|
||||||
|
ComputePlan.objects.all()
|
||||||
|
.values_list("cloud_provider__name", flat=True)
|
||||||
|
.distinct()
|
||||||
|
.order_by("cloud_provider__name")
|
||||||
|
)
|
||||||
|
all_services = (
|
||||||
|
VSHNAppCatPrice.objects.values_list("service__name", flat=True)
|
||||||
|
.distinct()
|
||||||
|
.order_by("service__name")
|
||||||
|
)
|
||||||
|
all_compute_plan_groups = list(
|
||||||
|
ComputePlan.objects.filter(group__isnull=False)
|
||||||
|
.values_list("group__name", flat=True)
|
||||||
|
.distinct()
|
||||||
|
.order_by("group__name")
|
||||||
|
)
|
||||||
|
all_compute_plan_groups.append("No Group") # Add option for plans without groups
|
||||||
|
all_service_levels = [choice[1] for choice in VSHNAppCatPrice.ServiceLevel.choices]
|
||||||
|
|
||||||
|
# Only process pricing data if both cloud provider and service are selected
|
||||||
|
if not filter_cloud_provider or not filter_service:
|
||||||
|
context = {
|
||||||
|
"pricing_data_by_group_and_service_level": {},
|
||||||
|
"show_discount_details": show_discount_details,
|
||||||
|
"show_addon_details": show_addon_details,
|
||||||
|
"show_price_comparison": show_price_comparison,
|
||||||
|
"filter_cloud_provider": filter_cloud_provider,
|
||||||
|
"filter_service": filter_service,
|
||||||
|
"filter_compute_plan_group": filter_compute_plan_group,
|
||||||
|
"filter_service_level": filter_service_level,
|
||||||
|
"all_cloud_providers": all_cloud_providers,
|
||||||
|
"all_services": all_services,
|
||||||
|
"all_compute_plan_groups": all_compute_plan_groups,
|
||||||
|
"all_service_levels": all_service_levels,
|
||||||
|
"show_empty_state": True, # Flag to show empty state message
|
||||||
|
}
|
||||||
|
return render(request, "services/pricelist.html", context)
|
||||||
|
|
||||||
# Fetch all compute plans (active and inactive) with related data
|
# Fetch all compute plans (active and inactive) with related data
|
||||||
compute_plans_qs = ComputePlan.objects.all()
|
compute_plans_qs = ComputePlan.objects.all()
|
||||||
if filter_cloud_provider:
|
if filter_cloud_provider:
|
||||||
compute_plans_qs = compute_plans_qs.filter(cloud_provider__name=filter_cloud_provider)
|
compute_plans_qs = compute_plans_qs.filter(
|
||||||
|
cloud_provider__name=filter_cloud_provider
|
||||||
|
)
|
||||||
if filter_compute_plan_group:
|
if filter_compute_plan_group:
|
||||||
if filter_compute_plan_group == "No Group":
|
if filter_compute_plan_group == "No Group":
|
||||||
compute_plans_qs = compute_plans_qs.filter(group__isnull=True)
|
compute_plans_qs = compute_plans_qs.filter(group__isnull=True)
|
||||||
else:
|
else:
|
||||||
compute_plans_qs = compute_plans_qs.filter(group__name=filter_compute_plan_group)
|
compute_plans_qs = compute_plans_qs.filter(
|
||||||
|
group__name=filter_compute_plan_group
|
||||||
|
)
|
||||||
compute_plans = list(
|
compute_plans = list(
|
||||||
compute_plans_qs
|
compute_plans_qs.select_related("cloud_provider", "group")
|
||||||
.select_related("cloud_provider", "group")
|
|
||||||
.prefetch_related("prices")
|
.prefetch_related("prices")
|
||||||
.order_by("group__order", "group__name", "cloud_provider__name", "name")
|
.order_by("group__order", "group__name", "cloud_provider__name", "name")
|
||||||
)
|
)
|
||||||
|
@ -186,20 +234,30 @@ def pricelist(request):
|
||||||
units = int(plan.vcpus)
|
units = int(plan.vcpus)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
base_fee_currencies = set(appcat_price.base_fees.values_list("currency", flat=True))
|
base_fee_currencies = set(
|
||||||
service_levels = appcat_price.unit_rates.values_list("service_level", flat=True).distinct()
|
appcat_price.base_fees.values_list("currency", flat=True)
|
||||||
|
)
|
||||||
|
service_levels = appcat_price.unit_rates.values_list(
|
||||||
|
"service_level", flat=True
|
||||||
|
).distinct()
|
||||||
# Apply service level filter
|
# Apply service level filter
|
||||||
if filter_service_level:
|
if filter_service_level:
|
||||||
service_levels = [
|
service_levels = [
|
||||||
sl for sl in service_levels
|
sl
|
||||||
if dict(VSHNAppCatPrice.ServiceLevel.choices)[sl] == filter_service_level
|
for sl in service_levels
|
||||||
|
if dict(VSHNAppCatPrice.ServiceLevel.choices)[sl]
|
||||||
|
== filter_service_level
|
||||||
]
|
]
|
||||||
for service_level in service_levels:
|
for service_level in service_levels:
|
||||||
unit_rate_currencies = set(
|
unit_rate_currencies = set(
|
||||||
appcat_price.unit_rates.filter(service_level=service_level).values_list("currency", flat=True)
|
appcat_price.unit_rates.filter(
|
||||||
|
service_level=service_level
|
||||||
|
).values_list("currency", flat=True)
|
||||||
)
|
)
|
||||||
# Find currencies that exist across all pricing components
|
# Find currencies that exist across all pricing components
|
||||||
matching_currencies = plan_currencies.intersection(base_fee_currencies).intersection(unit_rate_currencies)
|
matching_currencies = plan_currencies.intersection(
|
||||||
|
base_fee_currencies
|
||||||
|
).intersection(unit_rate_currencies)
|
||||||
if not matching_currencies:
|
if not matching_currencies:
|
||||||
continue
|
continue
|
||||||
for currency in matching_currencies:
|
for currency in matching_currencies:
|
||||||
|
@ -217,7 +275,10 @@ def pricelist(request):
|
||||||
compute_plan_price = plan.get_price(currency)
|
compute_plan_price = plan.get_price(currency)
|
||||||
base_fee = appcat_price.get_base_fee(currency, service_level)
|
base_fee = appcat_price.get_base_fee(currency, service_level)
|
||||||
unit_rate = appcat_price.get_unit_rate(currency, service_level)
|
unit_rate = appcat_price.get_unit_rate(currency, service_level)
|
||||||
if any(price is None for price in [compute_plan_price, base_fee, unit_rate]):
|
if any(
|
||||||
|
price is None
|
||||||
|
for price in [compute_plan_price, base_fee, unit_rate]
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
# Calculate replica enforcement based on service level
|
# Calculate replica enforcement based on service level
|
||||||
if service_level == VSHNAppCatPrice.ServiceLevel.GUARANTEED:
|
if service_level == VSHNAppCatPrice.ServiceLevel.GUARANTEED:
|
||||||
|
@ -228,12 +289,27 @@ def pricelist(request):
|
||||||
standard_sla_price = base_fee + (total_units * unit_rate)
|
standard_sla_price = base_fee + (total_units * unit_rate)
|
||||||
# Apply discount if available
|
# Apply discount if available
|
||||||
discount_breakdown = None
|
discount_breakdown = None
|
||||||
if appcat_price.discount_model and appcat_price.discount_model.active:
|
if (
|
||||||
discounted_price = appcat_price.discount_model.calculate_discount(unit_rate, total_units)
|
appcat_price.discount_model
|
||||||
|
and appcat_price.discount_model.active
|
||||||
|
):
|
||||||
|
discounted_price = (
|
||||||
|
appcat_price.discount_model.calculate_discount(
|
||||||
|
unit_rate, total_units
|
||||||
|
)
|
||||||
|
)
|
||||||
sla_price = base_fee + discounted_price
|
sla_price = base_fee + discounted_price
|
||||||
discount_savings = standard_sla_price - sla_price
|
discount_savings = standard_sla_price - sla_price
|
||||||
discount_percentage = (discount_savings / standard_sla_price) * 100 if standard_sla_price > 0 else 0
|
discount_percentage = (
|
||||||
discount_breakdown = appcat_price.discount_model.get_discount_breakdown(unit_rate, total_units)
|
(discount_savings / standard_sla_price) * 100
|
||||||
|
if standard_sla_price > 0
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
discount_breakdown = (
|
||||||
|
appcat_price.discount_model.get_discount_breakdown(
|
||||||
|
unit_rate, total_units
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
sla_price = standard_sla_price
|
sla_price = standard_sla_price
|
||||||
discounted_price = total_units * unit_rate
|
discounted_price = total_units * unit_rate
|
||||||
|
@ -259,7 +335,9 @@ def pricelist(request):
|
||||||
if addon.addon_type == "BF": # Base Fee
|
if addon.addon_type == "BF": # Base Fee
|
||||||
addon_price = addon.get_price(currency, service_level)
|
addon_price = addon.get_price(currency, service_level)
|
||||||
elif addon.addon_type == "UR": # Unit Rate
|
elif addon.addon_type == "UR": # Unit Rate
|
||||||
addon_price_per_unit = addon.get_price(currency, service_level)
|
addon_price_per_unit = addon.get_price(
|
||||||
|
currency, service_level
|
||||||
|
)
|
||||||
if addon_price_per_unit:
|
if addon_price_per_unit:
|
||||||
addon_price = addon_price_per_unit * total_units
|
addon_price = addon_price_per_unit * total_units
|
||||||
addon_info = {
|
addon_info = {
|
||||||
|
@ -276,89 +354,131 @@ def pricelist(request):
|
||||||
optional_addons.append(addon_info)
|
optional_addons.append(addon_info)
|
||||||
service_price_with_addons = price_calculation["total_price"]
|
service_price_with_addons = price_calculation["total_price"]
|
||||||
final_price = compute_plan_price + service_price_with_addons
|
final_price = compute_plan_price + service_price_with_addons
|
||||||
service_level_display = dict(VSHNAppCatPrice.ServiceLevel.choices).get(service_level, service_level)
|
service_level_display = dict(
|
||||||
|
VSHNAppCatPrice.ServiceLevel.choices
|
||||||
|
).get(service_level, service_level)
|
||||||
# Get external/internal price comparisons if enabled (unchanged, but could be optimized further)
|
# Get external/internal price comparisons if enabled (unchanged, but could be optimized further)
|
||||||
external_comparisons = []
|
external_comparisons = []
|
||||||
internal_comparisons = []
|
internal_comparisons = []
|
||||||
if show_price_comparison:
|
if show_price_comparison:
|
||||||
external_prices = get_external_price_comparisons(plan, appcat_price, currency, service_level)
|
external_prices = get_external_price_comparisons(
|
||||||
|
plan, appcat_price, currency, service_level
|
||||||
|
)
|
||||||
for ext_price in external_prices:
|
for ext_price in external_prices:
|
||||||
difference = ext_price.amount - final_price
|
difference = ext_price.amount - final_price
|
||||||
ratio = ext_price.amount / final_price if final_price > 0 else 0
|
ratio = (
|
||||||
external_comparisons.append({
|
ext_price.amount / final_price if final_price > 0 else 0
|
||||||
"plan_name": ext_price.plan_name,
|
)
|
||||||
"provider": ext_price.cloud_provider.name,
|
external_comparisons.append(
|
||||||
"description": ext_price.description,
|
{
|
||||||
"amount": ext_price.amount,
|
"plan_name": ext_price.plan_name,
|
||||||
"currency": ext_price.currency,
|
"provider": ext_price.cloud_provider.name,
|
||||||
"vcpus": ext_price.vcpus,
|
"description": ext_price.description,
|
||||||
"ram": ext_price.ram,
|
"amount": ext_price.amount,
|
||||||
"storage": ext_price.storage,
|
"currency": ext_price.currency,
|
||||||
"replicas": ext_price.replicas,
|
"vcpus": ext_price.vcpus,
|
||||||
"difference": difference,
|
"ram": ext_price.ram,
|
||||||
"ratio": ratio,
|
"storage": ext_price.storage,
|
||||||
"source": ext_price.source,
|
"replicas": ext_price.replicas,
|
||||||
"date_retrieved": ext_price.date_retrieved,
|
"difference": difference,
|
||||||
"is_internal": False,
|
"ratio": ratio,
|
||||||
})
|
"source": ext_price.source,
|
||||||
internal_price_comparisons = get_internal_cloud_provider_comparisons(plan, appcat_price, currency, service_level)
|
"date_retrieved": ext_price.date_retrieved,
|
||||||
|
"is_internal": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
internal_price_comparisons = (
|
||||||
|
get_internal_cloud_provider_comparisons(
|
||||||
|
plan, appcat_price, currency, service_level
|
||||||
|
)
|
||||||
|
)
|
||||||
for int_price in internal_price_comparisons:
|
for int_price in internal_price_comparisons:
|
||||||
difference = int_price["final_price"] - final_price
|
difference = int_price["final_price"] - final_price
|
||||||
ratio = int_price["final_price"] / final_price if final_price > 0 else 0
|
ratio = (
|
||||||
internal_comparisons.append({
|
int_price["final_price"] / final_price
|
||||||
"plan_name": int_price["plan_name"],
|
if final_price > 0
|
||||||
"provider": int_price["provider"],
|
else 0
|
||||||
"description": f"Same specs with {int_price['provider']}",
|
)
|
||||||
"amount": int_price["final_price"],
|
internal_comparisons.append(
|
||||||
"currency": int_price["currency"],
|
{
|
||||||
"vcpus": int_price["vcpus"],
|
"plan_name": int_price["plan_name"],
|
||||||
"ram": int_price["ram"],
|
"provider": int_price["provider"],
|
||||||
"group_name": int_price["group_name"],
|
"description": f"Same specs with {int_price['provider']}",
|
||||||
"compute_plan_price": int_price["compute_plan_price"],
|
"amount": int_price["final_price"],
|
||||||
"service_price": int_price["service_price"],
|
"currency": int_price["currency"],
|
||||||
"difference": difference,
|
"vcpus": int_price["vcpus"],
|
||||||
"ratio": ratio,
|
"ram": int_price["ram"],
|
||||||
"is_internal": True,
|
"group_name": int_price["group_name"],
|
||||||
})
|
"compute_plan_price": int_price[
|
||||||
|
"compute_plan_price"
|
||||||
|
],
|
||||||
|
"service_price": int_price["service_price"],
|
||||||
|
"difference": difference,
|
||||||
|
"ratio": ratio,
|
||||||
|
"is_internal": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
group_name = plan.group.name if plan.group else "No Group"
|
group_name = plan.group.name if plan.group else "No Group"
|
||||||
# Use prefetched storage plans
|
# Use prefetched storage plans
|
||||||
storage_plans = storage_plans_by_provider.get(plan.cloud_provider_id, [])
|
storage_plans = storage_plans_by_provider.get(
|
||||||
pricing_data_by_group_and_service_level[group_name][service_level_display].append({
|
plan.cloud_provider_id, []
|
||||||
"cloud_provider": plan.cloud_provider.name,
|
)
|
||||||
"service": appcat_price.service.name,
|
pricing_data_by_group_and_service_level[group_name][
|
||||||
"compute_plan": plan.name,
|
service_level_display
|
||||||
"compute_plan_group": group_name,
|
].append(
|
||||||
"compute_plan_group_description": (plan.group.description if plan.group else ""),
|
{
|
||||||
"compute_plan_group_node_label": (plan.group.node_label if plan.group else ""),
|
"cloud_provider": plan.cloud_provider.name,
|
||||||
"storage_plans": storage_plans,
|
"service": appcat_price.service.name,
|
||||||
"vcpus": plan.vcpus,
|
"compute_plan": plan.name,
|
||||||
"ram": plan.ram,
|
"compute_plan_group": group_name,
|
||||||
"cpu_mem_ratio": plan.cpu_mem_ratio,
|
"compute_plan_group_description": (
|
||||||
"term": plan.get_term_display(),
|
plan.group.description if plan.group else ""
|
||||||
"currency": currency,
|
),
|
||||||
"compute_plan_price": compute_plan_price,
|
"compute_plan_group_node_label": (
|
||||||
"variable_unit": appcat_price.get_variable_unit_display(),
|
plan.group.node_label if plan.group else ""
|
||||||
"units": units,
|
),
|
||||||
"replica_enforce": replica_enforce,
|
"storage_plans": storage_plans,
|
||||||
"total_units": total_units,
|
"vcpus": plan.vcpus,
|
||||||
"service_level": service_level_display,
|
"ram": plan.ram,
|
||||||
"sla_base": base_fee,
|
"cpu_mem_ratio": plan.cpu_mem_ratio,
|
||||||
"sla_per_unit": unit_rate,
|
"term": plan.get_term_display(),
|
||||||
"sla_price": service_price_with_addons,
|
"currency": currency,
|
||||||
"standard_sla_price": base_sla_price,
|
"compute_plan_price": compute_plan_price,
|
||||||
"discounted_sla_price": (base_fee + discounted_price if appcat_price.discount_model and appcat_price.discount_model.active else None),
|
"variable_unit": appcat_price.get_variable_unit_display(),
|
||||||
"discount_savings": discount_savings,
|
"units": units,
|
||||||
"discount_percentage": discount_percentage,
|
"replica_enforce": replica_enforce,
|
||||||
"discount_breakdown": discount_breakdown,
|
"total_units": total_units,
|
||||||
"final_price": final_price,
|
"service_level": service_level_display,
|
||||||
"discount_model": (appcat_price.discount_model.name if appcat_price.discount_model else None),
|
"sla_base": base_fee,
|
||||||
"has_discount": bool(appcat_price.discount_model and appcat_price.discount_model.active),
|
"sla_per_unit": unit_rate,
|
||||||
"external_comparisons": external_comparisons,
|
"sla_price": service_price_with_addons,
|
||||||
"internal_comparisons": internal_comparisons,
|
"standard_sla_price": base_sla_price,
|
||||||
"mandatory_addons": mandatory_addons,
|
"discounted_sla_price": (
|
||||||
"optional_addons": optional_addons,
|
base_fee + discounted_price
|
||||||
"is_active": plan.active,
|
if appcat_price.discount_model
|
||||||
})
|
and appcat_price.discount_model.active
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"discount_savings": discount_savings,
|
||||||
|
"discount_percentage": discount_percentage,
|
||||||
|
"discount_breakdown": discount_breakdown,
|
||||||
|
"final_price": final_price,
|
||||||
|
"discount_model": (
|
||||||
|
appcat_price.discount_model.name
|
||||||
|
if appcat_price.discount_model
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"has_discount": bool(
|
||||||
|
appcat_price.discount_model
|
||||||
|
and appcat_price.discount_model.active
|
||||||
|
),
|
||||||
|
"external_comparisons": external_comparisons,
|
||||||
|
"internal_comparisons": internal_comparisons,
|
||||||
|
"mandatory_addons": mandatory_addons,
|
||||||
|
"optional_addons": optional_addons,
|
||||||
|
"is_active": plan.active,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Order groups correctly, placing "No Group" last
|
# Order groups correctly, placing "No Group" last
|
||||||
ordered_groups_intermediate = {}
|
ordered_groups_intermediate = {}
|
||||||
all_group_names = list(pricing_data_by_group_and_service_level.keys())
|
all_group_names = list(pricing_data_by_group_and_service_level.keys())
|
||||||
|
@ -366,7 +486,9 @@ def pricelist(request):
|
||||||
all_group_names.remove("No Group")
|
all_group_names.remove("No Group")
|
||||||
all_group_names.append("No Group")
|
all_group_names.append("No Group")
|
||||||
for group_name_key in all_group_names:
|
for group_name_key in all_group_names:
|
||||||
ordered_groups_intermediate[group_name_key] = pricing_data_by_group_and_service_level[group_name_key]
|
ordered_groups_intermediate[group_name_key] = (
|
||||||
|
pricing_data_by_group_and_service_level[group_name_key]
|
||||||
|
)
|
||||||
# Convert defaultdicts to regular dicts for the template
|
# Convert defaultdicts to regular dicts for the template
|
||||||
final_context_data = {}
|
final_context_data = {}
|
||||||
for group_key, service_levels_dict in ordered_groups_intermediate.items():
|
for group_key, service_levels_dict in ordered_groups_intermediate.items():
|
||||||
|
@ -394,11 +516,7 @@ def pricelist(request):
|
||||||
)
|
)
|
||||||
all_compute_plan_groups.append("No Group") # Add option for plans without groups
|
all_compute_plan_groups.append("No Group") # Add option for plans without groups
|
||||||
all_service_levels = [choice[1] for choice in VSHNAppCatPrice.ServiceLevel.choices]
|
all_service_levels = [choice[1] for choice in VSHNAppCatPrice.ServiceLevel.choices]
|
||||||
# If no filter is specified, select the first available provider/service by default
|
|
||||||
if not filter_cloud_provider and all_cloud_providers:
|
|
||||||
filter_cloud_provider = all_cloud_providers[0]
|
|
||||||
if not filter_service and all_services:
|
|
||||||
filter_service = all_services[0]
|
|
||||||
context = {
|
context = {
|
||||||
"pricing_data_by_group_and_service_level": final_context_data,
|
"pricing_data_by_group_and_service_level": final_context_data,
|
||||||
"show_discount_details": show_discount_details,
|
"show_discount_details": show_discount_details,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue