Improve the frontend modals

This commit is contained in:
Urtzi Alfaro
2025-10-27 16:33:26 +01:00
parent 61376b7a9f
commit 858d985c92
143 changed files with 9289 additions and 2306 deletions

View File

@@ -15,7 +15,7 @@ from app.services.supplier_service import SupplierService
from app.models.suppliers import SupplierPriceList
from app.schemas.suppliers import (
SupplierCreate, SupplierUpdate, SupplierResponse, SupplierSummary,
SupplierSearchParams
SupplierSearchParams, SupplierDeletionSummary
)
from shared.auth.decorators import get_current_user_dep
from shared.routing import RouteBuilder
@@ -30,7 +30,7 @@ router = APIRouter(tags=["suppliers"])
logger = structlog.get_logger()
audit_logger = create_audit_logger("suppliers-service")
@router.post(route_builder.build_base_route("suppliers"), response_model=SupplierResponse)
@router.post(route_builder.build_base_route(""), response_model=SupplierResponse)
@require_user_role(['admin', 'owner', 'member'])
async def create_supplier(
supplier_data: SupplierCreate,
@@ -41,10 +41,15 @@ async def create_supplier(
"""Create a new supplier"""
try:
service = SupplierService(db)
# Get user role from current_user dict
user_role = current_user.get("role", "member").lower()
supplier = await service.create_supplier(
tenant_id=UUID(tenant_id),
supplier_data=supplier_data,
created_by=current_user.user_id
created_by=current_user["user_id"],
created_by_role=user_role
)
return SupplierResponse.from_orm(supplier)
except ValueError as e:
@@ -54,7 +59,7 @@ async def create_supplier(
raise HTTPException(status_code=500, detail="Failed to create supplier")
@router.get(route_builder.build_base_route("suppliers"), response_model=List[SupplierSummary])
@router.get(route_builder.build_base_route(""), response_model=List[SupplierSummary])
async def list_suppliers(
tenant_id: str = Path(..., description="Tenant ID"),
search_term: Optional[str] = Query(None, description="Search term"),
@@ -84,7 +89,7 @@ async def list_suppliers(
raise HTTPException(status_code=500, detail="Failed to retrieve suppliers")
@router.get(route_builder.build_resource_detail_route("suppliers", "supplier_id"), response_model=SupplierResponse)
@router.get(route_builder.build_resource_detail_route("", "supplier_id"), response_model=SupplierResponse)
async def get_supplier(
supplier_id: UUID = Path(..., description="Supplier ID"),
tenant_id: str = Path(..., description="Tenant ID"),
@@ -106,7 +111,7 @@ async def get_supplier(
raise HTTPException(status_code=500, detail="Failed to retrieve supplier")
@router.put(route_builder.build_resource_detail_route("suppliers", "supplier_id"), response_model=SupplierResponse)
@router.put(route_builder.build_resource_detail_route("", "supplier_id"), response_model=SupplierResponse)
@require_user_role(['admin', 'owner', 'member'])
async def update_supplier(
supplier_data: SupplierUpdate,
@@ -126,7 +131,7 @@ async def update_supplier(
supplier = await service.update_supplier(
supplier_id=supplier_id,
supplier_data=supplier_data,
updated_by=current_user.user_id
updated_by=current_user["user_id"]
)
if not supplier:
@@ -142,7 +147,7 @@ async def update_supplier(
raise HTTPException(status_code=500, detail="Failed to update supplier")
@router.delete(route_builder.build_resource_detail_route("suppliers", "supplier_id"))
@router.delete(route_builder.build_resource_detail_route("", "supplier_id"))
@require_user_role(['admin', 'owner'])
async def delete_supplier(
supplier_id: UUID = Path(..., description="Supplier ID"),
@@ -207,6 +212,77 @@ async def delete_supplier(
raise HTTPException(status_code=500, detail="Failed to delete supplier")
@router.delete(
route_builder.build_resource_action_route("", "supplier_id", "hard"),
response_model=SupplierDeletionSummary
)
@require_user_role(['admin', 'owner'])
async def hard_delete_supplier(
supplier_id: UUID = Path(..., description="Supplier ID"),
tenant_id: str = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
"""Hard delete supplier and all associated data (Admin/Owner only, permanent)"""
try:
service = SupplierService(db)
# Check supplier exists
existing_supplier = await service.get_supplier(supplier_id)
if not existing_supplier:
raise HTTPException(status_code=404, detail="Supplier not found")
# Capture supplier data before deletion
supplier_data = {
"id": str(existing_supplier.id),
"name": existing_supplier.name,
"status": existing_supplier.status.value,
"supplier_code": existing_supplier.supplier_code
}
# Perform hard deletion
deletion_summary = await service.hard_delete_supplier(supplier_id, UUID(tenant_id))
# Log audit event for hard deletion
try:
# Get sync db session for audit logging
from app.core.database import SessionLocal
sync_db = SessionLocal()
try:
await audit_logger.log_deletion(
db_session=sync_db,
tenant_id=tenant_id,
user_id=current_user["user_id"],
resource_type="supplier",
resource_id=str(supplier_id),
resource_data=supplier_data,
description=f"Hard deleted supplier '{supplier_data['name']}' and all associated data",
endpoint=f"/suppliers/{supplier_id}/hard",
method="DELETE",
metadata=deletion_summary
)
sync_db.commit()
finally:
sync_db.close()
except Exception as audit_error:
logger.warning("Failed to log audit event", error=str(audit_error))
logger.info("Hard deleted supplier",
supplier_id=str(supplier_id),
tenant_id=tenant_id,
user_id=current_user["user_id"],
deletion_summary=deletion_summary)
return deletion_summary
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except HTTPException:
raise
except Exception as e:
logger.error("Error hard deleting supplier", supplier_id=str(supplier_id), error=str(e))
raise HTTPException(status_code=500, detail="Failed to hard delete supplier")
@router.get(
route_builder.build_base_route("count"),
response_model=dict
@@ -237,7 +313,7 @@ async def count_suppliers(
@router.get(
route_builder.build_resource_action_route("suppliers", "supplier_id", "products"),
route_builder.build_resource_action_route("", "supplier_id", "products"),
response_model=List[Dict[str, Any]]
)
async def get_supplier_products(