from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from datetime import datetime, timezone from ..database import get_db, SelectionOffer as SelectionOfferModel from ..models.selection_offer import ( SelectionOffer, SelectionOfferCreate, SelectionOfferUpdate, ) router = APIRouter( prefix="/selection-offers", tags=["selection-offers"], responses={404: {"description": "Not found"}}, ) # Get all selection offers @router.get("/", response_model=List[SelectionOffer]) def get_all_selection_offers(db: Session = Depends(get_db)): return db.query(SelectionOfferModel).order_by(SelectionOfferModel.min_amount).all() # Get active selection offers @router.get("/active", response_model=List[SelectionOffer]) def get_active_selection_offers(db: Session = Depends(get_db)): return ( db.query(SelectionOfferModel) .filter(SelectionOfferModel.is_active == True) .order_by(SelectionOfferModel.min_amount) .all() ) # Get selection offer by ID @router.get("/{offer_id}", response_model=SelectionOffer) def get_selection_offer(offer_id: int, db: Session = Depends(get_db)): db_offer = ( db.query(SelectionOfferModel).filter(SelectionOfferModel.id == offer_id).first() ) if not db_offer: raise HTTPException(status_code=404, detail="Selection offer not found") return db_offer # Create new selection offer @router.post("/", response_model=SelectionOffer) def create_selection_offer(offer: SelectionOfferCreate, db: Session = Depends(get_db)): # Check if an offer with this min_amount already exists existing_offer = ( db.query(SelectionOfferModel) .filter(SelectionOfferModel.min_amount == offer.min_amount) .first() ) if existing_offer: raise HTTPException( status_code=400, detail=f"Selection offer with minimum amount {offer.min_amount} already exists", ) # Create new offer db_offer = SelectionOfferModel( min_amount=offer.min_amount, discount_amount=offer.discount_amount, is_active=offer.is_active, description=offer.description, created_at=datetime.now(timezone.utc), updated_at=datetime.now(timezone.utc), ) db.add(db_offer) db.commit() db.refresh(db_offer) return db_offer # Update selection offer @router.put("/{offer_id}", response_model=SelectionOffer) def update_selection_offer( offer_id: int, offer_update: SelectionOfferUpdate, db: Session = Depends(get_db) ): db_offer = ( db.query(SelectionOfferModel).filter(SelectionOfferModel.id == offer_id).first() ) if not db_offer: raise HTTPException(status_code=404, detail="Selection offer not found") # Check if updating min_amount and if it already exists if ( offer_update.min_amount is not None and offer_update.min_amount != db_offer.min_amount ): existing_offer = ( db.query(SelectionOfferModel) .filter( SelectionOfferModel.min_amount == offer_update.min_amount, SelectionOfferModel.id != offer_id, ) .first() ) if existing_offer: raise HTTPException( status_code=400, detail=f"Selection offer with minimum amount {offer_update.min_amount} already exists", ) db_offer.min_amount = offer_update.min_amount # Update other fields if provided if offer_update.discount_amount is not None: db_offer.discount_amount = offer_update.discount_amount if offer_update.is_active is not None: db_offer.is_active = offer_update.is_active if offer_update.description is not None: db_offer.description = offer_update.description db_offer.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(db_offer) return db_offer # Delete selection offer @router.delete("/{offer_id}") def delete_selection_offer(offer_id: int, db: Session = Depends(get_db)): db_offer = ( db.query(SelectionOfferModel).filter(SelectionOfferModel.id == offer_id).first() ) if not db_offer: raise HTTPException(status_code=404, detail="Selection offer not found") db.delete(db_offer) db.commit() return {"message": "Selection offer deleted successfully"} # Get applicable discount for an order amount @router.get("/discount/{order_amount}") def get_discount_for_order_amount(order_amount: float, db: Session = Depends(get_db)): # Find the highest tier that the order amount qualifies for applicable_offer = ( db.query(SelectionOfferModel) .filter( SelectionOfferModel.min_amount <= order_amount, SelectionOfferModel.is_active == True, ) .order_by(SelectionOfferModel.min_amount.desc()) .first() ) if not applicable_offer: return { "discount_amount": 0, "message": "No applicable selection offer discount", } return { "discount_amount": applicable_offer.discount_amount, "offer_id": applicable_offer.id, "min_amount": applicable_offer.min_amount, "message": f"Selection offer discount of ${applicable_offer.discount_amount} applied", }