- Reformatted function signatures in `organization_service.py` and `task_service.py` for better alignment. - Updated import statements across multiple files for consistency and organization. - Enhanced test files by improving formatting and ensuring consistent use of async session factories. - Added type hints and improved type safety in various service and test files. - Adjusted `pyproject.toml` to include configuration for isort, mypy, and ruff for better code quality checks. - Cleaned up unused imports and organized existing ones in several test files.
This commit is contained in:
+9
-4
@@ -1,9 +1,11 @@
|
||||
"""Reusable FastAPI dependencies."""
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, Header, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
from redis.asyncio.client import Redis
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.cache import get_cache_client
|
||||
@@ -18,9 +20,9 @@ from app.repositories.deal_repo import DealRepository
|
||||
from app.repositories.org_repo import OrganizationRepository
|
||||
from app.repositories.task_repo import TaskRepository
|
||||
from app.repositories.user_repo import UserRepository
|
||||
from app.services.activity_service import ActivityService
|
||||
from app.services.analytics_service import AnalyticsService
|
||||
from app.services.auth_service import AuthService
|
||||
from app.services.activity_service import ActivityService
|
||||
from app.services.contact_service import ContactService
|
||||
from app.services.deal_service import DealService
|
||||
from app.services.organization_service import (
|
||||
@@ -30,7 +32,6 @@ from app.services.organization_service import (
|
||||
OrganizationService,
|
||||
)
|
||||
from app.services.task_service import TaskService
|
||||
from redis.asyncio.client import Redis
|
||||
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.api_v1_prefix}/auth/token")
|
||||
|
||||
@@ -45,7 +46,9 @@ def get_user_repository(session: AsyncSession = Depends(get_db_session)) -> User
|
||||
return UserRepository(session=session)
|
||||
|
||||
|
||||
def get_organization_repository(session: AsyncSession = Depends(get_db_session)) -> OrganizationRepository:
|
||||
def get_organization_repository(
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
) -> OrganizationRepository:
|
||||
return OrganizationRepository(session=session)
|
||||
|
||||
|
||||
@@ -65,7 +68,9 @@ def get_activity_repository(session: AsyncSession = Depends(get_db_session)) ->
|
||||
return ActivityRepository(session=session)
|
||||
|
||||
|
||||
def get_analytics_repository(session: AsyncSession = Depends(get_db_session)) -> AnalyticsRepository:
|
||||
def get_analytics_repository(
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
) -> AnalyticsRepository:
|
||||
return AnalyticsRepository(session=session)
|
||||
|
||||
|
||||
|
||||
+8
-7
@@ -1,14 +1,15 @@
|
||||
"""Root API router that aggregates versioned routers."""
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.api.v1 import (
|
||||
activities,
|
||||
analytics,
|
||||
auth,
|
||||
contacts,
|
||||
deals,
|
||||
organizations,
|
||||
tasks,
|
||||
activities,
|
||||
analytics,
|
||||
auth,
|
||||
contacts,
|
||||
deals,
|
||||
organizations,
|
||||
tasks,
|
||||
)
|
||||
from app.core.config import settings
|
||||
|
||||
|
||||
+15
-14
@@ -1,20 +1,21 @@
|
||||
"""Version 1 API routers."""
|
||||
|
||||
from . import (
|
||||
activities,
|
||||
analytics,
|
||||
auth,
|
||||
contacts,
|
||||
deals,
|
||||
organizations,
|
||||
tasks,
|
||||
activities,
|
||||
analytics,
|
||||
auth,
|
||||
contacts,
|
||||
deals,
|
||||
organizations,
|
||||
tasks,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"activities",
|
||||
"analytics",
|
||||
"auth",
|
||||
"contacts",
|
||||
"deals",
|
||||
"organizations",
|
||||
"tasks",
|
||||
"activities",
|
||||
"analytics",
|
||||
"auth",
|
||||
"contacts",
|
||||
"deals",
|
||||
"organizations",
|
||||
"tasks",
|
||||
]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Activity timeline endpoints and payload schemas."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Analytics API endpoints for summaries and funnels."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
@@ -16,6 +17,7 @@ def _decimal_to_str(value: Decimal) -> str:
|
||||
normalized = value.normalize()
|
||||
return format(normalized, "f")
|
||||
|
||||
|
||||
router = APIRouter(prefix="/analytics", tags=["analytics"])
|
||||
|
||||
|
||||
@@ -92,4 +94,6 @@ async def deals_funnel(
|
||||
"""Return funnel breakdown by stages and statuses."""
|
||||
|
||||
breakdowns: list[StageBreakdown] = await service.get_deal_funnel(context.organization_id)
|
||||
return DealFunnelResponse(stages=[StageBreakdownModel.model_validate(item) for item in breakdowns])
|
||||
return DealFunnelResponse(
|
||||
stages=[StageBreakdownModel.model_validate(item) for item in breakdowns]
|
||||
)
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
"""Authentication API endpoints and payloads."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, EmailStr
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from pydantic import BaseModel, EmailStr
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
@@ -41,7 +42,7 @@ async def register_user(
|
||||
organization: Organization | None = None
|
||||
if payload.organization_name:
|
||||
existing_org = await repo.session.scalar(
|
||||
select(Organization).where(Organization.name == payload.organization_name)
|
||||
select(Organization).where(Organization.name == payload.organization_name),
|
||||
)
|
||||
if existing_org is not None:
|
||||
raise HTTPException(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Contact API endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
@@ -81,7 +82,9 @@ async def create_contact(
|
||||
context: OrganizationContext = Depends(get_organization_context),
|
||||
service: ContactService = Depends(get_contact_service),
|
||||
) -> ContactRead:
|
||||
data = payload.to_domain(organization_id=context.organization_id, fallback_owner=context.user_id)
|
||||
data = payload.to_domain(
|
||||
organization_id=context.organization_id, fallback_owner=context.user_id
|
||||
)
|
||||
try:
|
||||
contact = await service.create_contact(data, context=context)
|
||||
except ContactForbiddenError as exc:
|
||||
|
||||
+8
-3
@@ -1,4 +1,5 @@
|
||||
"""Deal API endpoints backed by DealService with inline payload schemas."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
@@ -8,7 +9,7 @@ from pydantic import BaseModel
|
||||
|
||||
from app.api.deps import get_deal_repository, get_deal_service, get_organization_context
|
||||
from app.models.deal import DealCreate, DealRead, DealStage, DealStatus
|
||||
from app.repositories.deal_repo import DealRepository, DealAccessError, DealQueryParams
|
||||
from app.repositories.deal_repo import DealAccessError, DealQueryParams, DealRepository
|
||||
from app.services.deal_service import (
|
||||
DealService,
|
||||
DealStageTransitionError,
|
||||
@@ -66,7 +67,9 @@ async def list_deals(
|
||||
statuses_value = [DealStatus(value) for value in status_filter] if status_filter else None
|
||||
stage_value = DealStage(stage) if stage else None
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid deal filter") from exc
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid deal filter"
|
||||
) from exc
|
||||
|
||||
params = DealQueryParams(
|
||||
organization_id=context.organization_id,
|
||||
@@ -96,7 +99,9 @@ async def create_deal(
|
||||
) -> DealRead:
|
||||
"""Create a new deal within the current organization."""
|
||||
|
||||
data = payload.to_domain(organization_id=context.organization_id, fallback_owner=context.user_id)
|
||||
data = payload.to_domain(
|
||||
organization_id=context.organization_id, fallback_owner=context.user_id
|
||||
)
|
||||
try:
|
||||
deal = await service.create_deal(data, context=context)
|
||||
except DealAccessError as exc:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Organization-related API endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Task API endpoints with inline schemas."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime, time, timezone
|
||||
|
||||
Reference in New Issue
Block a user