db/herodb/src/models/py/api.py
2025-04-19 08:39:40 +02:00

455 lines
14 KiB
Python
Executable File

#!/usr/bin/env python3
"""
FastAPI server providing CRUD operations for business models.
"""
import os
from datetime import datetime
from typing import List, Optional
from fastapi import Depends, FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from sqlmodel import Session, SQLModel, create_engine, select
from models import (
Currency,
Customer,
Product,
ProductComponent,
ProductStatus,
ProductType,
Sale,
SaleItem,
SaleStatus,
)
# Create database
DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///business.db")
engine = create_engine(DATABASE_URL, echo=False)
# Create tables
SQLModel.metadata.create_all(engine)
# Create FastAPI app
app = FastAPI(
title="Business API",
description="API for business models",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Dependency to get database session
def get_session():
with Session(engine) as session:
yield session
# Root endpoint
@app.get("/")
async def root():
return {"message": "Welcome to the Business API"}
# Currency endpoints
@app.post("/currencies/", response_model=Currency, tags=["Currencies"])
def create_currency(currency: Currency, session: Session = Depends(get_session)):
"""Create a new currency"""
session.add(currency)
session.commit()
session.refresh(currency)
return currency
@app.get("/currencies/", response_model=List[Currency], tags=["Currencies"])
def read_currencies(
skip: int = 0, limit: int = 100, session: Session = Depends(get_session)
):
"""Get all currencies"""
currencies = session.exec(select(Currency).offset(skip).limit(limit)).all()
return currencies
@app.get("/currencies/{currency_id}", response_model=Currency, tags=["Currencies"])
def read_currency(currency_id: int, session: Session = Depends(get_session)):
"""Get a currency by ID"""
currency = session.get(Currency, currency_id)
if not currency:
raise HTTPException(status_code=404, detail="Currency not found")
return currency
@app.put("/currencies/{currency_id}", response_model=Currency, tags=["Currencies"])
def update_currency(
currency_id: int, currency_data: Currency, session: Session = Depends(get_session)
):
"""Update a currency"""
currency = session.get(Currency, currency_id)
if not currency:
raise HTTPException(status_code=404, detail="Currency not found")
# Update currency attributes
currency_data_dict = currency_data.dict(exclude_unset=True)
for key, value in currency_data_dict.items():
setattr(currency, key, value)
session.add(currency)
session.commit()
session.refresh(currency)
return currency
@app.delete("/currencies/{currency_id}", tags=["Currencies"])
def delete_currency(currency_id: int, session: Session = Depends(get_session)):
"""Delete a currency"""
currency = session.get(Currency, currency_id)
if not currency:
raise HTTPException(status_code=404, detail="Currency not found")
session.delete(currency)
session.commit()
return {"message": "Currency deleted successfully"}
# Customer endpoints
@app.post("/customers/", response_model=Customer, tags=["Customers"])
def create_customer(customer: Customer, session: Session = Depends(get_session)):
"""Create a new customer"""
session.add(customer)
session.commit()
session.refresh(customer)
return customer
@app.get("/customers/", response_model=List[Customer], tags=["Customers"])
def read_customers(
skip: int = 0, limit: int = 100, session: Session = Depends(get_session)
):
"""Get all customers"""
customers = session.exec(select(Customer).offset(skip).limit(limit)).all()
return customers
@app.get("/customers/{customer_id}", response_model=Customer, tags=["Customers"])
def read_customer(customer_id: int, session: Session = Depends(get_session)):
"""Get a customer by ID"""
customer = session.get(Customer, customer_id)
if not customer:
raise HTTPException(status_code=404, detail="Customer not found")
return customer
@app.put("/customers/{customer_id}", response_model=Customer, tags=["Customers"])
def update_customer(
customer_id: int, customer_data: Customer, session: Session = Depends(get_session)
):
"""Update a customer"""
customer = session.get(Customer, customer_id)
if not customer:
raise HTTPException(status_code=404, detail="Customer not found")
# Update customer attributes
customer_data_dict = customer_data.dict(exclude_unset=True)
for key, value in customer_data_dict.items():
setattr(customer, key, value)
session.add(customer)
session.commit()
session.refresh(customer)
return customer
@app.delete("/customers/{customer_id}", tags=["Customers"])
def delete_customer(customer_id: int, session: Session = Depends(get_session)):
"""Delete a customer"""
customer = session.get(Customer, customer_id)
if not customer:
raise HTTPException(status_code=404, detail="Customer not found")
session.delete(customer)
session.commit()
return {"message": "Customer deleted successfully"}
# Product endpoints
@app.post("/products/", response_model=Product, tags=["Products"])
def create_product(product: Product, session: Session = Depends(get_session)):
"""Create a new product"""
session.add(product)
session.commit()
session.refresh(product)
return product
@app.get("/products/", response_model=List[Product], tags=["Products"])
def read_products(
skip: int = 0,
limit: int = 100,
category: Optional[str] = None,
status: Optional[ProductStatus] = None,
istemplate: Optional[bool] = None,
session: Session = Depends(get_session)
):
"""Get all products with optional filtering"""
query = select(Product)
if category:
query = query.where(Product.category == category)
if status:
query = query.where(Product.status == status)
if istemplate is not None:
query = query.where(Product.istemplate == istemplate)
products = session.exec(query.offset(skip).limit(limit)).all()
return products
@app.get("/products/{product_id}", response_model=Product, tags=["Products"])
def read_product(product_id: int, session: Session = Depends(get_session)):
"""Get a product by ID"""
product = session.get(Product, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
return product
@app.put("/products/{product_id}", response_model=Product, tags=["Products"])
def update_product(
product_id: int, product_data: Product, session: Session = Depends(get_session)
):
"""Update a product"""
product = session.get(Product, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
# Update product attributes
product_data_dict = product_data.dict(exclude_unset=True)
for key, value in product_data_dict.items():
setattr(product, key, value)
session.add(product)
session.commit()
session.refresh(product)
return product
@app.delete("/products/{product_id}", tags=["Products"])
def delete_product(product_id: int, session: Session = Depends(get_session)):
"""Delete a product"""
product = session.get(Product, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
session.delete(product)
session.commit()
return {"message": "Product deleted successfully"}
# Product Component endpoints
@app.post("/products/{product_id}/components/", response_model=ProductComponent, tags=["Product Components"])
def create_product_component(
product_id: int, component: ProductComponent, session: Session = Depends(get_session)
):
"""Add a component to a product"""
product = session.get(Product, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
component.product_id = product_id
session.add(component)
session.commit()
session.refresh(component)
return component
@app.get("/products/{product_id}/components/", response_model=List[ProductComponent], tags=["Product Components"])
def read_product_components(
product_id: int, session: Session = Depends(get_session)
):
"""Get all components for a product"""
product = session.get(Product, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
return product.components
# Sale endpoints
@app.post("/sales/", response_model=Sale, tags=["Sales"])
def create_sale(sale: Sale, session: Session = Depends(get_session)):
"""Create a new sale"""
# Ensure customer exists if customer_id is provided
if sale.customer_id:
customer = session.get(Customer, sale.customer_id)
if not customer:
raise HTTPException(status_code=404, detail="Customer not found")
session.add(sale)
session.commit()
session.refresh(sale)
return sale
@app.get("/sales/", response_model=List[Sale], tags=["Sales"])
def read_sales(
skip: int = 0,
limit: int = 100,
status: Optional[SaleStatus] = None,
customer_id: Optional[int] = None,
session: Session = Depends(get_session)
):
"""Get all sales with optional filtering"""
query = select(Sale)
if status:
query = query.where(Sale.status == status)
if customer_id:
query = query.where(Sale.customer_id == customer_id)
sales = session.exec(query.offset(skip).limit(limit)).all()
return sales
@app.get("/sales/{sale_id}", response_model=Sale, tags=["Sales"])
def read_sale(sale_id: int, session: Session = Depends(get_session)):
"""Get a sale by ID"""
sale = session.get(Sale, sale_id)
if not sale:
raise HTTPException(status_code=404, detail="Sale not found")
return sale
@app.put("/sales/{sale_id}", response_model=Sale, tags=["Sales"])
def update_sale(
sale_id: int, sale_data: Sale, session: Session = Depends(get_session)
):
"""Update a sale"""
sale = session.get(Sale, sale_id)
if not sale:
raise HTTPException(status_code=404, detail="Sale not found")
# Update sale attributes
sale_data_dict = sale_data.dict(exclude_unset=True)
for key, value in sale_data_dict.items():
setattr(sale, key, value)
session.add(sale)
session.commit()
session.refresh(sale)
return sale
@app.delete("/sales/{sale_id}", tags=["Sales"])
def delete_sale(sale_id: int, session: Session = Depends(get_session)):
"""Delete a sale"""
sale = session.get(Sale, sale_id)
if not sale:
raise HTTPException(status_code=404, detail="Sale not found")
session.delete(sale)
session.commit()
return {"message": "Sale deleted successfully"}
# Sale Item endpoints
@app.post("/sales/{sale_id}/items/", response_model=SaleItem, tags=["Sale Items"])
def create_sale_item(
sale_id: int, item: SaleItem, session: Session = Depends(get_session)
):
"""Add an item to a sale"""
sale = session.get(Sale, sale_id)
if not sale:
raise HTTPException(status_code=404, detail="Sale not found")
item.sale_id = sale_id
session.add(item)
session.commit()
session.refresh(item)
# Update the sale's total amount
sale.add_item(item)
session.add(sale)
session.commit()
return item
@app.get("/sales/{sale_id}/items/", response_model=List[SaleItem], tags=["Sale Items"])
def read_sale_items(
sale_id: int, session: Session = Depends(get_session)
):
"""Get all items for a sale"""
sale = session.get(Sale, sale_id)
if not sale:
raise HTTPException(status_code=404, detail="Sale not found")
return sale.items
# Convenience endpoints
@app.put("/sales/{sale_id}/status/{status}", response_model=Sale, tags=["Convenience"])
def update_sale_status(
sale_id: int, status: SaleStatus, session: Session = Depends(get_session)
):
"""Update the status of a sale"""
sale = session.get(Sale, sale_id)
if not sale:
raise HTTPException(status_code=404, detail="Sale not found")
sale.update_status(status)
session.add(sale)
session.commit()
session.refresh(sale)
return sale
@app.get("/products/available/", response_model=List[Product], tags=["Convenience"])
def get_available_products(
istemplate: Optional[bool] = False,
session: Session = Depends(get_session)
):
"""Get all available products"""
query = select(Product).where(
Product.status == ProductStatus.AVAILABLE,
Product.purchase_till > datetime.utcnow(),
Product.istemplate == istemplate
)
products = session.exec(query).all()
return products
@app.get("/customers/{customer_id}/sales/", response_model=List[Sale], tags=["Convenience"])
def get_customer_sales(
customer_id: int,
status: Optional[SaleStatus] = None,
session: Session = Depends(get_session)
):
"""Get all sales for a customer"""
customer = session.get(Customer, customer_id)
if not customer:
raise HTTPException(status_code=404, detail="Customer not found")
query = select(Sale).where(Sale.customer_id == customer_id)
if status:
query = query.where(Sale.status == status)
sales = session.exec(query).all()
return sales
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)