organizations.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. """
  2. Superadmin endpoints for organization management.
  3. """
  4. from typing import Annotated
  5. from fastapi import APIRouter, Depends, HTTPException, Query, status
  6. from sqlalchemy.ext.asyncio import AsyncSession
  7. from app.api.deps import get_current_superadmin
  8. from app.core.database import get_db
  9. from app.models.user import User
  10. from app.schemas.organization import (
  11. OrganizationCreate,
  12. OrganizationListResponse,
  13. OrganizationResponse,
  14. OrganizationUpdate,
  15. )
  16. from app.services import organization_service
  17. router = APIRouter()
  18. @router.get("", response_model=OrganizationListResponse)
  19. async def list_organizations(
  20. db: Annotated[AsyncSession, Depends(get_db)],
  21. current_user: Annotated[User, Depends(get_current_superadmin)],
  22. skip: int = Query(0, ge=0, description="Number of records to skip"),
  23. limit: int = Query(100, ge=1, le=1000, description="Max records to return"),
  24. status: str | None = Query(None, description="Filter by status"),
  25. ):
  26. """
  27. List all organizations (superadmin only).
  28. Returns paginated list of organizations with optional status filter.
  29. """
  30. organizations, total = await organization_service.list_organizations(
  31. db, skip=skip, limit=limit, status=status
  32. )
  33. return OrganizationListResponse(
  34. organizations=organizations,
  35. total=total,
  36. )
  37. @router.get("/{organization_id}", response_model=OrganizationResponse)
  38. async def get_organization(
  39. organization_id: int,
  40. db: Annotated[AsyncSession, Depends(get_db)],
  41. current_user: Annotated[User, Depends(get_current_superadmin)],
  42. ):
  43. """
  44. Get organization by ID (superadmin only).
  45. """
  46. org = await organization_service.get_organization(db, organization_id)
  47. if not org:
  48. raise HTTPException(
  49. status_code=status.HTTP_404_NOT_FOUND,
  50. detail="Organization not found",
  51. )
  52. return org
  53. @router.post("", response_model=OrganizationResponse, status_code=status.HTTP_201_CREATED)
  54. async def create_organization(
  55. data: OrganizationCreate,
  56. db: Annotated[AsyncSession, Depends(get_db)],
  57. current_user: Annotated[User, Depends(get_current_superadmin)],
  58. ):
  59. """
  60. Create a new organization (superadmin only).
  61. Creates an organization with active status and specified product modules.
  62. """
  63. org = await organization_service.create_organization(db, data)
  64. return org
  65. @router.patch("/{organization_id}", response_model=OrganizationResponse)
  66. async def update_organization(
  67. organization_id: int,
  68. data: OrganizationUpdate,
  69. db: Annotated[AsyncSession, Depends(get_db)],
  70. current_user: Annotated[User, Depends(get_current_superadmin)],
  71. ):
  72. """
  73. Update organization (superadmin only).
  74. Can update organization details, status, and enable/disable product modules.
  75. """
  76. org = await organization_service.update_organization(db, organization_id, data)
  77. if not org:
  78. raise HTTPException(
  79. status_code=status.HTTP_404_NOT_FOUND,
  80. detail="Organization not found",
  81. )
  82. return org
  83. @router.delete("/{organization_id}", status_code=status.HTTP_204_NO_CONTENT)
  84. async def delete_organization(
  85. organization_id: int,
  86. db: Annotated[AsyncSession, Depends(get_db)],
  87. current_user: Annotated[User, Depends(get_current_superadmin)],
  88. ):
  89. """
  90. Delete organization (superadmin only).
  91. Warning: This will cascade delete all users and devices in the organization.
  92. """
  93. deleted = await organization_service.delete_organization(db, organization_id)
  94. if not deleted:
  95. raise HTTPException(
  96. status_code=status.HTTP_404_NOT_FOUND,
  97. detail="Organization not found",
  98. )