Files
service-finder/code-server-config/data/User/History/-3487e1e/7zSH.py

140 lines
5.6 KiB
Python
Executable File

from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from pydantic import BaseModel, validator, EmailStr
from typing import Optional, List
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
import os
from datetime import date
import uuid # Token generáláshoz
from dotenv import load_dotenv
load_dotenv()
# DB Config
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
fixed_url = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
engine = create_async_engine(fixed_url)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
app = FastAPI(title="Service Finder API")
# --- MODELLEK ---
class VehicleRegister(BaseModel):
model_id: int
vin: str
plate: str
mileage: int
purchase_date: date
role: str = "OWNER"
@validator('vin')
def clean_vin(cls, v):
if len(v) < 5: raise ValueError('Túl rövid alvázszám')
return v.upper().replace("-", "").replace(" ", "")
@validator('plate')
def clean_plate(cls, v):
return v.upper().replace("-", "").replace(" ", "")
@validator('mileage')
def positive_mileage(cls, v):
if v < 0: raise ValueError('Negatív km nem lehet')
return v
class InviteRequest(BaseModel):
email: EmailStr
role: str # 'DRIVER', 'FLEET_MANAGER'
access_level: str # 'FULL', 'LOG_ONLY'
# --- VÉGPONTOK ---
@app.get("/api/vehicles")
async def get_vehicles():
async with AsyncSessionLocal() as session:
result = await session.execute(text("""
SELECT vm.id, m.name as brand, vm.model_name, vm.category
FROM ref.vehicle_models vm
JOIN ref.vehicle_makes m ON vm.make_id = m.id
ORDER BY m.name, vm.model_name
"""))
return [{"id": r.id, "brand": r.brand, "model": r.model_name, "category": r.category} for r in result.fetchall()]
@app.get("/api/my_vehicles")
async def get_my_garage():
user_id = 1
async with AsyncSessionLocal() as session:
query = text("""
SELECT v.id as vehicle_id, v.vin, v.current_plate, m.name as brand, mo.model_name, mo.category, vh.start_mileage, vh.role
FROM data.vehicle_history vh
JOIN data.vehicles v ON vh.vehicle_id = v.id
JOIN ref.vehicle_models mo ON v.model_id = mo.id
JOIN ref.vehicle_makes m ON mo.make_id = m.id
WHERE vh.user_id = :uid AND vh.end_date IS NULL
ORDER BY vh.start_date DESC
""")
result = await session.execute(query, {"uid": user_id})
return [{"vehicle_id": r.vehicle_id, "brand": r.brand, "model": r.model_name, "plate": r.current_plate, "category": r.category, "role": r.role} for r in result.fetchall()]
@app.post("/api/register")
async def register_vehicle(data: VehicleRegister):
async with AsyncSessionLocal() as session:
async with session.begin():
res = await session.execute(text("SELECT id FROM data.vehicles WHERE vin = :vin"), {"vin": data.vin})
vid = res.scalar()
if not vid:
ins = text("INSERT INTO data.vehicles (model_id, vin, current_plate) VALUES (:mid, :vin, :plt) RETURNING id")
r = await session.execute(ins, {"mid": data.model_id, "vin": data.vin, "plt": data.plate})
vid = r.scalar()
hist = text("INSERT INTO data.vehicle_history (vehicle_id, user_id, role, start_date, start_mileage) VALUES (:vid, 1, :role, :sd, :sm)")
await session.execute(hist, {"vid": vid, "role": data.role, "sd": data.purchase_date, "sm": data.mileage})
return {"status": "success"}
# --- ÚJ FLOTTA VÉGPONTOK ---
# 1. Csapat lista
@app.get("/api/fleet/members")
async def get_team_members():
user_id = 1 # Demo Boss
async with AsyncSessionLocal() as session:
# Lekérjük a fleet_members táblát összekötve a users-el
query = text("""
SELECT u.email, fm.role, fm.joined_at, u.country
FROM data.fleet_members fm
JOIN data.users u ON fm.user_id = u.id
WHERE fm.owner_id = :uid
""")
result = await session.execute(query, {"uid": user_id})
return [{"email": r.email, "role": r.role, "joined_at": r.joined_at, "country": r.country} for r in result.fetchall()]
# 2. Meghívó küldése
@app.post("/api/fleet/invite")
async def invite_member(data: InviteRequest):
user_id = 1
token = str(uuid.uuid4()) # Generálunk egy egyedi kódot
async with AsyncSessionLocal() as session:
async with session.begin():
# MENTÉS az invitations táblába
await session.execute(text("""
INSERT INTO data.invitations (email, inviter_id, role, access_level, token, expires_at)
VALUES (:email, :uid, :role, :lvl, :token, NOW() + INTERVAL '7 days')
"""), {
"email": data.email, "uid": user_id, "role": data.role,
"lvl": data.access_level, "token": token
})
# Itt küldenénk az EMAILT a valóságban
print(f"📧 EMAIL KÜLDÉSE: {data.email} -> Link: /invite/{token}")
return {"status": "success", "message": "Meghívó elküldve!", "debug_token": token}
@app.get("/")
async def serve_frontend():
if os.path.exists("/app/frontend/index.html"):
return FileResponse("/app/frontend/index.html")
return {"error": "Frontend hiányzik"}