Add traslations

This commit is contained in:
Urtzi Alfaro
2025-12-18 20:12:32 +01:00
parent f10a2b92ea
commit acb3a40844
15 changed files with 726 additions and 228 deletions

View File

@@ -219,10 +219,11 @@ async def get_tenant_children_count(
)
@router.post(route_builder.build_base_route("bulk-children", include_tenant_prefix=False), response_model=BulkChildTenantsResponse)
@router.post("/api/v1/tenants/{tenant_id}/bulk-children", response_model=BulkChildTenantsResponse)
@track_endpoint_metrics("bulk_create_child_tenants")
async def bulk_create_child_tenants(
request: BulkChildTenantsCreate,
tenant_id: str = Path(..., description="Parent tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
tenant_service: EnhancedTenantService = Depends(get_enhanced_tenant_service)
):
@@ -242,7 +243,7 @@ async def bulk_create_child_tenants(
try:
logger.info(
"Bulk child tenant creation request received",
parent_tenant_id=request.parent_tenant_id,
parent_tenant_id=tenant_id,
child_count=len(request.child_tenants),
user_id=current_user.get("user_id")
)
@@ -252,7 +253,7 @@ async def bulk_create_child_tenants(
from app.models.tenants import Tenant
tenant_repo = TenantRepository(Tenant, session)
parent_tenant = await tenant_repo.get_by_id(request.parent_tenant_id)
parent_tenant = await tenant_repo.get_by_id(tenant_id)
if not parent_tenant:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -262,7 +263,7 @@ async def bulk_create_child_tenants(
# Verify user has access to parent tenant (owners/admins only)
access_info = await tenant_service.verify_user_access(
current_user["user_id"],
request.parent_tenant_id
tenant_id
)
if not access_info.has_access or access_info.role not in ["owner", "admin"]:
raise HTTPException(
@@ -271,8 +272,8 @@ async def bulk_create_child_tenants(
)
# Verify parent is enterprise tier
parent_subscription_tier = await tenant_service.get_subscription_tier(request.parent_tenant_id)
if parent_subscription_tier != "enterprise":
parent_subscription = await tenant_service.subscription_repo.get_active_subscription(tenant_id)
if not parent_subscription or parent_subscription.plan != "enterprise":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only enterprise tier tenants can have child tenants"
@@ -290,121 +291,136 @@ async def bulk_create_child_tenants(
failed_tenants = []
for child_data in request.child_tenants:
try:
# Create child tenant
child_tenant = Tenant(
name=child_data.name,
subdomain=None, # Child tenants typically don't have subdomains
business_type=parent_tenant.business_type,
business_model="retail_bakery", # Child outlets are typically retail
address=child_data.address,
city=child_data.city,
postal_code=child_data.postal_code,
latitude=child_data.latitude,
longitude=child_data.longitude,
phone=child_data.phone or parent_tenant.phone,
email=child_data.email or parent_tenant.email,
timezone=parent_tenant.timezone,
owner_id=parent_tenant.owner_id,
parent_tenant_id=parent_tenant.id,
tenant_type="child",
hierarchy_path=f"{parent_tenant.hierarchy_path}/{str(parent_tenant.id)}",
is_active=True,
is_demo=parent_tenant.is_demo,
demo_session_id=parent_tenant.demo_session_id,
demo_expires_at=parent_tenant.demo_expires_at
)
session.add(child_tenant)
await session.flush() # Get the ID without committing
# Create TenantLocation record for the child with location_code
from app.models.tenant_location import TenantLocation
location = TenantLocation(
tenant_id=child_tenant.id,
name=child_data.name,
location_code=child_data.location_code,
city=child_data.city,
zone=child_data.zone,
address=child_data.address,
postal_code=child_data.postal_code,
latitude=child_data.latitude,
longitude=child_data.longitude,
status="ACTIVE",
is_primary=True,
enterprise_location=True,
location_type="retail"
)
session.add(location)
# Inherit subscription from parent
from app.models.tenants import Subscription
parent_subscription = await session.execute(
session.query(Subscription).filter(
Subscription.tenant_id == parent_tenant.id,
Subscription.status == "active"
).statement
)
parent_sub = parent_subscription.scalar_one_or_none()
if parent_sub:
child_subscription = Subscription(
tenant_id=child_tenant.id,
plan=parent_sub.plan,
status="active",
billing_cycle=parent_sub.billing_cycle,
price=0, # Child tenants don't pay separately
trial_ends_at=parent_sub.trial_ends_at
# Create a nested transaction (savepoint) for each child tenant
# This allows us to rollback individual child tenant creation without affecting others
async with session.begin_nested():
try:
# Create child tenant with full tenant model fields
child_tenant = Tenant(
name=child_data.name,
subdomain=None, # Child tenants typically don't have subdomains
business_type=child_data.business_type or parent_tenant.business_type,
business_model=child_data.business_model or "retail_bakery", # Child outlets are typically retail
address=child_data.address,
city=child_data.city,
postal_code=child_data.postal_code,
latitude=child_data.latitude,
longitude=child_data.longitude,
phone=child_data.phone or parent_tenant.phone,
email=child_data.email or parent_tenant.email,
timezone=child_data.timezone or parent_tenant.timezone,
owner_id=parent_tenant.owner_id,
parent_tenant_id=parent_tenant.id,
tenant_type="child",
hierarchy_path=f"{parent_tenant.hierarchy_path}", # Will be updated after flush
is_active=True,
is_demo=parent_tenant.is_demo,
demo_session_id=parent_tenant.demo_session_id,
demo_expires_at=parent_tenant.demo_expires_at,
metadata_={
"location_code": child_data.location_code,
"zone": child_data.zone,
**(child_data.metadata or {})
}
)
session.add(child_subscription)
await session.commit()
await session.refresh(child_tenant)
await session.refresh(location)
session.add(child_tenant)
await session.flush() # Get the ID without committing
# Build response
created_tenants.append(ChildTenantResponse(
id=str(child_tenant.id),
name=child_tenant.name,
subdomain=child_tenant.subdomain,
business_type=child_tenant.business_type,
business_model=child_tenant.business_model,
tenant_type=child_tenant.tenant_type,
parent_tenant_id=str(child_tenant.parent_tenant_id),
address=child_tenant.address,
city=child_tenant.city,
postal_code=child_tenant.postal_code,
phone=child_tenant.phone,
is_active=child_tenant.is_active,
subscription_plan="enterprise",
ml_model_trained=child_tenant.ml_model_trained,
last_training_date=child_tenant.last_training_date,
owner_id=str(child_tenant.owner_id),
created_at=child_tenant.created_at,
location_code=location.location_code,
zone=location.zone,
hierarchy_path=child_tenant.hierarchy_path
))
# Update hierarchy_path now that we have the child tenant ID
child_tenant.hierarchy_path = f"{parent_tenant.hierarchy_path}.{str(child_tenant.id)}"
logger.info(
"Child tenant created successfully",
child_tenant_id=str(child_tenant.id),
child_name=child_tenant.name,
location_code=child_data.location_code
)
# Create TenantLocation record for the child
from app.models.tenant_location import TenantLocation
location = TenantLocation(
tenant_id=child_tenant.id,
name=child_data.name,
city=child_data.city,
address=child_data.address,
postal_code=child_data.postal_code,
latitude=child_data.latitude,
longitude=child_data.longitude,
is_active=True,
location_type="retail"
)
session.add(location)
except Exception as child_error:
logger.error(
"Failed to create child tenant",
child_name=child_data.name,
error=str(child_error)
)
failed_tenants.append({
"name": child_data.name,
"location_code": child_data.location_code,
"error": str(child_error)
})
await session.rollback()
# Inherit subscription from parent
from app.models.tenants import Subscription
from sqlalchemy import select
parent_subscription_result = await session.execute(
select(Subscription).where(
Subscription.tenant_id == parent_tenant.id,
Subscription.status == "active"
)
)
parent_sub = parent_subscription_result.scalar_one_or_none()
if parent_sub:
child_subscription = Subscription(
tenant_id=child_tenant.id,
plan=parent_sub.plan,
status="active",
billing_cycle=parent_sub.billing_cycle,
monthly_price=0, # Child tenants don't pay separately
trial_ends_at=parent_sub.trial_ends_at
)
session.add(child_subscription)
# Commit the nested transaction (savepoint)
await session.flush()
# Refresh objects to get their final state
await session.refresh(child_tenant)
await session.refresh(location)
# Build response
created_tenants.append(ChildTenantResponse(
id=str(child_tenant.id),
name=child_tenant.name,
subdomain=child_tenant.subdomain,
business_type=child_tenant.business_type,
business_model=child_tenant.business_model,
tenant_type=child_tenant.tenant_type,
parent_tenant_id=str(child_tenant.parent_tenant_id),
address=child_tenant.address,
city=child_tenant.city,
postal_code=child_tenant.postal_code,
phone=child_tenant.phone,
is_active=child_tenant.is_active,
subscription_plan="enterprise",
ml_model_trained=child_tenant.ml_model_trained,
last_training_date=child_tenant.last_training_date,
owner_id=str(child_tenant.owner_id),
created_at=child_tenant.created_at,
location_code=child_data.location_code,
zone=child_data.zone,
hierarchy_path=child_tenant.hierarchy_path
))
logger.info(
"Child tenant created successfully",
child_tenant_id=str(child_tenant.id),
child_name=child_tenant.name,
location_code=child_data.location_code
)
except Exception as child_error:
logger.error(
"Failed to create child tenant",
child_name=child_data.name,
error=str(child_error)
)
failed_tenants.append({
"name": child_data.name,
"location_code": child_data.location_code,
"error": str(child_error)
})
# Nested transaction will automatically rollback on exception
# This only rolls back the current child tenant, not the entire batch
# Commit all successful child tenant creations
await session.commit()
# TODO: Configure distribution routes if requested
distribution_configured = False
@@ -414,7 +430,7 @@ async def bulk_create_child_tenants(
# For now, we'll skip this and just log
logger.info(
"Distribution route configuration requested",
parent_tenant_id=request.parent_tenant_id,
parent_tenant_id=tenant_id,
child_count=len(created_tenants)
)
# distribution_configured = await configure_distribution_routes(...)
@@ -426,13 +442,13 @@ async def bulk_create_child_tenants(
logger.info(
"Bulk child tenant creation completed",
parent_tenant_id=request.parent_tenant_id,
parent_tenant_id=tenant_id,
created_count=len(created_tenants),
failed_count=len(failed_tenants)
)
return BulkChildTenantsResponse(
parent_tenant_id=request.parent_tenant_id,
parent_tenant_id=tenant_id,
created_count=len(created_tenants),
failed_count=len(failed_tenants),
created_tenants=created_tenants,
@@ -445,7 +461,7 @@ async def bulk_create_child_tenants(
except Exception as e:
logger.error(
"Bulk child tenant creation failed",
parent_tenant_id=request.parent_tenant_id,
parent_tenant_id=tenant_id,
user_id=current_user.get("user_id"),
error=str(e)
)