Add subcription level filtering

This commit is contained in:
Urtzi Alfaro
2025-09-21 13:27:50 +02:00
parent 29065f5337
commit e1b3184413
21 changed files with 1137 additions and 122 deletions

View File

@@ -69,6 +69,30 @@ async def create_ingredient(
)
@router.get("/tenants/{tenant_id}/ingredients/count")
async def count_ingredients(
tenant_id: UUID = Path(...),
current_user: dict = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
) -> dict:
"""Get count of ingredients for a tenant"""
try:
service = InventoryService()
count = await service.count_ingredients_by_tenant(tenant_id)
return {
"tenant_id": str(tenant_id),
"ingredient_count": count
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to count ingredients: {str(e)}"
)
@router.get("/tenants/{tenant_id}/ingredients/{ingredient_id}", response_model=IngredientResponse)
async def get_ingredient(
ingredient_id: UUID,

View File

@@ -219,6 +219,30 @@ class InventoryService:
logger.error("Failed to get ingredients", error=str(e), tenant_id=tenant_id)
raise
async def count_ingredients_by_tenant(self, tenant_id: UUID) -> int:
"""Count total number of active ingredients for a tenant"""
try:
async with get_db_transaction() as db:
# Use SQLAlchemy count query for efficiency
from sqlalchemy import select, func, and_
query = select(func.count(Ingredient.id)).where(
and_(
Ingredient.tenant_id == tenant_id,
Ingredient.is_active == True
)
)
result = await db.execute(query)
count = result.scalar() or 0
logger.info("Counted ingredients", tenant_id=tenant_id, count=count)
return count
except Exception as e:
logger.error("Failed to count ingredients", error=str(e), tenant_id=tenant_id)
raise
# ===== STOCK MANAGEMENT =====
async def add_stock(

View File

@@ -39,7 +39,6 @@ def get_subscription_repository():
raise HTTPException(status_code=500, detail="Repository initialization failed")
@router.get("/subscriptions/{tenant_id}/limits")
@track_endpoint_metrics("subscription_get_limits")
async def get_subscription_limits(
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
@@ -62,7 +61,6 @@ async def get_subscription_limits(
)
@router.get("/subscriptions/{tenant_id}/usage")
@track_endpoint_metrics("subscription_get_usage")
async def get_usage_summary(
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
@@ -85,7 +83,6 @@ async def get_usage_summary(
)
@router.get("/subscriptions/{tenant_id}/can-add-location")
@track_endpoint_metrics("subscription_check_location_limit")
async def can_add_location(
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
@@ -108,7 +105,6 @@ async def can_add_location(
)
@router.get("/subscriptions/{tenant_id}/can-add-product")
@track_endpoint_metrics("subscription_check_product_limit")
async def can_add_product(
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
@@ -131,7 +127,6 @@ async def can_add_product(
)
@router.get("/subscriptions/{tenant_id}/can-add-user")
@track_endpoint_metrics("subscription_check_user_limit")
async def can_add_user(
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
@@ -154,7 +149,6 @@ async def can_add_user(
)
@router.get("/subscriptions/{tenant_id}/features/{feature}")
@track_endpoint_metrics("subscription_check_feature")
async def has_feature(
tenant_id: UUID = Path(..., description="Tenant ID"),
feature: str = Path(..., description="Feature name"),
@@ -179,7 +173,6 @@ async def has_feature(
)
@router.get("/subscriptions/{tenant_id}/validate-upgrade/{new_plan}")
@track_endpoint_metrics("subscription_validate_upgrade")
async def validate_plan_upgrade(
tenant_id: UUID = Path(..., description="Tenant ID"),
new_plan: str = Path(..., description="New plan name"),
@@ -204,7 +197,6 @@ async def validate_plan_upgrade(
)
@router.post("/subscriptions/{tenant_id}/upgrade")
@track_endpoint_metrics("subscription_upgrade_plan")
async def upgrade_subscription_plan(
tenant_id: UUID = Path(..., description="Tenant ID"),
new_plan: str = Query(..., description="New plan name"),
@@ -250,7 +242,6 @@ async def upgrade_subscription_plan(
)
@router.get("/plans/available")
@track_endpoint_metrics("subscription_get_available_plans")
async def get_available_plans():
"""Get all available subscription plans with features and pricing"""

View File

@@ -9,7 +9,7 @@ from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.core.database import database_manager
from app.api import tenants
from app.api import tenants, subscriptions
from shared.monitoring.logging import setup_logging
from shared.monitoring.metrics import MetricsCollector
@@ -41,6 +41,7 @@ app.add_middleware(
# Include routers
app.include_router(tenants.router, prefix="/api/v1", tags=["tenants"])
app.include_router(subscriptions.router, prefix="/api/v1", tags=["subscriptions"])
@app.on_event("startup")
async def startup_event():

View File

@@ -7,6 +7,7 @@ import structlog
from typing import Dict, Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import HTTPException, status
import httpx
from app.repositories import SubscriptionRepository, TenantRepository, TenantMemberRepository
from app.models.tenants import Subscription, Tenant, TenantMember
@@ -287,10 +288,12 @@ class SubscriptionLimitService:
# Get current usage
members = await self.member_repo.get_tenant_members(tenant_id, active_only=True)
current_users = len(members)
# TODO: Implement actual location and product counts
# Get actual ingredient/product count from inventory service
current_products = await self._get_ingredient_count(tenant_id)
# TODO: Implement actual location count
current_locations = 1
current_products = 0
return {
"plan": subscription.plan,
@@ -327,6 +330,32 @@ class SubscriptionLimitService:
error=str(e))
return {"error": "Failed to get usage summary"}
async def _get_ingredient_count(self, tenant_id: str) -> int:
"""Get ingredient count from inventory service using shared client"""
try:
from app.core.config import settings
from shared.clients.inventory_client import create_inventory_client
# Use the shared inventory client with proper authentication
inventory_client = create_inventory_client(settings)
count = await inventory_client.count_ingredients(tenant_id)
logger.info(
"Retrieved ingredient count via inventory client",
tenant_id=tenant_id,
count=count
)
return count
except Exception as e:
logger.error(
"Error getting ingredient count via inventory client",
tenant_id=tenant_id,
error=str(e)
)
# Return 0 as fallback to avoid breaking subscription display
return 0
# Legacy alias for backward compatibility
SubscriptionService = SubscriptionLimitService

View File

@@ -12,4 +12,5 @@ prometheus-client==0.17.1
python-json-logger==2.0.4
pytz==2023.3
python-logstash==0.4.8
structlog==23.2.0
structlog==23.2.0
python-jose[cryptography]==3.3.0