Improve the frontend 3
This commit is contained in:
@@ -455,3 +455,174 @@ async def resolve_or_create_products_batch(
|
||||
logger.error("Batch product resolution failed",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
raise HTTPException(status_code=500, detail=f"Batch resolution failed: {str(e)}")
|
||||
|
||||
|
||||
# ================================================================
|
||||
# NEW: BATCH API ENDPOINTS FOR ORCHESTRATOR
|
||||
# ================================================================
|
||||
|
||||
class BatchIngredientsRequest(BaseModel):
|
||||
"""Request for batch ingredient fetching"""
|
||||
ingredient_ids: List[UUID] = Field(..., description="List of ingredient IDs to fetch")
|
||||
|
||||
|
||||
class BatchIngredientsResponse(BaseModel):
|
||||
"""Response with ingredient data"""
|
||||
ingredients: List[Dict[str, Any]] = Field(..., description="List of ingredient data")
|
||||
found_count: int = Field(..., description="Number of ingredients found")
|
||||
missing_ids: List[str] = Field(default_factory=list, description="IDs not found")
|
||||
|
||||
|
||||
@router.post(
|
||||
route_builder.build_operations_route("ingredients/batch"),
|
||||
response_model=BatchIngredientsResponse
|
||||
)
|
||||
async def get_ingredients_batch(
|
||||
request: BatchIngredientsRequest,
|
||||
tenant_id: UUID = Path(..., description="Tenant ID"),
|
||||
current_user: Dict[str, Any] = Depends(get_current_user_dep),
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Fetch multiple ingredients in a single request (for Orchestrator).
|
||||
|
||||
This endpoint reduces N API calls to 1, improving performance when
|
||||
the orchestrator needs ingredient data for production/procurement planning.
|
||||
"""
|
||||
try:
|
||||
if not request.ingredient_ids:
|
||||
return BatchIngredientsResponse(
|
||||
ingredients=[],
|
||||
found_count=0,
|
||||
missing_ids=[]
|
||||
)
|
||||
|
||||
service = InventoryService()
|
||||
ingredients = []
|
||||
found_ids = set()
|
||||
|
||||
for ingredient_id in request.ingredient_ids:
|
||||
try:
|
||||
ingredient = await service.get_ingredient_by_id(ingredient_id, tenant_id, db)
|
||||
if ingredient:
|
||||
ingredients.append({
|
||||
'id': str(ingredient.id),
|
||||
'name': ingredient.name,
|
||||
'type': ingredient.type,
|
||||
'unit': ingredient.unit,
|
||||
'current_stock': float(ingredient.current_stock) if ingredient.current_stock else 0,
|
||||
'reorder_point': float(ingredient.reorder_point) if ingredient.reorder_point else 0,
|
||||
'cost_per_unit': float(ingredient.cost_per_unit) if ingredient.cost_per_unit else 0,
|
||||
'category': ingredient.category,
|
||||
'is_active': ingredient.is_active,
|
||||
'shelf_life_days': ingredient.shelf_life_days
|
||||
})
|
||||
found_ids.add(str(ingredient_id))
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"Failed to fetch ingredient in batch",
|
||||
ingredient_id=str(ingredient_id),
|
||||
error=str(e)
|
||||
)
|
||||
continue
|
||||
|
||||
missing_ids = [str(id) for id in request.ingredient_ids if str(id) not in found_ids]
|
||||
|
||||
logger.info(
|
||||
"Batch ingredient fetch complete",
|
||||
requested=len(request.ingredient_ids),
|
||||
found=len(ingredients),
|
||||
missing=len(missing_ids),
|
||||
tenant_id=str(tenant_id)
|
||||
)
|
||||
|
||||
return BatchIngredientsResponse(
|
||||
ingredients=ingredients,
|
||||
found_count=len(ingredients),
|
||||
missing_ids=missing_ids
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
"Batch ingredient fetch failed",
|
||||
error=str(e),
|
||||
tenant_id=str(tenant_id)
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Batch ingredient fetch failed: {str(e)}"
|
||||
)
|
||||
|
||||
|
||||
class BatchStockLevelsRequest(BaseModel):
|
||||
"""Request for batch stock level fetching"""
|
||||
ingredient_ids: List[UUID] = Field(..., description="List of ingredient IDs")
|
||||
|
||||
|
||||
class BatchStockLevelsResponse(BaseModel):
|
||||
"""Response with stock level data"""
|
||||
stock_levels: Dict[str, float] = Field(..., description="Ingredient ID to stock level mapping")
|
||||
found_count: int = Field(..., description="Number of stock levels found")
|
||||
|
||||
|
||||
@router.post(
|
||||
route_builder.build_operations_route("stock-levels/batch"),
|
||||
response_model=BatchStockLevelsResponse
|
||||
)
|
||||
async def get_stock_levels_batch(
|
||||
request: BatchStockLevelsRequest,
|
||||
tenant_id: UUID = Path(..., description="Tenant ID"),
|
||||
current_user: Dict[str, Any] = Depends(get_current_user_dep),
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Fetch stock levels for multiple ingredients in a single request.
|
||||
|
||||
Optimized endpoint for Orchestrator to quickly check inventory levels
|
||||
without making individual API calls per ingredient.
|
||||
"""
|
||||
try:
|
||||
if not request.ingredient_ids:
|
||||
return BatchStockLevelsResponse(
|
||||
stock_levels={},
|
||||
found_count=0
|
||||
)
|
||||
|
||||
service = InventoryService()
|
||||
stock_levels = {}
|
||||
|
||||
for ingredient_id in request.ingredient_ids:
|
||||
try:
|
||||
ingredient = await service.get_ingredient_by_id(ingredient_id, tenant_id, db)
|
||||
if ingredient:
|
||||
stock_levels[str(ingredient_id)] = float(ingredient.current_stock) if ingredient.current_stock else 0.0
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"Failed to fetch stock level in batch",
|
||||
ingredient_id=str(ingredient_id),
|
||||
error=str(e)
|
||||
)
|
||||
continue
|
||||
|
||||
logger.info(
|
||||
"Batch stock level fetch complete",
|
||||
requested=len(request.ingredient_ids),
|
||||
found=len(stock_levels),
|
||||
tenant_id=str(tenant_id)
|
||||
)
|
||||
|
||||
return BatchStockLevelsResponse(
|
||||
stock_levels=stock_levels,
|
||||
found_count=len(stock_levels)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
"Batch stock level fetch failed",
|
||||
error=str(e),
|
||||
tenant_id=str(tenant_id)
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Batch stock level fetch failed: {str(e)}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user