2025-08-21 20:28:14 +02:00
|
|
|
# ================================================================
|
|
|
|
|
# services/orders/app/api/orders.py
|
|
|
|
|
# ================================================================
|
|
|
|
|
"""
|
|
|
|
|
Orders API endpoints for Orders Service
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from datetime import date, datetime
|
|
|
|
|
from typing import List, Optional
|
|
|
|
|
from uuid import UUID
|
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Path, Query, status
|
|
|
|
|
from fastapi.responses import JSONResponse
|
|
|
|
|
import structlog
|
|
|
|
|
|
|
|
|
|
from shared.auth.decorators import get_current_user_dep, get_current_tenant_id_dep
|
|
|
|
|
from app.core.database import get_db
|
|
|
|
|
from app.services.orders_service import OrdersService
|
|
|
|
|
from app.schemas.order_schemas import (
|
|
|
|
|
OrderCreate,
|
|
|
|
|
OrderUpdate,
|
|
|
|
|
OrderResponse,
|
|
|
|
|
CustomerCreate,
|
|
|
|
|
CustomerUpdate,
|
|
|
|
|
CustomerResponse,
|
|
|
|
|
OrdersDashboardSummary,
|
|
|
|
|
DemandRequirements,
|
|
|
|
|
ProcurementPlanningData
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Dependency Injection =====
|
|
|
|
|
|
|
|
|
|
async def get_orders_service(db = Depends(get_db)) -> OrdersService:
|
|
|
|
|
"""Get orders service with dependencies"""
|
|
|
|
|
from app.repositories.order_repository import (
|
|
|
|
|
OrderRepository,
|
|
|
|
|
CustomerRepository,
|
|
|
|
|
OrderItemRepository,
|
|
|
|
|
OrderStatusHistoryRepository
|
|
|
|
|
)
|
|
|
|
|
from shared.clients import (
|
2025-08-23 16:30:45 +02:00
|
|
|
get_inventory_client,
|
|
|
|
|
get_production_client,
|
|
|
|
|
get_sales_client
|
2025-08-21 20:28:14 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return OrdersService(
|
|
|
|
|
order_repo=OrderRepository(),
|
|
|
|
|
customer_repo=CustomerRepository(),
|
|
|
|
|
order_item_repo=OrderItemRepository(),
|
|
|
|
|
status_history_repo=OrderStatusHistoryRepository(),
|
2025-08-23 16:30:45 +02:00
|
|
|
inventory_client=get_inventory_client(),
|
|
|
|
|
production_client=get_production_client(),
|
|
|
|
|
sales_client=get_sales_client(),
|
|
|
|
|
notification_client=None # Notification client not available
|
2025-08-21 20:28:14 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Dashboard and Analytics Endpoints =====
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/orders/dashboard-summary", response_model=OrdersDashboardSummary)
|
|
|
|
|
async def get_dashboard_summary(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Get comprehensive dashboard summary for orders"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
summary = await orders_service.get_dashboard_summary(db, tenant_id)
|
|
|
|
|
|
|
|
|
|
logger.info("Dashboard summary retrieved",
|
|
|
|
|
tenant_id=str(tenant_id),
|
|
|
|
|
total_orders=summary.total_orders_today)
|
|
|
|
|
|
|
|
|
|
return summary
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting dashboard summary",
|
|
|
|
|
tenant_id=str(tenant_id),
|
|
|
|
|
error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to retrieve dashboard summary"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/orders/demand-requirements", response_model=DemandRequirements)
|
|
|
|
|
async def get_demand_requirements(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
target_date: date = Query(..., description="Date for demand analysis"),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Get demand requirements for production planning"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
requirements = await orders_service.get_demand_requirements(db, tenant_id, target_date)
|
|
|
|
|
|
|
|
|
|
logger.info("Demand requirements calculated",
|
|
|
|
|
tenant_id=str(tenant_id),
|
|
|
|
|
target_date=str(target_date),
|
|
|
|
|
total_orders=requirements.total_orders)
|
|
|
|
|
|
|
|
|
|
return requirements
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting demand requirements",
|
|
|
|
|
tenant_id=str(tenant_id),
|
|
|
|
|
error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to calculate demand requirements"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Order Management Endpoints =====
|
|
|
|
|
|
|
|
|
|
@router.post("/tenants/{tenant_id}/orders", response_model=OrderResponse, status_code=status.HTTP_201_CREATED)
|
|
|
|
|
async def create_order(
|
|
|
|
|
order_data: OrderCreate,
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Create a new customer order"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Ensure tenant_id matches
|
|
|
|
|
order_data.tenant_id = tenant_id
|
|
|
|
|
|
|
|
|
|
order = await orders_service.create_order(
|
|
|
|
|
db,
|
|
|
|
|
order_data,
|
|
|
|
|
user_id=UUID(current_user["sub"])
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger.info("Order created successfully",
|
|
|
|
|
order_id=str(order.id),
|
|
|
|
|
order_number=order.order_number)
|
|
|
|
|
|
|
|
|
|
return order
|
|
|
|
|
|
|
|
|
|
except ValueError as e:
|
|
|
|
|
logger.warning("Invalid order data", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail=str(e)
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error creating order", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to create order"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/orders/{order_id}", response_model=OrderResponse)
|
|
|
|
|
async def get_order(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
order_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Get order details with items"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
order = await orders_service.get_order_with_items(db, order_id, tenant_id)
|
|
|
|
|
if not order:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="Order not found"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return order
|
|
|
|
|
|
|
|
|
|
except HTTPException:
|
|
|
|
|
raise
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting order",
|
|
|
|
|
order_id=str(order_id),
|
|
|
|
|
error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to retrieve order"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/orders", response_model=List[OrderResponse])
|
|
|
|
|
async def get_orders(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
status_filter: Optional[str] = Query(None, description="Filter by order status"),
|
|
|
|
|
start_date: Optional[date] = Query(None, description="Start date for date range filter"),
|
|
|
|
|
end_date: Optional[date] = Query(None, description="End date for date range filter"),
|
|
|
|
|
skip: int = Query(0, ge=0, description="Number of orders to skip"),
|
|
|
|
|
limit: int = Query(100, ge=1, le=1000, description="Number of orders to return"),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Get orders with filtering and pagination"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Determine which repository method to use based on filters
|
|
|
|
|
if status_filter:
|
|
|
|
|
orders = await orders_service.order_repo.get_orders_by_status(
|
|
|
|
|
db, tenant_id, status_filter, skip, limit
|
|
|
|
|
)
|
|
|
|
|
elif start_date and end_date:
|
|
|
|
|
orders = await orders_service.order_repo.get_orders_by_date_range(
|
|
|
|
|
db, tenant_id, start_date, end_date, skip, limit
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
orders = await orders_service.order_repo.get_multi(
|
|
|
|
|
db, tenant_id, skip, limit, order_by="order_date", order_desc=True
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return [OrderResponse.from_orm(order) for order in orders]
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting orders", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to retrieve orders"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put("/tenants/{tenant_id}/orders/{order_id}/status", response_model=OrderResponse)
|
|
|
|
|
async def update_order_status(
|
|
|
|
|
new_status: str,
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
order_id: UUID = Path(...),
|
|
|
|
|
reason: Optional[str] = Query(None, description="Reason for status change"),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Update order status"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Validate status
|
|
|
|
|
valid_statuses = ["pending", "confirmed", "in_production", "ready", "out_for_delivery", "delivered", "cancelled", "failed"]
|
|
|
|
|
if new_status not in valid_statuses:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail=f"Invalid status. Must be one of: {', '.join(valid_statuses)}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
order = await orders_service.update_order_status(
|
|
|
|
|
db,
|
|
|
|
|
order_id,
|
|
|
|
|
tenant_id,
|
|
|
|
|
new_status,
|
|
|
|
|
user_id=UUID(current_user["sub"]),
|
|
|
|
|
reason=reason
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if not order:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="Order not found"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger.info("Order status updated",
|
|
|
|
|
order_id=str(order_id),
|
|
|
|
|
new_status=new_status)
|
|
|
|
|
|
|
|
|
|
return order
|
|
|
|
|
|
|
|
|
|
except HTTPException:
|
|
|
|
|
raise
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error updating order status",
|
|
|
|
|
order_id=str(order_id),
|
|
|
|
|
error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to update order status"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Customer Management Endpoints =====
|
|
|
|
|
|
|
|
|
|
@router.post("/tenants/{tenant_id}/customers", response_model=CustomerResponse, status_code=status.HTTP_201_CREATED)
|
|
|
|
|
async def create_customer(
|
|
|
|
|
customer_data: CustomerCreate,
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Create a new customer"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Ensure tenant_id matches
|
|
|
|
|
customer_data.tenant_id = tenant_id
|
|
|
|
|
|
|
|
|
|
# Check if customer code already exists
|
|
|
|
|
existing_customer = await orders_service.customer_repo.get_by_customer_code(
|
|
|
|
|
db, customer_data.customer_code, tenant_id
|
|
|
|
|
)
|
|
|
|
|
if existing_customer:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="Customer code already exists"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
customer = await orders_service.customer_repo.create(
|
|
|
|
|
db,
|
|
|
|
|
obj_in=customer_data.dict(),
|
|
|
|
|
created_by=UUID(current_user["sub"])
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger.info("Customer created successfully",
|
|
|
|
|
customer_id=str(customer.id),
|
|
|
|
|
customer_code=customer.customer_code)
|
|
|
|
|
|
|
|
|
|
return CustomerResponse.from_orm(customer)
|
|
|
|
|
|
|
|
|
|
except HTTPException:
|
|
|
|
|
raise
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error creating customer", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to create customer"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/customers", response_model=List[CustomerResponse])
|
|
|
|
|
async def get_customers(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
active_only: bool = Query(True, description="Filter for active customers only"),
|
|
|
|
|
skip: int = Query(0, ge=0, description="Number of customers to skip"),
|
|
|
|
|
limit: int = Query(100, ge=1, le=1000, description="Number of customers to return"),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Get customers with filtering and pagination"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if active_only:
|
|
|
|
|
customers = await orders_service.customer_repo.get_active_customers(
|
|
|
|
|
db, tenant_id, skip, limit
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
customers = await orders_service.customer_repo.get_multi(
|
|
|
|
|
db, tenant_id, skip, limit, order_by="name"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return [CustomerResponse.from_orm(customer) for customer in customers]
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting customers", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to retrieve customers"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/customers/{customer_id}", response_model=CustomerResponse)
|
|
|
|
|
async def get_customer(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
customer_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Get customer details"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
customer = await orders_service.customer_repo.get(db, customer_id, tenant_id)
|
|
|
|
|
if not customer:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="Customer not found"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return CustomerResponse.from_orm(customer)
|
|
|
|
|
|
|
|
|
|
except HTTPException:
|
|
|
|
|
raise
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting customer",
|
|
|
|
|
customer_id=str(customer_id),
|
|
|
|
|
error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to retrieve customer"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Business Intelligence Endpoints =====
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/orders/business-model")
|
|
|
|
|
async def detect_business_model(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep),
|
|
|
|
|
orders_service: OrdersService = Depends(get_orders_service),
|
|
|
|
|
db = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""Detect business model based on order patterns"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
business_model = await orders_service.detect_business_model(db, tenant_id)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"business_model": business_model,
|
|
|
|
|
"confidence": "high" if business_model else "unknown",
|
|
|
|
|
"detected_at": datetime.now().isoformat()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error detecting business model", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to detect business model"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Health and Status Endpoints =====
|
|
|
|
|
|
|
|
|
|
@router.get("/tenants/{tenant_id}/orders/status")
|
|
|
|
|
async def get_service_status(
|
|
|
|
|
tenant_id: UUID = Path(...),
|
|
|
|
|
current_tenant: str = Depends(get_current_tenant_id_dep),
|
|
|
|
|
current_user: dict = Depends(get_current_user_dep)
|
|
|
|
|
):
|
|
|
|
|
"""Get orders service status"""
|
|
|
|
|
try:
|
|
|
|
|
if str(tenant_id) != current_tenant:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
|
|
|
detail="Access denied to tenant data"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"service": "orders-service",
|
|
|
|
|
"status": "healthy",
|
|
|
|
|
"timestamp": datetime.now().isoformat(),
|
|
|
|
|
"tenant_id": str(tenant_id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Error getting service status", error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to get service status"
|
|
|
|
|
)
|