Files
gkachele-saas/memoria/MEMORIA_PROYECTO_COMPLETA.md
2026-01-17 11:40:17 +01:00

479 lines
17 KiB
Markdown

# 🎯 MEMORIA COMPLETA DEL PROYECTO - SaaS PageBuilder
**Fecha:** 13 Enero 2025
**Hash:** `gkachele-login-customizer-20250114-v3`
**Última actualización:** 14 Enero 2025 - 11:35
## 🇦🇷 OBJETIVO ARGENTINA
**Meta:** Lanzar GKACHELE™ SaaS en Argentina con funcionalidad completa y profesional.
**Criterio de Éxito:** Si funciona 1 rubro bien en Raspberry Pi → PAGAR VPS
**Dominio:** Ya tienes dominio configurado
**Ver:** `OBJETIVOS_ARGENTINA.md` y `GITEA_WORKFLOWS.md` para detalles completos
## 🎯 OBJETIVOS ACTUALES (Memorizado)
### 🚀 PRIORIDAD: ARGENTINA 🇦🇷
**Objetivo:** Lanzar GKACHELE™ SaaS en Argentina con funcionalidad completa.
**Criterio de Éxito:** Si funciona 1 rubro bien en Raspberry Pi → PAGAR VPS
### Objetivos Inmediatos:
1. **✅ Template y Menús Profesionales (COMPLETADO):**
- ✅ Sistema modular (_gkachele/header.php, footer.php, sidebar.php)
- ✅ Sistema de menús dinámicos
- ✅ Sistema de widgets
- ⚠️ UI completa para gestionar menús (pendiente)
2. **🔧 Funcionalidad Core (EN PROGRESO):**
- ✅ Registro de clientes
-**Login → Customizer directo (FUNCIONANDO - Hash v3)**
- ✅ Dashboard del cliente (`/dashboard`)
- ✅ Customizer básico (`/customizer/{site_id}`)
- ✅ Panel admin (`/admin`)
3. **🔄 Gitea y Workflows (PENDIENTE):**
- Integración Gitea para repos por cliente
- Workflows automáticos:
- Aceptar peticiones desde dashboard admin
- Desplegar sitios automáticamente
- Generar repositorios por cliente
- Versionado automático
- Integración con dashboard admin
4. **📝 Control de Versiones:**
- Git para landing page
- Versionado de templates
- Historial de cambios
- Rollback de versiones
5. **🎨 Mejorar Landing (PENDIENTE):**
- Diseño optimizado para Argentina
- Mejor UX/UI
- Optimización de conversión
- Performance optimizado
- Responsive mejorado
6. **📊 Workflows Dashboard Admin:**
- Aceptar/rechazar peticiones
- Gestionar usuarios
- Ver estadísticas
- Gestionar despliegues
- Control de versiones
- Integración con Gitea
## ⚠️ REQUISITOS PRINCIPALES (MEMORIZAR)
1. **Sincronización con Hash:** Raspberry y Local deben estar sincronizados con hash
2. **Modularizado:** Código debe estar modularizado
3. **PRIMERO copiar funcionalidad similar:** NO inventar, copiar funcionalidad similar primero en Raspberry, luego ver qué sirve y qué no
4. **Iterar:** Probar → Ver qué sirve → Eliminar lo que no sirve → Mejorar
**Ver:** `MEMORIA_SINCRONIZACION.md` para detalles
## 📍 CONEXIÓN RASPBERRY PI
**Credenciales SSH:**
- **Host:** `komkida.duckdns.org` o `192.168.1.134`
- **Puerto:** `2222`
- **Usuario:** `pi`
- **Password:** `Gdk1983gdk45@`
**Comandos de conexión (CON sshpass):**
```bash
# Desde WSL - CONECTAR
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134"
# COPIAR ARCHIVOS
wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no /mnt/c/word/demo/app.py pi@192.168.1.134:/home/pi/gkachele-saas/app.py"
# EJECUTAR COMANDO REMOTO
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'comando aqui'"
```
## 🏗️ ARQUITECTURA
### Stack Tecnológico
- **Backend:** Flask (Python 3) - NO Docker, directo
- **Base de datos:** SQLite (main.db + cliente-X.db)
- **Web Server:** Nginx (reverse proxy)
- **Dominio:** `gk-saas.komkida.duckdns.org`
- **Puerto Flask:** 5001
- **Puerto Nginx:** 80
### Estructura en Raspberry Pi
```
/home/pi/gkachele-saas/
├── app.py # Flask backend principal
├── database/
│ ├── main.db # DB principal (users, sites, requests, media)
│ └── sites/ # DBs por cliente
│ ├── cliente-1.db
│ └── cliente-2.db
├── sites/ # Sitios compilados/publicados
├── themes/ # Templates (como WordPress)
│ ├── gimnasio-claro/
│ ├── restaurante-moderno/
│ └── restaurante-elegante/
├── static/ # CSS, JS, imágenes
├── templates/ # HTML templates
│ ├── landing_real.html # Landing GKACHELE™
│ ├── register.html
│ ├── login.html
│ ├── dashboard.html # Dashboard CLIENTE
│ ├── customizer.html # Personalizador WordPress-like
│ ├── admin.html # Dashboard PRINCIPAL (tuyo)
│ └── client_admin.html # Admin del cliente
└── uploads/ # Media subida por clientes
```
### Estructura en Local (Desarrollo)
```
C:\word\
├── demo/ # Código del SaaS
│ ├── app.py
│ ├── database/
│ ├── themes/
│ ├── templates/
│ └── static/
├── update-raspberry.sh # Script para actualizar Raspberry
└── MEMORIA_PROYECTO_COMPLETA.md # Este archivo
```
## 🔄 FLUJO COMPLETO
```
1. Cliente → Landing (gk-saas.komkida.duckdns.org)
2. Cliente elige plan + rubro → /register?plan=base&rubro=restaurante
3. Cliente se registra → POST /register
├── Crea usuario en main.db (tabla users)
├── Crea sitio automático (tema según rubro) en main.db (tabla sites)
└── Guarda sesión → Redirige a /dashboard (equivalente a wp-admin)
4. Dashboard → Cliente ve SUS sitios
5. Customizer → /customizer/{site_id} (sidebar + preview)
6. Cliente envía → POST /dashboard/submit/{site_id}
7. Admin → /admin (solo user_id=1) aprueba
8. Publicado → /site/{slug}
```
## 🗄️ BASES DE DATOS
### main.db (SQLite) - TODO EN UNA SOLA BASE DE DATOS (Multi-tenant como WordPress)
**✅ Sistema Multi-tenant:** Todos los clientes en una sola base de datos, cada cliente solo ve SUS datos a través de `/dashboard` (equivalente a wp-admin)
**Tabla: users**
- id, email (UNIQUE), password (hash), plan, rubro, created_at
- Todos los usuarios/clientes están aquí
**Tabla: sites**
- id, user_id (FK), slug (UNIQUE), theme, status (draft/pending/published), content_json, created_at
- Todos los sitios, filtrados por user_id (cada cliente solo ve los suyos)
**Tabla: requests**
- id, site_id (FK), user_id (FK), status (pending/approved/rejected), created_at
- Solicitudes de publicación
**Tabla: media**
- id, user_id (FK), site_id (FK), filename, filepath, file_type, uploaded_at
- Archivos subidos por clientes, filtrados por user_id
**Tabla: content**
- id, user_id (FK), site_id (FK), section, data_json, updated_at
- Contenido por sección (futuro uso), filtrado por user_id y site_id
**Tabla: settings**
- id, user_id (FK), site_id, key, value, created_at, updated_at
- Configuraciones (como wp_options en WordPress), filtrado por user_id y site_id
**Tabla: menus**
- id, user_id (FK), site_id (FK), location (header/footer/sidebar), title, url, order_index, parent_id, created_at
- Sistema de menús dinámicos por ubicación, filtrado por user_id y site_id
**Tabla: widgets**
- id, user_id (FK), site_id (FK), area (sidebar/footer/etc), type, title, content, order_index, created_at, updated_at
- Sistema de widgets dinámicos por área, filtrado por user_id y site_id
## 🎨 TEMPLATES (Sistema WordPress-like)
### Templates Disponibles
- **gimnasio-claro:** Tema para gimnasios (rojo/negro)
- **restaurante-moderno:** Tema moderno (rojo/naranja) - 2 variantes
- **restaurante-elegante:** Tema elegante (marrón/dorado)
### Estructura de Template (Sistema Modular GKACHELE™)
```
themes/
├── _gkachele/ # Sistema base modular (como WordPress)
│ ├── header.php # Header con menús dinámicos
│ ├── footer.php # Footer con copyright GKACHELE™
│ └── sidebar.php # Sidebar con widgets dinámicos
├── {nombre}/ # Temas específicos
│ ├── config.json # Configuración (colores, tipografía, secciones)
│ ├── template.html # HTML del template (contenido principal)
│ └── style.css # CSS (opcional)
```
**Sistema de Renderizado:**
- `render_gkachele_template()` concatena: `header.php` + `template.html` + `sidebar.php` + `footer.php`
- Menús y widgets se cargan dinámicamente desde la base de datos
- Soporte para múltiples ubicaciones de menú (header, footer, sidebar)
- Widgets por área (sidebar, footer, etc.)
### Asignación Automática
- **restaurante:** Aleatorio entre `restaurante-moderno` y `restaurante-elegante`
- **gimnasio/gimnasios:** `gimnasio-claro`
- **Otros:** `default`
## 🔧 CONFIGURACIÓN NGINX
**Archivo:** `/etc/nginx/sites-available/gk-saas.komkida.duckdns.org.conf`
```nginx
server {
listen 80;
server_name gk-saas.komkida.duckdns.org;
location / {
proxy_pass http://localhost:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
**Comandos:**
```bash
sudo nginx -t # Verificar configuración
sudo systemctl reload nginx # Recargar
tail -f /var/log/nginx/gk-saas-error.log # Ver logs
```
## 🔄 SERVICIO SYSTEMD
**Archivo:** `/etc/systemd/system/gkachele-saas.service`
```ini
[Unit]
Description=GKACHELE SaaS Flask App
After=network.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/gkachele-saas
Environment="PATH=/usr/bin:/usr/local/bin:/home/pi/.local/bin"
ExecStart=/usr/bin/python3 /home/pi/gkachele-saas/app.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
**Comandos:**
```bash
sudo systemctl start gkachele-saas # Iniciar
sudo systemctl stop gkachele-saas # Detener
sudo systemctl restart gkachele-saas # Reiniciar
sudo systemctl status gkachele-saas # Estado
journalctl -u gkachele-saas -f # Ver logs
```
## 🚀 ACTUALIZAR CÓDIGO EN RASPBERRY
### Método Correcto (con sshpass desde WSL):
```bash
# 1. Copiar código actualizado
wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no /mnt/c/word/demo/app.py pi@192.168.1.134:/home/pi/gkachele-saas/app.py"
# 2. Reiniciar app (matar proceso y reiniciar)
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'pkill -f \"python3 app.py\" && cd ~/gkachele-saas && nohup python3 app.py > /tmp/app.log 2>&1 &'"
```
### Instalar Servicio Systemd (una vez):
```bash
# Copiar servicio
wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no gkachele-saas.service pi@192.168.1.134:/tmp/"
# Instalar servicio
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'sudo mv /tmp/gkachele-saas.service /etc/systemd/system/ && sudo systemctl daemon-reload && sudo systemctl enable gkachele-saas && sudo systemctl start gkachele-saas'"
```
### Configurar Cron en Raspberry (actualizar automáticamente):
```bash
# 1. Crear script de actualización
wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no update-app-raspberry.sh pi@192.168.1.134:~/scripts/update-app.sh"
# 2. Dar permisos
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'chmod +x ~/scripts/update-app.sh'"
# 3. Agregar a crontab (cada hora) - requiere permisos
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'echo \"0 * * * * /home/pi/scripts/update-app.sh\" | crontab -'"
# Verificar cron
wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'crontab -l'"
```
**NOTA:** El cron actualiza cada hora. Para actualizar manualmente el código, usar el método de SCP arriba.
## 📋 RUTAS PRINCIPALES
### Públicas
- `GET /` - Landing page
- `GET /register` - Formulario registro
- `POST /register` - Crear usuario (JSON)
- `GET /login` - Formulario login
- `POST /login` - Iniciar sesión (JSON)
- `GET /site/{slug}` - Sitio público publicado
### Cliente (requiere sesión)
- `GET /dashboard` - Dashboard del cliente
- `GET /customizer/{site_id}` - Personalizador
- `POST /api/customizer/save` - Guardar cambios
- `GET /api/customizer/preview-frame/{site_id}` - Preview iframe
- `POST /dashboard/submit/{site_id}` - Enviar para aprobación
- `GET /dashboard/admin` - Admin del cliente (media, config)
### APIs de Menús y Widgets
- `GET /api/menus/<site_id>` - Obtener menús del sitio
- `POST /api/menus/<site_id>` - Guardar/actualizar menús
- `GET /api/widgets/<site_id>` - Obtener widgets del sitio
- `POST /api/widgets/<site_id>` - Guardar/actualizar widgets
### Admin Principal (solo user_id=1)
- `GET /admin` - Dashboard principal
- `POST /admin/approve/{request_id}` - Aprobar solicitud
- `POST /admin/reject/{request_id}` - Rechazar solicitud
## 🔐 SEGURIDAD
### Sesiones
- Flask `session` con `secret_key`
- Cookie `SESSION_COOKIE_SAMESITE = 'Lax'`
- Sesión se guarda después de login exitoso
### Acceso
- **Clientes:** Solo ven SUS sitios (filtrado por `user_id` en sesión)
- **Admin:** Solo `user_id = 1` puede acceder a `/admin`
- **Passwords:** Hash con `werkzeug.security.generate_password_hash`
## 🎯 ESTADO ACTUAL
### ✅ Funcionando
- Landing page (GKACHELE™ original)
- Registro de clientes → Redirige a `/login` (sin sesión automática)
- Login de clientes → Redirige a `/dashboard`
- Dashboard del cliente
- Customizer básico (sidebar + preview)
- Templates: gimnasio-claro, restaurante-moderno, restaurante-elegante
- **Sistema modular de templates (_gkachele/header.php, footer.php, sidebar.php)**
- **Sistema de menús dinámicos (header, footer, sidebar)**
- **Sistema de widgets dinámicos (sidebar, footer, etc.)**
- **Función `render_gkachele_template()` para renderizado completo**
- **APIs para gestionar menús y widgets**
- Base de datos SQLite multi-tenant (main.db con tablas menus y widgets)
- Nginx reverse proxy
- Systemd service
- DuckDNS para dominio remoto
- Scripts de gestión: `ver_usuarios.py`, `limpiar_db.py`
### ⚠️ Pendiente
- Drag & drop de secciones (SortableJS)
- Edición inline (contenteditable)
- Gitea para repos por cliente + automatización
- Dashboard principal para aprobar solicitudes
- Plugins sencillos (colores, tipografía avanzada)
- SSL/HTTPS (Let's Encrypt)
### 🎯 PRÓXIMOS OBJETIVOS (PRIORITARIOS)
1. **✅ Template y Menús Profesionales (COMPLETADO):**
- ✅ Sistema modular (_gkachele/header.php, footer.php, sidebar.php)
- ✅ Sistema de menús dinámicos (header, footer, sidebar)
- ✅ Múltiples ubicaciones de menú
- ✅ Sistema de widgets/áreas
- ⚠️ **PENDIENTE:** UI completa para gestionar menús desde customizer (actualmente solo placeholder)
2. **Mejorar Landing:**
- Diseño más profesional
- Mejor UX/UI
- Optimización de conversión
3. **Automatización con Gitea:**
- Integración Gitea para repos por cliente
- Automatización de despliegues
- Workflows automáticos
- Integración con n8n (futuro)
## 📦 DEPENDENCIAS
**Python:**
- Flask
- Werkzeug (password hashing)
- SQLite3 (built-in)
**Instalación:**
```bash
pip3 install Flask Werkzeug
```
## 🌐 DUCKDNS
**Dominios:**
- **komkida.duckdns.org:** Token `9c5cff88-b6d7-4704-9b10-4a69afdff797`
- **gkachele.duckdns.org:** Token `578331b3-ad7b-4154-835d-e496465257b0`
**Actualizar IP:**
```bash
python3 update-komkida-duckdns.py
```
## 🚀 MIGRACIÓN A VPS
**Pasos:**
1. Copiar `/home/pi/gkachele-saas/` completo
2. Instalar Python3, Nginx en VPS
3. Copiar configuración Nginx
4. Copiar servicio systemd
5. Cambiar dominio (DuckDNS o dominio real)
6. Configurar SSL (Let's Encrypt)
**Ventajas:**
- ✅ Mismo código (sin cambios)
- ✅ Misma estructura
- ✅ Más recursos
- ✅ Mejor rendimiento
## 📝 NOTAS IMPORTANTES
- **NO usar Docker:** Todo corre directamente (Python + Nginx)
- **NO usar GitHub:** Todo es independiente en Raspberry
- **SQLite es suficiente:** Para SaaS pequeño, no necesita MySQL
- **Raspberry Pi 3:** Recursos limitados, pero suficiente para desarrollo
- **VPS recomendado:** Para producción con muchos clientes
## 📦 BACKUP Y VERSIONADO
**Hash Actual:** `gkachele-template-system-20250114-v1`
**Estado Verificado:**
- ✅ Templates _gkachele en Raspberry: header.php, footer.php, sidebar.php
- ✅ Función render_gkachele_template en app.py
- ✅ Tablas menus y widgets en main.db
- ✅ Servicio gkachele-saas activo
- ✅ Flujo de registro: Registro → Login → Dashboard → Customizer
**Scripts de Gestión:**
- `ver_usuarios.py` - Ver usuarios y sitios registrados
- `limpiar_db.py` - Limpiar base de datos (con confirmación)
- `verificar_raspberry.sh` - Verificar estado en Raspberry
---
**Última actualización:** 14 Enero 2025 - 08:50