Hay que hacer una tabla de "caja menor"
Proposito:
Añadir al curso, no formalizado despues de apuntarse (necesitamos paso intermedio con informacion)
Mejorar instrucciones de estudio
Revisar flujo / inscribirme ahora
Antes de Incribirme ahora, poner informacion detallada, horarios etc
Donde se asigna el rol se ve negro
Añadir iconitos de ? que al pasar el mouse por encima den informacion en lugares relevantes
Aparte de enviar mensajes personales y campaña, deberiamos poder enviar el mensaje a mas de un usuario, y crear listas de usuarios para usarlas despues enviando mensajes a listas, o incluso seleccionar un grupo completo de rol, por ejemplo, enviar un mensaje a todos los lideres, o a todos los servidores, o a todos los estudiantes, estas listas personalizadas deberian poder persistirse en la base de datos, las de grupos como roles deberian poder gestionarse desde el front. Ademas, estas listas deberian poderse editar / eliminar / duplicar con otro nombre para editarla despues.
Al usuario que recibe el mensaje deberian aparecerle un numerito en la campana para decirle cuantas notificaciones o mensajes tiene sin leer (pero aun no tenemos la interfaz de usuario, ni logica en la campana) He comprobado que en la base de datos se guarda el mensaje, y llega el correo electronico, deberiamos poder crear una pequeña interfaz para ver los mensajes enviados y recibidos, y eliminarlos (una eliminacion persistente tambien de la bbdd)
Segmentar servicios que se activan con facilidad para cada iglesia
implementar canal push (SSE/WebSocket) para rol casi instantáneo cross-device.
implementar skeleton en todas las secciones, ahora solo esta en universidad
Mapear todas las cosas que se devuelven al front para poder verlas con zustand desde las herramientas de desarrollo ¿Es eso peligroso si se activan y las puede ver cualquiera? en ese caso podriamos tener algo en la interfaz de superadmin-saas para habilitar deshabilitar ver con zustand en las devtools
En la interfaz, poner el mismo sistema de alertdialog con confirmacion cuando se quieren guardar cambios de habilitar-deshabilitar widget con su spinner de espera bloqueante y el toast de exito al final
Mejorar el setup de primera vez, debe ser un formulario bonito como el de registro, comprobar que tiene validaciones en el front con zod y en el backend, solicitar todos los campos para no insertar valores por defecto como la fecha de nacimiento y el telefono, ademas, el sistema lo esta validando de una vez como active, eso no es correcto, debe seguir el mismo flujo que los otros usuarios, email con token, verifica y pasa a active.
Registro de usuarios a traves de formulario unico, con codigo de iglesia (pastor o admin deben validar al usuario) sin codigo debe añadirse a la iglesia universal (la no-iglesia) y se debe redirigir al usuario a ese login con slug, ademas de informarle en el email el enlace de inicio de sesion, pero si el superadmin del saas cambia los permisos de ese usuario generico convirtiendolo en parte del saas y otorgandole un rol ¿como gestionamos que ese usuario ya no inicie sesion a traves del slug?¿limpiamos ese campo para ese usuario en la base de datos? tambien debe existir la opcion inversa, degradar al usuario del saas con lo que deberia automaticamente añadirse a la iglesia universal y con una particularidad, y es que se remueven todos sus roles salvo el de believer y student si existen, porque un usuario que no pertenece a una organizacion y tampoco a una iglesia se supone que es, como mucho, un estudiante independiente.
En codigo de invitacion, se puede hacer que cuando el usuario meta el codigo aparezca la iglesia para seleccionarse (asi el usuario visualmente puede corroborar que la iglesia es correcta) pero solo aparece el nombre y es seleccionable hasta que se introduce todo el codigo, de esa manera evitamos "revelar nombres" por meter caracteres al azar, ¿query y tanstack para tener los codigos cacheados?
instructor principal promovido a principal -> deberia lanzar mensaje error
get assignments cuando no hay nada deberia retornar mensaje distinto a exito
Migrar vite a la version 8
Modificar o unificar dev-pro con las bases de datos porque no existe church id en pro y hay que revisar el fallo al editar las notas
Rotar secrets en doppler y pendiente crear proyecto de documentacion en vercel y doppler para global
Despues de asignar/revocar un rol hay que refrescar el usuario porque sino hay que hacer logout/login
Lo de los colores esta bien pero para un tema custom de la iglesia, no para que se sobrescriban todos los colores de los temas nativos en todos los temas
Necesitamos roles secundarios, es decir, los roles primarios de organizacion son los de la central (organizacion o app que controla a otras iglesias, admin, pastor, instructor, treasurer... etc. Ahora necesitamos roles secundarios que seran los de cada iglesia miembro o hija, tenant_admin, tenant_pastor, tenant_instructor etc, donde cada uno de ellos tendra los mismos privilegios que los primarios, pero SOLO y unicamente dentro de su iglesia u organizacion) que tendrian como superpoderes para verlos a todos de todas las iglesias y miembros sin iglesia, y los secundarios que tienen privilegios dentro de su propia organizacion o iglesia, pero no pueden ver la de los demas.
Agregar el rol main_pastor (es como un superadmin pero en pastor) ese main pastor puede crear a otros pastores para su congregacion, y ellos tendran el equivalente en privilegios a un admin, pero no pueden tener mas privilegios que el main pastor. Solo puede haber un main pastor, o este ceder su rol.
Enfatizar en que siempre use los componentes de shadcdn
Solo un main pastor, y solo el puede otorgar permisos a un segundo pastor para ver ciertas cosas
¿Que seria lo optimo? solo quienes tienen acceso a gestion de miembros pueden enviar y recibir mensajes? que enfoque es el mejor, mensajes como hasta ahora o algo tipo react socket / firebase? o una combinacion de los dos?
Todos los mensajes deben "encriptarse" al igual que mucha informacion en la base de datos, asi que hay que crear un componente que lo haga para que sea reutilizable
Añadir el editor wisywig para los textos
En la tabla users anadir "Genero" y añadirlo al formulario de registro
Añadir sistema de cupones de descuento
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-latest:generateContent"
-H 'Content-Type: application/json'
-H 'X-goog-api-key: AIzaSyChAb_1Brff0IhlTGQaZPz5XVmnxKiDiQM'
-X POST
-d '{
"contents": [
{
"parts": [
{
"text": "Explain how AI works in a few words"
}
]
}
]
}'
Cuando un usuario se crea, se crea con un booleano is_active, y esta persona se queda activo al registrar su correo y verificarlo, sin embargo, para crear la figura de iglesia, que tiene asociado a un pastor, deberia crearse las dos cosas a la vez por una parte (iglesia y usuario), que se tenga que validar igualmente el usuario con el correo (lo que cambiaria su status como el resto de usuario a is_active = true), pero tendriamos que validar manualmente para conceder su status de pastor, ya que inicialmente se crea con el role believer, y este rol se puede autoasignar cuando se valide por un admin la iglesia a la que pertenece el pastor. Inicialmente esa iglesia deberia quedar con un status pendiente de verificacion, esta se debe poder aceptar o rehusar (No se si es mejor hacer un hard delete de la iglesia en caso de rehuso y preservar al pastor, mantenerla en pending mientras se solicita informacion, o rehusarla pero mantenerla con un soft delete con un estado como unverifable, asi se mantiene al "pastor" como usuario sin el rol de pastor). Por otra parte, se debe tener un endpoint que pueda registrar la iglesia + pastor de un tiron, y otro para cuando un usuario se registro y validó, pero despues se convirtio en pastor y tiene iglesia (igualmente, hace la solicitud de anexar la iglesia pero hasta que no se valide deberia quedar como pending y solo se le asigna el rol pastor al validar ese anexado de la iglesia). Ademas estos endpoints deben ser publicos, no requieren de un token de usuario, deben ser igualmente como cuando te quieres registrar, la diferencia es que luego requieren validacion manual por un admin. ¿Deberia tener otro unique id formado por el id de la church y el id del pastor, es decir, el id del user que tiene rol pastor?
Un enum de status tambien para el user, por si se quiere desde el panel de admin "suspender" o "inactivar" o "bannear" la cuenta de un usuario, por algun motivo legal, etico, o de inactividad. Eso tambien serviria para luego a traves de una queri ver si hay usuarios con ese status desde hace x tiempo que puedan ser movidos a archived_users. Al hacer login se debe comprobar el status de la persona y se debe validar que, si su status es diferente de active, mostramos un mensaje de error y le pedimos que se comunique con un administrador a un correo, ademas, validamos si tambien esta en la tabla de archived, en ese caso tambien mostramos el error y pedimos que se comunique con un administrador. Asi tambien evitamos que si un usuario ha sido baneado o esta inactivo o suspendido, quiera crear otro usuario con el mismo correo, o el mismo telefono ademas de poder "limpiar" usuarios de tanto en tanto.
Imagino que en el registro de usuario se pregunta algo como "Si eres estudiante de una iglesia y conoces su codigo, introducelo" Ese codigo de invitacion se valida en el backend para vincular al usuario con una iglesia. El pastor de esa iglesia podra ver a sus estudiantes vinculados y podra aceptarlos (valida que evidentemente esa persona esta en su congregacion) o rehusarlos. En caso de rehusarlos el pastor ya no lo ve en la lista, pero esta persona no puede estar sin church_id asi que se le asignara de manera automatica el church_id "universal" que es el que no pertenece como tal a ninguna iglesia, sino que es estudiante independiente. Hay que revisar las tablas de student y user para ver cuales son los status (enums) y si son validos y suficientes para esto, porque ahora un pastor tiene que "admitirlo o validarlo" como parte de su congregacion, es decir, cualquier persona puede hacer el registro en la pagina como usuario, se registra y tiene dos opciones, no pertenezco a una congregacion (se crea el usuario pendiente de validar el is_active a traves del token del email (aqui solo es believer), y despues cuando se crea como estudiante quedara ligado como usuario y estudiante a una no congregacion, como usuario libre (añadimos esa no iglesia a churches? para que tenga ese slug o codigo generico?, esas personas solo podran verlas el superadmin y roles dentro de la organizacion central, pero luego las iglesias tenant, sus pastores no pueden ver a esos estudiantes sin iglesia). La otra opcion es, me registro y pongo un codigo de invitacion, se crea el usuario que tiene que validarse a traves el email, el usuario pasa a estar activo pero no se tiene aun rol de estudiante, solo believer, el pastor cuya iglesia tiene ese invite_code ve que hay una persona que solicita vinculacion (si lo rehusa se transfiere a la, no_church, si lo acepta el pastor podra verle como estudiante de su congregacion) y si acepta el estudiante pasa a estar vinculado a esa church_id, y cuando sea estudiante lo sera de esa iglesia.
Osea que el flujo es:
Usuario se registra:
No necesita token, endpoint publico
Puede registrarse sin iglesia -> vinculado en church_ig generico -> pendiente de validar como usuario -> validado
Solo rol believer, si se da de alta como estudiante estaria vinculado al church_id generico
Puede registrarse con iglesia -> validamos codigo invitacion
Si es válido, queda vinculado al church_id de la iglesia
La vinculacion debe quedar con un status de pending
El pastor de esa iglesia vera que una persona quiere vincularse, puede rehusarlo o aceptarlo
Si rehusa se cambia al usuario al church_id generico, si lo acepta quedara vinculado, hasta aqui solo sigue teniendo el rol believer
Si es aceptado y se da de alta como estudiante, pasara a ser un estudiante vinculado a esa iglesia
El pastor, e instructor pueden ver a sus miembros y estudiantes en los correspondientes paneles
Pastor se registra
Inicialmente no hay un endpoint ni un formulario para registrarse como pastor, solo como usuario, o como iglesia
En el caso de registro como iglesia:
Si antes no se ha registrado como usuario, haremos un registro doble, en un solo formulario pediremos los datos de la iglesia y del pastor. El Slug y el codigo de invitacion se crean automaticamente y son unicos
El superadmin central, recibe el registro de la iglesia y del pastor
Inicialmente el pastor es un user normal (debe verificar su email y solo tiene el rol believer)
La iglesia queda registrada pero tiene un status de pending (porque la tiene que validar el superadmin)
Aun no tenemos status en el model de church (enum)
Cuando el superadmin lo valida, automaticamente concedemos el rol pastor y queda vinculado a su iglesia
Este pastor podra ver a sus miembros y estudiantes
Revisar la response del register del usuario para que en la vista devuelva la iglesia, su nombre y codigo.
Como puedo aislar mi interfaz de una iglesia, y como puedo tener mi usuario SAAS desvinculado de una iglesia, con los superpoderes y demas
Despues del registro se genera el codigo de invitacion pero el usuario no sabe cual es su url para acceder
Hacer un script que haga una copia exacta sin dejarse nada nada de la base de datos y programarlo para que se pueda ejecutar desde el SaaS admin de manera por cron o a peticion, con opciones de copia, completa, por tenant, ¿base de datos con replica?
Elevar lo del too-many request
No se deberia recibir el email con el codigo de invitacion despues de registrar la iglesia -> activar la cuenta de pastor (porque aqui solo se ha verificado la cuenta de usuario sin ser validado aun como pastor y como iglesia) -> despues de que un administrador lo valide, ahi es cuando dispararemos el email con el codigo de invitacion y el inicio de sesion explicando lo del slug (podriamos llamarle otra cosa y no slug)
A un miembro que se registra con un codigo de invitacion de iglesia, despues le llega el email de cuenta activada con el codigo de invitacion (eso es solo para quien se registra como pastor + iglesia, no para miembros)
Hay que modernizar lo de gestion de permisos en la UI, ¿saas a tenant?, si un saas otorga un permiso, es dentro de su scope
Un creyente puede ver los datos de su iglesia
Ahora mismo el flujo es, si usuario se registra con codigo invitacion y valida su email, queda activo como miembro iglesia que le invita, pero lo correcto es, que el pastor debe validarlo como miembro o rechazarlo, hace falta gestionar estados, cambiar modelo.
Hay que revisar lo de impersonar, ahora no tiene mucho sentido, pero la idea seria que un usuario comodin pudiese entrar como parte de la iglesia a impersonar, para tener una vista desde dentro, tal vez con el rol admin? hay que gestionarlo bien
El website esta en el formulario pero no se inserta en la base de datos
Después de finalizar nuestra reestructuración o modificación de todo el dashboard de Universidad, que nos ha quedado muy bonito, hemos generado ademas la documentación de todo el estado actual de la aplicacion. He estado haciendo pruebas y he detectado cosas que se pueden mejorar o que funcionan mal.
A medida que voy probando la aplicación y voy desarrollando, surgen estos pensamientos y voy capturando estos pequeños requerimientos sin refinarlos. Te voy a pasar la lista de todos los puntos que he observado para que me ayudes a categorizarlos. Necesito saber:
Cuáles van agrupados por características comunes para implementarlos juntos.
Cuáles son dependientes de otros para desarrollar primero la característica base.
El orden de dificultad, de menor a mayor.
Reescribelos si es necesario para que haya mayor claridad en el objetivo de la tarea
Genera las preguntas o inquietudes necesarias para que al trazar el plan completo se haga todo sin dudas
El objetivo de analizar y categorizar esto es facilitar luego la creacion de un plan donde es primordial el SDD Spec drive development, que nos de una oportunidad clara de llegar al objetivo.
De esta manera, podremos elaborar planes con iteraciones y tareas más atómicas hasta cubrirlo todo, primero categorizamos o agrupamos con sentido, y en otra iteracion nos centramos en crear un plan detallado para cada grupo. Paso a detallarte las cosas que he visto:
Endpoint de Instructor Principal:
Cuando ya tenemos un instructor principal en una asignatura y lo volvemos a promover como tal, debería retornar un mensaje de error que diga "este instructor ya es instructor principal". Sin embargo, lo que hace es retornar un 200 diciendo que tuvo éxito, lo cual no tiene sentido.
Listado de Assignments (get):
Si se retorna una lista vacía, me tiene que devolver un mensaje que diga que no hay asignaciones, que no se encontraron o no existen. Actualmente, el comportamiento también es un mensaje de éxito cuando no hay nada.
Refresco de Roles y Dashboard:
Siempre tenemos que volver a hacer un GET del usuario trayendo sus roles para que se refresque el dashboard completo. Ahora mismo, la única forma de ver los cambios al otorgar o revocar un rol es cerrando e iniciando sesión, lo cual no es nada óptimo.
Estrategia Multitenancy y Roles:
Ahora que tenemos la aplicación como multitenant, iniciamos creando de manera primitiva ciertos roles (antes de ser multitenant) con una jerarquía (superadmin, admin, pastor, líder, etc.). Necesitamos roles que diferencien la organización central (SaaS) de las organizaciones que son Tenant (iglesias que entran a través de un slug en la URL). El rol de organización central debe poder controlar a todas las iglesias, pero los roles dentro de la iglesia deben estar diseñados para que funcionen solo dentro de su propia organización. Hay que pensar una estrategia para esto.
He pensado algo respecto a los roles: dentro de una iglesia, normalmente los pastores tienen a su esposa, que también tendría el rol de pastor. Además, en algunas iglesias más grandes hay copastores o pastores secundarios que desempeñan otras labores. Por eso, creo que podríamos agregar un rol nuevo que sea "Main Pastor". La estructura funcionaría de la siguiente manera:
Jerarquía de roles:
(a) Solo puede haber un Main Pastor por iglesia.
(b) Un Main Pastor puede otorgar el rol de pastor a otros (e.j se registra su esposa y con el rol believer, el Main Pastor le otorga el rol pastor). Analogamente el comportamiento es similar a los roles superadmin y admin
(c) Los pastores no pueden otorgar permisos a otros para convertirlos en pastores. (como los admin)
Búsqueda y mensajería masiva:
Actualmente, para enviar un mensaje masivo, el usuario tiene que conocer el ID, lo cual no es óptimo. Necesitaríamos implementar una barra de búsqueda para añadir personas por su nombre, teléfono o correo electrónico y así generar una lista para enviar mensajes masivos. En relación con esto, planteo una pregunta: ¿podríamos implementar un sistema mas moderno como react socket, firebase o una combinación? Es solo una idea por ahora, pero me gustaría determinar si, dentro de nuestra arquitectura, tenemos un stack de tecnologías compatibles que podamos acoplar al sistema.
Seguridad de los datos:
Tengo acceso a la base de datos en Neon y sé que muchos datos no son legibles para mí (como los passwords), pero me preocupa la privacidad de la información sensible. Por ejemplo:
(a) Mensajes privados entre personas.
(b) Notas de consejería que un consejero pueda escribir sobre alguien.
(c) Datos económicos que solo debería ver el pastor.
¿Cómo podemos asegurar que solo las personas autorizadas vean esa información? Lo óptimo sería poder encriptar esos datos sin que se rompa la usabilidad de la funcionalidad, que en las tablas de la base de datos sea ilegible y solo pueda ser legible desde el dashboard para cada usuario autorizado.
Editor de texto (WYSIWYG):
He visto algunas librerías en GitHub (desconozco cual podria ser optima) para añadir un editor de texto enriquecido. Lo necesitaremos en la interfaz del dashboard para cuando se cree un curso o un programa. En lugar de un simple TextBox, necesitamos un editor que permita poner saltos de línea, negritas o cursivas. Ahora mismo, las descripciones se guardan en un solo bloque de texto y se ven muy mal, porque el sistema mete saltos de línea después de una coma en lugar de hacerlo después de un punto (por una regla que tenemos para intentar dar formato pero no es eficiente). Necesitamos algo estilo Word para que las descripciones se visualicen correctamente.
Atributos de usuario y avatares:
En la tabla de usuarios es importante añadir el atributo de "género" (masculino o femenino). Si no tenemos el género en el perfil luego no podemos mostrar estadisticas en el dashboard. Además, podríamos usar un avatar real, la foto de perfil de cada uno y no un avatar genérico como ahora, me gustaría que, en vez de ver iniciales, podamos usar librerías especializadas para mostrar imágenes de avatares más trabajadas.
El siguiente es el idioma. Tenemos que buscar una forma que sea sencilla, obviamente. No vale duplicar todos los archivos del frontend. Hay alguna técnica mediante la cual se generan o se crean diccionarios y luego, cuando cambia el idioma, se mapean todas esas estructuras y se cambia al vuelo. Esto también hay que hacerlo para añadir al menos dos idiomas más.
Otra opción que está pendiente es que nosotros tenemos, dentro de la tabla de enrolment, un atributo que es el del discount para poder ofrecer a una persona la oportunidad de pagar una matrícula con descuento. Pero podríamos añadir un módulo un poco más inteligente y más avanzado de un sistema de cupones de descuento en el que, desde el dashboard, un admin pueda generar cualquier número de cupones de X porcentaje de descuento y, de manera inteligente, poder registrar en la base de datos quién utiliza el cupón y cuántos cupones quedan.
Otra parte importante es que tenemos que ver, según la estructura de nuestro proyecto, cómo podemos añadir dentro de la API una infraestructura o un apartado destinado a todo lo que será inteligencia artificial. Porque aquí vamos a meter agentes esp2ecializados que hagan tareas. Simplemente es, como primer paso, ver cuál es el sistema de ficheros que necesitamos: el óptimo, el que se usa ahora en el mercado, y cómo lo podemos encajar, asi que inicialmente veriamos la estructura (tree) del proyecto para evaluar donde creariamos la base de carpetas y anidaciones que nos permitan el desarrollo. Inicialmente he pensado en uno que, utilizando un modelo muy pequeño y muy veloz, y la ciudad donde está la iglesia (en el momento de enviar los datos de registro) pueda generar los slugs de manera dinámica, comprobando los que ya existen en la base de datos para no repetir, debe ser legible, bonito, sencillo, y que me generen los códigos de invitación tambien, estos se pueden formar mas facilmente con parte del nombre de la iglesia (4 caracteres) + 3 caracteres del lugar, ciudad o provincia donde esta la iglesia + codigo postal. Entonces, lo suyo es que este agente, a través de una query, se traiga los slugs creados en la base de datos y, con el nombre de la iglesia y la ciudad, genere un nombre distinto y una invitación. Además, es súper importante que, dentro de esta infraestructura, todos los agentes que creemos estén enmarcados en una interfaz donde yo puedo cambiar el agente rápidamente de modelo. Es decir, el mismo agente que genera los codigos de invitacion y los slugs lo pueda utilizar con Gemini, con GPT, con Claude, con cualquier modelo. Para eso, probablemente necesitamos un diseño tipo facade o factory, pero este punto es importante, definir un buen patron de diseño.
Dentro de esa arquitectura para la implementacion del punto anterior, ¿se hace en el back y el front? hay que guardar agentes, prompting, modulos con IA (los modulos van dentro de la estructura normal del back fuera de esta implementacion? o conservamos esos modulos dentro del scope de IA?
Luego, otro asunto es que, cuando un usuario se crea, se crea con un booleano. Este booleano es el is active y esta persona se queda activa después de que registra su correo y lo verifica. Sin embargo, cuando creamos la figura de la iglesia, que tiene asociado un pastor, deberíamos crear, en principio, las dos cosas a la vez. A través de un formulario, insertaríamos la iglesia en una tabla y el usuario en otra (esto ya lo tenemos funcionando). Este usuario se tiene que validar a través del correo, lo que cambia su estado de is active a true, y la iglesia también se cambia a active. Pero aquí tenemos que darle un poco una vuelta, que son los guardarraíles. Yo lo que quiero es que, cuando el pastor y la iglesia se registren, el administrador del SaaS tenga que validar manualmente si esa iglesia existe. Es decir, imagínate que yo soy el pastor, yo me registro, me llega el correo, yo lo valido. En ese instante, lo que tiene que hacer es que mi usuario se quede is active, pero mi rol únicamente es believer, no es pastor. Yo, como administrador, recibo una notificación de que ese usuario ha registrado una iglesia y entonces yo tengo que ver si es real, si yo reconozco ese pastor en esa iglesia. Si es real, yo, como administrador, lo valido. La iglesia pasaría ak estar activa por una parte y automáticamente le concederíamos el rol de pastor a ese usuario. Así es como tiene que estar el flujo, es el flujo adecuado para evitar registros indiscriminados o de iglesias que no estan asociadas al programa. También tienes que apuntar que, en esa validación, no solamente podemos aceptar, sino que podemos rehusar. ¿Qué sucede si rehusamos? Eliminamos la iglesia y conservamos al pastor. Hacemos un soft delete, un hard delete. Lo dejamos pending y pedimos información al usuario. No sé, esto hay que definirlo bien. Por otra parte, ahora tenemos el formulario que registra la iglesia y el pastor simultáneamente. Pero imagina que un usuario se registra y a los dos años se convierte en pastor y tiene su iglesia. Tenemos que tener también un formulario, una solicitud para anexar la iglesia a un usuario que se va a convertir posteriormente en pastor. Y el flujo es igual: yo, como usuario que tengo el rol de líder o incluso que ya tengo el rol de pastor, hago la solicitud, pero la valido como administrador. ¿Necesitariamos alguna unique key formada por el church id y el user id? ¿Alguna tabla extra para manejar esas relaciones de manera limpia?
Importante también: nuestros usuarios. Cuando un usuario se registra, para el usuario no tenemos un enum, y es necesario crear un enum status también para el user. Por si un administrador, desde el dashboard o desde el panel, imagínate que quiere suspender, inactivar o banear la cuenta de un usuario por algún motivo legal, ético o porque está inactivo. También me serviría para después hacer una query y ver si hay usuarios con ese estatus desde hace X tiempo y poderlos mover a archivados porque llevan, no sé, un año como inactivo. Entonces, hay que crear este enum con datos como, por ejemplo, si el usuario está activo, baneado, ausente o si ha fallecido. Tenemos que pensar que esto es útil para gestionar los usuarios y para poder agregarlos a la tabla de usuarios archivados. Resulta muy práctico porque, si archivamos o baneamos a una persona, implementaremos en el sistema global de login que, cada vez que usuario quiera iniciar sesion, comprobemos su estado y validar que sea "active". Si es diferente, mostramos un mensaje de error y pediremos que se comunique con un administrador por si es necesario desarchivarlo. Esta funcion inicialmente sera solo para los roles seleccionados en el sistema SaaS, no para la organizacion tenant, aunque hay que pensarlo de tal forma que podamos expandirla alli de manera muy simple si quisieramos, o tal vez implementarla en ambas partes pero poderla habilitar o deshabilitar desde el panel SaaS para todos los tenant.
Otro punto importante es el registro. Imagina que le pregunto al usuario: "¿Eres estudiante de una iglesia y conoces su código de invitación?" o aunque no sea estudiante, si es miembro de una iglesia. Si es así, ese código se valida en el backend para vincular al usuario con una iglesia, y después el pastor de esa congregación podrá ver a sus estudiantes vinculados.
Hay que planear bien este flujo de validación:
El usuario se registra con un código de invitación.
Valida su cuenta a través del enlace que le llega por email (status cambiado a "is_active").
El pastor debe validar que esa persona realmente es miembro de su congregación; tendrá que aceptarlo o rechazarlo.
Si el pastor lo rechaza, el usuario ya no aparece en su lista y pasa automáticamente a un código genérico (un usuario "vinculado" a una church universal), que indica que no está vinculado a una iglesia específica, como un estudiante independiente. (Esto tenemos que pensarlo un poco mejor, si creamos una iglesia "no iglesia" dentro de la tabla church para que el usuario tenga el church_id, o si los creamos en una tabla distinta, por ejemplo no_church aunque tambien tengan church_id.
No sé si esa vinculación del usuario con la iglesia debe ir a través de un enum o de un campo específico. Si luego se convierte en estudiante, ¿esa vinculación la mostramos en alguna tabla de "student" o tiene que ser una tabla común para "student", "user" y "church"? El pastor tiene que poder admitir o rehusar a alguien, el sistema le da al usuario el rol de "believer" y despues, cuando se genere como estudiante, poder vincularlo al lugar adecuado (iglesia o no iglesia) para que el pastor o un admin de SaaS puedan gestionarlo. Estos usuarios independientes solo deberían ser visibles para los superadmin y la organización central; los pastores de otras iglesias (tenants) no pueden verlos.
Por otro lado, dentro de la implementación actual, no puedo aislar mi interfaz del SaaS de una iglesia. Tenemos que pensar si creamos un dashboard para el SaaS desvinculado del login y del home actual, o si dentro de ese mismo panel integramos las funciones de superadministrador SaaS. Ahora mismo, cuando despliego la base de datos desde cero, no tengo ninguna forma de crearme como miembro del SaaS. Me creo un usuario, pero como el rol por defecto es "believer", no puedo darme superpoderes a mí mismo ni a nadie. Tengo que manipular la base de datos directamente, lo cual es una chapuza para cambiarme de rol. Además, para registrarme, el sistema me obliga a estar vinculado a un Church ID, así que tengo que crear una iglesia ficticia para poder entrar. Este no es el flujo ideal. Debería poder entrar a través del panel central (el que no tiene el slug) y tener control absoluto del SaaS, de los tenants y de los roles de la organización central (como instructores), independientemente de los roles de cada iglesia. Necesitamos un flujo de instalación o configuración inicial, de un solo uso, para cuando montamos el sistema limpio en un servidor, algo similar a cuando instalas una aplicacion de php que te va guiando, te creas el superadmin y te da acceso al panel principal, y que solo se gestiona una vez. Para mi lo mas intuitivo es que los miembos del SaaS ingresen a traves de la url principal, sin slug, y los tenant a traves del slug.
Otra mejora tiene que ver con los colores que estamos insertando por defecto al crear una iglesia nueva. Tendríamos que añadir al formulario del pastor un selector de colores para poder poner el color de manera manual, la tipica ruleta donde seleccionas el color en hexadecimal. Además, hay que añadir una configuración en el panel de administración del dashboard para cambiar esos colores, ya que están pensados para los temas específicos de la iglesia.
Por otro lado, tenemos que mantener el estado del slug cuando se cierra la sesión. Ahora mismo, si entro con un slug (como "?church=iglesia-madrid"), al cerrar la sesión me lo quita de la URL. Es necesario que se conserve completa porque es muy molesto tener que escribirlo cada vez que quiero acceder o que cualquier usuario quiera hacerlo.
Sobre la gestión de usuarios, tengo varias dudas:
El panel del SaaS dentro del login del dashboard: ¿cómo creamos un superadmin del SaaS?
No sé si eso debe ir en la misma tabla de "users", porque quedarían mezclados los usuarios normales con los superadmin de administración del SaaS.
Como en nuestra tabla users un usuario no puede existir sin un "church_id", quizás necesitemos una tabla independiente para la administración del SaaS con sus propios roles.
Otra propuesta para roles de administrador de SaaS es incluir una función en su dashboard que se comunique con el servidor de la base de datos para hacer copias exactas de toda la información (índices, foreign keys, funciones, triggers, etc. La base al completo). Ademas de la parte inversa para restaurar esas copias. Podríamos establecer un cron job para que se generen automáticamente en días y horas específicos y se envíen a un storage.
Respecto al almacenamiento:
Tenemos un giga disponible en Vercel que ya está creado pero no implementado.
Sería útil para mover ahí los recursos estáticos que ahora están en el servidor en React, como las imágenes de los cursos o los avatares de los perfiles.
También servirá para guardar los documentos PDF que generaremos en el futuro.
Hay un fallo en la configuración de la interfaz global. Antes podíamos activar y desactivar widgets al loguearnos con un usuario con "superadmin", pero ahora no aparece esa información, no se ven los selectores de la interfaz global ni los de la interfaz. No sé si es por el cambio a multitenant o por el "tenant_id".
Cuando se activa un curso se tienen que actualizar los kpis automaticamente del dashboard admin dentro de universidad
Dentro de gestion de usuarios y avanzado tenemos que añadir un icono para identificar si el usuario es tenant, saas, o iglesia universal
Cuando se crea un curso, no se pide lo que es el contenido de la asignatura, luego se muestra que el material se esta preparando pero tenemos que tener algun sitio de donde se introduce esa informacion
Monitoreo de la API
Creacion de informes completos en PDF
Certificaciones, Facturas, Diplomas en PDF
Hay tres temas principales que debemos contemplar:
Matrícula inicial por programa:
Quieren establecer una matrícula inicial parametrizable en importe, que se sume a la primera compra (sea de material o de pack completo, aqui todavia no hay upgrade porque hablamos de primera compra de un programa). Esto debe configurarse a nivel de programa, no de curso, permitiendo definir si se cobra matrícula o no, bajo dos modalidades:
(a) Cobro por inicio de programa: se cobra si es la primera asignatura que el alumno cursa en ese programa específico. Aplica a todos (tanto a usuarios totalmente nuevos como a estudiantes que ya estén en otro programa).
(b) Cobro exclusivo a nuevos estudiantes: se cobra únicamente a usuarios que no son estudiantes en ningún programa. Si ya están matriculados en otro, el sistema lo valida y los exime. Aquí veo una posible fricción o inconsistencia lógica, no a nivel funcional (porque a nivel funcional no hay problema), sino de orden entre un programa A y un programa B.
Por ejemplo:
• Si en A pagan solo los que no son estudiantes, y en B pagan todos aquellos que hagan la primera inscripción del programa:
(a) Si un alumno se matricula primero en A, paga porque no es estudiante; si luego se matricula en B, vuelve a pagar porque es su primera asignatura de ese programa. Ese alumno pagaría dos veces.
(b) Si lo hace al revés y se matricula primero en B, paga por ser su primera asignatura de ese programa; pero cuando vaya a matricularse en A, ya no paga porque ya es estudiante.
Como te digo, a nivel funcional no habría problema, pero sí parece una inconsistencia. Por tanto, tal vez sea mejor valorar dos opciones:
Se paga solo para nuevos estudiantes.
Se paga si es la primera asignatura del curso, pero permitiendo parametrizar si se exime del pago por haber cursado, estar matriculado o ser estudiante de un programa determinado (pudiendo ver la lista de programas y marcarlos con un check).
No sé si esta segunda opción mete mucha complejidad, pero permitiría gestionar los casos donde los cursos van por niveles de dificultad. Imagínate que 0 es la dificultad más baja y 5 la más alta:
• Para el programa 0, todos los estudiantes nuevos tienen que pagar.
• Para el curso de dificultad 1, todos los estudiantes nuevos pagan, pero si el estudiante ya se ha matriculado en aquellos de dificultad menor (que en la práctica no lo veremos por dificultad, sino por nombre), queda eximido de la matrícula.
Esto puede incentivar al estudiante a hacer los cursos en ese orden. De todos modos, hay que tener en cuenta que cualquiera se puede inscribir a cualquier programa directamente (por ejemplo, inscribirse al programa universitario sin pasar antes por Berea, Vida Cristiana o Servicio Cristiano).
En ambos casos, el sistema debe garantizar que la matrícula se pague solo una vez por estudiante (por programa o de forma global, según la modalidad elegida).
Compra de material sin vinculación a un programa:
Representa un reto porque el modelo de datos actual asocia todos los cursos a un programa. Forzar al usuario a seguir el flujo estándar genera dos problemas: queda registrado como matriculado en un programa sin desearlo y, al no presentar exámenes de unidad, deja registros sin notas que distorsionan los KPIs y la precisión de los datos. Venderlo fuera de la plataforma tampoco es ideal por duplicar flujos.
La solución que propongo es que, al crear un curso, se incluya como opción parametrizable la venta de pack, upgrade, solo libro y un concepto como "libro de reemplazo" o sustitutivo. Este flujo serviría tanto para alumnos matriculados que necesiten reponer un libro extraviado o dañado sin duplicar su matrícula, como para usuarios que solo quieren estudiar por su cuenta. De este modo, registramos únicamente la compra del material sin generar matrículas ficticias en el curso ni en el programa.
Compras y matrículas grupales (Scope Tenant):
Debemos habilitar una opción para casos como el de una iglesia que asume los gastos de un grupo (por ejemplo, 15 personas). Actualmente, un usuario solo compra para sí mismo o, si acaso, matricula a otro pagando en su nombre (confírmame esto en que casos, creo recordar que puede hacerlo un pastor, un instructor y no se si tesorero, nunca un estudiante o usuario a otro).
Falta un panel donde un pastor (a nivel de tenant) pueda visualizar a sus integrantes, seleccionar el programa y curso, y realizar un pago único global por todos para matricularlos de golpe, (algo como que el vea una lista de sus feligreses y los señale con un check, despues, cuando seleccione programa, curso, y modalidad (material, pack, upgrade (aqui implica matricula masiva), o material sustituto porque solo quiere libros) puede, pagar del tiron con la tarjeta o cualquier medio disponible, o bien generar una orden de pago offline para transferencia bancaria.
Respecto del flujo de creacion de programas, cursos y matricula:
- No me deja crear un programa sin creditos, y se supone que hay cursos que pueden ser solo examenes de unidad, sin acreditacion y sin trabajo final, asi que esto es contradictorio, si un programa te exige creditos y todos los cursos de este programa los tienen, lo logico es, si creo un programa sin creditos -> todos mis cursos que esten ligados a este programa deben tener 0 creditos (y debe existir un guardarrail para que nadie ponga creditos a un curso que hace parte de un programa sin creditos). Luego, si creo un programa que tiene por ejemplo 60 creditos, yo puedo ofrecer cursos dentro de ese programa en las dos modalidades, curso acreditado (pack completo ó un upgrade de previo material sin opcion a examen), o solo material, en cuyo caso sigue haciendo parte de un programa y obtendra un certificado de finalizacion de curso y programa, pero sin creditos ECTS. Hay que de paso revisar el modelo de datos por si necesitamos añadir campos para el certificado por asignatura, el recibo de pago (o recibos, porque primero puede coger solo material y luego el upgrade), y el diploma o certificado al completar un programa, los generaremos en PDF y habra que almacenarlos en el bucket, de ahi que puede que necesitemos añadir campos o crear una nueva tabla, debe ser lo mas prolijo y limpio posible. (falta por definir como crearemos esos PDF, tendremos que tener plantillas para cada operacion e incorporar esto a una arquitectura limpia y a una serie de eventos automaticos que se disparen, como, si hace un pago, se envia recibo, si completa curso o programa se envia certificado, todo esto al email, ademas de permanecer en la UI para el estudiante y la administracion)
En los chips que se crean de Pack certificado, Solo Mterial y Ampliacion a certificado, mostraria solo los checks de lo que incluye, no de lo que no incluye, porque si elegi la modalidad online para un curso, no tiene sentido mostrar tachado clases presenciales y profesor asignado, por cierto, que es lo de profesor asignado, porque aqui hay que tener en cuenta un matiz, la organizacion como universidad si que puede asignar el rol de instructor a un curso, pero con el proposito de que esa persona sea la encargada de calificar sus examenes de unidad, trabajo final, y reportar todas sus notas, pero esta personas no le da clases a nadie a pesar de ser una modalidad online, sin embargo, hay congregaciones donde ellas mismas pueden crear un curso para su congregacion, y asignar un instructor para que califique, y que a su vez da clases online, pero eso lo provee el propio tenant como iglesia, no la organizacion, asi que hay que buscar la manera de clarificar este punto para que no haya engaño o confusion y que alguien piense que lo del profesor asignado es porque la organizacion tiene a alguien que les va a dar clases.
En el cobro fuera de linea dice: "El pago se acuerda de forma presencial con la iglesia. No se cobra nada en línea.", esta bien pero yo antes de la manera presencial en la iglesia, diria algo como "El pago se hace por transferencia bancaria y se hace efectivo cuando comprobemos el ingreso en cuenta", luego, en las preguntas frecuentes añadimos el matiz, una persona si puede pagar en la iglesia, primero, si pertenece una congregacion cuyo pastor este registrado y el usuario haga parte de esa congregacion, segundo, si hay un acuerdo con el pastor y su congregacion, es decir, el pastor recibe el dinero de las personas que matriculen en esa modalidad offline y luego el es quien hace la transferencia o el pago online por todos (de aqui se desprende uno de los requisitos que te mencione arriba)
Lo del plan de estudios me gusta, separaria un poco mas lo de preguntas frecuentes
Usaria el ancho completo si caben las modalidades del curso (las tres en horizontal, luego si es una pantalla mas angosta pues se irian apilando)
