pénzügyi modul továbbfejlesztése (csomagkezelés)
This commit is contained in:
@@ -333,6 +333,14 @@ class SubscriptionService:
|
||||
"valid_from": org_sub.valid_from.isoformat() if org_sub.valid_from else None,
|
||||
"valid_until": org_sub.valid_until.isoformat() if org_sub.valid_until else None,
|
||||
"is_active": org_sub.is_active,
|
||||
# ── P0 AUTO-RENEWAL FIELDS ──
|
||||
"auto_renew": org_sub.auto_renew,
|
||||
"next_renewal_date": org_sub.next_renewal_date.isoformat() if org_sub.next_renewal_date else None,
|
||||
"wallet_auto_deduct": org_sub.wallet_auto_deduct,
|
||||
"renewal_failure_count": org_sub.renewal_failure_count,
|
||||
"provider_subscription_id": org_sub.provider_subscription_id,
|
||||
"renewal": rules.get("renewal", {}),
|
||||
# ── Existing fields ──
|
||||
"allowances": rules.get("allowances", {}),
|
||||
"pricing": rules.get("pricing", {}),
|
||||
"duration": rules.get("duration", {}),
|
||||
@@ -392,6 +400,14 @@ class SubscriptionService:
|
||||
"valid_from": user_sub.valid_from.isoformat() if user_sub.valid_from else None,
|
||||
"valid_until": user_sub.valid_until.isoformat() if user_sub.valid_until else None,
|
||||
"is_active": user_sub.is_active,
|
||||
# ── P0 AUTO-RENEWAL FIELDS ──
|
||||
"auto_renew": user_sub.auto_renew,
|
||||
"next_renewal_date": user_sub.next_renewal_date.isoformat() if user_sub.next_renewal_date else None,
|
||||
"wallet_auto_deduct": user_sub.wallet_auto_deduct,
|
||||
"renewal_failure_count": user_sub.renewal_failure_count,
|
||||
"provider_subscription_id": user_sub.provider_subscription_id,
|
||||
"renewal": rules.get("renewal", {}),
|
||||
# ── Existing fields ──
|
||||
"allowances": rules.get("allowances", {}),
|
||||
"pricing": rules.get("pricing", {}),
|
||||
"duration": rules.get("duration", {}),
|
||||
@@ -471,6 +487,65 @@ class SubscriptionService:
|
||||
|
||||
return visible
|
||||
|
||||
@staticmethod
|
||||
async def is_downgrade(
|
||||
db: AsyncSession,
|
||||
user_id: int,
|
||||
target_tier_id: int,
|
||||
active_org_id: Optional[int] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Determine if switching to the target tier constitutes a downgrade.
|
||||
|
||||
A downgrade is when the target tier's `tier_level` is LESS than the
|
||||
user's CURRENT tier's `tier_level`. Upgrades (same or higher level)
|
||||
should be activated immediately; downgrades should be deferred.
|
||||
|
||||
THOUGHT PROCESS:
|
||||
- Uses `get_user_tier()` which resolves the effective tier from
|
||||
UserSubscription, OrganizationSubscription, or fallback.
|
||||
- Compares integer `tier_level` (0=free, 1=premium, 2=enterprise).
|
||||
- Returns True when target_level < current_level (downgrade).
|
||||
- For equal levels or upgrades, returns False (immediate activation).
|
||||
|
||||
Args:
|
||||
db: Database session.
|
||||
user_id: The user making the change.
|
||||
target_tier_id: The SubscriptionTier ID they want to switch to.
|
||||
active_org_id: Optional org ID to determine subscription context.
|
||||
|
||||
Returns:
|
||||
True if this is a downgrade (should be deferred).
|
||||
False if this is an upgrade or same-level (immediate activation).
|
||||
|
||||
Raises:
|
||||
ValueError: If the target tier does not exist.
|
||||
"""
|
||||
# 1. Get the target tier's level
|
||||
target_stmt = select(SubscriptionTier.tier_level).where(
|
||||
SubscriptionTier.id == target_tier_id
|
||||
)
|
||||
target_result = await db.execute(target_stmt)
|
||||
target_level = target_result.scalar_one_or_none()
|
||||
|
||||
if target_level is None:
|
||||
raise ValueError(f"SubscriptionTier with id={target_tier_id} not found")
|
||||
|
||||
# 2. Get the current effective tier level via the existing resolver
|
||||
current_tier_name = await SubscriptionService.get_user_tier(db, user_id)
|
||||
current_level = SubscriptionService._get_user_level(current_tier_name)
|
||||
|
||||
# 3. Compare: downgrade if target < current
|
||||
is_down = target_level < current_level
|
||||
|
||||
logger.info(
|
||||
"Downgrade check: user_id=%d target_tier_id=%d "
|
||||
"current_level=%d target_level=%d is_downgrade=%s",
|
||||
user_id, target_tier_id, current_level, target_level, is_down,
|
||||
)
|
||||
|
||||
return is_down
|
||||
|
||||
@staticmethod
|
||||
def require_tier(user_tier: str, required_feature_or_min_tier: str) -> bool:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user