feat(T04): Rentman integration – equipment sync, API endpoints, frontend updates

- Update equipment model with Rentman-compatible fields
- Add/Update equipment router endpoints for sync operations
- Enhance rentman_service with full API client logic
- Improve sync_service for bidirectional equipment sync
- Update docker-compose with Rentman env vars
- Update frontend useApi composable and nuxt config
- Update mietkatalog pages with Rentman-integrated data display
- Add images/ to .gitignore (binary assets, 36MB)
This commit is contained in:
Agent Zero
2026-07-11 18:17:07 +02:00
parent 30db3491c0
commit 9a269aa54f
10 changed files with 289 additions and 151 deletions
+15 -2
View File
@@ -1,5 +1,7 @@
"""Equipment API router: list, detail, categories."""
"""Equipment API router: list, detail, categories, image."""
import os
from fastapi import APIRouter, Depends, HTTPException, Query, status
from fastapi.responses import FileResponse
from sqlalchemy import select, func, or_
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Any
@@ -10,6 +12,8 @@ from app.cache import cache
router = APIRouter(prefix="/api/equipment", tags=["equipment"])
IMAGES_DIR = "/data/images/equipment"
@router.get("", response_model=PaginatedResponse)
async def list_equipment(
@@ -73,6 +77,15 @@ async def list_categories(db: AsyncSession = Depends(get_db)) -> Any:
return categories
@router.get("/{equipment_id}/image")
async def get_equipment_image(equipment_id: int, db: AsyncSession = Depends(get_db)) -> Any:
"""Serve the locally stored image for an equipment item."""
image_path = os.path.join(IMAGES_DIR, f"{equipment_id}.jpg")
if os.path.exists(image_path):
return FileResponse(image_path, media_type="image/jpeg")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Image not found")
@router.get("/{equipment_id}", response_model=EquipmentDetail)
async def get_equipment(equipment_id: int, db: AsyncSession = Depends(get_db)) -> Any:
"""Return a single equipment detail by ID."""
@@ -86,5 +99,5 @@ async def get_equipment(equipment_id: int, db: AsyncSession = Depends(get_db)) -
if not item:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Equipment not found")
response = EquipmentDetail.model_validate(item).model_dump()
await cache.set(cache_key, response.model_dump(), ttl=3600)
await cache.set(cache_key, response, ttl=3600)
return response