Spaces:
Running
Running
Sync backend: FK idempotentes + tablas financieras en startup; relaciones usuarios/cotizaciones
6e394e9 | import enum | |
| from datetime import datetime, date | |
| from sqlalchemy import ( | |
| Column, Integer, String, Text, Boolean, Numeric, | |
| DateTime, Date, BigInteger, ForeignKey, Interval, | |
| CheckConstraint | |
| ) | |
| from sqlalchemy.orm import relationship | |
| from app.database import Base | |
| # ── Enums ────────────────────────────────────────────────────────────────── | |
| class TipoMiembroEnum(str, enum.Enum): | |
| comprometido = "Comprometido" | |
| registrado = "Registrado" | |
| voluntario = "Voluntario" | |
| class CotizacionEstadoEnum(str, enum.Enum): | |
| pendiente = "pendiente" | |
| aprobado = "aprobado" | |
| rechazado = "rechazado" | |
| class EstadoPresenciaMisionEnum(str, enum.Enum): | |
| con_iglesia = "Con iglesia" | |
| evangelizado = "Evangelizado" | |
| en_proceso = "En proceso" | |
| class CuentaTipoEnum(str, enum.Enum): | |
| banco = "Banco" | |
| caja = "Caja" | |
| class TipoSangreEnum(str, enum.Enum): | |
| a_positivo = "A+" | |
| a_negativo = "A-" | |
| b_positivo = "B+" | |
| b_negativo = "B-" | |
| ab_positivo = "AB+" | |
| ab_negativo = "AB-" | |
| o_positivo = "O+" | |
| o_negativo = "O-" | |
| # ── Models ───────────────────────────────────────────────────────────────── | |
| class Pais(Base): | |
| __tablename__ = "paises" | |
| id = Column(Integer, primary_key=True) | |
| iso = Column(String(2)) | |
| nombre = Column(String(100), nullable=False) | |
| continente_id = Column(Integer, ForeignKey("continentes.id", ondelete="SET NULL")) | |
| miembros = relationship("Miembro", back_populates="pais_rel") | |
| contactos = relationship("Contacto", back_populates="pais_rel") | |
| reportes = relationship("Reporte", back_populates="pais_rel") | |
| presupuestos = relationship("Presupuesto", back_populates="pais_rel") | |
| ejecuciones = relationship("Ejecucion", back_populates="pais_rel") | |
| estadisticas = relationship("EstadisticaPais", back_populates="pais_rel") | |
| ciudades = relationship("Ciudad", back_populates="pais_rel") | |
| ingresos = relationship("Ingreso", back_populates="pais_rel") | |
| saldos = relationship("SaldoCajaBanco", back_populates="pais_rel") | |
| traslados = relationship("Traslado", back_populates="pais_rel") | |
| continente_rel = relationship("Continente", back_populates="paises") | |
| class Ciudad(Base): | |
| __tablename__ = "ciudades" | |
| id = Column(Integer, primary_key=True) | |
| nombre = Column(String(100), nullable=False) | |
| nombre_ascii = Column(String(100)) | |
| lat = Column(Numeric(10, 7)) | |
| lng = Column(Numeric(10, 7)) | |
| pais_iso2 = Column(String(2), ForeignKey("paises.iso", ondelete="SET NULL")) | |
| admin_name = Column(String(100)) | |
| capital = Column(String(20)) | |
| population = Column(BigInteger) | |
| worldcity_id = Column(BigInteger) | |
| pais_rel = relationship("Pais", back_populates="ciudades") | |
| miembros = relationship("Miembro", back_populates="ciudad_rel") | |
| contactos = relationship("Contacto", back_populates="ciudad_rel") | |
| reportes = relationship("Reporte", back_populates="ciudad_rel") | |
| misiones = relationship("CiudadMision", back_populates="ciudad_rel") | |
| class Rol(Base): | |
| __tablename__ = "roles" | |
| id = Column(Integer, primary_key=True) | |
| nombre = Column(String(30), nullable=False, default="") | |
| descripcion = Column(String(100)) | |
| permisos = relationship("RolPermiso", back_populates="rol") | |
| usuarios = relationship("Usuario", back_populates="rol_rel") | |
| class RolPermiso(Base): | |
| __tablename__ = "rol_permisos" | |
| rol_id = Column(Integer, ForeignKey("roles.id"), primary_key=True) | |
| permiso_id = Column(Integer, primary_key=True) | |
| activo = Column(Boolean, default=True) | |
| rol = relationship("Rol", back_populates="permisos") | |
| class UsuarioPermiso(Base): | |
| __tablename__ = "usuario_permisos" | |
| id = Column(Integer, primary_key=True, index=True) | |
| usuario_id = Column(String(30), ForeignKey("public.usuarios.id", ondelete="CASCADE"), nullable=False) | |
| permiso_id = Column(Integer, nullable=False) | |
| tiene_acceso = Column(Boolean, default=True) | |
| class Usuario(Base): | |
| __tablename__ = "usuarios" | |
| id = Column(String(30), primary_key=True) | |
| nombre = Column(Text, nullable=False) | |
| email = Column(Text, nullable=False, unique=True) | |
| password_hash = Column(Text, nullable=False) | |
| rol = Column(Integer, ForeignKey("roles.id"), nullable=False) | |
| fecha_registro = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| activo = Column(Boolean, default=False, nullable=False) | |
| region = Column(String(20), nullable=True) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| ciudad_id = Column(Integer, ForeignKey("ciudades.id", ondelete="SET NULL")) | |
| miembro_id = Column(String(30), ForeignKey("miembros.id", ondelete="SET NULL")) | |
| rol_rel = relationship("Rol", back_populates="usuarios") | |
| pais_rel = relationship("Pais") | |
| ciudad_rel = relationship("Ciudad") | |
| miembro_rel = relationship("Miembro", foreign_keys=[miembro_id], primaryjoin="Usuario.miembro_id == Miembro.id") | |
| class Miembro(Base): | |
| __tablename__ = "miembros" | |
| id = Column(String(30), primary_key=True) | |
| nombre = Column(Text, nullable=False) | |
| identidad = Column(String(30)) | |
| pais = Column(Text) | |
| ciudad = Column(Text) | |
| edad = Column(Integer) | |
| evangelizado_por = Column(Text) | |
| estado_civil = Column(Text) | |
| profesion = Column(Text) | |
| comentarios = Column(Text) | |
| tipo_miembro = Column(String(20), nullable=False) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| ciudad_id = Column(Integer, ForeignKey("ciudades.id", ondelete="SET NULL")) | |
| cargo_funcion = Column(Text, nullable=True) | |
| ministerio_of = Column(Text, nullable=True) | |
| avance_audio = Column(Text, nullable=True) | |
| pais_rel = relationship("Pais", back_populates="miembros") | |
| ciudad_rel = relationship("Ciudad", back_populates="miembros") | |
| contactos = relationship("Contacto", back_populates="miembro_rel") | |
| reportes = relationship("Reporte", back_populates="miembro_rel") | |
| cotizaciones = relationship("Cotizacion", back_populates="miembro_rel") | |
| info_adicional = relationship("MiembroInfoAdicional", back_populates="miembro_rel", uselist=False) | |
| estudios_diarios = relationship("EstudioDiario", back_populates="miembro_rel") | |
| class Contacto(Base): | |
| __tablename__ = "contactos" | |
| id = Column(Integer, primary_key=True) | |
| miembro_responsable = Column(Text, nullable=False) | |
| nombre = Column(Text, nullable=False) | |
| telefono = Column(Text) | |
| pais = Column(Text) | |
| notas = Column(Text) | |
| profesion = Column(Text) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| miembro_responsable_id = Column(String(30), ForeignKey("miembros.id", ondelete="SET NULL")) | |
| ciudad_id = Column(Integer, ForeignKey("ciudades.id", ondelete="SET NULL")) | |
| pais_rel = relationship("Pais", back_populates="contactos") | |
| ciudad_rel = relationship("Ciudad", back_populates="contactos") | |
| miembro_rel = relationship("Miembro", back_populates="contactos") | |
| class Reporte(Base): | |
| __tablename__ = "reportes" | |
| id = Column(Integer, primary_key=True) | |
| miembro_que_reporta = Column(Text, nullable=False) | |
| fecha = Column(Date, nullable=False) | |
| tiempo_evangelizacion = Column(Interval) | |
| contactos_obtenidos = Column(Integer, default=0) | |
| contactos_estudian = Column(Integer, default=0) | |
| numero_estudios_dados = Column(Integer, default=0) | |
| total_estudiantes = Column(Integer, default=0) | |
| pais = Column(Text) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| miembro_id = Column(String(30), ForeignKey("miembros.id", ondelete="SET NULL")) | |
| ciudad_id = Column(Integer, ForeignKey("ciudades.id", ondelete="SET NULL")) | |
| pais_rel = relationship("Pais", back_populates="reportes") | |
| ciudad_rel = relationship("Ciudad", back_populates="reportes") | |
| miembro_rel = relationship("Miembro", back_populates="reportes") | |
| class Cotizacion(Base): | |
| __tablename__ = "cotizaciones" | |
| id = Column(Integer, primary_key=True) | |
| fecha = Column(Date, nullable=False) | |
| solicitante = Column(Text, nullable=False) | |
| concepto = Column(Text, nullable=False) | |
| monto = Column(Numeric(15, 2), nullable=False) | |
| moneda = Column(String(10), default="USD", nullable=False) | |
| estado = Column(String(20), default="pendiente", nullable=False) | |
| agregado_a_gastos = Column(Boolean, default=False, nullable=False) | |
| mes_agregado = Column(Integer) | |
| anio_agregado = Column(Integer) | |
| notas = Column(Text) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| fecha_actualizacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| miembro_id = Column(String(30), ForeignKey("miembros.id", ondelete="SET NULL")) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| ciudad_id = Column(Integer, ForeignKey("ciudades.id", ondelete="SET NULL")) | |
| miembro_rel = relationship("Miembro", back_populates="cotizaciones") | |
| pais_rel = relationship("Pais") | |
| ciudad_rel = relationship("Ciudad") | |
| class Presupuesto(Base): | |
| __tablename__ = "presupuestos" | |
| id = Column(Integer, primary_key=True) | |
| pais = Column(String(100), nullable=False) | |
| mes = Column(Integer) | |
| anio = Column(Integer, nullable=False) | |
| tipo_gasto = Column(String(100), nullable=False) | |
| concepto = Column(Text) | |
| monto = Column(Numeric(15, 2), nullable=False) | |
| moneda = Column(String(10), nullable=False) | |
| tasa_cambio = Column(Numeric(15, 6)) | |
| notas = Column(Text) | |
| fecha_registro = Column(DateTime, default=datetime.utcnow) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| pais_rel = relationship("Pais", back_populates="presupuestos") | |
| ejecuciones = relationship("Ejecucion", back_populates="presupuesto_rel") | |
| class Ejecucion(Base): | |
| __tablename__ = "ejecuciones" | |
| id = Column(Integer, primary_key=True) | |
| pais = Column(String(100), nullable=False) | |
| mes = Column(Integer, nullable=False) | |
| anio = Column(Integer, nullable=False) | |
| monto_recibido_usd = Column(Numeric(15, 2), nullable=False) | |
| presupuesto_id = Column(Integer, ForeignKey("presupuestos.id", ondelete="SET NULL")) | |
| notas = Column(Text) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| fecha_actualizacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| pais_rel = relationship("Pais", back_populates="ejecuciones") | |
| presupuesto_rel = relationship("Presupuesto", back_populates="ejecuciones") | |
| gastos = relationship("GastoReal", back_populates="ejecucion_rel", cascade="all, delete") | |
| class GastoReal(Base): | |
| __tablename__ = "gastos_reales" | |
| id = Column(Integer, primary_key=True) | |
| ejecucion_id = Column(Integer, ForeignKey("ejecuciones.id", ondelete="CASCADE"), nullable=False) | |
| concepto = Column(Text, nullable=False) | |
| monto = Column(Numeric(15, 2), nullable=False) | |
| tipo_gasto = Column(String(100), nullable=False) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| ejecucion_rel = relationship("Ejecucion", back_populates="gastos") | |
| class EstadisticaPais(Base): | |
| __tablename__ = "estadisticas_paises" | |
| id = Column(Integer, primary_key=True) | |
| nombre_pais = Column(String(100), nullable=False) | |
| cantidad_miembros = Column(Integer, default=0) | |
| cantidad_estudios = Column(Integer, default=0) | |
| cantidad_reportes = Column(Integer, default=0) | |
| color = Column(String(20)) | |
| mes = Column(Integer) | |
| anio = Column(Integer, nullable=False) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow) | |
| fecha_actualizacion = Column(DateTime, default=datetime.utcnow) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| pais_rel = relationship("Pais", back_populates="estadisticas") | |
| class Configuracion(Base): | |
| __tablename__ = "configuracion" | |
| id = Column(Integer, primary_key=True) | |
| clave = Column(String(100), nullable=False, unique=True) | |
| valor = Column(Text, nullable=False) | |
| descripcion = Column(Text) | |
| fecha_actualizacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| class CiudadMision(Base): | |
| __tablename__ = "ciudades_mision" | |
| id = Column(Integer, primary_key=True) | |
| ciudad_id = Column(Integer, ForeignKey("ciudades.id", ondelete="SET NULL"), nullable=False) | |
| region = Column(String(150)) | |
| estado_presencia = Column(String(30), nullable=False, default="En proceso") | |
| fecha_inicio_trabajo = Column(Date) | |
| pastor_encargado_id = Column(String(30), ForeignKey("miembros.id", ondelete="SET NULL")) | |
| pastor_encargado_nombre = Column(Text) | |
| cantidad_miembros_activos = Column(Integer, default=0) | |
| notas = Column(Text) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| fecha_actualizacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| ciudad_rel = relationship("Ciudad", back_populates="misiones") | |
| pastor_rel = relationship("Miembro", foreign_keys=[pastor_encargado_id]) | |
| class Ingreso(Base): | |
| __tablename__ = "ingresos" | |
| id = Column(Integer, primary_key=True) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| mes = Column(Integer, nullable=False) | |
| anio = Column(Integer, nullable=False) | |
| tipo = Column(String(100), nullable=False) | |
| origen = Column(Text) | |
| donde_ingresa = Column(String(10), nullable=False) | |
| valor = Column(Numeric(15, 2), nullable=False) | |
| observaciones = Column(Text) | |
| fecha = Column(Date, nullable=False) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| pais_rel = relationship("Pais", back_populates="ingresos") | |
| class MiembroInfoAdicional(Base): | |
| __tablename__ = "miembros_info_adicional" | |
| id = Column(String(30), ForeignKey("miembros.id", ondelete="CASCADE"), primary_key=True) | |
| nombre_padre = Column(Text) | |
| telefono_padre = Column(String(30)) | |
| nombre_madre = Column(Text) | |
| telefono_madre = Column(String(30)) | |
| tipo_sangre = Column(String(5)) | |
| correo_electronico = Column(String(255)) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| fecha_actualizacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| miembro_rel = relationship("Miembro", back_populates="info_adicional") | |
| class SaldoCajaBanco(Base): | |
| __tablename__ = "saldos_caja_banco" | |
| id = Column(Integer, primary_key=True) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| saldo_caja = Column(Numeric(15, 2), nullable=False, default=0) | |
| saldo_banco = Column(Numeric(15, 2), nullable=False, default=0) | |
| updated_at = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| pais_rel = relationship("Pais", back_populates="saldos") | |
| class Traslado(Base): | |
| __tablename__ = "traslados" | |
| id = Column(Integer, primary_key=True) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| de = Column(String(10), nullable=False) | |
| a = Column(String(10), nullable=False) | |
| valor = Column(Numeric(15, 2), nullable=False) | |
| observaciones = Column(Text) | |
| fecha = Column(Date, nullable=False) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| pais_rel = relationship("Pais", back_populates="traslados") | |
| class Continente(Base): | |
| __tablename__ = "continentes" | |
| id = Column(Integer, primary_key=True) | |
| nombre = Column(String(100), nullable=False, unique=True) | |
| paises = relationship("Pais", back_populates="continente_rel") | |
| class EstudioDiario(Base): | |
| __tablename__ = "estudios_diarios" | |
| id = Column(Integer, primary_key=True) | |
| miembro_id = Column(String(30), ForeignKey("miembros.id", ondelete="CASCADE"), nullable=False) | |
| pais_id = Column(Integer, ForeignKey("paises.id", ondelete="SET NULL")) | |
| contacto_id = Column(Integer, ForeignKey("contactos.id", ondelete="SET NULL")) | |
| mes = Column(Integer, nullable=False) | |
| anio = Column(Integer, nullable=False) | |
| dia = Column(Integer, nullable=False) | |
| capitulo = Column(String(255)) | |
| horas = Column(Numeric(5, 2)) | |
| tipo = Column(String(50)) | |
| donde = Column(String(255)) | |
| dijeron_si = Column(Integer, default=0) | |
| nuevos_contactos = Column(Integer, default=0) | |
| fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False) | |
| miembro_rel = relationship("Miembro", back_populates="estudios_diarios") | |
| pais_rel = relationship("Pais") | |
| contacto_rel = relationship("Contacto") | |