Aplicacion pequena de gestion para gimnasios, estudios de entrenamiento personal y entrenadores. Esta construida como una unica app Next.js con InsForge como backend para autenticacion, base de datos, funciones, almacenamiento y despliegue.
La Fase 2 anade un portal de cliente separado bajo /cliente/* sin romper la app operativa de staff existente. Los roles de staff siguen siendo solo admin y trainer; el cliente del portal no cuenta como rol de staff.
Para el asistente de nutricion, el objetivo de modelo en produccion es google/gemini-2.5-flash-lite. Antes de activar comportamiento productivo, hay que verificar su disponibilidad en el backend mediante GET /api/ai/models o el MCP get-backend-metadata.
Estado actual de Fase 2, Fase 0:
- verificado que
google/gemini-2.5-flash-liteesta disponible en el backend enlazado - anadido informe admin de calidad de emails para preparar el claim del portal sin tocar aun el comportamiento del staff app
- pendiente la migracion de tablas del portal y nutricion antes de construir
/cliente/*
Estado actual de Fase 2, Fase 1:
- anadido el esquema
client_portal_accountscon claim controlado y auditoria deportal_claimyportal_login - anadidas las rutas
/cliente/login,/cliente/registroy/cliente/recuperar-clave - el login del portal ya soporta email/password y Google OAuth sin reutilizar la sesion del staff
/cliente/dashboardqueda solo como placeholder tecnico hasta la siguiente fase
Estado actual de Fase 2, Fase 2:
/cliente/dashboardqueda como Actividad y muestra metricas, grafica semanal, bonos activos e historial reciente/cliente/actividadredirige a Actividad para no romper enlaces antiguos/cliente/agendaya ofrece vistas de semana y mes, solo muestra sesiones propias y permite cancelar una sesion programada con mas de 24 horas de antelacion/cliente/ajustesya permite editar el telefono mediante Function sin exponer escritura directa desde cliente- los bonos compartidos se muestran sin revelar otros titulares, usando
Otro titular
Estado actual de Fase 2, Fase 3:
- anadidas las tablas
client_nutrition_profiles,nutrition_threads,nutrition_messagesynutrition_usage_events /cliente/nutricionya ofrece chat persistente con hilo activo por cliente- el acceso rapido flotante al asistente aparece en todas las pantallas autenticadas del portal cliente y abre un modal responsive a pantalla completa
- la configuracion de aplicacion
nutrition_assistant_v1usa el modelo verificadogoogle/gemini-2.5-flash-litey onboarding inicial por chat
Estado actual de Fase 2, Fase 4:
- la memoria nutricional persistente ya guarda datos clave como altura, peso, objetivo, comidas al dia, preferencias y restricciones
- el asistente ya monta contexto acotado con memoria, resumen reciente de entrenamiento, rolling summary y ventana corta de mensajes
- se han activado cuotas de 20 mensajes de usuario por dia y 300 por mes con contadores visibles en el portal
- los rechazos por fuera de alcance, diagnostico, TCA y patologia compleja son breves y consistentes
Estado actual de Fase 2, Fase 5:
- anadida la tabla
weekly_nutrition_planspara guardar menus semanales en JSON estructurado - el asistente ya puede guardar un menu semanal cuando el cliente lo pide explicitamente
/cliente/nutricionya muestra los menus semanales guardados/cliente/ajustesya incluye acciones avanzadas con confirmacion para limpiar chat, memoria y planes guardados
Estado actual de agenda staff:
/agendaes la pantalla operativa de sesiones de staff- la agenda permite vistas de dia, semana y mes, filtrado por entrenador y seleccion por horas completas
- las citas se asocian a bonos sin consumir sesiones al crearlas; el consumo sigue siendo manual
- los bonos compartidos asocian automaticamente todos sus titulares a la cita
- cada perfil staff puede elegir un color pastel para diferenciar visualmente sus citas
- las citas canceladas se mantienen visibles en gris suave y aparecen al final del dia para no mezclarse con las activas
Estado actual de agenda cliente:
/cliente/agendaofrece vistas de semana y mes dentro del portal- el cliente solo ve sus propias sesiones o sesiones compartidas sin revelar la identidad del otro titular
- el cliente puede cancelar una sesion programada solo si faltan mas de 24 horas para el inicio
- las sesiones canceladas siguen visibles en gris suave y ya no se pueden volver a cancelar
Estado actual de consumo automatico:
- existe la Function
auto_consume_calendar_sessionspara consumir bonos de sesiones ya finalizadas; se ejecuta cada hora y deja una hora de margen antes de consumir - el job solo actua sobre sesiones
scheduledocompleted; ignoracancelledyno_show - si encuentra un consumo manual compatible, lo vincula a la sesion para no duplicar el descuento
- existe la Function
run_daily_expiry_scanpara caducar bonos vencidos y emitir avisos D-7/D-0; debe ejecutarse a diario con el token de sistema - los bonos en pausa no caducan mientras la pausa esta activa; la pausa extiende
expires_ony el job solo caduca tras reanudar el bono
Nota de UX del asistente:
- las respuestas del chat nutricional ya renderizan markdown basico con estilos visibles, incluyendo negritas, listas y saltos de linea
Estado actual de Fase 2, Fase 6:
- la ficha staff del cliente ya muestra estado del portal, proveedor,
claimed_at,last_login_aty permite desvincular la cuenta del portal como admin - la edicion de cliente ya muestra si la ficha esta lista para portal, si el email esta duplicado o si falta email, y permite desactivar/reactivar un acceso ya reclamado
- ajustes de admin incluye activacion manual de portal cliente para crear o reparar accesos con contrasena directa sin depender del codigo de email
- se ha preparado una checklist de smoke test especifica de Fase 2 para validar separacion staff/cliente, nutricion y soporte operativo
- quedan documentados los pasos de despliegue en InsForge Deployments para migraciones SQL, Functions y build final
Trainium resuelve el gimnasio activo desde el host. El gimnasio inicial es eltemplo, accesible en eltemplo.trainium.es; el dominio raiz trainium.es no resuelve gimnasio y no debe mostrar datos operativos. En local y preview se usa TRAINIUM_DEFAULT_GYM_SLUG=eltemplo como fallback explicito.
La migracion insforge/sql/032_multitenant_subdomains.sql crea gyms, inserta eltemplo de forma idempotente, anade gym_id obligatorio a todas las tablas tenantables, migra todos los datos existentes a eltemplo.id, reemplaza constraints globales por constraints por gimnasio y prepara facturas con contador independiente por gym_id.
Despues de aplicar la migracion no existe modo legacy: cualquier tabla tenantable debe tener gym_id NOT NULL y COUNT(*) WHERE gym_id IS NULL = 0. Las Functions reciben el contexto de gimnasio desde el subdominio y todas las rutas staff/portal consultan filtrando por gym_id.
Orden de rollout de Fase 2:
client portal authclient dashboardclient activity historynutrition assistantweekly nutrition plansadvanced client settings
- Next.js App Router
- TypeScript
- Tailwind CSS
- shadcn/ui-style components
@insforge/sdk- InsForge Auth, Database, Functions, Storage y Deployments
- Tipos por sesiones flexibles entre
1y30 - Tipo
mensualcon caducidad al final del mes natural contratado - Compartidos de hasta
5titulares - Solo los bonos por sesiones descuentan consumos manuales
- Crear un bono registra tambien su venta con metodo de pago y precio pactado
- Al crear o renovar un bono por sesiones se puede adjuntar un patron semanal para agendar automaticamente sus citas
- La fecha contable de ventas y renovaciones de bonos sigue
contracted_on, aunque el alta en el sistema se haga mas tarde
- Instala dependencias:
npm install- Crea
.env.locala partir de.env.exampley completa:
NEXT_PUBLIC_INSFORGE_URLNEXT_PUBLIC_INSFORGE_ANON_KEYNEXT_PUBLIC_APP_URLcomo fallback/canonical URL; los redirects de auth intentan usar primero el host publico de la request actualTRAINIUM_ROOT_DOMAIN=trainium.esTRAINIUM_DEFAULT_GYM_SLUG=eltemploAPP_TIMEZONEBUSINESS_NAME
- Arranca el entorno local:
npm run dev- Verificaciones previas a despliegue:
npm run lint
npm run typecheck
npm run buildnpm run build fuerza Webpack porque Next.js 16 usa Turbopack por defecto y en este workspace falla al recolectar paginas App Router existentes.
Los usuarios staff nuevos pueden necesitar verificar su email con un codigo de 6 digitos antes de entrar por primera vez. Si intentan acceder desde /login sin haber activado la cuenta, Trainium redirige el flujo al modo de activacion y les pide el codigo recibido por email para completar el acceso.
La pantalla /settings ya incluye dos operaciones protegidas para admins:
- alta y mantenimiento de usuarios staff (
traineryadmin) mediante la Functioncreate_staff_user - reenvio del codigo de activacion para staff pendiente mediante la Function
resend_staff_activation - ejecucion manual de
run_daily_expiry_scancomo fallback si el Schedule falla o no esta disponible - edicion del negocio y subida de imagen PNG cuadrada para generar automaticamente logos, favicon e iconos PWA por
gym_id
La pantalla /products ya permite a admins:
- anadir stock
- reducir stock con motivo obligatorio
- borrar productos solo si no tienen historial en
sale_items
La pantalla /sales muestra la anulacion de ventas como una tarjeta propia para admins, usando la Function protegida void_sale.
Para revisar cambios visuales sin InsForge ni login real, activa el modo preview solo en .env.local:
TRAINIUM_VISUAL_PREVIEW=1Despues arranca la app y abre una de estas rutas iniciales:
npm run dev- Staff:
http://localhost:3000/dashboard?preview=staff - Cliente:
http://localhost:3000/cliente/dashboard?preview=cliente
El parametro inicial guarda una cookie local trainium_visual_preview, asi que puedes navegar internamente sin repetir la query. En produccion el modo preview se ignora aunque alguien conozca el parametro. Las acciones sensibles en preview no escriben en InsForge y devuelven respuestas simuladas para facilitar pruebas visuales.
Los tests e2e usan el preview visual local para cubrir smoke de staff, smoke del portal cliente y regresiones responsive del menu inferior:
npm run test:e2eVariantes utiles:
npm run test:e2e:headed
npm run test:e2e:uiLa configuracion levanta Next.js en http://127.0.0.1:3005 con TRAINIUM_VISUAL_PREVIEW=1.
Trainium expone un manifest App Router en /manifest.webmanifest, registra un service worker en /sw.js y carga iconos por tenant desde settings.brand_assets cuando existen. Si un gimnasio aun no ha subido imagen, se usan los iconos por defecto de public/icons. La instalacion PWA y las notificaciones push web se mantienen separadas: el push solo se activa desde /cliente/ajustes tras accion explicita del cliente.
Los iconos por defecto se generan desde public/trainium-icon.png:
npm run generate:pwa-icons- Abrir la URL publica activa de la app en Chrome.
- Iniciar sesion si corresponde.
- Tocar el aviso
Instalar Trainiumsi aparece, o abrir el menu de Chrome. - Elegir
Instalar appoAnadir a pantalla de inicio. - Abrir Trainium desde el nuevo icono.
- Abrir Trainium en Safari.
- Tocar Compartir.
- Tocar
Anadir a pantalla de inicio. - Confirmar el nombre
Trainium. - Abrir Trainium desde el nuevo icono.
Limitacion conocida de iOS: los permisos de notificaciones push solo pueden solicitarse cuando la PWA ya esta instalada en la pantalla de inicio.
- Abrir la app en Chrome.
- Abrir DevTools.
- Entrar en
Application. - Revisar
Manifesty comprobarname,start_url,display,theme_colore iconos. - Revisar
Service Workersy confirmar que/sw.jsesta registrado.
La Fase 2 de PWA usa Web Push estandar sobre InsForge Database, Auth, Functions y Schedules. No usa Firebase Cloud Messaging ni apps nativas. Las comunicaciones de negocio se centralizan en send_client_communication, que intenta email y push cuando el canal esta disponible. En esta fase existen estos eventos:
pass_expiry_d7: aviso 7 dias antes de caducar un bono.pass_expiry_d0: aviso el dia de caducidad de un bono.pass_assigned: confirmacion de nuevo bono o renovacion.calendar_session_24h: recordatorio 24 horas antes de una sesion agendada.manual_note: aviso manual o confirmacion operativa.
No hay notificaciones push de nutricion, stock, informes ni alertas genericas de staff.
Anadir en .env.local y en las variables del deployment de InsForge:
NEXT_PUBLIC_VAPID_PUBLIC_KEYVAPID_PUBLIC_KEYVAPID_PRIVATE_KEYVAPID_SUBJECT
NEXT_PUBLIC_VAPID_PUBLIC_KEY y VAPID_PUBLIC_KEY deben tener el mismo valor publico. VAPID_SUBJECT puede ser mailto:soporte@trainium.app o el email de soporte del negocio.
Opcion compatible con Deno/Web Crypto:
deno run https://raw.githubusercontent.com/negrel/webpush/master/cmd/generate-vapid-keys.tsLa Function de envio usa jsr:@negrel/webpush, una libreria Web Push basada en Web APIs compatible con runtimes Deno/Web Worker. Se evita web-push de Node porque depende de APIs Node que no son apropiadas para InsForge Functions.
Aplicar la migracion:
npx @insforge/cli db import insforge/sql/018_pwa_push_notifications.sqlTablas nuevas:
push_subscriptionspush_preferences
notification_log queda ampliada para canal push, los event_type soportados y dedupe_key.
Para homogeneizar email y push, aplicar tambien:
npx @insforge/cli db import insforge/sql/026_homogeneous_client_communications.sqlPublicar o actualizar:
save_push_subscriptionremove_push_subscriptionupdate_push_preferencessend_client_communicationsend_push_notificationsend_push_to_clientsend_pass_expiry_d7_pushessend_calendar_session_24h_reminders
save_push_subscription, remove_push_subscription y update_push_preferences resuelven la identidad del cliente desde InsForge Auth y client_portal_accounts; el navegador nunca envia un client_id.
Crear estos Schedules en InsForge:
- Diario, despues de medianoche en
Europe/Madrid:send_pass_expiry_d7_pushes - Cada hora:
send_calendar_session_24h_reminders
Ejemplo de creacion usando la API_KEY reservada de InsForge como credencial estable para jobs programados:
npx @insforge/cli schedules create \
--name "Push caducidad bonos D-7" \
--cron "10 0 * * *" \
--url "<INSFORGE_BASE_URL>/functions/send_pass_expiry_d7_pushes" \
--method POST \
--headers '{"Authorization":"Bearer ${{secrets.API_KEY}}","Content-Type":"application/json"}' \
--body '{}'
npx @insforge/cli schedules create \
--name "Push recordatorio sesiones 24h" \
--cron "0 * * * *" \
--url "<INSFORGE_BASE_URL>/functions/send_calendar_session_24h_reminders" \
--method POST \
--headers '{"Authorization":"Bearer ${{secrets.API_KEY}}","Content-Type":"application/json"}' \
--body '{}'Los envios usan dedupe por evento, canal, cliente y entidad:
pass_expiry_d7:email:{client_id}:{pass_id}:{expires_on}pass_expiry_d7:push:{client_id}:{pass_id}:{expires_on}pass_assigned:{channel}:{client_id}:{pass_id}calendar_session_24h:{channel}:{client_id}:{calendar_session_id}
- Servir la app en HTTPS o
localhost. - Entrar como cliente en
/cliente/login. - Abrir
/cliente/ajustes. - Pulsar
Activar notificaciones. - Confirmar el permiso del navegador.
- Ver en DevTools,
Application > Service Workers, que/sw.jsesta activo. - Crear o renovar un bono desde staff y verificar el evento
pass_assigned.
- Instalar Trainium desde Chrome.
- Abrir Trainium desde el icono instalado.
- Entrar en
/cliente/ajustes. - Activar notificaciones y confirmar permisos.
- Crear una cita para el cliente y ejecutar
send_calendar_session_24h_reminderscon una cita dentro de la ventana de 23-25 horas.
- Abrir Trainium en Safari.
- Instalar con Compartir >
Anadir a pantalla de inicio. - Abrir Trainium desde el icono.
- Iniciar sesion como cliente.
- Ir a
/cliente/ajustesy activar notificaciones.
Limitacion iOS: Safari solo permite pedir permiso push a PWAs instaladas en pantalla de inicio.
- Permiso denegado: cambiar permisos del sitio en el navegador y volver a activar.
- No hay service worker: revisar
/sw.js,Application > Service Workersy que la app este en HTTPS o localhost. - Suscripcion inactiva: volver a activar desde
/cliente/ajustes. - Endpoint caducado: los envios con respuesta
404o410marcan la suscripcion como inactiva. - Faltan claves VAPID: revisar
NEXT_PUBLIC_VAPID_PUBLIC_KEY,VAPID_PUBLIC_KEY,VAPID_PRIVATE_KEYyVAPID_SUBJECTen InsForge.
app/: rutas App Routercomponents/: componentes UI compartidosfeatures/: componentes y helpers por modulolib/insforge/: cliente, auth y utilidades InsForgeinsforge/sql/: esquema y migracionesinsforge/functions/: funciones de negocio
- Esquema base:
insforge/sql/001_schema.sql - Seed inicial:
insforge/sql/002_seed.sql - Migracion de bonos flexibles y hasta 5 titulares:
insforge/sql/010_passes_flexible_model.sql
npx @insforge/cli db import insforge/sql/005_grant_invoice_sequence.sql
npx @insforge/cli db import insforge/sql/010_passes_flexible_model.sql
npx @insforge/cli db import insforge/sql/003_phase3_clients_passes.sql
npx @insforge/cli db import insforge/sql/009_delete_client.sql
npx @insforge/cli db import insforge/sql/017_agenda_multi_passes.sql
npx @insforge/cli db import insforge/sql/020_clients_last_name_optional.sql
npx @insforge/cli db import insforge/sql/023_delete_pass_cascade_cleanup.sql
npx @insforge/cli db import insforge/sql/022_grant_invoice_sequence_all_roles.sqlCrear un bucket llamado tickets en InsForge Storage para los PDFs de ventas.
Crear tambien un bucket publico llamado gym-branding para las imagenes por gimnasio. La Function update_business_settings guarda las variantes en rutas versionadas:
gyms/{gym_id}/branding/{version}/{variant}.{ext}
Aplicar la migracion de columnas de branding antes de usar la subida desde Ajustes:
npx @insforge/cli db import insforge/sql/036_business_branding_assets.sql- Estrategia preferida: InsForge Schedules ejecutando
run_daily_expiry_scan - Fallback: usar la accion protegida expuesta en Ajustes o invocar manualmente la funcion hasta que Schedules este disponible
- Las comunicaciones de negocio usan
client.emails.send()desdesend_client_communicationcuando el cliente tiene email. - Si falta email, el intento queda en
notification_logcomoskipped. - Si InsForge Email devuelve error, el canal email queda como
failedy el resto de canales continua. - Los emails de Auth siguen gestionados por InsForge Auth y no pasan por este dispatcher.
Desplegar solo despues de lint, typecheck y build correctos:
npm run deploySi InsForge Deployments no estuviera disponible en este workspace, mantener la app buildable y ejecutar el flujo equivalente del panel/CLI cuando quede habilitado.
Antes de publicar la Fase 2 en InsForge Deployments:
- Importar las migraciones de portal y nutricion en orden:
npx @insforge/cli db import insforge/sql/013_phase2_client_portal_accounts.sql
npx @insforge/cli db import insforge/sql/014_phase2_nutrition_assistant.sql
npx @insforge/cli db import insforge/sql/015_phase2_nutrition_memory_and_quotas.sql
npx @insforge/cli db import insforge/sql/016_phase2_weekly_nutrition_plans.sql
npx @insforge/cli db import insforge/sql/018_pwa_push_notifications.sql
npx @insforge/cli db import insforge/sql/026_homogeneous_client_communications.sql
npx @insforge/cli db import insforge/sql/037_manual_client_portal_activation.sql
npx @insforge/cli db import insforge/sql/038_hourly_auto_consume_job_runs.sql- Publicar o actualizar las Functions de Fase 2:
claim_client_portal_accountrecord_client_portal_loginupdate_client_portal_profileensure_client_nutrition_threadappend_nutrition_messageupdate_client_nutrition_memoryrefresh_client_nutrition_summarysave_weekly_nutrition_planreset_client_nutrition_chatreset_client_nutrition_memorydelete_client_weekly_nutrition_plansset_client_portal_account_statusunlink_client_portal_accountmanually_activate_client_portal_accountsave_push_subscriptionremove_push_subscriptionupdate_push_preferencessend_client_communicationsend_push_notificationsend_push_to_clientsend_pass_expiry_d7_pushessend_calendar_session_24h_reminders
- Ejecutar validacion local final:
npm run lint
npm run typecheck
npm run build- Desplegar la app:
npm run deploy- Hacer smoke test inmediato sobre staff y portal usando la checklist de Fase 2.
Nota operativa:
- el despliegue debe ignorar
.next,node_modules, logs y ficheros locales mediante.vercelignorepara evitar subidas innecesarias y errores de upload en Vercel
- URL publica actual: la definida en InsForge Custom Domains o, en su defecto, la URL nativa
*.insforge.site - Ultimo deployment validado antes de esta iteracion:
64910067-0f06-43cb-97c1-312a3787cb9d
- Abrir
/loginy comprobar que carga la pantalla de acceso. - Abrir
/dashboardsin sesion y comprobar que redirige al login. - Iniciar sesion con un usuario de
profiles. - Verificar dashboard.
- Ejecutar los 3 flujos core:
- crear cliente
- renovar bono
- crear venta de producto
- Listar deployments:
npx @insforge/cli deployments list-
Identificar el ultimo deployment sano anterior.
-
Si el problema es de variables, corregirlas y redeplegar:
npx @insforge/cli deployments env list
npx @insforge/cli deployments env set NEXT_PUBLIC_APP_URL https://eltemplo.trainium.es
npx @insforge/cli deployments env set TRAINIUM_ROOT_DOMAIN trainium.es
npx @insforge/cli deployments env set TRAINIUM_DEFAULT_GYM_SLUG eltemplo
npm run deploy- Si el problema es de codigo, volver al estado local sano anterior y lanzar un nuevo
npm run deploy.
- Iniciar sesion como admin.
- Crear cliente.
- Editar cliente.
- Crear pase.
- Editar un pase existente.
- Borrar un pase de prueba y comprobar que tambien limpia consumos, pausas y la venta asociada cuando no hay renovaciones ni agenda vinculada.
- Crear o editar un tipo de bono con sesiones flexibles o mensual.
- Borrar un tipo de bono limpio sin bonos asociados.
- Consumir una sesion.
- Pausar pase dentro de reglas.
- Renovar pase y verificar notificacion interna.
- Crear producto.
- Anadir stock como admin.
- Reducir stock como admin con motivo.
- Borrar un producto limpio sin historial de ventas.
- Crear venta y verificar decremento de stock.
- Anular una venta como admin y verificar reposicion de stock si aplica.
- Crear o actualizar un usuario staff desde Ajustes.
- Reenviar el codigo de activacion de un staff pendiente desde Ajustes.
- Crear gasto.
- Crear sesion de agenda.
- Verificar que un bono compartido asocia todos sus titulares a la cita.
- Ejecutar
run_daily_expiry_scanuna vez y verificar idempotencia. - Generar ticket PDF.
- Verificar que cargan los informes.
- Iniciar sesion como admin en
/login. - Iniciar sesion como trainer y comprobar que no ve acciones admin-only de portal ni de stock.
- Abrir un cliente con email unico y verificar en staff:
- estado del portal
- proveedor
- fecha de claim
- ultimo acceso
- Como admin, desvincular una cuenta de portal desde la ficha del cliente y verificar que desaparece el estado reclamado.
- Volver a reclamar el portal desde
/cliente/logino/cliente/registrocon el mismo email valido. - Verificar que un usuario del portal no obtiene acceso a
/dashboardni a rutas staff. - Verificar que un usuario staff sin
profilesqueda bloqueado aunque exista en Auth. - Comprobar en
/cliente/dashboardque los bonos compartidos muestranOtro titulary nunca el nombre real del segundo titular. - Abrir
/cliente/agenday verificar que carga la vista mensual. - Abrir
/cliente/nutriciony enviar mensajes hasta comprobar que:
- el contador diario sube
- el contador mensual sube
- el hilo persiste al recargar
- Intentar superar 20 mensajes diarios y verificar bloqueo.
- Intentar una consulta fuera de nutricion y verificar rechazo corto.
- Intentar una consulta de diagnostico medico, TCA y patologia compleja y verificar rechazo corto.
- Pedir explicitamente un menu semanal y verificar que aparece en la lista de planes guardados.
- En
/cliente/ajustes, borrar chat, memoria y planes guardados, confirmando cada accion. - Verificar en
audit_logseventos de:
portal_claimportal_loginnutrition_memory_updatenutrition_chat_resetnutrition_memory_resetnutrition_plan_savenutrition_plan_delete