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()}