Spaces:
Running
Running
GitHub Action commited on
Commit ·
be94759
1
Parent(s): c6b12ce
Despliegue limpio sin archivos pesados
Browse files- .env.example +62 -0
- .gitattributes +0 -35
- CAMBIOS_REALIZADOS.md +14 -0
- app/models/aprendizaje.py +0 -110
- app/models/iglesia.py +0 -218
- app/models/lyrics.py +0 -120
- app/models/midi.py +0 -19
- app/models/process.py +0 -59
- app/models/sync.py +0 -32
- app/models/user.py +0 -116
- models/btc_chord.pth +0 -3
- tunnel_url.txt +1 -0
.env.example
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ==========================================
|
| 2 |
+
# MELODIX - Variables de Entorno
|
| 3 |
+
# ==========================================
|
| 4 |
+
# Copia este archivo a .env y ajusta los valores
|
| 5 |
+
|
| 6 |
+
# --- BASE DE DATOS ---
|
| 7 |
+
# PostgreSQL (producción):
|
| 8 |
+
# DATABASE_URL=postgresql://usuario:password@localhost:5432/melodix_db
|
| 9 |
+
# SQLite (desarrollo - dejar comentado para usar SQLite por defecto)
|
| 10 |
+
# DATABASE_URL=
|
| 11 |
+
|
| 12 |
+
# --- SEGURIDAD ---
|
| 13 |
+
# Clave secreta para JWT (cambiar en producción)
|
| 14 |
+
SECRET_KEY=tu_clave_secreta_muy_segura_cambia_esto_en_produccion_2024
|
| 15 |
+
ALGORITHM=HS256
|
| 16 |
+
ACCESS_TOKEN_EXPIRE_MINUTES=43200
|
| 17 |
+
|
| 18 |
+
# --- SUPABASE ---
|
| 19 |
+
SUPABASE_JWT_SECRET=tu_supabase_jwt_secret_aqui
|
| 20 |
+
|
| 21 |
+
# Contraseña por defecto para el usuario administrador inicial (isaacsalgado105@gmail.com)
|
| 22 |
+
DEFAULT_ADMIN_PASSWORD=Dis147258369
|
| 23 |
+
|
| 24 |
+
# --- REDIS (Celery) ---
|
| 25 |
+
# Redis local (desarrollo)
|
| 26 |
+
REDIS_URL=redis://localhost:6379/0
|
| 27 |
+
# Redis con contraseña (producción)
|
| 28 |
+
# REDIS_URL=redis://:tu_password_redis@localhost:6379/0
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# --- BACKBLAZE B2 (almacenamiento de stems Premium/Grupos) ---
|
| 32 |
+
# Crear bucket privado en https://secure.backblaze.com/b2_buckets.htm
|
| 33 |
+
# Crear Application Key en https://secure.backblaze.com/app_keys.htm
|
| 34 |
+
B2_KEY_ID=tu_key_id_aqui
|
| 35 |
+
B2_APPLICATION_KEY=tu_application_key_aqui
|
| 36 |
+
B2_ENDPOINT=https://s3.us-east-005.backblazeb2.com
|
| 37 |
+
B2_BUCKET_NAME=melodix-stems
|
| 38 |
+
|
| 39 |
+
# --- DIRECTORIOS ---
|
| 40 |
+
BASE_DIR=C:\mfmm
|
| 41 |
+
PROCESSED_DIR=C:\mfmm\processed
|
| 42 |
+
UPLOADS_DIR=C:\mfmm\uploads
|
| 43 |
+
|
| 44 |
+
# --- DEMUCS ---
|
| 45 |
+
# Modelo por defecto: htdemucs, mdx_extra, htdemucs_6s
|
| 46 |
+
DEFAULT_MODEL=htdemucs
|
| 47 |
+
# Dispositivo: cuda, cpu
|
| 48 |
+
DEFAULT_DEVICE=cuda
|
| 49 |
+
|
| 50 |
+
# --- LIMITES DE ARCHIVOS ---
|
| 51 |
+
# Tamaño máximo de archivo en MB
|
| 52 |
+
MAX_FILE_SIZE_MB=100
|
| 53 |
+
# Extensiones permitidas
|
| 54 |
+
ALLOWED_EXTENSIONS=mp3,wav,flac,m4a,aac,ogg
|
| 55 |
+
|
| 56 |
+
# --- CORS ---
|
| 57 |
+
# Orígenes permitidos (separados por coma)
|
| 58 |
+
ALLOWED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
|
| 59 |
+
|
| 60 |
+
# --- AWS COMPATIBILIDAD CON TEBI ---
|
| 61 |
+
# AWS_REQUEST_CHECKSUM_CALCULATION=when_required
|
| 62 |
+
# AWS_RESPONSE_CHECKSUM_VALIDATION=when_required
|
.gitattributes
DELETED
|
@@ -1,35 +0,0 @@
|
|
| 1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CAMBIOS_REALIZADOS.md
CHANGED
|
@@ -271,3 +271,17 @@ Si encuentras errores:
|
|
| 271 |
---
|
| 272 |
|
| 273 |
**¡Todo está listo para usar Melodix v2.0! 🎵**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
---
|
| 272 |
|
| 273 |
**¡Todo está listo para usar Melodix v2.0! 🎵**
|
| 274 |
+
|
| 275 |
+
---
|
| 276 |
+
|
| 277 |
+
## 📱 Sincronización y Caché Offline en Melodix Mobile (v2.1)
|
| 278 |
+
|
| 279 |
+
| Archivo | Cambio |
|
| 280 |
+
|---------|--------|
|
| 281 |
+
| `MelodixMobile/src/services/api.js` | Implementación de fallback en caché offline (búsqueda por prefijo si la clave exacta de parámetros falla) y soporte de peticiones silenciadas para evitar alertas molestas de conexión. |
|
| 282 |
+
| `MelodixMobile/src/screens/iglesia/FinanzasScreen.js` | Carga de caché usando los parámetros dinámicos de fechas del mes y actualizaciones silenciosas. |
|
| 283 |
+
| `MelodixMobile/src/screens/iglesia/InventarioScreen.js` | Carga de caché admitiendo listas vacías sin bloquear la interfaz y refresco automático silenciado. |
|
| 284 |
+
| `MelodixMobile/src/screens/iglesia/MomentosScreen.js` | Soporte de caché en momentos y miembros sin validaciones restrictivas de longitud, y refresco silencioso. |
|
| 285 |
+
| `MelodixMobile/src/components/OfflineSyncBanner.js` | Registro global del callback de conflictos de asistencia offline para alertar en cualquier pantalla. |
|
| 286 |
+
| `MelodixMobile/src/screens/iglesia/TomarAsistenciaScreen.js` | Remoción del callback de conflicto local para evitar race conditions al desmontar. |
|
| 287 |
+
| `MelodixMobile/src/navigation/AppNavigator.js` | Remoción del chequeo de torneos en el montaje inicial, evitando redirección no deseada al Quiz en Expo. |
|
app/models/aprendizaje.py
DELETED
|
@@ -1,110 +0,0 @@
|
|
| 1 |
-
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Text, Float
|
| 2 |
-
from sqlalchemy.orm import relationship
|
| 3 |
-
from datetime import datetime
|
| 4 |
-
from app.database import Base
|
| 5 |
-
from app.models.user import User
|
| 6 |
-
from app.models.iglesia import Iglesia
|
| 7 |
-
|
| 8 |
-
class BibliaLibro(Base):
|
| 9 |
-
__tablename__ = "biblia_libros"
|
| 10 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 11 |
-
nombre = Column(String, index=True)
|
| 12 |
-
testamento = Column(String) # "Antiguo" o "Nuevo"
|
| 13 |
-
|
| 14 |
-
class BibliaVersiculo(Base):
|
| 15 |
-
__tablename__ = "biblia_versiculos"
|
| 16 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 17 |
-
libro_id = Column(Integer, ForeignKey("biblia_libros.id"))
|
| 18 |
-
capitulo = Column(Integer, index=True)
|
| 19 |
-
versiculo = Column(Integer, index=True)
|
| 20 |
-
texto = Column(Text)
|
| 21 |
-
|
| 22 |
-
libro = relationship("BibliaLibro")
|
| 23 |
-
|
| 24 |
-
class PlanLectura(Base):
|
| 25 |
-
__tablename__ = "planes_lectura"
|
| 26 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 27 |
-
nombre = Column(String)
|
| 28 |
-
descripcion = Column(Text)
|
| 29 |
-
dias_totales = Column(Integer)
|
| 30 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 31 |
-
|
| 32 |
-
class DiaLectura(Base):
|
| 33 |
-
__tablename__ = "dias_lectura"
|
| 34 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 35 |
-
plan_id = Column(Integer, ForeignKey("planes_lectura.id"))
|
| 36 |
-
dia_numero = Column(Integer)
|
| 37 |
-
pasajes = Column(String) # "Génesis 1-3"
|
| 38 |
-
titulo = Column(String, nullable=True)
|
| 39 |
-
|
| 40 |
-
plan = relationship("PlanLectura")
|
| 41 |
-
|
| 42 |
-
class PreguntaQuiz(Base):
|
| 43 |
-
__tablename__ = "preguntas_quiz"
|
| 44 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 45 |
-
dia_lectura_id = Column(Integer, ForeignKey("dias_lectura.id"))
|
| 46 |
-
tipo = Column(String) # multiple, verdadero_falso, unir, manual
|
| 47 |
-
pregunta = Column(String)
|
| 48 |
-
opciones = Column(Text) # JSON string
|
| 49 |
-
respuesta_correcta = Column(String)
|
| 50 |
-
|
| 51 |
-
dia_lectura = relationship("DiaLectura")
|
| 52 |
-
|
| 53 |
-
class ProgresoPlan(Base):
|
| 54 |
-
__tablename__ = "progresos_plan"
|
| 55 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 56 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 57 |
-
plan_id = Column(Integer, ForeignKey("planes_lectura.id"))
|
| 58 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id", ondelete="CASCADE"), nullable=True)
|
| 59 |
-
dia_actual = Column(Integer, default=1)
|
| 60 |
-
completado = Column(Boolean, default=False)
|
| 61 |
-
ultima_lectura_fecha = Column(String, nullable=True) # "YYYY-MM-DD"
|
| 62 |
-
racha_actual = Column(Integer, default=0)
|
| 63 |
-
repaso_completado_hasta = Column(Integer, default=0)
|
| 64 |
-
escudos_racha = Column(Integer, default=0)
|
| 65 |
-
|
| 66 |
-
user = relationship("User")
|
| 67 |
-
plan = relationship("PlanLectura")
|
| 68 |
-
iglesia = relationship("Iglesia")
|
| 69 |
-
|
| 70 |
-
class PuntuacionLiga(Base):
|
| 71 |
-
__tablename__ = "puntuaciones_liga"
|
| 72 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 73 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 74 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 75 |
-
puntos_totales = Column(Integer, default=0)
|
| 76 |
-
maxima_racha = Column(Integer, default=0)
|
| 77 |
-
|
| 78 |
-
user = relationship("User")
|
| 79 |
-
iglesia = relationship("Iglesia")
|
| 80 |
-
|
| 81 |
-
class Torneo(Base):
|
| 82 |
-
__tablename__ = "torneos"
|
| 83 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 84 |
-
codigo = Column(String, unique=True, index=True) # e.g. "BIB-7A2F"
|
| 85 |
-
nombre = Column(String)
|
| 86 |
-
creador_id = Column(Integer, ForeignKey("users.id"))
|
| 87 |
-
estado = Column(String, default="activo") # "activo", "desempate", "terminado"
|
| 88 |
-
ganador_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
| 89 |
-
preguntas_json = Column(Text) # JSON list of 5 question IDs
|
| 90 |
-
desempate_preguntas_json = Column(Text, nullable=True)
|
| 91 |
-
fecha_creacion = Column(String)
|
| 92 |
-
primero_termino_en = Column(String, nullable=True)
|
| 93 |
-
|
| 94 |
-
creador = relationship("User", foreign_keys=[creador_id])
|
| 95 |
-
ganador = relationship("User", foreign_keys=[ganador_id])
|
| 96 |
-
|
| 97 |
-
class ParticipanteTorneo(Base):
|
| 98 |
-
__tablename__ = "participantes_torneo"
|
| 99 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 100 |
-
torneo_id = Column(Integer, ForeignKey("torneos.id"))
|
| 101 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 102 |
-
score = Column(Integer, default=0)
|
| 103 |
-
tiempo_empleado = Column(Float, default=0.0) # seconds taken
|
| 104 |
-
score_desempate = Column(Integer, default=0)
|
| 105 |
-
tiempo_desempate = Column(Float, default=0.0)
|
| 106 |
-
eliminado = Column(Boolean, default=False)
|
| 107 |
-
estado = Column(String, default="pendiente") # "pendiente", "jugado", "desempate_pendiente", "desempate_jugado"
|
| 108 |
-
|
| 109 |
-
user = relationship("User")
|
| 110 |
-
torneo = relationship("Torneo")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models/iglesia.py
DELETED
|
@@ -1,218 +0,0 @@
|
|
| 1 |
-
# ==========================================
|
| 2 |
-
# MELODIX - Modelos de Iglesia
|
| 3 |
-
# ==========================================
|
| 4 |
-
|
| 5 |
-
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Float, Text
|
| 6 |
-
from sqlalchemy.orm import relationship
|
| 7 |
-
from datetime import datetime
|
| 8 |
-
from app.database import Base
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
class Iglesia(Base):
|
| 12 |
-
__tablename__ = "iglesias"
|
| 13 |
-
|
| 14 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 15 |
-
nombre = Column(String, index=True)
|
| 16 |
-
pastor = Column(String)
|
| 17 |
-
codigo = Column(String(5), unique=True, index=True) # Código único de 5 dígitos
|
| 18 |
-
admin_id = Column(Integer, ForeignKey("users.id"))
|
| 19 |
-
icono = Column(String, nullable=True)
|
| 20 |
-
foto_base64 = Column(Text, nullable=True)
|
| 21 |
-
foto_pastor = Column(String, nullable=True)
|
| 22 |
-
imgbb_api_key = Column(String(100), nullable=True)
|
| 23 |
-
requiere_aprobacion = Column(Boolean, default=False)
|
| 24 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 25 |
-
|
| 26 |
-
admin = relationship("User")
|
| 27 |
-
miembros_app = relationship("IglesiaMember", back_populates="iglesia")
|
| 28 |
-
miembros = relationship("Miembro", back_populates="iglesia")
|
| 29 |
-
calendarios = relationship("Calendario", back_populates="iglesia")
|
| 30 |
-
finanzas = relationship("Finanza", back_populates="iglesia")
|
| 31 |
-
momentos = relationship("Momento", back_populates="iglesia")
|
| 32 |
-
inventario = relationship("Inventario", back_populates="iglesia")
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
class IglesiaRol(Base):
|
| 36 |
-
"""Roles personalizados y granulares de la iglesia (RBAC)"""
|
| 37 |
-
__tablename__ = "iglesia_roles"
|
| 38 |
-
|
| 39 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 40 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 41 |
-
nombre = Column(String) # Administrador, Tesorero, Lider, Miembro
|
| 42 |
-
descripcion = Column(String, nullable=True)
|
| 43 |
-
permisos = Column(Text) # JSON string con permisos granulares (CRUD por modulo)
|
| 44 |
-
is_system = Column(Boolean, default=False) # Para roles fijos que no se pueden borrar
|
| 45 |
-
|
| 46 |
-
iglesia = relationship("Iglesia")
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
class IglesiaMember(Base):
|
| 50 |
-
"""Usuarios de la app que pertenecen a esta iglesia"""
|
| 51 |
-
__tablename__ = "iglesia_members"
|
| 52 |
-
|
| 53 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 54 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 55 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 56 |
-
rol = Column(String, default="miembro") # Mantenido por retrocompatibilidad temporal
|
| 57 |
-
rol_id = Column(Integer, ForeignKey("iglesia_roles.id"), nullable=True)
|
| 58 |
-
estado = Column(String, default="activo") # activo, pendiente, expulsado
|
| 59 |
-
joined_at = Column(DateTime, default=datetime.utcnow)
|
| 60 |
-
|
| 61 |
-
iglesia = relationship("Iglesia", back_populates="miembros_app")
|
| 62 |
-
user = relationship("User")
|
| 63 |
-
rol_obj = relationship("IglesiaRol")
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
class Miembro(Base):
|
| 67 |
-
"""Personas registradas en la iglesia (no necesariamente usuarios de la app)"""
|
| 68 |
-
__tablename__ = "miembros"
|
| 69 |
-
|
| 70 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 71 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 72 |
-
nombre_completo = Column(String, index=True)
|
| 73 |
-
tipo = Column(String) # Caballero, Dama, Señorita, Joven, Niño, Niña
|
| 74 |
-
edad = Column(Integer, nullable=True)
|
| 75 |
-
fecha_nacimiento = Column(String, nullable=True) # Guardado como string "YYYY-MM-DD"
|
| 76 |
-
documento_identidad = Column(String, nullable=True)
|
| 77 |
-
foto_base64 = Column(Text, nullable=True) # Foto en Base64 reducida
|
| 78 |
-
activo = Column(Boolean, default=True)
|
| 79 |
-
telefono = Column(String, nullable=True)
|
| 80 |
-
direccion = Column(String, nullable=True)
|
| 81 |
-
estado = Column(String, default="Activo") # Activo, Visita
|
| 82 |
-
ministerio = Column(String, default="Miembro")
|
| 83 |
-
user_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
| 84 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 85 |
-
|
| 86 |
-
iglesia = relationship("Iglesia", back_populates="miembros")
|
| 87 |
-
user = relationship("User")
|
| 88 |
-
asistencias = relationship("Asistencia", back_populates="miembro")
|
| 89 |
-
momentos = relationship("Momento", back_populates="miembro")
|
| 90 |
-
relaciones = relationship("RelacionFamiliar", foreign_keys="[RelacionFamiliar.miembro_id]")
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
class RelacionFamiliar(Base):
|
| 94 |
-
__tablename__ = "relaciones_familiares"
|
| 95 |
-
|
| 96 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 97 |
-
miembro_id = Column(Integer, ForeignKey("miembros.id"))
|
| 98 |
-
pariente_id = Column(Integer, ForeignKey("miembros.id"))
|
| 99 |
-
tipo_relacion = Column(String) # Padre, Hijo, Esposo, Esposa, etc.
|
| 100 |
-
|
| 101 |
-
miembro = relationship("Miembro", foreign_keys=[miembro_id])
|
| 102 |
-
pariente = relationship("Miembro", foreign_keys=[pariente_id])
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
class Calendario(Base):
|
| 106 |
-
__tablename__ = "calendarios"
|
| 107 |
-
|
| 108 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 109 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 110 |
-
nombre = Column(String) # "Culto Dominical", "Limpieza", etc.
|
| 111 |
-
icono = Column(String, default="calendar")
|
| 112 |
-
color_fondo = Column(String, default="#CE93D8")
|
| 113 |
-
created_by = Column(Integer, ForeignKey("users.id"))
|
| 114 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 115 |
-
|
| 116 |
-
iglesia = relationship("Iglesia", back_populates="calendarios")
|
| 117 |
-
creator = relationship("User")
|
| 118 |
-
servicios = relationship("Servicio", back_populates="calendario")
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
class Servicio(Base):
|
| 122 |
-
"""Un día específico de servicio dentro de un calendario"""
|
| 123 |
-
__tablename__ = "servicios"
|
| 124 |
-
|
| 125 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 126 |
-
calendario_id = Column(Integer, ForeignKey("calendarios.id"))
|
| 127 |
-
nombre = Column(String, nullable=True) # Nombre del servicio/evento
|
| 128 |
-
fecha = Column(String) # "YYYY-MM-DD"
|
| 129 |
-
descripcion = Column(String, nullable=True)
|
| 130 |
-
hora = Column(String, nullable=True)
|
| 131 |
-
color_fondo = Column(String, nullable=True)
|
| 132 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 133 |
-
|
| 134 |
-
calendario = relationship("Calendario", back_populates="servicios")
|
| 135 |
-
asistencias = relationship("Asistencia", back_populates="servicio")
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
class Asistencia(Base):
|
| 139 |
-
__tablename__ = "asistencias"
|
| 140 |
-
|
| 141 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 142 |
-
servicio_id = Column(Integer, ForeignKey("servicios.id"))
|
| 143 |
-
miembro_id = Column(Integer, ForeignKey("miembros.id"))
|
| 144 |
-
asistio = Column(Boolean, default=False)
|
| 145 |
-
registrado_por = Column(Integer, ForeignKey("users.id"))
|
| 146 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 147 |
-
|
| 148 |
-
servicio = relationship("Servicio", back_populates="asistencias")
|
| 149 |
-
miembro = relationship("Miembro", back_populates="asistencias")
|
| 150 |
-
registrador = relationship("User")
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
class Finanza(Base):
|
| 154 |
-
__tablename__ = "finanzas"
|
| 155 |
-
|
| 156 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 157 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 158 |
-
tipo = Column(String) # "entrada" | "salida"
|
| 159 |
-
monto = Column(Float)
|
| 160 |
-
concepto = Column(String)
|
| 161 |
-
responsable = Column(String) # Nombre libre de quien realizó el movimiento
|
| 162 |
-
registrado_por = Column(Integer, ForeignKey("users.id")) # Usuario de la app
|
| 163 |
-
fecha = Column(DateTime, default=datetime.utcnow)
|
| 164 |
-
reference_uuid = Column(String, unique=True, nullable=True, index=True)
|
| 165 |
-
|
| 166 |
-
iglesia = relationship("Iglesia", back_populates="finanzas")
|
| 167 |
-
registrador = relationship("User")
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
class Momento(Base):
|
| 171 |
-
"""Momentos espirituales importantes: bautizos, reconciliaciones, etc."""
|
| 172 |
-
__tablename__ = "momentos"
|
| 173 |
-
|
| 174 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 175 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 176 |
-
miembro_id = Column(Integer, ForeignKey("miembros.id"), nullable=True)
|
| 177 |
-
tipo = Column(String) # "Bautizo", "Reconciliación", "Aceptar a Cristo", etc.
|
| 178 |
-
descripcion = Column(Text, nullable=True)
|
| 179 |
-
fecha = Column(String) # "YYYY-MM-DD"
|
| 180 |
-
registrado_por = Column(Integer, ForeignKey("users.id"))
|
| 181 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 182 |
-
|
| 183 |
-
iglesia = relationship("Iglesia", back_populates="momentos")
|
| 184 |
-
miembro = relationship("Miembro", back_populates="momentos")
|
| 185 |
-
registrador = relationship("User")
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
class Inventario(Base):
|
| 189 |
-
__tablename__ = "inventario"
|
| 190 |
-
|
| 191 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 192 |
-
iglesia_id = Column(Integer, ForeignKey("iglesias.id"))
|
| 193 |
-
nombre = Column(String)
|
| 194 |
-
marca = Column(String)
|
| 195 |
-
cantidad = Column(Integer)
|
| 196 |
-
fecha_compra = Column(String)
|
| 197 |
-
precio = Column(Float)
|
| 198 |
-
foto_url = Column(Text, nullable=True)
|
| 199 |
-
estado = Column(String, default="Activo")
|
| 200 |
-
nota = Column(Text, nullable=True)
|
| 201 |
-
registrado_por = Column(Integer, ForeignKey("users.id"))
|
| 202 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 203 |
-
|
| 204 |
-
iglesia = relationship("Iglesia", back_populates="inventario")
|
| 205 |
-
registrador = relationship("User")
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
class DismissedVisita(Base):
|
| 209 |
-
"""Notificaciones de visita que un administrador en particular ya marcó como vista/leída"""
|
| 210 |
-
__tablename__ = "dismissed_visitas"
|
| 211 |
-
|
| 212 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 213 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 214 |
-
miembro_id = Column(Integer, ForeignKey("miembros.id"))
|
| 215 |
-
dismissed_at = Column(DateTime, default=datetime.utcnow)
|
| 216 |
-
|
| 217 |
-
user = relationship("User")
|
| 218 |
-
miembro = relationship("Miembro")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models/lyrics.py
DELETED
|
@@ -1,120 +0,0 @@
|
|
| 1 |
-
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Table, Boolean
|
| 2 |
-
from sqlalchemy.orm import relationship
|
| 3 |
-
from datetime import datetime
|
| 4 |
-
from app.database import Base
|
| 5 |
-
|
| 6 |
-
lyric_groups = Table(
|
| 7 |
-
"lyric_groups",
|
| 8 |
-
Base.metadata,
|
| 9 |
-
Column("lyric_id", Integer, ForeignKey("lyrics.id", ondelete="CASCADE"), primary_key=True),
|
| 10 |
-
Column("group_id", Integer, ForeignKey("groups.id", ondelete="CASCADE"), primary_key=True),
|
| 11 |
-
)
|
| 12 |
-
|
| 13 |
-
task_groups = Table(
|
| 14 |
-
"task_groups",
|
| 15 |
-
Base.metadata,
|
| 16 |
-
Column("task_id", Integer, ForeignKey("tasks.id", ondelete="CASCADE"), primary_key=True),
|
| 17 |
-
Column("group_id", Integer, ForeignKey("groups.id", ondelete="CASCADE"), primary_key=True),
|
| 18 |
-
)
|
| 19 |
-
|
| 20 |
-
class Group(Base):
|
| 21 |
-
__tablename__ = "groups"
|
| 22 |
-
|
| 23 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 24 |
-
name = Column(String, index=True)
|
| 25 |
-
codigo = Column(String, unique=True, index=True, nullable=True)
|
| 26 |
-
foto_base64 = Column(String, nullable=True)
|
| 27 |
-
requiere_aprobacion = Column(Boolean, default=False)
|
| 28 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 29 |
-
|
| 30 |
-
members = relationship("UserGroup", back_populates="group")
|
| 31 |
-
lyrics = relationship("Lyric", back_populates="group")
|
| 32 |
-
repertorios = relationship("Repertorio", back_populates="group")
|
| 33 |
-
lyrics_shared = relationship("Lyric", secondary=lyric_groups, back_populates="groups_shared")
|
| 34 |
-
tasks_shared = relationship("Task", secondary=task_groups, back_populates="groups_shared")
|
| 35 |
-
|
| 36 |
-
class UserGroup(Base):
|
| 37 |
-
__tablename__ = "user_groups"
|
| 38 |
-
|
| 39 |
-
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
| 40 |
-
group_id = Column(Integer, ForeignKey("groups.id"), primary_key=True)
|
| 41 |
-
role = Column(String, default="member") # admin, member
|
| 42 |
-
estado = Column(String, default="activo") # activo, pendiente, expulsado
|
| 43 |
-
joined_at = Column(DateTime, default=datetime.utcnow)
|
| 44 |
-
|
| 45 |
-
# Permisos granulares
|
| 46 |
-
perm_compartir_pistas = Column(Boolean, default=True)
|
| 47 |
-
perm_compartir_letras = Column(Boolean, default=True)
|
| 48 |
-
perm_crud_repertorios = Column(Boolean, default=False)
|
| 49 |
-
perm_crud_letras = Column(Boolean, default=True)
|
| 50 |
-
perm_ver_pistas = Column(Boolean, default=True)
|
| 51 |
-
perm_ver_letras = Column(Boolean, default=True)
|
| 52 |
-
perm_ver_repertorios = Column(Boolean, default=True)
|
| 53 |
-
perm_gestionar_solicitudes = Column(Boolean, default=False)
|
| 54 |
-
|
| 55 |
-
# Registro de última lectura para notificaciones
|
| 56 |
-
last_read_pistas = Column(DateTime, nullable=True, default=None)
|
| 57 |
-
last_read_letras = Column(DateTime, nullable=True, default=None)
|
| 58 |
-
last_read_repertorios = Column(DateTime, nullable=True, default=None)
|
| 59 |
-
|
| 60 |
-
user = relationship("User", back_populates="groups")
|
| 61 |
-
group = relationship("Group", back_populates="members")
|
| 62 |
-
|
| 63 |
-
class Lyric(Base):
|
| 64 |
-
__tablename__ = "lyrics"
|
| 65 |
-
|
| 66 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 67 |
-
title = Column(String, index=True)
|
| 68 |
-
artist = Column(String, index=True)
|
| 69 |
-
content = Column(String) # ChordPro format
|
| 70 |
-
key = Column(String) # Original key (e.g., "C")
|
| 71 |
-
group_id = Column(Integer, ForeignKey("groups.id"))
|
| 72 |
-
created_by = Column(Integer, ForeignKey("users.id"))
|
| 73 |
-
transpose_offset = Column(Integer, default=0, nullable=True)
|
| 74 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 75 |
-
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 76 |
-
|
| 77 |
-
group = relationship("Group", back_populates="lyrics")
|
| 78 |
-
creator = relationship("User")
|
| 79 |
-
groups_shared = relationship("Group", secondary=lyric_groups, back_populates="lyrics_shared")
|
| 80 |
-
|
| 81 |
-
@property
|
| 82 |
-
def group_ids(self):
|
| 83 |
-
return [g.id for g in self.groups_shared]
|
| 84 |
-
|
| 85 |
-
class Repertorio(Base):
|
| 86 |
-
__tablename__ = "repertorios"
|
| 87 |
-
|
| 88 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 89 |
-
name = Column(String, index=True)
|
| 90 |
-
group_id = Column(Integer, ForeignKey("groups.id"))
|
| 91 |
-
created_by = Column(Integer, ForeignKey("users.id"))
|
| 92 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 93 |
-
|
| 94 |
-
group = relationship("Group", back_populates="repertorios")
|
| 95 |
-
creator = relationship("User")
|
| 96 |
-
lyrics = relationship("RepertorioLyric", back_populates="repertorio")
|
| 97 |
-
|
| 98 |
-
class RepertorioLyric(Base):
|
| 99 |
-
__tablename__ = "repertorio_lyrics"
|
| 100 |
-
|
| 101 |
-
repertorio_id = Column(Integer, ForeignKey("repertorios.id"), primary_key=True)
|
| 102 |
-
lyric_id = Column(Integer, ForeignKey("lyrics.id"), primary_key=True)
|
| 103 |
-
order = Column(Integer) # Order in the setlist
|
| 104 |
-
|
| 105 |
-
repertorio = relationship("Repertorio", back_populates="lyrics")
|
| 106 |
-
lyric = relationship("Lyric")
|
| 107 |
-
|
| 108 |
-
class Invitation(Base):
|
| 109 |
-
__tablename__ = "invitations"
|
| 110 |
-
|
| 111 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 112 |
-
code = Column(String, unique=True, index=True) # Unique code or link token
|
| 113 |
-
group_id = Column(Integer, ForeignKey("groups.id"))
|
| 114 |
-
created_by = Column(Integer, ForeignKey("users.id"))
|
| 115 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 116 |
-
expires_at = Column(DateTime)
|
| 117 |
-
used_at = Column(DateTime) # Nullable, if used
|
| 118 |
-
|
| 119 |
-
group = relationship("Group")
|
| 120 |
-
creator = relationship("User")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models/midi.py
DELETED
|
@@ -1,19 +0,0 @@
|
|
| 1 |
-
from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey
|
| 2 |
-
from sqlalchemy.orm import relationship
|
| 3 |
-
from datetime import datetime
|
| 4 |
-
from app.database import Base
|
| 5 |
-
|
| 6 |
-
class PartituraMidi(Base):
|
| 7 |
-
__tablename__ = "partituras_midi"
|
| 8 |
-
|
| 9 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 10 |
-
title = Column(String, index=True, nullable=False)
|
| 11 |
-
artist = Column(String, default="Artista desconocido")
|
| 12 |
-
filename = Column(String, nullable=False)
|
| 13 |
-
filepath = Column(String, nullable=False)
|
| 14 |
-
tempo_bpm = Column(Float, default=120.0)
|
| 15 |
-
device_id = Column(String, index=True, nullable=True)
|
| 16 |
-
user_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
| 17 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 18 |
-
|
| 19 |
-
user = relationship("User")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models/process.py
DELETED
|
@@ -1,59 +0,0 @@
|
|
| 1 |
-
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Text
|
| 2 |
-
from sqlalchemy.orm import relationship
|
| 3 |
-
from datetime import datetime
|
| 4 |
-
from app.database import Base
|
| 5 |
-
from app.models.user import User
|
| 6 |
-
from app.models.lyrics import task_groups
|
| 7 |
-
|
| 8 |
-
class Task(Base):
|
| 9 |
-
__tablename__ = "tasks"
|
| 10 |
-
|
| 11 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 12 |
-
task_id = Column(String, unique=True, index=True)
|
| 13 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 14 |
-
device_id = Column(String)
|
| 15 |
-
song_name = Column(String)
|
| 16 |
-
artist = Column(String, nullable=True, default=None)
|
| 17 |
-
album = Column(String, nullable=True, default=None)
|
| 18 |
-
cover_url = Column(String, nullable=True, default=None)
|
| 19 |
-
stems = Column(Integer)
|
| 20 |
-
status = Column(String, default="PENDING")
|
| 21 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 22 |
-
# Fecha en que el cliente confirmó que descargó todos los stems.
|
| 23 |
-
downloaded_at = Column(DateTime, nullable=True, default=None)
|
| 24 |
-
cloud_url = Column(Text, nullable=True, default=None)
|
| 25 |
-
# JSON: {"vocals": "BQACAgIA...", "bass": "BQACAgIB..."} - file_ids de Telegram por stem
|
| 26 |
-
telegram_file_ids = Column(Text, nullable=True, default=None)
|
| 27 |
-
# JSON: {"vocals": 12345, "bass": 12346} - message_ids de Telegram (para borrar si el usuario elimina)
|
| 28 |
-
telegram_message_ids = Column(Text, nullable=True, default=None)
|
| 29 |
-
group_id = Column(Integer, ForeignKey("groups.id"), nullable=True)
|
| 30 |
-
# JSON string con lista de acordes editados por el usuario [{"t": 0.5, "ch": "Am"}, ...]
|
| 31 |
-
chords = Column(Text, nullable=True, default=None)
|
| 32 |
-
# Fecha en que los archivos de Tebi (stems + voces corales) serán eliminados automáticamente
|
| 33 |
-
# Normal: 3 días, Premium: 7 días desde la subida. NULL = ya expirado o tarea anterior al feature.
|
| 34 |
-
cloud_expires_at = Column(DateTime, nullable=True, default=None)
|
| 35 |
-
|
| 36 |
-
user = relationship("User", back_populates="tasks")
|
| 37 |
-
group = relationship("Group", foreign_keys=[group_id])
|
| 38 |
-
groups_shared = relationship("Group", secondary=task_groups, back_populates="tasks_shared")
|
| 39 |
-
|
| 40 |
-
@property
|
| 41 |
-
def group_ids(self):
|
| 42 |
-
return [g.id for g in self.groups_shared]
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
class Worker(Base):
|
| 46 |
-
__tablename__ = "workers"
|
| 47 |
-
|
| 48 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 49 |
-
hostname = Column(String, unique=True, index=True)
|
| 50 |
-
name = Column(String, nullable=True) # User-friendly custom name
|
| 51 |
-
status = Column(String, default="offline") # online | offline | busy
|
| 52 |
-
last_seen = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 53 |
-
|
| 54 |
-
# BYOK / Local Worker
|
| 55 |
-
user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True, unique=True)
|
| 56 |
-
token = Column(String, unique=True, index=True, nullable=True)
|
| 57 |
-
command = Column(String, default="none") # start | stop | none
|
| 58 |
-
is_active = Column(Boolean, default=False)
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models/sync.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
| 1 |
-
from sqlalchemy import Column, String, DateTime, JSON, Boolean, Integer
|
| 2 |
-
from datetime import datetime
|
| 3 |
-
import uuid
|
| 4 |
-
from app.database import Base
|
| 5 |
-
|
| 6 |
-
class B2SyncQueue(Base):
|
| 7 |
-
__tablename__ = "b2_sync_queue"
|
| 8 |
-
|
| 9 |
-
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
|
| 10 |
-
file_key = Column(String, nullable=False)
|
| 11 |
-
file_url = Column(String, nullable=False)
|
| 12 |
-
sync_type = Column(String, nullable=False) # "device" o "group"
|
| 13 |
-
target_id = Column(String, nullable=False) # userId o groupId
|
| 14 |
-
pending_recipients = Column(JSON, nullable=False) # lista de IDs de dispositivos o usuarios
|
| 15 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 16 |
-
|
| 17 |
-
is_uploaded = Column(Boolean, default=True)
|
| 18 |
-
uploading_by = Column(String, nullable=True, default=None)
|
| 19 |
-
uploading_claimed_at = Column(DateTime, nullable=True, default=None)
|
| 20 |
-
missing_stems = Column(JSON, nullable=True, default=None) # JSON: {"recipient_id": ["vocals", "drums"]}
|
| 21 |
-
|
| 22 |
-
class MigrationBackup(Base):
|
| 23 |
-
__tablename__ = "migration_backups"
|
| 24 |
-
|
| 25 |
-
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
|
| 26 |
-
user_id = Column(Integer, nullable=False, index=True)
|
| 27 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 28 |
-
expires_at = Column(DateTime, nullable=False)
|
| 29 |
-
status = Column(String, default="pending") # "pending", "completed", "restored", "expired"
|
| 30 |
-
metadata_json = Column(JSON, nullable=True) # Mapa de metadatos locales
|
| 31 |
-
files_info = Column(JSON, nullable=True, default=[]) # Lista de stems respaldados: [{"task_id": "...", "stem_name": "..."}]
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/models/user.py
DELETED
|
@@ -1,116 +0,0 @@
|
|
| 1 |
-
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, JSON
|
| 2 |
-
from sqlalchemy.orm import relationship
|
| 3 |
-
from datetime import datetime
|
| 4 |
-
from app.database import Base
|
| 5 |
-
|
| 6 |
-
class User(Base):
|
| 7 |
-
__tablename__ = "users"
|
| 8 |
-
|
| 9 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 10 |
-
username = Column(String, unique=True, index=True)
|
| 11 |
-
email = Column(String, unique=True, index=True)
|
| 12 |
-
hashed_password = Column(String)
|
| 13 |
-
credits = Column(Integer, default=10)
|
| 14 |
-
is_premium = Column(Boolean, default=False)
|
| 15 |
-
avatar_url = Column(String, nullable=True)
|
| 16 |
-
reset_token = Column(String, nullable=True)
|
| 17 |
-
reset_token_expires = Column(DateTime, nullable=True)
|
| 18 |
-
|
| 19 |
-
devices = relationship("Device", back_populates="user")
|
| 20 |
-
tasks = relationship("Task", back_populates="user")
|
| 21 |
-
groups = relationship("UserGroup", back_populates="user")
|
| 22 |
-
credit_transactions = relationship("CreditTransaction", back_populates="user", cascade="all, delete-orphan")
|
| 23 |
-
|
| 24 |
-
class Device(Base):
|
| 25 |
-
__tablename__ = "devices"
|
| 26 |
-
|
| 27 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 28 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 29 |
-
device_id = Column(String, index=True)
|
| 30 |
-
name = Column(String)
|
| 31 |
-
registered_at = Column(DateTime, default=datetime.utcnow)
|
| 32 |
-
last_active = Column(DateTime, default=datetime.utcnow)
|
| 33 |
-
|
| 34 |
-
user = relationship("User", back_populates="devices")
|
| 35 |
-
|
| 36 |
-
class CreditTransaction(Base):
|
| 37 |
-
__tablename__ = "credit_transactions"
|
| 38 |
-
|
| 39 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 40 |
-
user_id = Column(Integer, ForeignKey("users.id"))
|
| 41 |
-
amount = Column(Integer)
|
| 42 |
-
concept = Column(String)
|
| 43 |
-
reference_id = Column(String, nullable=True)
|
| 44 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 45 |
-
|
| 46 |
-
user = relationship("User", back_populates="credit_transactions")
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
class SystemNotification(Base):
|
| 50 |
-
__tablename__ = "system_notifications"
|
| 51 |
-
|
| 52 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 53 |
-
title = Column(String, index=True)
|
| 54 |
-
message = Column(String)
|
| 55 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
class AdminUser(Base):
|
| 59 |
-
__tablename__ = "admin_users"
|
| 60 |
-
|
| 61 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 62 |
-
username = Column(String, unique=True, index=True)
|
| 63 |
-
hashed_password = Column(String)
|
| 64 |
-
avatar_url = Column(String, nullable=True)
|
| 65 |
-
perm_users = Column(Boolean, default=True)
|
| 66 |
-
perm_workers = Column(Boolean, default=True)
|
| 67 |
-
perm_churches = Column(Boolean, default=True)
|
| 68 |
-
perm_groups = Column(Boolean, default=True)
|
| 69 |
-
perm_notifications = Column(Boolean, default=True)
|
| 70 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
class AdminNotification(Base):
|
| 74 |
-
__tablename__ = "admin_notifications"
|
| 75 |
-
|
| 76 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 77 |
-
title = Column(String, index=True)
|
| 78 |
-
message = Column(String)
|
| 79 |
-
created_at = Column(DateTime, default=datetime.utcnow)
|
| 80 |
-
read = Column(Boolean, default=False)
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
class LandingFeature(Base):
|
| 84 |
-
__tablename__ = "landing_features"
|
| 85 |
-
|
| 86 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 87 |
-
icon_svg = Column(String, nullable=True)
|
| 88 |
-
icon_color = Column(String, default="cyan") # cyan | purple | green | blue | yellow | red
|
| 89 |
-
title = Column(String)
|
| 90 |
-
description = Column(String)
|
| 91 |
-
order = Column(Integer, default=0)
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
class LandingPlatform(Base):
|
| 95 |
-
__tablename__ = "landing_platforms"
|
| 96 |
-
|
| 97 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 98 |
-
name = Column(String, nullable=False)
|
| 99 |
-
version = Column(String, nullable=True)
|
| 100 |
-
os_details = Column(String, nullable=True)
|
| 101 |
-
description = Column(String, nullable=True)
|
| 102 |
-
download_url = Column(String, nullable=True)
|
| 103 |
-
button_text = Column(String, nullable=True)
|
| 104 |
-
os_type = Column(String, default="windows") # windows | android | apple
|
| 105 |
-
is_visible = Column(Boolean, default=True)
|
| 106 |
-
order = Column(Integer, default=0)
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
class LandingTutorial(Base):
|
| 110 |
-
__tablename__ = "landing_tutorials"
|
| 111 |
-
|
| 112 |
-
id = Column(Integer, primary_key=True, index=True)
|
| 113 |
-
title = Column(String, nullable=False)
|
| 114 |
-
desc = Column(String, nullable=True)
|
| 115 |
-
steps = Column(JSON, default=[]) # list of strings
|
| 116 |
-
order = Column(Integer, default=0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
models/btc_chord.pth
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:71c2c5db17e8c43b8a9a9da5db36ef2d667158c07a214eba16344c154c00bf54
|
| 3 |
-
size 12154754
|
|
|
|
|
|
|
|
|
|
|
|
tunnel_url.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
https://proceeds-sol-entirely-maximize.trycloudflare.com
|