mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-23 08:55:44 +08:00
feat(cloud): show purchased plan revision alongside the latest revision
- Expose the workspace's purchased plan revision from the entitlement snapshot. - Stack the purchased revision card in front of the latest revision in the plan comparison dialog; both cards share the same layout, and the purchased card's copy and prices come from the Space revision endpoint while benefits stay on the entitlement snapshot. - Add a cancel-first tooltip for subscribing to the newer revision. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ececcb8749
commit
16cfb6f8bd
@@ -160,6 +160,7 @@ class WorkspacesRouterGroup(group.RouterGroup):
|
||||
workspace = await self.ap.workspace_service.get_workspace(request_context.workspace_uuid)
|
||||
plan_name: str | None = None
|
||||
limitation = None
|
||||
current_plan = None
|
||||
resolver = getattr(self.ap, 'entitlement_resolver', None)
|
||||
if workspace.source == WorkspaceSource.CLOUD_PROJECTION.value and resolver is not None:
|
||||
entitlement = await resolver.resolve(
|
||||
@@ -167,6 +168,15 @@ class WorkspacesRouterGroup(group.RouterGroup):
|
||||
minimum_revision=request_context.entitlement_revision,
|
||||
)
|
||||
plan_name = entitlement.plan_name
|
||||
if entitlement.plan_revision is not None and entitlement.monthly_bonus_credits is not None:
|
||||
current_plan = {
|
||||
'name': entitlement.plan_name,
|
||||
'subscription_started_at': entitlement.subscription_started_at,
|
||||
'revision': entitlement.plan_revision,
|
||||
'monthly_bonus_credits': entitlement.monthly_bonus_credits,
|
||||
'limits': entitlement.limits,
|
||||
'entitlement_features': entitlement.features,
|
||||
}
|
||||
from ...service.workspace_limits import LIMIT_KEYS
|
||||
|
||||
limitation = {key: entitlement.limit(value) for key, value in LIMIT_KEYS.items()}
|
||||
@@ -188,6 +198,7 @@ class WorkspacesRouterGroup(group.RouterGroup):
|
||||
'permissions': sorted(request_context.workspace.permissions),
|
||||
'placement_generation': request_context.placement_generation,
|
||||
'plan_name': plan_name,
|
||||
'current_plan': current_plan,
|
||||
'limitation': limitation,
|
||||
}
|
||||
)
|
||||
@@ -205,6 +216,7 @@ class WorkspacesRouterGroup(group.RouterGroup):
|
||||
'permissions': sorted(request_context.workspace.permissions),
|
||||
'placement_generation': request_context.placement_generation,
|
||||
'plan_name': plan_name,
|
||||
'current_plan': current_plan,
|
||||
'limitation': limitation,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -55,6 +55,10 @@ class EntitlementSnapshot(pydantic.BaseModel):
|
||||
# must continue to use generic ``features`` and ``limits`` exclusively.
|
||||
plan_name: str | None = pydantic.Field(default=None, min_length=1, max_length=128)
|
||||
|
||||
subscription_started_at: int | None = pydantic.Field(default=None, ge=0)
|
||||
plan_revision: int | None = pydantic.Field(default=None, ge=1)
|
||||
monthly_bonus_credits: int | None = pydantic.Field(default=None, ge=0)
|
||||
|
||||
@pydantic.field_validator('features')
|
||||
@classmethod
|
||||
def _validate_feature_names(cls, value: dict[str, bool]) -> dict[str, bool]:
|
||||
|
||||
Reference in New Issue
Block a user