from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from typing import List from database.session import get_db from database.models import Order as OrderModel, User as UserModel, Service as ServiceModel from auth import get_current_user import schemas router = APIRouter( prefix="/orders", tags=["orders"] ) @router.post("/", response_model=schemas.Order, status_code=status.HTTP_201_CREATED) async def create_order( order: schemas.OrderCreate, current_user: UserModel = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ Create a new order. Deducts balance from user. """ # 1. Check if service exists and is active result = await db.execute(select(ServiceModel).where(ServiceModel.id == order.service_id)) service = result.scalar_one_or_none() if not service or not service.is_active: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Service not found or inactive") # 2. Validate quantity limits if order.quantity < service.min_quantity or order.quantity > service.max_quantity: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Quantity must be between {service.min_quantity} and {service.max_quantity}" ) # 3. Calculate charge charge = (service.price / 1000) * order.quantity # 4. Check user balance if current_user.balance < charge: raise HTTPException(status_code=status.HTTP_402_PAYMENT_REQUIRED, detail="Insufficient balance") # 5. Deduct balance current_user.balance -= charge current_user.spent += charge # 6. Create order new_order = OrderModel( user_id=current_user.id, service_id=service.id, link=order.link, quantity=order.quantity, charge=charge, remains=order.quantity, status="Pending", api_provider_id=service.api_provider_id ) db.add(new_order) # 7. Update service stats service.total_orders += 1 await db.commit() await db.refresh(new_order) return new_order @router.get("/", response_model=List[schemas.Order]) async def get_orders( skip: int = 0, limit: int = 100, current_user: UserModel = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ Get user's orders. """ result = await db.execute( select(OrderModel) .where(OrderModel.user_id == current_user.id) .order_by(OrderModel.created_at.desc()) .offset(skip) .limit(limit) ) return result.scalars().all() @router.get("/{order_id}", response_model=schemas.Order) async def get_order( order_id: int, current_user: UserModel = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ Get specific order details. """ result = await db.execute( select(OrderModel) .where(OrderModel.id == order_id) .where(OrderModel.user_id == current_user.id) ) order = result.scalar_one_or_none() if not order: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Order not found") return order