Sitio público orientado a venta consultiva e implementación de las recomendaciones de la auditoría de marca y mercado: - Inicio con tres rutas (industria, riesgo, cumplimiento) y clasificador de riesgo en el héroe, contra el hallazgo de que el visitante tenía que inferir qué solución le correspondía. - Cinco páginas por segmento prioritario y catálogo comparable por clase de fuego, capacidad y agente. - Los claims sin evidencia por modelo quedan aislados y se presentan como compromiso de documentación, nunca como característica del producto. - SEO técnico completo: metadatos por página, sitemap derivado de los datos, JSON-LD, iconos y tarjeta social generadas. Micro CRM: - Captura por formulario embebido y por widget de WhatsApp que registra antes de abrir la conversación. - Atribución de primer toque que sobrevive a la navegación. - Deduplicación de contacto; un mismo contacto acumula oportunidades. - Motor de asignación por reglas con reparto por turno de respaldo. - Panel con dos roles de alcance distinto, tablero analítico, bitácora, pedidos y reglas. No enlazado desde el sitio público y con noindex. Empaquetado en Docker multietapa con la base de demostración horneada en la imagen y el volumen de datos separado, para que los leads capturados sobrevivan a los redespliegues. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
86 lines
3.3 KiB
Bash
86 lines
3.3 KiB
Bash
#!/bin/sh
|
|
# =============================================================================
|
|
# Punto de entrada del contenedor de FSPM.
|
|
#
|
|
# Hace tres cosas antes de arrancar el servidor, en este orden:
|
|
#
|
|
# 1. Asegura que exista la base de datos en el volumen. Si el volumen viene
|
|
# vacío, copia la base de demostración que se horneó en la imagen durante
|
|
# la construcción.
|
|
# 2. Aplica el esquema con `prisma db push`.
|
|
# 3. Entrega el control al servidor de Next con `exec`, para que Next quede
|
|
# como PID 1 y reciba las señales de parada de Docker.
|
|
#
|
|
# CÓMO DETECTA QUE YA ESTÁ SEMBRADA
|
|
#
|
|
# Por la existencia del archivo de base de datos en el volumen ($BD).
|
|
# Si existe, no se toca su contenido: ni se copia la base de demostración
|
|
# encima, ni se ejecuta ningún seed.
|
|
#
|
|
# Y no puede duplicar el seed por una razón más fuerte que una comprobación:
|
|
# el seed no se ejecuta aquí. `prisma/seed.ts` es destructivo —borra todas las
|
|
# tablas antes de reconstruirlas— y `tsx`, que lo ejecuta, es dependencia de
|
|
# desarrollo y no está en esta imagen. La siembra ocurrió una única vez, en la
|
|
# etapa de construcción. Lo que hace este script es copiar un archivo.
|
|
#
|
|
# $MARCADOR es solo una traza legible con la fecha del primer arranque, para
|
|
# que quien opere el servidor pueda distinguir una base heredada de una nueva.
|
|
# No se usa como condición.
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
DIR_DATOS="/app/data"
|
|
BD="${DIR_DATOS}/fspm.db"
|
|
MARCADOR="${DIR_DATOS}/.sembrado"
|
|
SEMILLA="/app/semilla/fspm.db"
|
|
|
|
log() {
|
|
echo "[fspm] $1"
|
|
}
|
|
|
|
# --- 1. base de datos en el volumen ------------------------------------------
|
|
|
|
if [ ! -d "$DIR_DATOS" ]; then
|
|
log "el directorio de datos no existe, se crea: ${DIR_DATOS}"
|
|
mkdir -p "$DIR_DATOS"
|
|
fi
|
|
|
|
if [ ! -w "$DIR_DATOS" ]; then
|
|
log "ERROR: ${DIR_DATOS} no es escribible por el usuario $(id -un) (uid $(id -u))."
|
|
log " Si montaste una carpeta del anfitrión, dale permisos: chown -R 1001:1001 <carpeta>"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -f "$BD" ]; then
|
|
log "ya existe ${BD}: su contenido no se toca."
|
|
if [ -f "$MARCADOR" ]; then
|
|
log "primer arranque de este volumen: $(cat "$MARCADOR")"
|
|
fi
|
|
elif [ -f "$SEMILLA" ]; then
|
|
log "volumen vacío: se copia la base de demostración horneada en la imagen."
|
|
cp "$SEMILLA" "$BD"
|
|
date -u '+%Y-%m-%dT%H:%M:%SZ' > "$MARCADOR" 2>/dev/null || true
|
|
log "listo. Los datos del panel son de demostración; los leads que capture el sitio se suman a esta base."
|
|
else
|
|
log "volumen vacío y la imagen no trae base de demostración: se creará vacía."
|
|
log "El panel no tendrá usuarios y no se podrá iniciar sesión en /admin/login."
|
|
fi
|
|
|
|
# --- 2. esquema ---------------------------------------------------------------
|
|
#
|
|
# Idempotente: si el esquema del código y el de la base ya coinciden, no hace
|
|
# nada. A propósito NO se pasa --accept-data-loss: si una versión nueva exigiera
|
|
# eliminar una columna o una tabla con filas, se prefiere que el arranque falle
|
|
# y quede en los registros antes que borrar leads capturados en silencio.
|
|
|
|
log "aplicando el esquema (prisma db push)"
|
|
node /app/prisma-cli/node_modules/prisma/build/index.js db push \
|
|
--schema=/app/prisma/schema.prisma \
|
|
--skip-generate
|
|
|
|
# --- 3. servidor --------------------------------------------------------------
|
|
|
|
log "arrancando Next en ${HOSTNAME}:${PORT}"
|
|
exec "$@"
|