Files
ShooterHub/blueprints/api/utils.py

80 lines
3.1 KiB
Python

from flask import jsonify
from flask_jwt_extended import get_jwt_identity
from extensions import db
from models import User
def ok(data, status=200):
return jsonify({"data": data}), status
def created(data):
return jsonify({"data": data}), 201
def no_content():
return "", 204
def err(message: str, status: int = 400, code: str | None = None):
_codes = {400: "BAD_REQUEST", 401: "UNAUTHORIZED", 403: "FORBIDDEN",
404: "NOT_FOUND", 409: "CONFLICT", 422: "UNPROCESSABLE"}
return jsonify({"error": {"code": code or _codes.get(status, "ERROR"), "message": message}}), status
def current_api_user() -> User | None:
uid = get_jwt_identity()
return db.session.get(User, int(uid)) if uid else None
# ---------------------------------------------------------------------------
# Serializers
# ---------------------------------------------------------------------------
def serialize_user(u) -> dict:
return {"id": u.id, "email": u.email, "display_name": u.display_name,
"avatar_url": u.avatar_url, "provider": u.provider,
"created_at": u.created_at.isoformat()}
def serialize_equipment(item) -> dict:
base = {"id": item.id, "category": item.category, "name": item.name,
"brand": item.brand, "model": item.model, "serial_number": item.serial_number,
"notes": item.notes, "photo_url": item.photo_url,
"created_at": item.created_at.isoformat(), "updated_at": item.updated_at.isoformat()}
if item.category == "scope":
base.update({"magnification": item.magnification, "reticle": item.reticle, "unit": item.unit})
else:
base["caliber"] = item.caliber
return base
def serialize_session_photo(p) -> dict:
return {"id": p.id, "photo_url": p.photo_url, "caption": p.caption,
"created_at": p.created_at.isoformat()}
def serialize_session(s, include_user: bool = False) -> dict:
d = {"id": s.id, "label": s.label, "session_date": s.session_date.isoformat(),
"is_public": s.is_public, "location_name": s.location_name,
"location_lat": s.location_lat, "location_lon": s.location_lon,
"distance_m": s.distance_m, "weather_cond": s.weather_cond,
"weather_temp_c": float(s.weather_temp_c) if s.weather_temp_c is not None else None,
"weather_wind_kph": float(s.weather_wind_kph) if s.weather_wind_kph is not None else None,
"rifle_id": s.rifle_id, "scope_id": s.scope_id,
"ammo_brand": s.ammo_brand,
"ammo_weight_gr": float(s.ammo_weight_gr) if s.ammo_weight_gr is not None else None,
"ammo_lot": s.ammo_lot, "notes": s.notes,
"photos": [serialize_session_photo(p) for p in s.photos],
"created_at": s.created_at.isoformat(), "updated_at": s.updated_at.isoformat()}
if include_user:
d["user"] = serialize_user(s.user)
return d
def serialize_analysis(a) -> dict:
return {"id": a.id, "title": a.title, "is_public": a.is_public,
"shot_count": a.shot_count, "group_count": a.group_count,
"overall_stats": a.overall_stats, "group_stats": a.group_stats,
"session_id": a.session_id, "created_at": a.created_at.isoformat()}