# app/api/v1/admin/companies.py """ Company management endpoints for admin. """ import logging from fastapi import APIRouter, Body, Depends, Path, Query from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.exceptions import CompanyHasVendorsException, ConfirmationRequiredException from app.services.company_service import company_service from models.database.user import User from models.schema.company import ( CompanyCreate, CompanyCreateResponse, CompanyDetailResponse, CompanyListResponse, CompanyResponse, CompanyUpdate, ) router = APIRouter(prefix="/companies") logger = logging.getLogger(__name__) @router.post("", response_model=CompanyCreateResponse) def create_company_with_owner( company_data: CompanyCreate, db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """ Create a new company with owner user account (Admin only). This endpoint: 1. Creates a new company record 2. Creates an owner user account with owner_email (if not exists) 3. Returns credentials (temporary password shown ONCE if new user created) **Email Fields:** - `owner_email`: Used for owner's login/authentication (stored in users.email) - `contact_email`: Public business contact (stored in companies.contact_email) Returns company details with owner credentials. """ company, owner_user, temp_password = company_service.create_company_with_owner( db, company_data ) db.commit() return CompanyCreateResponse( company=CompanyResponse( id=company.id, name=company.name, description=company.description, owner_user_id=company.owner_user_id, contact_email=company.contact_email, contact_phone=company.contact_phone, website=company.website, business_address=company.business_address, tax_number=company.tax_number, is_active=company.is_active, is_verified=company.is_verified, created_at=company.created_at.isoformat(), updated_at=company.updated_at.isoformat(), ), owner_user_id=owner_user.id, owner_username=owner_user.username, owner_email=owner_user.email, temporary_password=temp_password or "N/A (Existing user)", login_url=f"http://localhost:8000/admin/login", ) @router.get("", response_model=CompanyListResponse) def get_all_companies( skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), search: str | None = Query(None, description="Search by company name"), is_active: bool | None = Query(None), is_verified: bool | None = Query(None), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """Get all companies with filtering (Admin only).""" companies, total = company_service.get_companies( db, skip=skip, limit=limit, search=search, is_active=is_active, is_verified=is_verified, ) return CompanyListResponse( companies=[ CompanyResponse( id=c.id, name=c.name, description=c.description, owner_user_id=c.owner_user_id, contact_email=c.contact_email, contact_phone=c.contact_phone, website=c.website, business_address=c.business_address, tax_number=c.tax_number, is_active=c.is_active, is_verified=c.is_verified, created_at=c.created_at.isoformat(), updated_at=c.updated_at.isoformat(), ) for c in companies ], total=total, skip=skip, limit=limit, ) @router.get("/{company_id}", response_model=CompanyDetailResponse) def get_company_details( company_id: int = Path(..., description="Company ID"), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """ Get detailed company information including vendor counts (Admin only). """ company = company_service.get_company_by_id(db, company_id) # Count vendors vendor_count = len(company.vendors) active_vendor_count = sum(1 for v in company.vendors if v.is_active) return CompanyDetailResponse( id=company.id, name=company.name, description=company.description, owner_user_id=company.owner_user_id, contact_email=company.contact_email, contact_phone=company.contact_phone, website=company.website, business_address=company.business_address, tax_number=company.tax_number, is_active=company.is_active, is_verified=company.is_verified, created_at=company.created_at.isoformat(), updated_at=company.updated_at.isoformat(), vendor_count=vendor_count, active_vendor_count=active_vendor_count, ) @router.put("/{company_id}", response_model=CompanyResponse) def update_company( company_id: int = Path(..., description="Company ID"), company_update: CompanyUpdate = Body(...), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """ Update company information (Admin only). **Can update:** - Basic info: name, description - Business contact: contact_email, contact_phone, website - Business details: business_address, tax_number - Status: is_active, is_verified **Cannot update:** - `owner_user_id` (would require ownership transfer feature) """ company = company_service.update_company(db, company_id, company_update) db.commit() return CompanyResponse( id=company.id, name=company.name, description=company.description, owner_user_id=company.owner_user_id, contact_email=company.contact_email, contact_phone=company.contact_phone, website=company.website, business_address=company.business_address, tax_number=company.tax_number, is_active=company.is_active, is_verified=company.is_verified, created_at=company.created_at.isoformat(), updated_at=company.updated_at.isoformat(), ) @router.put("/{company_id}/verification", response_model=CompanyResponse) def toggle_company_verification( company_id: int = Path(..., description="Company ID"), verification_data: dict = Body(..., example={"is_verified": True}), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """ Toggle company verification status (Admin only). Request body: { "is_verified": true/false } """ is_verified = verification_data.get("is_verified", False) company = company_service.toggle_verification(db, company_id, is_verified) db.commit() return CompanyResponse( id=company.id, name=company.name, description=company.description, owner_user_id=company.owner_user_id, contact_email=company.contact_email, contact_phone=company.contact_phone, website=company.website, business_address=company.business_address, tax_number=company.tax_number, is_active=company.is_active, is_verified=company.is_verified, created_at=company.created_at.isoformat(), updated_at=company.updated_at.isoformat(), ) @router.put("/{company_id}/status", response_model=CompanyResponse) def toggle_company_status( company_id: int = Path(..., description="Company ID"), status_data: dict = Body(..., example={"is_active": True}), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """ Toggle company active status (Admin only). Request body: { "is_active": true/false } """ is_active = status_data.get("is_active", True) company = company_service.toggle_active(db, company_id, is_active) db.commit() return CompanyResponse( id=company.id, name=company.name, description=company.description, owner_user_id=company.owner_user_id, contact_email=company.contact_email, contact_phone=company.contact_phone, website=company.website, business_address=company.business_address, tax_number=company.tax_number, is_active=company.is_active, is_verified=company.is_verified, created_at=company.created_at.isoformat(), updated_at=company.updated_at.isoformat(), ) @router.delete("/{company_id}") def delete_company( company_id: int = Path(..., description="Company ID"), confirm: bool = Query(False, description="Must be true to confirm deletion"), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), ): """ Delete company and all associated vendors (Admin only). ⚠️ **WARNING: This is destructive and will delete:** - Company account - All vendors under this company - All products under those vendors - All orders, customers, team members Requires confirmation parameter: `confirm=true` """ if not confirm: raise ConfirmationRequiredException( operation="delete_company", message="Deletion requires confirmation parameter: confirm=true", ) # Get company to check vendor count company = company_service.get_company_by_id(db, company_id) vendor_count = len(company.vendors) if vendor_count > 0: raise CompanyHasVendorsException(company_id, vendor_count) company_service.delete_company(db, company_id) db.commit() return {"message": f"Company {company_id} deleted successfully"}