80 lines
3.1 KiB
Python
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()}
|