""" 组织关系 API 品牌方管理代理商,代理商管理达人 """ from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func from sqlalchemy.orm import selectinload from app.database import get_db from app.models.user import User, UserRole from app.models.organization import ( Brand, Agency, Creator, brand_agency_association, agency_creator_association, ) from app.api.deps import get_current_user, get_current_brand, get_current_agency from app.schemas.organization import ( BrandSummary, AgencySummary, CreatorSummary, InviteAgencyRequest, InviteCreatorRequest, UpdateAgencyPermissionRequest, AgencyListResponse, CreatorListResponse, BrandListResponse, ) router = APIRouter(prefix="/organizations", tags=["组织关系"]) # ===== 品牌方管理代理商 ===== @router.get("/brand/agencies", response_model=AgencyListResponse) async def list_brand_agencies( brand: Brand = Depends(get_current_brand), db: AsyncSession = Depends(get_db), ): """查询品牌方的代理商列表""" result = await db.execute( select(Brand) .options(selectinload(Brand.agencies)) .where(Brand.id == brand.id) ) brand_with_agencies = result.scalar_one() items = [ AgencySummary( id=a.id, name=a.name, logo=a.logo, contact_name=a.contact_name, force_pass_enabled=a.force_pass_enabled, ) for a in brand_with_agencies.agencies ] return AgencyListResponse(items=items, total=len(items)) @router.post("/brand/agencies", status_code=status.HTTP_201_CREATED) async def invite_agency( request: InviteAgencyRequest, brand: Brand = Depends(get_current_brand), db: AsyncSession = Depends(get_db), ): """邀请代理商加入品牌方""" # 查找代理商 result = await db.execute( select(Agency).where(Agency.id == request.agency_id) ) agency = result.scalar_one_or_none() if not agency: raise HTTPException(status_code=404, detail="代理商不存在") # 检查是否已关联 brand_result = await db.execute( select(Brand) .options(selectinload(Brand.agencies)) .where(Brand.id == brand.id) ) brand_with_agencies = brand_result.scalar_one() if agency in brand_with_agencies.agencies: raise HTTPException(status_code=400, detail="该代理商已加入") brand_with_agencies.agencies.append(agency) await db.flush() return {"message": "邀请成功", "agency_id": agency.id} @router.delete("/brand/agencies/{agency_id}") async def remove_agency( agency_id: str, brand: Brand = Depends(get_current_brand), db: AsyncSession = Depends(get_db), ): """移除代理商""" brand_result = await db.execute( select(Brand) .options(selectinload(Brand.agencies)) .where(Brand.id == brand.id) ) brand_with_agencies = brand_result.scalar_one() agency_result = await db.execute( select(Agency).where(Agency.id == agency_id) ) agency = agency_result.scalar_one_or_none() if agency and agency in brand_with_agencies.agencies: brand_with_agencies.agencies.remove(agency) await db.flush() return {"message": "已移除"} @router.put("/brand/agencies/{agency_id}/permission") async def update_agency_permission( agency_id: str, request: UpdateAgencyPermissionRequest, brand: Brand = Depends(get_current_brand), db: AsyncSession = Depends(get_db), ): """更新代理商权限(如强制通过权)""" # 验证代理商是否属于该品牌 brand_result = await db.execute( select(Brand) .options(selectinload(Brand.agencies)) .where(Brand.id == brand.id) ) brand_with_agencies = brand_result.scalar_one() agency_result = await db.execute( select(Agency).where(Agency.id == agency_id) ) agency = agency_result.scalar_one_or_none() if not agency or agency not in brand_with_agencies.agencies: raise HTTPException(status_code=404, detail="代理商不存在或未加入") agency.force_pass_enabled = request.force_pass_enabled await db.flush() return {"message": "权限已更新"} # ===== 代理商管理达人 ===== @router.get("/agency/creators", response_model=CreatorListResponse) async def list_agency_creators( agency: Agency = Depends(get_current_agency), db: AsyncSession = Depends(get_db), ): """查询代理商的达人列表""" result = await db.execute( select(Agency) .options(selectinload(Agency.creators)) .where(Agency.id == agency.id) ) agency_with_creators = result.scalar_one() items = [ CreatorSummary( id=c.id, name=c.name, avatar=c.avatar, douyin_account=c.douyin_account, xiaohongshu_account=c.xiaohongshu_account, bilibili_account=c.bilibili_account, ) for c in agency_with_creators.creators ] return CreatorListResponse(items=items, total=len(items)) @router.post("/agency/creators", status_code=status.HTTP_201_CREATED) async def invite_creator( request: InviteCreatorRequest, agency: Agency = Depends(get_current_agency), db: AsyncSession = Depends(get_db), ): """邀请达人加入代理商""" result = await db.execute( select(Creator).where(Creator.id == request.creator_id) ) creator = result.scalar_one_or_none() if not creator: raise HTTPException(status_code=404, detail="达人不存在") agency_result = await db.execute( select(Agency) .options(selectinload(Agency.creators)) .where(Agency.id == agency.id) ) agency_with_creators = agency_result.scalar_one() if creator in agency_with_creators.creators: raise HTTPException(status_code=400, detail="该达人已加入") agency_with_creators.creators.append(creator) await db.flush() return {"message": "邀请成功", "creator_id": creator.id} @router.delete("/agency/creators/{creator_id}") async def remove_creator( creator_id: str, agency: Agency = Depends(get_current_agency), db: AsyncSession = Depends(get_db), ): """移除达人""" agency_result = await db.execute( select(Agency) .options(selectinload(Agency.creators)) .where(Agency.id == agency.id) ) agency_with_creators = agency_result.scalar_one() creator_result = await db.execute( select(Creator).where(Creator.id == creator_id) ) creator = creator_result.scalar_one_or_none() if creator and creator in agency_with_creators.creators: agency_with_creators.creators.remove(creator) await db.flush() return {"message": "已移除"} # ===== 代理商查看关联品牌方 ===== @router.get("/agency/brands", response_model=BrandListResponse) async def list_agency_brands( agency: Agency = Depends(get_current_agency), db: AsyncSession = Depends(get_db), ): """查询代理商关联的品牌方列表""" result = await db.execute( select(Agency) .options(selectinload(Agency.brands)) .where(Agency.id == agency.id) ) agency_with_brands = result.scalar_one() items = [ BrandSummary( id=b.id, name=b.name, logo=b.logo, contact_name=b.contact_name, ) for b in agency_with_brands.brands ] return BrandListResponse(items=items, total=len(items)) # ===== 搜索(用于邀请时查找) ===== @router.get("/search/agencies") async def search_agencies( keyword: str = Query(..., min_length=1), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """搜索代理商(用于邀请)""" result = await db.execute( select(Agency) .where(Agency.name.ilike(f"%{keyword}%")) .limit(20) ) agencies = list(result.scalars().all()) return { "items": [ AgencySummary( id=a.id, name=a.name, logo=a.logo, contact_name=a.contact_name, force_pass_enabled=a.force_pass_enabled, ).model_dump() for a in agencies ] } @router.get("/search/creators") async def search_creators( keyword: str = Query(..., min_length=1), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """搜索达人(用于邀请)""" result = await db.execute( select(Creator) .where(Creator.name.ilike(f"%{keyword}%")) .limit(20) ) creators = list(result.scalars().all()) return { "items": [ CreatorSummary( id=c.id, name=c.name, avatar=c.avatar, douyin_account=c.douyin_account, xiaohongshu_account=c.xiaohongshu_account, bilibili_account=c.bilibili_account, ).model_dump() for c in creators ] }