from typing import List, Optional, Dict, Any, Union from sqlalchemy.orm import Session from app.crud.base import CRUDBase from app.models.order import Order, OrderItem, OrderStatus from app.schemas.order import OrderCreate, OrderUpdate, OrderItemCreate, OrderItemUpdate from app.models.product import Product class CRUDOrderItem(CRUDBase[OrderItem, OrderItemCreate, OrderItemUpdate]): def create_with_order( self, db: Session, *, obj_in: OrderItemCreate, order_id: int ) -> OrderItem: # Get product to get current price if not provided product = db.query(Product).filter(Product.id == obj_in.product_id).first() if not product: raise ValueError(f"Product with id {obj_in.product_id} not found") # Check if stock is available if product.stock < obj_in.quantity: raise ValueError(f"Not enough stock for product {product.name}") # Create order item db_obj = OrderItem( order_id=order_id, product_id=obj_in.product_id, quantity=obj_in.quantity, price=obj_in.price if obj_in.price else product.price, ) # Update product stock product.stock -= obj_in.quantity db.add(db_obj) db.add(product) db.commit() db.refresh(db_obj) return db_obj order_item = CRUDOrderItem(OrderItem) class CRUDOrder(CRUDBase[Order, OrderCreate, OrderUpdate]): def get_by_user( self, db: Session, *, user_id: int, skip: int = 0, limit: int = 100 ) -> List[Order]: return ( db.query(Order) .filter(Order.user_id == user_id) .offset(skip) .limit(limit) .all() ) def get_by_status( self, db: Session, *, status: OrderStatus, skip: int = 0, limit: int = 100 ) -> List[Order]: return ( db.query(Order) .filter(Order.status == status) .offset(skip) .limit(limit) .all() ) def create(self, db: Session, *, obj_in: OrderCreate) -> Order: # Calculate total amount from items total_amount = 0 for item in obj_in.items: product = db.query(Product).filter(Product.id == item.product_id).first() if not product: raise ValueError(f"Product with id {item.product_id} not found") if product.stock < item.quantity: raise ValueError(f"Not enough stock for product {product.name}") price = item.price if item.price else product.price total_amount += price * item.quantity # Create order db_obj = Order( user_id=obj_in.user_id, status=OrderStatus.PENDING, total_amount=total_amount, shipping_address=obj_in.shipping_address, ) db.add(db_obj) db.commit() db.refresh(db_obj) # Create order items for item in obj_in.items: order_item.create_with_order(db=db, obj_in=item, order_id=db_obj.id) db.refresh(db_obj) return db_obj def update_status( self, db: Session, *, db_obj: Order, status: OrderStatus ) -> Order: db_obj.status = status db.add(db_obj) db.commit() db.refresh(db_obj) return db_obj order = CRUDOrder(Order)