178 lines
5.1 KiB
Python
178 lines
5.1 KiB
Python
"""
|
|
Admin classes for services and service offerings
|
|
"""
|
|
|
|
from django.contrib import admin
|
|
from django.utils.html import format_html
|
|
|
|
from ..models import (
|
|
Service,
|
|
ServiceOffering,
|
|
ExternalLink,
|
|
ExternalLinkOffering,
|
|
Plan,
|
|
PlanPrice,
|
|
)
|
|
|
|
|
|
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")
|
|
|
|
|
|
class PlanPriceInline(admin.TabularInline):
|
|
"""Inline admin for PlanPrice model"""
|
|
|
|
model = PlanPrice
|
|
extra = 1
|
|
fields = ("currency", "amount")
|
|
ordering = ("currency",)
|
|
|
|
|
|
class PlanInline(admin.StackedInline):
|
|
"""Inline admin for Plan model with sortable ordering"""
|
|
|
|
model = Plan
|
|
extra = 1
|
|
fieldsets = (
|
|
(None, {"fields": ("name", "description", "plan_description")}),
|
|
("Display Options", {"fields": ("is_best",)}),
|
|
)
|
|
show_change_link = True # This allows clicking through to the Plan admin where prices can be managed
|
|
|
|
|
|
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"""
|
|
|
|
list_display = ("service", "cloud_provider", "plan_count", "total_prices")
|
|
list_filter = ("service", "cloud_provider")
|
|
search_fields = ("service__name", "cloud_provider__name", "description")
|
|
inlines = [ExternalLinkOfferingInline, PlanInline]
|
|
|
|
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"""
|
|
|
|
list_display = ("name", "offering", "is_best", "price_summary", "order")
|
|
list_filter = ("offering__service", "offering__cloud_provider", "is_best")
|
|
search_fields = ("name", "description", "offering__service__name")
|
|
list_editable = ("is_best",)
|
|
inlines = [PlanPriceInline]
|
|
fieldsets = (
|
|
(None, {"fields": ("name", "offering", "description", "plan_description")}),
|
|
("Display Options", {"fields": ("is_best", "order")}),
|
|
)
|
|
|
|
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")
|