Files
bin/finance/app/routers/categories.py
2026-07-20 14:17:48 +02:00

92 lines
3.1 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, ConfigDict
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.auth import require_auth
from app.db import get_session
from app.models.tables import Category, CategoryRule
router = APIRouter(prefix="/api", tags=["categories"],
dependencies=[Depends(require_auth)])
class CategoryIn(BaseModel):
name: str
class CategoryOut(CategoryIn):
model_config = ConfigDict(from_attributes=True)
id: int
class CategoryRuleIn(BaseModel):
pattern: str
category_id: int
priority: int = 100
class CategoryRuleOut(CategoryRuleIn):
model_config = ConfigDict(from_attributes=True)
id: int
@router.get("/categories", response_model=list[CategoryOut])
def list_categories(session: Session = Depends(get_session)):
return [CategoryOut.model_validate(c)
for c in session.execute(select(Category)).scalars()]
@router.post("/categories", response_model=CategoryOut, status_code=201)
def create_category(data: CategoryIn, session: Session = Depends(get_session)):
if session.execute(select(Category).where(Category.name == data.name)).scalar():
raise HTTPException(409, "Kategorie existiert bereits")
cat = Category(**data.model_dump())
session.add(cat)
session.commit()
session.refresh(cat)
return CategoryOut.model_validate(cat)
@router.patch("/categories/{category_id}", response_model=CategoryOut)
def patch_category(category_id: int, data: CategoryIn,
session: Session = Depends(get_session)):
cat = session.get(Category, category_id)
if cat is None:
raise HTTPException(404, "Kategorie nicht gefunden")
clash = session.execute(
select(Category).where(Category.name == data.name)).scalar()
if clash is not None and clash.id != category_id:
raise HTTPException(409, "Kategorie existiert bereits")
cat.name = data.name
session.commit()
session.refresh(cat)
return CategoryOut.model_validate(cat)
@router.get("/category-rules", response_model=list[CategoryRuleOut])
def list_category_rules(session: Session = Depends(get_session)):
rules = session.execute(
select(CategoryRule).order_by(CategoryRule.priority)).scalars()
return [CategoryRuleOut.model_validate(r) for r in rules]
@router.post("/category-rules", response_model=CategoryRuleOut, status_code=201)
def create_category_rule(data: CategoryRuleIn, session: Session = Depends(get_session)):
if session.get(Category, data.category_id) is None:
raise HTTPException(404, "Kategorie nicht gefunden")
rule = CategoryRule(**data.model_dump())
session.add(rule)
session.commit()
session.refresh(rule)
return CategoryRuleOut.model_validate(rule)
@router.delete("/category-rules/{rule_id}", status_code=204)
def delete_category_rule(rule_id: int, session: Session = Depends(get_session)):
rule = session.get(CategoryRule, rule_id)
if rule is None:
raise HTTPException(404, "Regel nicht gefunden")
session.delete(rule)
session.commit()