appcat price model

This commit is contained in:
Tobias Brunner 2025-05-20 15:27:45 +02:00
parent f14cc0e39e
commit 3a0cc248a7
Signed by: tobru
SSH key fingerprint: SHA256:kOXg1R6c11XW3/Pt9dbLdQvOJGFAy+B2K6v6PtRWBGQ
3 changed files with 448 additions and 13 deletions

View file

@ -10,6 +10,7 @@ from .models import (
Category,
CloudProvider,
ComputePlan,
ComputePlanPrice,
ConsultingPartner,
ExternalLink,
ExternalLinkOffering,
@ -18,6 +19,9 @@ from .models import (
ReusableText,
Service,
ServiceOffering,
VSHNAppCatBaseFee,
VSHNAppCatPrice,
VSHNAppCatUnitRate,
WebsiteFaq,
)
@ -72,10 +76,10 @@ class CategoryAdmin(admin.ModelAdmin):
ordering = ("order", "name")
class ComputePlansInline(SortableAdminMixin, admin.ModelAdmin):
class ComputePlanItemInline(admin.TabularInline):
model = ComputePlan
extra = 1
fieldsets = ((None, {"fields": ("name", "vcpus", "ram", "price_chf")}),)
fields = ("name", "vcpus", "ram", "active", "valid_from", "valid_to")
@admin.register(CloudProvider)
@ -192,6 +196,12 @@ class WebsiteFaqAdmin(SortableAdminMixin, admin.ModelAdmin):
ordering = ("order",)
class ComputePlanPriceInline(admin.TabularInline):
model = ComputePlanPrice
extra = 1
fields = ("currency", "amount")
class ComputePlanResource(resources.ModelResource):
cloud_provider = Field(
column_name="cloud_provider",
@ -209,14 +219,83 @@ class ComputePlanResource(resources.ModelResource):
"vcpus",
"ram",
"cpu_mem_ratio",
"price_chf",
"cloud_provider",
"active",
"valid_from",
"valid_to",
)
@admin.register(ComputePlan)
class ComputePlansAdmin(ImportExportModelAdmin):
resource_class = ComputePlanResource
list_display = ("name", "cloud_provider", "vcpus", "ram", "price_chf", "active")
search_fields = ("name", "cloud_provider__name") # Search by cloud_provider name
list_display = (
"name",
"cloud_provider",
"vcpus",
"ram",
"display_prices",
"active",
)
search_fields = ("name", "cloud_provider__name")
list_filter = ("active", "cloud_provider")
ordering = ("name",)
inlines = [ComputePlanPriceInline]
def display_prices(self, obj):
prices = obj.prices.all()
if not prices:
return "No prices set"
return format_html("<br>".join([f"{p.amount} {p.currency}" for p in prices]))
display_prices.short_description = "Prices (Amount Currency)"
class VSHNAppCatBaseFeeInline(admin.TabularInline):
model = VSHNAppCatBaseFee
extra = 1
fields = ("currency", "amount")
class VSHNAppCatUnitRateInline(admin.TabularInline):
model = VSHNAppCatUnitRate
extra = 1
fields = ("currency", "service_level", "amount")
@admin.register(VSHNAppCatPrice)
class VSHNAppCatPriceAdmin(admin.ModelAdmin):
list_display = (
"service",
"variable_unit",
"admin_display_base_fees",
"admin_display_unit_rates",
)
list_filter = ("variable_unit", "service")
search_fields = ("service__name",)
inlines = [VSHNAppCatBaseFeeInline, VSHNAppCatUnitRateInline]
def admin_display_base_fees(self, obj):
fees = obj.base_fees.all()
if not fees:
return "No base fees"
return format_html(
"<br>".join([f"{fee.amount} {fee.currency}" for fee in fees])
)
admin_display_base_fees.short_description = "Base Fees"
def admin_display_unit_rates(self, obj):
rates = obj.unit_rates.all()
if not rates:
return "No unit rates"
return format_html(
"<br>".join(
[
f"{rate.amount} {rate.currency} ({rate.get_service_level_display()})"
for rate in rates
]
)
)
admin_display_unit_rates.short_description = "Unit Rates"