@cryptotaxi247 / CoPilot / commits / e6776459

Implement customer deletion functionality with appropriate response model and error handling (#545)

taylor_socfortress committed Dec 2, 2025 at 11:24 UTC e6776459fe86250013d4f5ae927b4367bbb7be43
2 files changed +65 -17
backend/app/customers/routes/customers.py
+43 -17
@@ -4,6 +4,7 @@ from fastapi import HTTPException
4 from fastapi import Query
5 from fastapi import Security
6 from loguru import logger
7 +from sqlalchemy.exc import IntegrityError
8 from sqlalchemy.ext.asyncio import AsyncSession
9 from sqlalchemy.future import select
10 from starlette.status import HTTP_401_UNAUTHORIZED
@@ -19,6 +20,7 @@ from app.customers.schema.customers import CustomerMetaResponse
20 from app.customers.schema.customers import CustomerRequestBody
21 from app.customers.schema.customers import CustomerResponse
22 from app.customers.schema.customers import CustomersResponse
23 +from app.customers.schema.customers import DeleteCustomerResponse
24 from app.db.db_session import get_db
25 from app.db.universal_models import Agents
26 from app.db.universal_models import Customers
@@ -351,14 +353,14 @@ async def update_customer(
353 # ! TODO - Add a check to ensure that the customer_code is not being used by any agents
354 @customers_router.delete(
355 "/{customer_code}",
354 - response_model=CustomerResponse,
356 + response_model=DeleteCustomerResponse,
357 description="Delete customer by customer_code",
358 dependencies=[Security(AuthHandler().require_any_scope("admin"))],
359 )
360 async def delete_customer(
361 customer_code: str,
362 session: AsyncSession = Depends(get_db),
361 -) -> CustomerResponse:
363 +) -> DeleteCustomerResponse:
364 """
365 Delete a customer by customer_code.
366
@@ -367,10 +369,10 @@ async def delete_customer(
369 session (AsyncSession, optional): The database session. Defaults to Depends(get_db).
370
371 Returns:
370 - CustomerResponse: The response containing the deleted customer data.
372 + DeleteCustomerResponse: The response containing the deletion status.
373
374 Raises:
373 - HTTPException: If the customer with the given customer_code is not found.
375 + HTTPException: If the customer with the given customer_code is not found or has associated users.
376 """
377 logger.info(f"Deleting customer with customer_code: {customer_code}")
378
@@ -385,21 +387,45 @@ async def delete_customer(
387 detail=f"Customer with customer_code {customer_code} not found",
388 )
389
388 - # Capture the customer data before deleting
389 - customer_data = CustomerRequestBody.from_orm(existing_customer)
390 + try:
391 + # Delete the customer
392 + await session.delete(existing_customer)
393 + await session.flush() # Flush to trigger any constraint violations
394 + await session.commit() # Commit the transaction
395 + await session.close() # Close the session
396 +
397 + logger.info(f"Successfully deleted customer with customer_code: {customer_code}")
398 + return DeleteCustomerResponse(
399 + success=True,
400 + message=f"Customer '{customer_code}' deleted successfully",
401 + )
402
391 - # Delete the customer
392 - await session.delete(existing_customer)
393 - await session.flush() # Optional: Flush the changes to the database
394 - await session.commit() # Commit the transaction
395 - # Close the session
396 - await session.close()
403 + except IntegrityError as e:
404 + await session.rollback()
405 + error_message = str(e.orig)
406
398 - return CustomerResponse(
399 - customer=customer_data,
400 - success=True,
401 - message="Customer deleted successfully",
402 - )
407 + # Check if it's the user_customer_access foreign key constraint
408 + if "user_customer_access" in error_message and "FOREIGN KEY" in error_message:
409 + logger.error(f"Cannot delete customer {customer_code}: users are still assigned to this customer")
410 + raise HTTPException(
411 + status_code=400,
412 + detail=f"Cannot delete customer '{customer_code}'. There are still users assigned to this customer. Please remove all user assignments before deleting the customer.",
413 + )
414 +
415 + # For other integrity errors
416 + logger.error(f"Integrity error deleting customer {customer_code}: {error_message}")
417 + raise HTTPException(
418 + status_code=400,
419 + detail="Cannot delete customer due to existing dependencies. Please ensure all related data is removed first.",
420 + )
421 +
422 + except Exception as e:
423 + await session.rollback()
424 + logger.error(f"Error deleting customer {customer_code}: {str(e)}")
425 + raise HTTPException(
426 + status_code=500,
427 + detail=f"An error occurred while deleting the customer: {str(e)}",
428 + )
429
430
431 @customers_router.post(
backend/app/customers/schema/customers.py
+22
@@ -152,3 +152,25 @@ class AgentsResponse(BaseModel):
152 agents: Optional[List[AgentModel]] = Field([], description="List of agents")
153 success: bool
154 message: str
155 +
156 +
157 +class DeleteCustomerResponse(BaseModel):
158 + """
159 + Response model for customer deletion.
160 + """
161 +
162 + success: bool
163 + message: str
164 +
165 + class Config:
166 + """
167 + Pydantic configuration class.
168 + """
169 +
170 + from_attributes = True
171 + json_schema_extra = {
172 + "example": {
173 + "success": True,
174 + "message": "Customer 'customer_code' deleted successfully",
175 + },
176 + }