website/hub/services/admin/services.py

179 lines
5.1 KiB
Python
Raw Normal View History

2025-05-26 11:33:04 +02:00
"""
Admin classes for services and service offerings
"""
from django.contrib import admin
from django.utils.html import format_html
2025-06-23 11:58:09 +02:00
from ..models import (
Service,
ServiceOffering,
ExternalLink,
ExternalLinkOffering,
Plan,
PlanPrice,
)
2025-05-26 11:33:04 +02:00
class ExternalLinkInline(admin.TabularInline):
"""Inline admin for ExternalLink model"""
model = ExternalLink
extra = 1
fields = ("description", "url", "order")
ordering = ("order", "description")
class ExternalLinkOfferingInline(admin.TabularInline):
"""Inline admin for ExternalLinkOffering model"""
model = ExternalLinkOffering
extra = 1
fields = ("description", "url", "order")
ordering = ("order", "description")
2025-06-23 11:58:09 +02:00
class PlanPriceInline(admin.TabularInline):
"""Inline admin for PlanPrice model"""
model = PlanPrice
extra = 1
fields = ("currency", "amount")
ordering = ("currency",)
2025-05-26 11:33:04 +02:00
class PlanInline(admin.StackedInline):
"""Inline admin for Plan model with sortable ordering"""
2025-05-26 11:33:04 +02:00
model = Plan
extra = 1
fieldsets = (
(None, {"fields": ("name", "description", "plan_description")}),
("Display Options", {"fields": ("is_best",)}),
)
2025-06-23 11:58:09 +02:00
show_change_link = True # This allows clicking through to the Plan admin where prices can be managed
2025-05-26 11:33:04 +02:00
class OfferingInline(admin.StackedInline):
"""Inline admin for ServiceOffering model"""
model = ServiceOffering
extra = 1
fieldsets = (
(
None,
{
"fields": (
"description",
"service",
"cloud_provider",
"offer_description",
)
},
),
)
show_change_link = True
@admin.register(Service)
class ServiceAdmin(admin.ModelAdmin):
"""Admin configuration for Service model"""
list_display = (
"name",
"logo_preview",
"category_list",
"is_featured",
"is_coming_soon",
"disable_listing",
)
list_filter = ("categories",)
search_fields = ("name", "description", "slug")
prepopulated_fields = {"slug": ("name",)}
filter_horizontal = ("categories",)
inlines = [ExternalLinkInline, OfferingInline]
def logo_preview(self, obj):
"""Display logo preview in admin list view"""
if obj.logo:
return format_html(
'<img src="{}" style="max-height: 50px;"/>', obj.logo.url
)
return "No logo"
logo_preview.short_description = "Logo"
def category_list(self, obj):
"""Display categories as comma-separated list"""
return ", ".join([cat.name for cat in obj.categories.all()])
category_list.short_description = "Categories"
def partner_list(self, obj):
"""Display consulting partners as comma-separated list"""
return ", ".join([partner.name for partner in obj.consulting_partners.all()])
partner_list.short_description = "Consulting Partners"
@admin.register(ServiceOffering)
class ServiceOfferingAdmin(admin.ModelAdmin):
"""Admin configuration for ServiceOffering model"""
2025-06-23 11:58:09 +02:00
list_display = ("service", "cloud_provider", "plan_count", "total_prices")
2025-05-26 11:33:04 +02:00
list_filter = ("service", "cloud_provider")
search_fields = ("service__name", "cloud_provider__name", "description")
inlines = [ExternalLinkOfferingInline, PlanInline]
2025-06-23 11:58:09 +02:00
def plan_count(self, obj):
"""Display number of plans for this offering"""
return obj.plans.count()
plan_count.short_description = "Plans"
def total_prices(self, obj):
"""Display total number of plan prices for this offering"""
total = sum(plan.plan_prices.count() for plan in obj.plans.all())
return f"{total} prices"
total_prices.short_description = "Total Prices"
@admin.register(Plan)
class PlanAdmin(admin.ModelAdmin):
"""Admin configuration for Plan model with sortable ordering"""
2025-06-23 11:58:09 +02:00
list_display = ("name", "offering", "is_best", "price_summary", "order")
list_filter = ("offering__service", "offering__cloud_provider", "is_best")
2025-06-23 11:58:09 +02:00
search_fields = ("name", "description", "offering__service__name")
list_editable = ("is_best",)
2025-06-23 11:58:09 +02:00
inlines = [PlanPriceInline]
fieldsets = (
(None, {"fields": ("name", "offering", "description", "plan_description")}),
("Display Options", {"fields": ("is_best", "order")}),
)
2025-06-23 11:58:09 +02:00
def price_summary(self, obj):
"""Display a summary of prices for this plan"""
prices = obj.plan_prices.all()
if prices:
price_strs = [f"{price.amount} {price.currency}" for price in prices]
return ", ".join(price_strs)
return "No prices set"
price_summary.short_description = "Prices"
@admin.register(PlanPrice)
class PlanPriceAdmin(admin.ModelAdmin):
"""Admin configuration for PlanPrice model"""
list_display = ("plan", "currency", "amount")
list_filter = (
"currency",
"plan__offering__service",
"plan__offering__cloud_provider",
)
search_fields = ("plan__name", "plan__offering__service__name")
ordering = ("plan__offering__service__name", "plan__name", "currency")