Automated Action c8aed27755 Create SaaS invoicing application with FastAPI and SQLite
- Set up project structure with modular organization
- Implement database models for users, organizations, clients, invoices
- Create Alembic migration scripts for database setup
- Implement JWT-based authentication and authorization
- Create API endpoints for users, organizations, clients, invoices
- Add PDF generation for invoices using ReportLab
- Add comprehensive documentation in README
2025-06-06 11:21:11 +00:00

137 lines
4.0 KiB
Python

from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app import crud, models, schemas
from app.api import deps
router = APIRouter()
@router.get("/", response_model=List[schemas.Client])
def read_clients(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Retrieve clients.
"""
if crud.user.is_superuser(current_user):
clients = crud.client.get_multi(db, skip=skip, limit=limit)
elif current_user.organization_id:
# Filter clients by the user's organization
clients = (
db.query(models.Client)
.filter(models.Client.organization_id == current_user.organization_id)
.offset(skip)
.limit(limit)
.all()
)
else:
clients = []
return clients
@router.post("/", response_model=schemas.Client)
def create_client(
*,
db: Session = Depends(deps.get_db),
client_in: schemas.ClientCreate,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Create new client.
"""
# Ensure user has permission to create a client for the specified organization
if not crud.user.is_superuser(current_user) and (
current_user.organization_id != client_in.organization_id
):
raise HTTPException(status_code=400, detail="Not enough permissions")
# Create client with created_by information
client_data = client_in.dict()
client = models.Client(**client_data, created_by_id=current_user.id)
db.add(client)
db.commit()
db.refresh(client)
return client
@router.get("/{id}", response_model=schemas.Client)
def read_client(
*,
db: Session = Depends(deps.get_db),
id: int,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Get client by ID.
"""
client = crud.client.get(db, id=id)
if not client:
raise HTTPException(status_code=404, detail="Client not found")
if not crud.user.is_superuser(current_user) and (
current_user.organization_id != client.organization_id
):
raise HTTPException(status_code=400, detail="Not enough permissions")
return client
@router.put("/{id}", response_model=schemas.Client)
def update_client(
*,
db: Session = Depends(deps.get_db),
id: int,
client_in: schemas.ClientUpdate,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Update a client.
"""
client = crud.client.get(db, id=id)
if not client:
raise HTTPException(status_code=404, detail="Client not found")
if not crud.user.is_superuser(current_user) and (
current_user.organization_id != client.organization_id
):
raise HTTPException(status_code=400, detail="Not enough permissions")
# Prevent changing organization_id if not a superuser
if (
client_in.organization_id is not None
and client_in.organization_id != client.organization_id
and not crud.user.is_superuser(current_user)
):
raise HTTPException(
status_code=400, detail="Cannot change client's organization"
)
client = crud.client.update(db, db_obj=client, obj_in=client_in)
return client
@router.delete("/{id}", response_model=schemas.Client)
def delete_client(
*,
db: Session = Depends(deps.get_db),
id: int,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Delete a client.
"""
client = crud.client.get(db, id=id)
if not client:
raise HTTPException(status_code=404, detail="Client not found")
if not crud.user.is_superuser(current_user) and (
current_user.organization_id != client.organization_id
):
raise HTTPException(status_code=400, detail="Not enough permissions")
client = crud.client.remove(db, id=id)
return client