feat(crud): full CRUD endpoints for NetObject (POST/PUT/PATCH/DELETE)
CI / basic-check (push) Has been cancelled

This commit is contained in:
2026-08-06 16:09:13 +00:00
parent 45fb390cb7
commit f47443ad98
+98 -1
View File
@@ -1,14 +1,25 @@
import re
from datetime import datetime, timezone
from uuid import uuid4
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.database import get_db from app.database import get_db
from app.models import NetObjectModel from app.models import NetObjectModel
from app.schemas import EntityResponse, ListResponse, NetObject from app.schemas import EntityResponse, ListResponse, NetObject, NetObjectCreate, NetObjectUpdate
from app.services.inventory import _to_net_object from app.services.inventory import _to_net_object
router = APIRouter(prefix='/objects', tags=['objects']) router = APIRouter(prefix='/objects', tags=['objects'])
def _slugify(name: str) -> str:
slug = name.lower().strip()
slug = re.sub(r'[^\w\s-]', '', slug)
slug = re.sub(r'[\s_-]+', '-', slug)
return slug.strip('-')
@router.get('', response_model=ListResponse[NetObject]) @router.get('', response_model=ListResponse[NetObject])
def list_objects(db: Session = Depends(get_db)): def list_objects(db: Session = Depends(get_db)):
rows = db.query(NetObjectModel).all() rows = db.query(NetObjectModel).all()
@@ -21,3 +32,89 @@ def get_object(object_id: str, db: Session = Depends(get_db)):
if not row: if not row:
raise HTTPException(status_code=404, detail='Object not found') raise HTTPException(status_code=404, detail='Object not found')
return EntityResponse(item=_to_net_object(row)) return EntityResponse(item=_to_net_object(row))
@router.post('', response_model=EntityResponse[NetObject], status_code=201)
def create_object(body: NetObjectCreate, db: Session = Depends(get_db)):
if body.parent_id:
parent = db.query(NetObjectModel).filter(NetObjectModel.id == body.parent_id).first()
if not parent:
raise HTTPException(status_code=422, detail=f'parent_id {body.parent_id!r} not found')
now = datetime.now(timezone.utc)
obj = NetObjectModel(
id=f'obj_{uuid4().hex[:8]}',
name=body.name,
slug=_slugify(body.name),
type=body.type,
parent_id=body.parent_id,
status=body.status,
vendor=body.vendor,
model=body.model,
serial=body.serial,
notes=body.notes,
created_at=now,
updated_at=now,
)
db.add(obj)
db.commit()
db.refresh(obj)
return EntityResponse(item=_to_net_object(obj))
@router.put('/{object_id}', response_model=EntityResponse[NetObject])
def replace_object(object_id: str, body: NetObjectCreate, db: Session = Depends(get_db)):
row = db.query(NetObjectModel).filter(NetObjectModel.id == object_id).first()
if not row:
raise HTTPException(status_code=404, detail='Object not found')
if body.parent_id and body.parent_id != row.parent_id:
parent = db.query(NetObjectModel).filter(NetObjectModel.id == body.parent_id).first()
if not parent:
raise HTTPException(status_code=422, detail=f'parent_id {body.parent_id!r} not found')
row.name = body.name
row.slug = _slugify(body.name)
row.type = body.type
row.parent_id = body.parent_id
row.status = body.status
row.vendor = body.vendor
row.model = body.model
row.serial = body.serial
row.notes = body.notes
row.updated_at = datetime.now(timezone.utc)
db.commit()
db.refresh(row)
return EntityResponse(item=_to_net_object(row))
@router.patch('/{object_id}', response_model=EntityResponse[NetObject])
def update_object(object_id: str, body: NetObjectUpdate, db: Session = Depends(get_db)):
row = db.query(NetObjectModel).filter(NetObjectModel.id == object_id).first()
if not row:
raise HTTPException(status_code=404, detail='Object not found')
data = body.model_dump(exclude_unset=True)
if 'parent_id' in data and data['parent_id']:
parent = db.query(NetObjectModel).filter(NetObjectModel.id == data['parent_id']).first()
if not parent:
raise HTTPException(status_code=422, detail=f'parent_id {data["parent_id"]!r} not found')
if 'name' in data:
row.slug = _slugify(data['name'])
for field, value in data.items():
setattr(row, field, value)
row.updated_at = datetime.now(timezone.utc)
db.commit()
db.refresh(row)
return EntityResponse(item=_to_net_object(row))
@router.delete('/{object_id}', status_code=204)
def delete_object(object_id: str, db: Session = Depends(get_db)):
row = db.query(NetObjectModel).filter(NetObjectModel.id == object_id).first()
if not row:
raise HTTPException(status_code=404, detail='Object not found')
children = db.query(NetObjectModel).filter(NetObjectModel.parent_id == object_id).count()
if children:
raise HTTPException(
status_code=409,
detail=f'Cannot delete: object has {children} child object(s). Remove or re-parent them first.',
)
db.delete(row)
db.commit()