Fix new services implementation 1
This commit is contained in:
@@ -4,122 +4,83 @@ Inventory Service Client - Inter-service communication
|
||||
Handles communication with the inventory service to fetch product data
|
||||
"""
|
||||
|
||||
import httpx
|
||||
import structlog
|
||||
from typing import Dict, Any, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from shared.clients.inventory_client import InventoryServiceClient as SharedInventoryClient
|
||||
from app.core.config import settings
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
class InventoryServiceClient:
|
||||
"""Client for communicating with the inventory service"""
|
||||
"""Client for communicating with the inventory service via shared client"""
|
||||
|
||||
def __init__(self):
|
||||
self.base_url = settings.INVENTORY_SERVICE_URL
|
||||
self.timeout = 30.0
|
||||
self._shared_client = SharedInventoryClient(settings)
|
||||
|
||||
async def classify_products_batch(self, product_list: Dict[str, Any], tenant_id: UUID) -> Optional[Dict[str, Any]]:
|
||||
"""Get product details from inventory service by ID"""
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.post(
|
||||
f"{self.base_url}/api/v1/tenants/{tenant_id}/inventory/classify-products-batch",
|
||||
headers=self._get_headers(),
|
||||
product_list=product_list
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
product_data = response.json()
|
||||
logger.info("Retrieved product from inventory service",
|
||||
tenant_id=tenant_id)
|
||||
return product_data
|
||||
elif response.status_code == 404:
|
||||
logger.warning("Product not found in inventory service",
|
||||
tenant_id=tenant_id)
|
||||
return None
|
||||
else:
|
||||
logger.error("Failed to fetch product from inventory service",
|
||||
status_code=response.status_code,
|
||||
tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
except httpx.TimeoutException:
|
||||
logger.error("Timeout fetching product from inventory service",
|
||||
tenant_id=tenant_id)
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error("Error communicating with inventory service",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
async def classify_products_batch(self, product_list: List[Dict[str, Any]], tenant_id: UUID) -> Optional[Dict[str, Any]]:
|
||||
"""Classify multiple products for inventory creation"""
|
||||
try:
|
||||
# Convert product_list to expected format for shared client
|
||||
products = []
|
||||
for item in product_list:
|
||||
if isinstance(item, str):
|
||||
# If it's just a product name
|
||||
products.append({"product_name": item})
|
||||
elif isinstance(item, dict):
|
||||
# If it's already a dict, ensure required fields
|
||||
product_data = {
|
||||
"product_name": item.get("product_name", item.get("name", str(item))),
|
||||
"sales_volume": item.get("sales_volume", item.get("total_quantity"))
|
||||
}
|
||||
products.append(product_data)
|
||||
|
||||
result = await self._shared_client.classify_products_batch(products, str(tenant_id))
|
||||
if result:
|
||||
logger.info("Classified products batch",
|
||||
count=len(products), tenant_id=tenant_id)
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error in batch product classification",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
async def get_product_by_id(self, product_id: UUID, tenant_id: UUID) -> Optional[Dict[str, Any]]:
|
||||
"""Get product details from inventory service by ID"""
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.get(
|
||||
f"{self.base_url}/api/v1/tenants/{tenant_id}/ingredients/{product_id}",
|
||||
headers=self._get_headers()
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
product_data = response.json()
|
||||
logger.info("Retrieved product from inventory service",
|
||||
product_id=product_id, tenant_id=tenant_id)
|
||||
return product_data
|
||||
elif response.status_code == 404:
|
||||
logger.warning("Product not found in inventory service",
|
||||
product_id=product_id, tenant_id=tenant_id)
|
||||
return None
|
||||
else:
|
||||
logger.error("Failed to fetch product from inventory service",
|
||||
status_code=response.status_code,
|
||||
product_id=product_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
except httpx.TimeoutException:
|
||||
logger.error("Timeout fetching product from inventory service",
|
||||
product_id=product_id, tenant_id=tenant_id)
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error("Error communicating with inventory service",
|
||||
error=str(e), product_id=product_id, tenant_id=tenant_id)
|
||||
return None
|
||||
"""Get product details from inventory service by ID"""
|
||||
try:
|
||||
result = await self._shared_client.get_ingredient_by_id(product_id, str(tenant_id))
|
||||
if result:
|
||||
logger.info("Retrieved product from inventory service",
|
||||
product_id=product_id, tenant_id=tenant_id)
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error fetching product by ID",
|
||||
error=str(e), product_id=product_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
async def get_product_by_sku(self, sku: str, tenant_id: UUID) -> Optional[Dict[str, Any]]:
|
||||
"""Get product details from inventory service by SKU"""
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.get(
|
||||
f"{self.base_url}/api/v1/tenants/{tenant_id}/ingredients",
|
||||
params={"sku": sku, "limit": 1},
|
||||
headers=self._get_headers()
|
||||
)
|
||||
# Search for product by SKU using shared client
|
||||
products = await self._shared_client.search_ingredients(
|
||||
str(tenant_id), search=sku, limit=1
|
||||
)
|
||||
|
||||
if products:
|
||||
product_data = products[0]
|
||||
logger.info("Retrieved product by SKU from inventory service",
|
||||
sku=sku, tenant_id=tenant_id)
|
||||
return product_data
|
||||
else:
|
||||
logger.warning("Product not found by SKU in inventory service",
|
||||
sku=sku, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
products = data.get("items", [])
|
||||
if products:
|
||||
product_data = products[0]
|
||||
logger.info("Retrieved product by SKU from inventory service",
|
||||
sku=sku, tenant_id=tenant_id)
|
||||
return product_data
|
||||
else:
|
||||
logger.warning("Product not found by SKU in inventory service",
|
||||
sku=sku, tenant_id=tenant_id)
|
||||
return None
|
||||
else:
|
||||
logger.error("Failed to fetch product by SKU from inventory service",
|
||||
status_code=response.status_code,
|
||||
sku=sku, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
except httpx.TimeoutException:
|
||||
logger.error("Timeout fetching product by SKU from inventory service",
|
||||
sku=sku, tenant_id=tenant_id)
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error("Error communicating with inventory service for SKU",
|
||||
logger.error("Error fetching product by SKU",
|
||||
error=str(e), sku=sku, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
@@ -127,38 +88,16 @@ class InventoryServiceClient:
|
||||
product_type: Optional[str] = None) -> List[Dict[str, Any]]:
|
||||
"""Search products in inventory service"""
|
||||
try:
|
||||
params = {
|
||||
"search": search_term,
|
||||
"limit": 50
|
||||
}
|
||||
if product_type:
|
||||
params["product_type"] = product_type
|
||||
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.get(
|
||||
f"{self.base_url}/api/v1/tenants/{tenant_id}/ingredients",
|
||||
params=params,
|
||||
headers=self._get_headers()
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
products = data.get("items", [])
|
||||
logger.info("Searched products in inventory service",
|
||||
search_term=search_term, count=len(products), tenant_id=tenant_id)
|
||||
return products
|
||||
else:
|
||||
logger.error("Failed to search products in inventory service",
|
||||
status_code=response.status_code,
|
||||
search_term=search_term, tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
except httpx.TimeoutException:
|
||||
logger.error("Timeout searching products in inventory service",
|
||||
search_term=search_term, tenant_id=tenant_id)
|
||||
return []
|
||||
products = await self._shared_client.search_ingredients(
|
||||
str(tenant_id), search=search_term, limit=50
|
||||
)
|
||||
|
||||
logger.info("Searched products in inventory service",
|
||||
search_term=search_term, count=len(products), tenant_id=tenant_id)
|
||||
return products
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error searching products in inventory service",
|
||||
logger.error("Error searching products",
|
||||
error=str(e), search_term=search_term, tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
@@ -166,55 +105,18 @@ class InventoryServiceClient:
|
||||
product_type: Optional[str] = None) -> List[Dict[str, Any]]:
|
||||
"""Get products by category from inventory service"""
|
||||
try:
|
||||
params = {
|
||||
"limit": 100
|
||||
}
|
||||
if product_type == "ingredient":
|
||||
params["ingredient_category"] = category
|
||||
elif product_type == "finished_product":
|
||||
params["product_category"] = category
|
||||
else:
|
||||
# Search in both categories if type not specified
|
||||
params["category"] = category
|
||||
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.get(
|
||||
f"{self.base_url}/api/v1/tenants/{tenant_id}/ingredients",
|
||||
params=params,
|
||||
headers=self._get_headers()
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
products = data.get("items", [])
|
||||
logger.info("Retrieved products by category from inventory service",
|
||||
category=category, count=len(products), tenant_id=tenant_id)
|
||||
return products
|
||||
else:
|
||||
logger.error("Failed to fetch products by category from inventory service",
|
||||
status_code=response.status_code,
|
||||
category=category, tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
except httpx.TimeoutException:
|
||||
logger.error("Timeout fetching products by category from inventory service",
|
||||
category=category, tenant_id=tenant_id)
|
||||
return []
|
||||
products = await self._shared_client.search_ingredients(
|
||||
str(tenant_id), category=category, limit=100
|
||||
)
|
||||
|
||||
logger.info("Retrieved products by category from inventory service",
|
||||
category=category, count=len(products), tenant_id=tenant_id)
|
||||
return products
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error fetching products by category from inventory service",
|
||||
logger.error("Error fetching products by category",
|
||||
error=str(e), category=category, tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
# Cache synchronization removed - no longer needed with pure inventory reference approach
|
||||
|
||||
def _get_headers(self) -> Dict[str, str]:
|
||||
"""Get headers for inventory service requests"""
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
"X-Service-Name": "sales-service",
|
||||
# Add authentication headers if needed
|
||||
}
|
||||
|
||||
|
||||
# Dependency injection
|
||||
async def get_inventory_client() -> InventoryServiceClient:
|
||||
|
||||
Reference in New Issue
Block a user