plan price admin

This commit is contained in:
Tobias Brunner 2025-06-23 11:58:09 +02:00
parent 656b59904c
commit 9e0ccb6025
No known key found for this signature in database
2 changed files with 69 additions and 5 deletions

View file

@ -5,7 +5,14 @@ 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
from ..models import (
Service,
ServiceOffering,
ExternalLink,
ExternalLinkOffering,
Plan,
PlanPrice,
)
class ExternalLinkInline(admin.TabularInline):
@ -26,14 +33,22 @@ class ExternalLinkOfferingInline(admin.TabularInline):
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"""
model = Plan
extra = 1
fieldsets = (
(None, {"fields": ("name", "description", "pricing", "plan_description")}),
)
fieldsets = ((None, {"fields": ("name", "description", "plan_description")}),)
show_change_link = True # This allows clicking through to the Plan admin where prices can be managed
class OfferingInline(admin.StackedInline):
@ -102,7 +117,54 @@ class ServiceAdmin(admin.ModelAdmin):
class ServiceOfferingAdmin(admin.ModelAdmin):
"""Admin configuration for ServiceOffering model"""
list_display = ("service", "cloud_provider")
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"""
list_display = ("name", "offering", "price_summary")
list_filter = ("offering__service", "offering__cloud_provider")
search_fields = ("name", "description", "offering__service__name")
inlines = [PlanPriceInline]
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")

View file

@ -255,6 +255,8 @@ JAZZMIN_SETTINGS = {
"services.ProgressiveDiscountModel": "single",
"services.VSHNAppCatPrice": "single",
"services.VSHNAppCatAddon": "single",
"services.ServiceOffering": "single",
"services.Plan": "single",
},
"related_modal_active": True,
}