""" Circumference Tracking Endpoints for Mitai Jinkendo Handles body circumference measurements (8 measurement points). """ import uuid import logging from typing import Optional from fastapi import APIRouter, Header, Depends, HTTPException from db import get_db, get_cursor, r2d from auth import require_auth, check_feature_access, increment_feature_usage from models import CircumferenceEntry from routers.profiles import get_pid from feature_logger import log_feature_usage router = APIRouter(prefix="/api/circumferences", tags=["circumference"]) logger = logging.getLogger(__name__) @router.get("") def list_circs(limit: int=100, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Get circumference entries for current profile.""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute( "SELECT * FROM circumference_log WHERE profile_id=%s ORDER BY date DESC LIMIT %s", (pid,limit)) return [r2d(r) for r in cur.fetchall()] @router.post("") def upsert_circ(e: CircumferenceEntry, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Create or update circumference entry (upsert by date).""" pid = get_pid(x_profile_id) # Phase 4: Check feature access and ENFORCE access = check_feature_access(pid, 'circumference_entries') log_feature_usage(pid, 'circumference_entries', access, 'create') if not access['allowed']: logger.warning( f"[FEATURE-LIMIT] User {pid} blocked: " f"circumference_entries {access['reason']} (used: {access['used']}, limit: {access['limit']})" ) raise HTTPException( status_code=403, detail=f"Limit erreicht: Du hast das Kontingent für Umfangs-Einträge überschritten ({access['used']}/{access['limit']}). " f"Bitte kontaktiere den Admin oder warte bis zum nächsten Reset." ) with get_db() as conn: cur = get_cursor(conn) cur.execute("SELECT id FROM circumference_log WHERE profile_id=%s AND date=%s", (pid,e.date)) ex = cur.fetchone() d = e.model_dump() is_new_entry = not ex if ex: # UPDATE existing entry eid = ex['id'] sets = ', '.join(f"{k}=%s" for k in d if k!='date') cur.execute(f"UPDATE circumference_log SET {sets} WHERE id=%s", [v for k,v in d.items() if k!='date']+[eid]) else: # INSERT new entry eid = str(uuid.uuid4()) cur.execute("""INSERT INTO circumference_log (id,profile_id,date,c_neck,c_chest,c_waist,c_belly,c_hip,c_thigh,c_calf,c_arm,notes,photo_id,created) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,CURRENT_TIMESTAMP)""", (eid,pid,d['date'],d['c_neck'],d['c_chest'],d['c_waist'],d['c_belly'], d['c_hip'],d['c_thigh'],d['c_calf'],d['c_arm'],d['notes'],d['photo_id'])) # Phase 2: Increment usage counter (only for new entries) increment_feature_usage(pid, 'circumference_entries') return {"id":eid,"date":e.date} @router.put("/{eid}") def update_circ(eid: str, e: CircumferenceEntry, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Update existing circumference entry.""" pid = get_pid(x_profile_id) with get_db() as conn: d = e.model_dump() cur = get_cursor(conn) cur.execute(f"UPDATE circumference_log SET {', '.join(f'{k}=%s' for k in d)} WHERE id=%s AND profile_id=%s", list(d.values())+[eid,pid]) return {"id":eid} @router.delete("/{eid}") def delete_circ(eid: str, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Delete circumference entry.""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute("DELETE FROM circumference_log WHERE id=%s AND profile_id=%s", (eid,pid)) return {"ok":True}