feat: T03+T04 backend - FastAPI, DB models, Rentman integration, admin auth, APScheduler

This commit is contained in:
Implementation Engineer
2026-07-09 01:36:46 +02:00
parent 3bfa54b4b3
commit 88cff68f73
78 changed files with 2174 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
"""FastAPI application assembly with CORS, routers, and APScheduler."""
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from app.config import get_settings
from app.database import engine, init_db
from app.cache import cache
from app.routers import equipment, health, admin, rental_requests, contact
from app.services.sync_service import SyncService
from app.database import async_session
logger = logging.getLogger(__name__)
settings = get_settings()
scheduler = AsyncIOScheduler()
async def run_equipment_sync() -> None:
"""Scheduled job: run equipment sync every 6 hours."""
logger.info("Starting scheduled equipment sync")
async with async_session() as db:
sync_service = SyncService(db)
result = await sync_service.run_sync()
logger.info("Scheduled sync complete: %s", result)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan: init DB, start scheduler, connect cache."""
# Create tables (for dev/testing; production uses Alembic)
await init_db()
# Connect Redis cache
await cache.connect()
# Start APScheduler
scheduler.add_job(
run_equipment_sync,
trigger="cron",
hour="*/6",
id="equipment_sync",
replace_existing=True,
)
scheduler.start()
logger.info("APScheduler started with equipment_sync job (every 6h)")
yield
# Shutdown
scheduler.shutdown(wait=False)
await cache.disconnect()
await engine.dispose()
app = FastAPI(
title="HMS Licht & Ton API",
version="1.0.0",
lifespan=lifespan,
)
# CORS
origins = [o.strip() for o in settings.cors_origins.split(",") if o.strip()]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_methods=["GET", "POST"],
allow_headers=["*"],
allow_credentials=True,
)
# Routers
app.include_router(equipment.router)
app.include_router(health.router)
app.include_router(admin.router)
app.include_router(rental_requests.router)
app.include_router(contact.router)