from sqlalchemy.orm import Session from sqlalchemy.exc import IntegrityError from fastapi import HTTPException, status from typing import Optional from app.models.tenant import Organization from app.models.user import User, UserRole from app.schemas.organization import OrganizationUpdate from app.services.audit import AuditService class OrganizationService: def __init__(self, db: Session): self.db = db self.audit_service = AuditService(db) def get_organization(self, organization_id: int) -> Optional[Organization]: return self.db.query(Organization).filter( Organization.id == organization_id ).first() def update_organization( self, organization_id: int, organization_update: OrganizationUpdate, current_user: User, ip_address: str, user_agent: str ) -> Organization: # Only org admins and super admins can update organization if current_user.role not in [UserRole.ORG_ADMIN, UserRole.SUPER_ADMIN]: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions to update organization" ) # Ensure user can only update their own organization if organization_id != current_user.organization_id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Cannot update different organization" ) db_org = self.get_organization(organization_id) if not db_org: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Organization not found" ) update_data = organization_update.dict(exclude_unset=True) old_values = {field: getattr(db_org, field) for field in update_data.keys()} for field, value in update_data.items(): setattr(db_org, field, value) try: self.db.commit() self.db.refresh(db_org) # Log organization update self.audit_service.log_user_activity( user=current_user, action="update", resource_type="organization", resource_id=str(db_org.id), details={ "updated_fields": list(update_data.keys()), "old_values": old_values, "new_values": update_data }, ip_address=ip_address, user_agent=user_agent ) return db_org except IntegrityError: self.db.rollback() raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Domain or subdomain already exists" ) def get_organization_stats(self, organization_id: int) -> dict: org = self.get_organization(organization_id) if not org: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Organization not found" ) # Get user count user_count = self.db.query(User).filter( User.organization_id == organization_id ).count() # Get active user count active_user_count = self.db.query(User).filter( User.organization_id == organization_id, User.is_active ).count() return { "total_users": user_count, "active_users": active_user_count, "organization_name": org.name, "organization_domain": org.domain, "created_at": org.created_at }