Nueva tabla telemetry_active(install_id, day) (create_all la crea). add_telemetry hace upsert (install_id, day) si viene install_id. El summary añade installsTotal (únicas de siempre), installsActive (en el periodo) y dauToday. Tests: dos ids únicos + uno duplicado → 2 únicas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
98 lines
3.9 KiB
Python
98 lines
3.9 KiB
Python
"""Modelos de la base de datos: alimentos y recetas del catálogo compartido."""
|
|
from sqlalchemy import Column, Float, Integer, String, JSON, DateTime, func
|
|
|
|
from db import Base
|
|
|
|
|
|
class Food(Base):
|
|
__tablename__ = "foods"
|
|
|
|
id = Column(String, primary_key=True)
|
|
name = Column(String, nullable=False, index=True)
|
|
kcal_100g = Column(Float, nullable=False)
|
|
zone = Column(String, default="otros")
|
|
portions = Column(JSON, default=list) # [{"name","grams"}]
|
|
barcode = Column(String, nullable=True)
|
|
source = Column(String, default="user") # off | user
|
|
off_id = Column(String, nullable=True, index=True)
|
|
author_token = Column(String, nullable=True)
|
|
created_at = Column(DateTime, server_default=func.now())
|
|
|
|
def to_app(self) -> dict:
|
|
"""Serializa a la forma que espera la app (Food.fromJson)."""
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"kcalPer100g": self.kcal_100g,
|
|
"zone": self.zone or "otros",
|
|
"portions": self.portions or [],
|
|
"origin": "remote",
|
|
}
|
|
|
|
|
|
class Recipe(Base):
|
|
__tablename__ = "recipes"
|
|
|
|
id = Column(String, primary_key=True)
|
|
name = Column(String, nullable=False, index=True)
|
|
servings = Column(Integer, default=1)
|
|
items = Column(JSON, default=list) # [{"food": {...}, "grams", "portionLabel"}]
|
|
category = Column(String, default="otros")
|
|
prep_minutes = Column(Integer, nullable=True)
|
|
steps = Column(JSON, default=list) # ["paso 1", "paso 2"]
|
|
notes = Column(String, nullable=True)
|
|
author_id = Column(String, nullable=True, index=True)
|
|
author_name = Column(String, nullable=True)
|
|
parent_id = Column(String, nullable=True)
|
|
parent_author_name = Column(String, nullable=True)
|
|
root_id = Column(String, nullable=True)
|
|
root_author_name = Column(String, nullable=True)
|
|
visibility = Column(String, default="public", index=True)
|
|
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
|
author_token = Column(String, nullable=True)
|
|
created_at = Column(DateTime, server_default=func.now())
|
|
|
|
def to_app(self) -> dict:
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"servings": self.servings,
|
|
"items": self.items or [],
|
|
"category": self.category or "otros",
|
|
"prepMinutes": self.prep_minutes,
|
|
"steps": self.steps or [],
|
|
"notes": self.notes,
|
|
"authorId": self.author_id,
|
|
"authorName": self.author_name,
|
|
"parentId": self.parent_id,
|
|
"parentAuthorName": self.parent_author_name,
|
|
"rootId": self.root_id,
|
|
"rootAuthorName": self.root_author_name,
|
|
"visibility": self.visibility or "public",
|
|
}
|
|
|
|
|
|
class TelemetryDaily(Base):
|
|
"""Contadores de uso ANÓNIMOS y agregados, por día y módulo. NO hay
|
|
identificador de usuario ni contenido de salud: solo cuántas instalaciones
|
|
tienen cada módulo activo (`active`) y cuántas veces lo abren (`opens`). La
|
|
fila especial module='__submissions__' cuenta los envíos del día (≈ nº de
|
|
instalaciones activas que ceden estadística)."""
|
|
__tablename__ = "telemetry_daily"
|
|
|
|
day = Column(String, primary_key=True) # 'YYYY-MM-DD'
|
|
module = Column(String, primary_key=True) # nombre del módulo/vista o '__submissions__'
|
|
active = Column(Integer, default=0)
|
|
opens = Column(Integer, default=0)
|
|
seconds = Column(Integer, default=0) # tiempo en pantalla acumulado
|
|
|
|
|
|
class TelemetryActive(Base):
|
|
"""Presencia (instalación, día) para contar instalaciones ÚNICAS, DAU/MAU y
|
|
retención. El install_id es un identificador anónimo de la instalación (un
|
|
número aleatorio, sin nada personal)."""
|
|
__tablename__ = "telemetry_active"
|
|
|
|
install_id = Column(String, primary_key=True)
|
|
day = Column(String, primary_key=True) # 'YYYY-MM-DD'
|