style: apply black and isort formatting across entire codebase
- Standardize quote style (single to double quotes) - Reorder and group imports alphabetically - Fix line breaks and indentation for consistency - Apply PEP 8 formatting standards Also updated Makefile to exclude both venv and .venv from code quality checks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
193
app/api/v1/vendor/team.py
vendored
193
app/api/v1/vendor/team.py
vendored
@@ -12,35 +12,24 @@ Implements complete team management with:
|
||||
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import (get_current_vendor_api, get_user_permissions,
|
||||
require_vendor_owner, require_vendor_permission)
|
||||
from app.core.database import get_db
|
||||
from app.core.permissions import VendorPermissions
|
||||
from app.api.deps import (
|
||||
get_current_vendor_api,
|
||||
require_vendor_owner,
|
||||
require_vendor_permission,
|
||||
get_user_permissions
|
||||
)
|
||||
from app.services.vendor_team_service import vendor_team_service
|
||||
from models.database.user import User
|
||||
from models.database.vendor import Vendor
|
||||
from models.schema.team import (
|
||||
TeamMemberInvite,
|
||||
TeamMemberUpdate,
|
||||
TeamMemberResponse,
|
||||
TeamMemberListResponse,
|
||||
InvitationAccept,
|
||||
InvitationResponse,
|
||||
InvitationAcceptResponse,
|
||||
RoleResponse,
|
||||
RoleListResponse,
|
||||
UserPermissionsResponse,
|
||||
TeamStatistics,
|
||||
BulkRemoveRequest,
|
||||
BulkRemoveResponse,
|
||||
)
|
||||
from models.schema.team import (BulkRemoveRequest, BulkRemoveResponse,
|
||||
InvitationAccept, InvitationAcceptResponse,
|
||||
InvitationResponse, RoleListResponse,
|
||||
RoleResponse, TeamMemberInvite,
|
||||
TeamMemberListResponse, TeamMemberResponse,
|
||||
TeamMemberUpdate, TeamStatistics,
|
||||
UserPermissionsResponse)
|
||||
|
||||
router = APIRouter(prefix="/team")
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -50,14 +39,15 @@ logger = logging.getLogger(__name__)
|
||||
# Team Member Routes
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/members", response_model=TeamMemberListResponse)
|
||||
def list_team_members(
|
||||
request: Request,
|
||||
include_inactive: bool = False,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_permission(
|
||||
VendorPermissions.TEAM_VIEW.value
|
||||
))
|
||||
request: Request,
|
||||
include_inactive: bool = False,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(
|
||||
require_vendor_permission(VendorPermissions.TEAM_VIEW.value)
|
||||
),
|
||||
):
|
||||
"""
|
||||
Get all team members for current vendor.
|
||||
@@ -74,9 +64,7 @@ def list_team_members(
|
||||
vendor = request.state.vendor
|
||||
|
||||
members = vendor_team_service.get_team_members(
|
||||
db=db,
|
||||
vendor=vendor,
|
||||
include_inactive=include_inactive
|
||||
db=db, vendor=vendor, include_inactive=include_inactive
|
||||
)
|
||||
|
||||
# Calculate statistics
|
||||
@@ -90,19 +78,16 @@ def list_team_members(
|
||||
)
|
||||
|
||||
return TeamMemberListResponse(
|
||||
members=members,
|
||||
total=total,
|
||||
active_count=active,
|
||||
pending_invitations=pending
|
||||
members=members, total=total, active_count=active, pending_invitations=pending
|
||||
)
|
||||
|
||||
|
||||
@router.post("/invite", response_model=InvitationResponse)
|
||||
def invite_team_member(
|
||||
invitation: TeamMemberInvite,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner) # Owner only
|
||||
invitation: TeamMemberInvite,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner), # Owner only
|
||||
):
|
||||
"""
|
||||
Invite a new team member to the vendor.
|
||||
@@ -135,7 +120,7 @@ def invite_team_member(
|
||||
vendor=vendor,
|
||||
inviter=current_user,
|
||||
email=invitation.email,
|
||||
role_id=invitation.role_id
|
||||
role_id=invitation.role_id,
|
||||
)
|
||||
elif invitation.role_name:
|
||||
# Use role name with optional custom permissions
|
||||
@@ -145,7 +130,7 @@ def invite_team_member(
|
||||
inviter=current_user,
|
||||
email=invitation.email,
|
||||
role_name=invitation.role_name,
|
||||
custom_permissions=invitation.custom_permissions
|
||||
custom_permissions=invitation.custom_permissions,
|
||||
)
|
||||
else:
|
||||
# Default to Staff role
|
||||
@@ -154,7 +139,7 @@ def invite_team_member(
|
||||
vendor=vendor,
|
||||
inviter=current_user,
|
||||
email=invitation.email,
|
||||
role_name="staff"
|
||||
role_name="staff",
|
||||
)
|
||||
|
||||
logger.info(
|
||||
@@ -166,15 +151,12 @@ def invite_team_member(
|
||||
message="Invitation sent successfully",
|
||||
email=result["email"],
|
||||
role=result["role"],
|
||||
invitation_sent=True
|
||||
invitation_sent=True,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/accept-invitation", response_model=InvitationAcceptResponse)
|
||||
def accept_invitation(
|
||||
acceptance: InvitationAccept,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
def accept_invitation(acceptance: InvitationAccept, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Accept a team invitation and activate account.
|
||||
|
||||
@@ -196,7 +178,7 @@ def accept_invitation(
|
||||
invitation_token=acceptance.invitation_token,
|
||||
password=acceptance.password,
|
||||
first_name=acceptance.first_name,
|
||||
last_name=acceptance.last_name
|
||||
last_name=acceptance.last_name,
|
||||
)
|
||||
|
||||
logger.info(
|
||||
@@ -210,26 +192,26 @@ def accept_invitation(
|
||||
"id": result["vendor"].id,
|
||||
"vendor_code": result["vendor"].vendor_code,
|
||||
"name": result["vendor"].name,
|
||||
"subdomain": result["vendor"].subdomain
|
||||
"subdomain": result["vendor"].subdomain,
|
||||
},
|
||||
user={
|
||||
"id": result["user"].id,
|
||||
"email": result["user"].email,
|
||||
"username": result["user"].username,
|
||||
"full_name": result["user"].full_name
|
||||
"full_name": result["user"].full_name,
|
||||
},
|
||||
role=result["role"]
|
||||
role=result["role"],
|
||||
)
|
||||
|
||||
|
||||
@router.get("/members/{user_id}", response_model=TeamMemberResponse)
|
||||
def get_team_member(
|
||||
user_id: int,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_permission(
|
||||
VendorPermissions.TEAM_VIEW.value
|
||||
))
|
||||
user_id: int,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(
|
||||
require_vendor_permission(VendorPermissions.TEAM_VIEW.value)
|
||||
),
|
||||
):
|
||||
"""
|
||||
Get details of a specific team member.
|
||||
@@ -239,14 +221,13 @@ def get_team_member(
|
||||
vendor = request.state.vendor
|
||||
|
||||
members = vendor_team_service.get_team_members(
|
||||
db=db,
|
||||
vendor=vendor,
|
||||
include_inactive=True
|
||||
db=db, vendor=vendor, include_inactive=True
|
||||
)
|
||||
|
||||
member = next((m for m in members if m["id"] == user_id), None)
|
||||
if not member:
|
||||
from app.exceptions import UserNotFoundException
|
||||
|
||||
raise UserNotFoundException(str(user_id))
|
||||
|
||||
return TeamMemberResponse(**member)
|
||||
@@ -254,11 +235,11 @@ def get_team_member(
|
||||
|
||||
@router.put("/members/{user_id}", response_model=TeamMemberResponse)
|
||||
def update_team_member(
|
||||
user_id: int,
|
||||
update_data: TeamMemberUpdate,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner) # Owner only
|
||||
user_id: int,
|
||||
update_data: TeamMemberUpdate,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner), # Owner only
|
||||
):
|
||||
"""
|
||||
Update a team member's role or status.
|
||||
@@ -280,7 +261,7 @@ def update_team_member(
|
||||
vendor=vendor,
|
||||
user_id=user_id,
|
||||
new_role_id=update_data.role_id,
|
||||
is_active=update_data.is_active
|
||||
is_active=update_data.is_active,
|
||||
)
|
||||
|
||||
logger.info(
|
||||
@@ -297,10 +278,10 @@ def update_team_member(
|
||||
|
||||
@router.delete("/members/{user_id}")
|
||||
def remove_team_member(
|
||||
user_id: int,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner) # Owner only
|
||||
user_id: int,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner), # Owner only
|
||||
):
|
||||
"""
|
||||
Remove a team member from the vendor.
|
||||
@@ -316,29 +297,22 @@ def remove_team_member(
|
||||
"""
|
||||
vendor = request.state.vendor
|
||||
|
||||
vendor_team_service.remove_team_member(
|
||||
db=db,
|
||||
vendor=vendor,
|
||||
user_id=user_id
|
||||
)
|
||||
vendor_team_service.remove_team_member(db=db, vendor=vendor, user_id=user_id)
|
||||
|
||||
logger.info(
|
||||
f"Team member removed: {user_id} from {vendor.vendor_code} "
|
||||
f"by {current_user.username}"
|
||||
)
|
||||
|
||||
return {
|
||||
"message": "Team member removed successfully",
|
||||
"user_id": user_id
|
||||
}
|
||||
return {"message": "Team member removed successfully", "user_id": user_id}
|
||||
|
||||
|
||||
@router.post("/members/bulk-remove", response_model=BulkRemoveResponse)
|
||||
def bulk_remove_team_members(
|
||||
bulk_remove: BulkRemoveRequest,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner)
|
||||
bulk_remove: BulkRemoveRequest,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_owner),
|
||||
):
|
||||
"""
|
||||
Remove multiple team members at once.
|
||||
@@ -354,17 +328,12 @@ def bulk_remove_team_members(
|
||||
for user_id in bulk_remove.user_ids:
|
||||
try:
|
||||
vendor_team_service.remove_team_member(
|
||||
db=db,
|
||||
vendor=vendor,
|
||||
user_id=user_id
|
||||
db=db, vendor=vendor, user_id=user_id
|
||||
)
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
failed_count += 1
|
||||
errors.append({
|
||||
"user_id": user_id,
|
||||
"error": str(e)
|
||||
})
|
||||
errors.append({"user_id": user_id, "error": str(e)})
|
||||
|
||||
logger.info(
|
||||
f"Bulk remove completed: {success_count} removed, {failed_count} failed "
|
||||
@@ -372,9 +341,7 @@ def bulk_remove_team_members(
|
||||
)
|
||||
|
||||
return BulkRemoveResponse(
|
||||
success_count=success_count,
|
||||
failed_count=failed_count,
|
||||
errors=errors
|
||||
success_count=success_count, failed_count=failed_count, errors=errors
|
||||
)
|
||||
|
||||
|
||||
@@ -382,13 +349,14 @@ def bulk_remove_team_members(
|
||||
# Role Management Routes
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/roles", response_model=RoleListResponse)
|
||||
def list_roles(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_permission(
|
||||
VendorPermissions.TEAM_VIEW.value
|
||||
))
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(
|
||||
require_vendor_permission(VendorPermissions.TEAM_VIEW.value)
|
||||
),
|
||||
):
|
||||
"""
|
||||
Get all available roles for the vendor.
|
||||
@@ -403,21 +371,19 @@ def list_roles(
|
||||
|
||||
roles = vendor_team_service.get_vendor_roles(db=db, vendor_id=vendor.id)
|
||||
|
||||
return RoleListResponse(
|
||||
roles=roles,
|
||||
total=len(roles)
|
||||
)
|
||||
return RoleListResponse(roles=roles, total=len(roles))
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Permission Routes
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/me/permissions", response_model=UserPermissionsResponse)
|
||||
def get_my_permissions(
|
||||
request: Request,
|
||||
permissions: List[str] = Depends(get_user_permissions),
|
||||
current_user: User = Depends(get_current_vendor_api)
|
||||
request: Request,
|
||||
permissions: List[str] = Depends(get_user_permissions),
|
||||
current_user: User = Depends(get_current_vendor_api),
|
||||
):
|
||||
"""
|
||||
Get current user's permissions in this vendor.
|
||||
@@ -443,7 +409,7 @@ def get_my_permissions(
|
||||
permissions=permissions,
|
||||
permission_count=len(permissions),
|
||||
is_owner=is_owner,
|
||||
role_name=role_name
|
||||
role_name=role_name,
|
||||
)
|
||||
|
||||
|
||||
@@ -451,13 +417,14 @@ def get_my_permissions(
|
||||
# Statistics Routes
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/statistics", response_model=TeamStatistics)
|
||||
def get_team_statistics(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_vendor_permission(
|
||||
VendorPermissions.TEAM_VIEW.value
|
||||
))
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(
|
||||
require_vendor_permission(VendorPermissions.TEAM_VIEW.value)
|
||||
),
|
||||
):
|
||||
"""
|
||||
Get team statistics for the vendor.
|
||||
@@ -474,9 +441,7 @@ def get_team_statistics(
|
||||
vendor = request.state.vendor
|
||||
|
||||
members = vendor_team_service.get_team_members(
|
||||
db=db,
|
||||
vendor=vendor,
|
||||
include_inactive=True
|
||||
db=db, vendor=vendor, include_inactive=True
|
||||
)
|
||||
|
||||
# Calculate statistics
|
||||
@@ -500,5 +465,5 @@ def get_team_statistics(
|
||||
pending_invitations=pending,
|
||||
owners=owners,
|
||||
team_members=team_members,
|
||||
roles_breakdown=roles_breakdown
|
||||
roles_breakdown=roles_breakdown,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user