fix(subscriptions): fix subscription banner not showing on merchant detail page

Fix 3 bugs preventing the subscription banner from rendering on
/admin/merchants/{id}: correct API response parsing for platforms and
tiers endpoints (response.items → response.platforms/response.tiers),
and replace broken model_validator with field_validator for tier code
extraction in the billing schema.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-09 21:54:10 +01:00
parent 7a9dda282d
commit c914e10cb8
2 changed files with 12 additions and 4 deletions

View File

@@ -7,7 +7,7 @@ Used for admin subscription management and merchant-level billing.
from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, ConfigDict, Field, field_validator
# ============================================================================
@@ -117,7 +117,7 @@ class MerchantSubscriptionAdminResponse(BaseModel):
id: int
merchant_id: int
platform_id: int
tier_id: int | None = None
tier: str | None = None
status: str
is_annual: bool
@@ -137,6 +137,14 @@ class MerchantSubscriptionAdminResponse(BaseModel):
created_at: datetime
updated_at: datetime
@field_validator("tier", mode="before")
@classmethod
def extract_tier_code(cls, v):
"""Convert SubscriptionTier ORM object to its code string."""
if v is not None and hasattr(v, "code"):
return v.code
return v
class MerchantSubscriptionWithMerchant(MerchantSubscriptionAdminResponse):
"""Subscription response with merchant info."""

View File

@@ -102,7 +102,7 @@ function adminMerchantDetail() {
async loadPlatforms() {
try {
const response = await apiClient.get('/admin/platforms');
const platforms = response.items || response;
const platforms = response.platforms || [];
const oms = platforms.find(p => p.code === 'oms');
if (oms) {
this.platformId = oms.id;
@@ -155,7 +155,7 @@ function adminMerchantDetail() {
try {
const response = await apiClient.get('/admin/subscriptions/tiers');
this.tiers = response.items || response;
this.tiers = response.tiers || [];
merchantDetailLog.info('Loaded tiers:', this.tiers.length);
} catch (error) {
merchantDetailLog.warn('Failed to load tiers:', error.message);