diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 094b12b..8988295 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -4,11 +4,11 @@ "type": "split", "children": [ { - "id": "7eb63950e584c8c8", + "id": "74bf841407436ba6", "type": "tabs", "children": [ { - "id": "52972da0bc9d4ad0", + "id": "0519cc60f14f90b9", "type": "leaf", "state": { "type": "markdown", @@ -41,7 +41,9 @@ "type": "file-explorer", "state": { "sortOrder": "alphabetical", - "autoReveal": false + "autoReveal": false, + "showSearch": false, + "searchQuery": "" }, "icon": "lucide-folder-closed", "title": "Files" @@ -183,16 +185,38 @@ "bases:Create new base": false } }, - "active": "52972da0bc9d4ad0", + "active": "0519cc60f14f90b9", "lastOpenFiles": [ - "005-Learn/Instructivo Git Gitea.md", + "005-Learn/Instructivo Entornos Virtuales Python.md", "005-Learn/Instructivo Git Branches.md", + "005-Learn/Instructivo Git Gitea.md", + "005-Learn/Planificación desarrollo agente ia.md", "005-Learn/Obsidian WorkingCopy Manual.md", - "005-Learn/Proyecto SAP B1 - FastAPI - React - Next.js.md", - "005-Learn/Roadmap Next.js.md", + "005-Learn/Instructivo launchd iOS.md", + "005-Learn/Guia_Entornos_Virtuales_Python.md", "005-Learn/Stack Tecnológico Recomendado.md", + "005-Learn/Roadmap Next.js.md", + "005-Learn/Proyecto SAP B1 - FastAPI - React - Next.js.md", + "006-Proyecto-Bingo/07 UI Components.md", + "006-Proyecto-Bingo/06 Estados (Zustand).md", + "006-Proyecto-Bingo/04 Motor lógico de Bingo.md", + "006-Proyecto-Bingo/02 Diagrama.md", + "006-Proyecto-Bingo/01 Markdown del proyecto.md", + "006-Proyecto-Bingo/00 App Bingo.md", + "006-Proyecto-Bingo/03 SQLite.md", + "006-Proyecto-Bingo/05 Navegación.md", + "005-Learn/Instructivo_launchd_SAP_B1_SUNAT.md", + "006-Proyecto-Bingo/sqlite_erd_flat_design.png", + "006-Proyecto-Bingo/mockup-bingo.png", + "006-Proyectos/01 Proyecto App Bingo.md", + "006-Proyectos/07 Modelo de datos Isar.md", + "006-Proyectos/02 Arquitectura técnica.md", + "006-Proyectos/03 Entorno de desarrollo.md", + "006-Proyectos/06 Mockups base.md", + "006-Proyectos/04 Estructura de carpetas.md", + "006-Proyectos/05 Mockups iniciales.md", + "006-Proyecto-Bingo", "005-Learn/roadmap_nextjs_erp.html", - "Instructivo Git Gitea.md", "005-Learn", "004-SDK-SAP", "003-Hana", @@ -200,9 +224,6 @@ "001-Linux", "Untitled.canvas", "Untitled.base", - "Roadmap-nextjs-erp.md", - "roadmap_nextjs_erp.html", - "2026-05-18.md", - "Welcome.md" + "roadmap_nextjs_erp.html" ] } \ No newline at end of file diff --git a/005-Learn/Instructivo Entornos Virtuales Python.md b/005-Learn/Instructivo Entornos Virtuales Python.md new file mode 100644 index 0000000..74e2b0b --- /dev/null +++ b/005-Learn/Instructivo Entornos Virtuales Python.md @@ -0,0 +1,84 @@ +# Creación de entornos virtuales en Python + +## Requisitos + +- Tener Python instalado. +- Verificar: + +``` bash +python --version +``` + +## Crear el entorno + +``` bash +python -m venv .venv +``` + +## Activar + +### macOS / Linux + +``` bash +source .venv/bin/activate +``` + +### Windows CMD + +``` cmd +.venv\Scripts\activate.bat +``` + +### Windows PowerShell + +``` powershell +.venv\Scripts\Activate.ps1 +``` + +## Instalar dependencias + +``` bash +pip install -r requirements.txt +``` + +o + +``` bash +pip install requests fastapi uvicorn +``` + +## Guardar dependencias + +``` bash +pip freeze > requirements.txt +``` + +## Desactivar + +``` bash +deactivate +``` + +## Verificar el intérprete + +``` bash +python -c "import sys; print(sys.executable)" +``` + +## .gitignore recomendado + +``` gitignore +.venv/ +__pycache__/ +*.py[cod] +.vscode/ +.idea/ +.env +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +*.sqlite3 +*.db +.DS_Store +Thumbs.db +``` diff --git a/005-Learn/Instructivo Git Branches.md b/005-Learn/Instructivo Git Branches.md index 2137c63..bdb4ad2 100644 --- a/005-Learn/Instructivo Git Branches.md +++ b/005-Learn/Instructivo Git Branches.md @@ -1,192 +1,755 @@ # 🌿 Guía Completa para Crear y Manejar un Branch en Git -Porque romper `main` directamente es una tradición demasiado popular en desarrollo de software. -Git existe precisamente para evitar ese tipo de tragedias humanas. + + +Romper `main` directamente sigue siendo una tradición muy popular en desarrollo de software. + +Git existe precisamente para evitar ese tipo de tragedias. + + + +En esta guía usaremos un caso real como hilo conductor: una agencia que lleva un **proyecto por cada cliente**, y necesita crear una rama nueva cada vez que empieza a trabajar en la funcionalidad de un cliente específico (por ejemplo, `cliente-acme`). + + + +```mermaid + +gitGraph + +commit id: "inicio" + +commit id: "version estable" + +branch cliente-acme + +checkout cliente-acme + +commit id: "dashboard acme" + +commit id: "ajustes acme" + +checkout main + +merge cliente-acme id: "merge acme a main" + +branch cliente-globex + +checkout cliente-globex + +commit id: "reporte globex" + +checkout main + +merge cliente-globex id: "merge globex a main" + +``` + + --- -# 1️⃣ Verifica el estado actual del proyecto + + +## 🗺️ Flujo general del proceso + + + +```mermaid + +flowchart TD + +A[git status] --> B{Hay cambios sin guardar?} + +B -- Si --> C[git add . + git commit] + +B -- No --> D + +C --> D[git checkout main] + +D --> E[git pull] + +E --> F["git checkout -b cliente-acme"] + +F --> G[git branch para confirmar] + +G --> H[Trabajar y hacer commits] + +H --> I[git checkout main] + +I --> J["git merge cliente-acme"] + +J --> K[git push] + +K --> L["git branch -d cliente-acme"] -```bash -git status ``` -Esto te mostrará: + + +--- + + + +## 1️⃣ Verifica el estado actual del proyecto + + + +```bash + +git status + +``` + + + +Esto te muestra: + + - Archivos modificados + - Archivos en stage + - Archivos sin seguimiento + + --- -# 2️⃣ Guarda tus cambios importantes + -Si tienes cambios importantes, crea un commit antes de crear el branch. +## 2️⃣ Guarda tus cambios importantes + + + +Si tienes cambios importantes, crea un commit antes de crear el branch: + + ```bash + git add . + git commit -m "Version estable antes de nueva funcionalidad" + ``` + + ✅ Esto crea un punto seguro al cual regresar. ---- + -## 📦 Alternativa: usar stash +### 📦 Alternativa: usar stash + + Si todavía no quieres hacer commit: + + ```bash + git stash + ``` + + Luego podrás recuperarlos con: + + ```bash + git stash pop + ``` + + --- -# 3️⃣ Ve a la rama principal + + +## 3️⃣ Ve a la rama principal + + ```bash + git checkout main + ``` + + --- -# 4️⃣ Descarga lo último del repositorio + + +## 4️⃣ Descarga lo último del repositorio + + ```bash + git pull + ``` + + Esto sincroniza tu proyecto local con el remoto. ---- - -# 5️⃣ Crea la nueva rama - -```bash -git checkout -b nueva-funcionalidad -``` - -## 📌 Ejemplo real - -```bash -git checkout -b agregar-dashboard-powerbi -``` + --- -# 6️⃣ Verifica que estás en la nueva rama + + +## 5️⃣ Crea la nueva rama + + ```bash + +git checkout -b nombre-de-la-rama + +``` + + + +### 📌 Ejemplo con proyecto por cliente + + + +Supongamos que la agencia empieza a trabajar en el dashboard del cliente **Acme**: + + + +```bash + +git checkout -b cliente-acme + +``` + + + +Si más adelante empieza otro proyecto, para el cliente **Globex**: + + + +```bash + +git checkout -b cliente-globex + +``` + + + +De esta forma cada cliente tiene su propio espacio de trabajo aislado, sin afectar el código de los demás. + + + +```mermaid + +gitGraph + +commit id: "main estable" + +branch cliente-acme + +branch cliente-globex + +``` + + + +--- + + + +## 6️⃣ Verifica que estás en la nueva rama + + + +```bash + git branch + ``` -La rama actual aparecerá con un `*` + -## 📌 Ejemplo +La rama actual aparecerá marcada con un `*`. + + + +### 📌 Ejemplo + + ```text + main -* agregar-dashboard-powerbi + +* cliente-acme + +cliente-globex + ``` + + --- -# 7️⃣ Trabaja normalmente y guarda cambios + + +## 7️⃣ Trabaja normalmente y guarda cambios + + ```bash + git add . -git commit -m "Agrega nueva funcionalidad" + +git commit -m "Agrega dashboard de ventas para Acme" + ``` + + +Puedes repetir este paso tantas veces como necesites mientras avanzas en el proyecto del cliente: + + + +```bash + +git add . + +git commit -m "Ajusta colores y logo segun manual de marca de Acme" + +``` + + + +```mermaid + +gitGraph + +commit id: "main estable" + +branch cliente-acme + +checkout cliente-acme + +commit id: "dashboard ventas" + +commit id: "ajustes de marca" + +``` + + + --- -# 8️⃣ Regresa a main cuando todo funcione + + +## 8️⃣ Regresa a main cuando todo funcione + + ```bash + git checkout main + ``` + + --- -# 9️⃣ Une la nueva funcionalidad a main + + +## 9️⃣ Une la nueva funcionalidad a main + + ```bash -git merge nueva-funcionalidad + +git merge cliente-acme + ``` + + +### 📌 Ejemplo del resultado + + + +```mermaid + +gitGraph + +commit id: "main estable" + +branch cliente-acme + +checkout cliente-acme + +commit id: "dashboard ventas" + +commit id: "ajustes de marca" + +checkout main + +merge cliente-acme id: "entrega a Acme lista" + +``` + + + --- -# 🔟 Sube los cambios al repositorio remoto + + +## 🔟 Sube los cambios al repositorio remoto + + ```bash + git push + ``` + + --- -# 1️⃣1️⃣ Elimina la rama si ya no la necesitas + + +## 1️⃣1️⃣ Elimina la rama si ya no la necesitas + + + +Una vez que el trabajo del cliente ya fue entregado y fusionado a `main`, puedes borrar la rama para mantener el repositorio limpio: + + ```bash -git branch -d nueva-funcionalidad + +git branch -d cliente-acme + ``` ---- + -# 🧠 Recomendaciones importantes +Si Git no te deja borrarla porque detecta cambios sin fusionar, y estás seguro de que quieres eliminarla de todos modos: -✅ Nunca trabajes directamente sobre `main` -✅ Haz commits pequeños y claros -✅ Usa nombres descriptivos para tus branches -✅ Verifica siempre con `git status` - ---- - -# 🚨 Comandos útiles extra - -## Ver historial de commits + ```bash + +git branch -D cliente-acme + +``` + + + +--- + + + +## 🧠 Recomendaciones importantes + + + +✅ Nunca trabajes directamente sobre `main` + +✅ Haz commits pequeños y claros + +✅ Usa nombres descriptivos para tus branches (por ejemplo, `cliente-acme`, no `rama1`) + +✅ Verifica siempre con `git status` antes de cambiar de rama + +✅ Si manejas varios clientes a la vez, mantén una rama por cliente para evitar mezclar entregas + + + +```mermaid + +gitGraph + +commit id: "main" + +branch cliente-acme + +branch cliente-globex + +branch cliente-initech + +checkout cliente-acme + +commit id: "avance acme" + +checkout cliente-globex + +commit id: "avance globex" + +checkout cliente-initech + +commit id: "avance initech" + +``` + + + +--- + + + +## ❓ ¿Siempre hay que hacer merge a main? + + + +No. El `merge` a `main` solo tiene sentido si `main` representa algo que **todos los clientes comparten**. Si los cambios son exclusivos de un cliente y no deben mezclarse con nada más, tienes otras opciones. + + + +### Opción 1: La rama del cliente vive sola (sin merge a main) + + + +Trabajas y subes esa rama directamente, sin tocar `main`: + + + +```bash + +git checkout -b cliente-acme + +# ... trabajas y haces commits ... + +git push origin cliente-acme + +``` + + + +`main` se queda intacto, y `cliente-acme` existe como una línea de desarrollo independiente para siempre (o hasta que ya no la necesites). + + + +```mermaid + +gitGraph + +commit id: "main estable" + +branch cliente-acme + +checkout cliente-acme + +commit id: "dashboard acme" + +commit id: "ajustes acme" + +``` + + + +Aquí `cliente-acme` nunca se vuelve a juntar con `main`. + + + +### Opción 2: main es solo una plantilla base + + + +Si cada cliente parte de una base común (por ejemplo, la plantilla del proyecto), tiene sentido traer cambios **de main hacia el cliente** cuando la plantilla mejora, pero no al revés: + + + +```bash + +git checkout cliente-acme + +git merge main + +``` + + + +Esto trae las mejoras de la plantilla al proyecto del cliente. Es al revés del flujo normal: en vez de `cliente-acme → main`, es `main → cliente-acme`. + + + +```mermaid + +gitGraph + +commit id: "plantilla v1" + +branch cliente-acme + +checkout main + +commit id: "plantilla v2 mejorada" + +checkout cliente-acme + +commit id: "avance acme" + +merge main id: "trae mejoras de plantilla" + +``` + + + +### Opción 3: Cada cliente es su propio repositorio o deploy + + + +Si el código de cada cliente es tan distinto que ni siquiera comparte historial útil con los demás, muchas agencias usan directamente **una rama por cliente que se despliega tal cual**, sin merges entre ellas. En este caso `main` queda solo como referencia general, o incluso no se usa en ese repo. + + + +```mermaid + +gitGraph + +commit id: "main (referencia)" + +branch cliente-acme + +branch cliente-globex + +checkout cliente-acme + +commit id: "deploy acme" + +checkout cliente-globex + +commit id: "deploy globex" + +``` + + + +> 💡 Elige la opción según qué tan relacionado esté el trabajo entre clientes: si comparten código base, usa la Opción 2; si son totalmente independientes, la Opción 1 o la Opción 3. + + + +--- + + + +## 🚨 Comandos útiles extra + + + +### Ver historial de commits + + + +```bash + git log --oneline + ``` ---- + -## Ver diferencias de archivos +### Ver diferencias de archivos + + ```bash + git diff + ``` ---- + -## Salir del visor de git diff +### Salir del visor de git diff / git log + + Presiona: + + ```text + q + ``` -Porque claramente mostrar texto simple en terminal era demasiado fácil para Unix. + + +### Ver todas las ramas, incluidas las remotas + + + +```bash + +git branch -a + +``` + + + +### Cambiar de una rama de cliente a otra rápidamente + + + +```bash + +git checkout cliente-globex + +``` + + --- -# 🎯 Resultado esperado + -Tu flujo ideal debería verse así: +## 🎯 Resultado esperado + + + +Tu flujo ideal, aplicado al caso de proyectos por cliente, debería verse así: + + ```text + main - └── nueva-funcionalidad - └── commits - └── merge a main + +├── cliente-acme + +│ └── commits del proyecto Acme + +│ └── merge a main + +├── cliente-globex + +│ └── commits del proyecto Globex + +│ └── merge a main + +└── cliente-initech + +└── commits del proyecto Initech + +└── merge a main + ``` -Un proceso ordenado. -Casi sospechosamente profesional para estándares normales de desarrollo. + + +Un proceso ordenado, con una rama independiente por cada cliente, y `main` siempre reflejando el estado estable y entregado del trabajo. \ No newline at end of file diff --git a/005-Learn/Instructivo Git Gitea.md b/005-Learn/Instructivo Git Gitea.md index 4bf281b..784a072 100644 --- a/005-Learn/Instructivo Git Gitea.md +++ b/005-Learn/Instructivo Git Gitea.md @@ -1,17 +1,30 @@ # 🚀 Subir proyecto local a Gitea (Mac + Tailscale) -## 1. Crear `.gitignore` +> Guía ordenada por **flujo normal de trabajo**. Si algo falla, sigue las marcas ⚠️ que apuntan a su resolución al final del documento. + +--- + +## PARTE A — FLUJO NORMAL (paso a paso) + +### 1. Crear repositorio en Gitea +- Nombre: `descarga_adjuntos_correos_cpe` +- Sin README +- Sin opciones automáticas + +> Guarda la URL del repositorio para usarla después. + +### 2. Crear `.gitignore` ```bash cd /Users/george/descarga_adjuntos_correos_cpe touch .gitignore ``` -## 2. Editar `.gitignore` +### 3. Editar `.gitignore` ```bash nano .gitignore ``` -### Contenido recomendado +#### Contenido recomendado ```bash __pycache__/ *.pyc @@ -23,100 +36,131 @@ secrets.yaml .idea/ ``` -## 3. Si ya hiciste `git add` antes del `.gitignore` -```bash -git rm -r --cached . -git add . -git commit -m "aplicar gitignore correctamente" -``` +> ⚠️ ¿Ya habías hecho `git add` antes de crear el `.gitignore`? → [[#Resolución: archivos que debían ignorarse siguen apareciendo]] -## 4. Inicializar repositorio Git +### 4. Inicializar repositorio Git ```bash cd /Users/george/descarga_adjuntos_correos_cpe git init ``` -## 5. Agregar archivos +### 5. Agregar archivos ```bash git add . ``` -## 6. Primer commit +> ⚠️ ¿Agregaste errores o archivos incorrectos? → [[#Resolución: quitar archivos del staging (deshacer git add)]] + +### 6. Primer commit ```bash git commit -m "primer commit" ``` -## 6.1 Commit de un proyecto dentro de una Solución +> ⚠️ ¿El commit quedó mal y aún no hice push? → [[#Resolución: deshacer un commit antes de subirlo]] + +### 7. Conectar repo local con Gitea +```bash +git remote add origin http://100.68.242.27:30000/george/descarga_adjuntos_correos_cpe.git +``` + +> ⚠️ ¿El remote ya existe o está mal configurado? → [[#Resolución: problemas con el remote]] + +### 8. Subir código por primera vez +```bash +git branch -M main +git push -u origin main +``` + +> ⚠️ ¿El push falla por conexión o autenticación? → [[#Resolución: no puedo subir (push)]] + +--- + +## PARTE B — VARIANTES DE COMMIT + +Estos pasos van **después** del commit básico según lo que necesites. + +### Commit de un proyecto dentro de una Solución ```bash git add ProyectoA/ git status git commit -m "mensaje commit para los archivos modificados del proyecto" ``` -## 6.2 Commit de un archivo específico dentro de un proyecto +### Commit de un archivo específico dentro de un proyecto ```bash git add ProyectoA/FacturaNegociable.cs git status git commit -m "mensaje commit para el archivo especifico del proyecto" ``` -## 6. 3 Git reset , quita todos los archivos del staging area que coloco git add, reversa el git add antes del git commit -```bash -git reset -``` +--- -## 6. 4 Git reset , si ya hice commit, pero aún no hice push -```bash -git reset --soft HEAD~1 -git reset -``` +## PARTE C — FLUJO DIARIO -## 7. Crear repositorio en Gitea -- Nombre: descarga_adjuntos_correos_cpe -- Sin README -- Sin opciones automáticas - -## 8. URL del repositorio -```bash -http://100.68.242.27:30000/george/descarga_adjuntos_correos_cpe.git -``` - -## 9. Conectar repo local con Gitea -```bash -git remote add origin http://100.68.242.27:30000/george/descarga_adjuntos_correos_cpe.git -``` - -## 10. Subir código por primera vez -```bash -git branch -M main -git push -u origin main -``` - -## 11. Cambiar URL del repositorio -```bash -git remote set-url origin http://100.x.x.x:3000/george/descarga_adjuntos_correos_cpe.git -git remote -v -``` - -## 12. Eliminar y volver a configurar remote -```bash -git remote remove origin -git remote add origin http://100.68.242.27:3000/george/descarga_adjuntos_correos_cpe.git -``` - -## 13. Validar conexión -```bash -curl http://100.68.242.27:30000 -``` - -## 14. Acceso a Gitea - - [URL de Gitea en NAS](http://100.68.242.27:30000) - - -## 15. Flujo diario ```bash git add . git commit -m "mensaje claro" git push ``` + +--- + +## PARTE D — CLONAR / REUTILIZAR + +### Clonar repositorio +```bash +git clone http://100.68.242.27:3000/george/descarga_adjuntos_correos_cpe.git +``` + +### Validar conexión con Gitea +```bash +curl http://100.68.242.27:30000 +``` + +--- + +## PARTE E — ACCESO + +- [URL de Gitea en NAS](http://100.68.242.27:30000) + +--- + +# 🔧 RESOLUCIÓN DE PROBLEMAS + +## Resolución: archivos que debían ignorarse siguen apareciendo +Si ya hiciste `git add` antes del `.gitignore`, quitalos del índice: +```bash +git rm -r --cached . +git add . +git commit -m "aplicar gitignore correctamente" +``` + +## Resolución: quitar archivos del staging (deshacer git add) +Si agregaste archivos que no deberían ir, reversa el `git add` **antes** de commitear: +```bash +git reset +``` + +## Resolución: deshacer un commit antes de subirlo +Si ya hiciste commit pero **aún no** hiciste push: +```bash +git reset --soft HEAD~1 +git reset +``` + +## Resolución: no puedo subir (push) +- Verifica la conexión con el NAS: `curl http://100.68.242.27:30000` +- Revisa si el remote está bien configurado: `git remote -v` + +## Resolución: problemas con el remote (URL incorrecta o antigua) +### Cambiar la URL del repositorio +```bash +git remote set-url origin http://100.x.x.x:3000/george/descarga_adjuntos_correos_cpe.git +git remote -v +``` + +### Eliminar y volver a configurar el remote +```bash +git remote remove origin +git remote add origin http://100.68.242.27:3000/george/descarga_adjuntos_correos_cpe.git +``` diff --git a/005-Learn/Instructivo launchd iOS.md b/005-Learn/Instructivo launchd iOS.md new file mode 100644 index 0000000..fd4bd0d --- /dev/null +++ b/005-Learn/Instructivo launchd iOS.md @@ -0,0 +1,171 @@ +# Instructivo: Ejecutar un servicio Python con launchd en macOS + +## Objetivo + +Ejecutar un servicio de Python de forma automática utilizando `launchd`. + +## Estructura sugerida + +``` text +/Users/george/services/sap_sunat/ + .venv/ + main.py + config.ini + logs/ + stdout.log + stderr.log +``` + +## Verificar el entorno virtual + +Activar: + +``` bash +source .venv/bin/activate +``` + +Obtener el intérprete: + +``` bash +which python +``` + +Usar esa ruta en `ProgramArguments`. + +## Archivo .plist + +Ubicación recomendada para un usuario: + +``` text +~/Library/LaunchAgents/com.george.sap.sunat.plist +``` + +Claves habituales: + +- `Label` +- `ProgramArguments` +- `WorkingDirectory` +- `RunAtLoad` +- `KeepAlive` +- `StandardOutPath` +- `StandardErrorPath` + +## Comentarios + +Se permiten comentarios XML: + +``` xml + +``` + +También se pueden comentar bloques completos de claves. + +## Cargar el servicio + +``` bash +launchctl load ~/Library/LaunchAgents/com.george.sap.sunat.plist +``` + +En versiones recientes también: + +``` bash +launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.george.sap.sunat.plist +``` + +## Verificar + +``` bash +launchctl list | grep sap +``` + +Información detallada: + +``` bash +launchctl print gui/$(id -u)/com.george.sap.sunat +``` + +## Detener + +``` bash +launchctl unload ~/Library/LaunchAgents/com.george.sap.sunat.plist +``` + +o + +``` bash +launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.george.sap.sunat.plist +``` + +## Monitorización + +Monitor de Actividad: - Buscar `python` o `python3`. + +Terminal: + +``` bash +ps -ef | grep python +``` + +Consumo: + +``` bash +ps -o pid,rss,vsz,%cpu,command -p +``` + +Ver logs: + +``` bash +tail -f logs/stdout.log +tail -f logs/stderr.log +``` + +## Recomendaciones + +- Usar `logging` con rotación. +- Manejar reconexión a SAP HANA. +- Implementar reintentos para SUNAT. +- Mantener configuración en `config.ini` o `.env`. +- Capturar `SIGTERM` para cerrar conexiones correctamente. +- Si el servicio es permanente, controlar internamente la frecuencia + de ejecución (cada 10 s entre 06:00 y 13:15; cada 30 min entre 13:15 + y 14:00). + + +## Ejemplo de archivo .plist + +```xml + + + + + + + + Label + com.george.sap.sunat + + ProgramArguments + + /Users/george/services/sap_sunat/.venv/bin/python + /Users/george/services/sap_sunat/main.py + + + WorkingDirectory + /Users/george/services/sap_sunat + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /Users/george/services/sap_sunat/logs/stdout.log + + StandardErrorPath + /Users/george/services/sap_sunat/logs/stderr.log + + + +``` \ No newline at end of file diff --git a/005-Learn/Planificación desarrollo agente ia.md b/005-Learn/Planificación desarrollo agente ia.md new file mode 100644 index 0000000..1d8b426 --- /dev/null +++ b/005-Learn/Planificación desarrollo agente ia.md @@ -0,0 +1,674 @@ +# Agente IA para SAP Business One + HANA + +## Objetivo + +Construir progresivamente un agente de IA tipo chat para la empresa, conectado a SAP Business One sobre HANA, usando modelos locales mediante Ollama. + +La evolución prevista es: + +- Consultas de negocio en lenguaje natural. +- KPIs. +- Análisis de datos. +- Gráficos y cuadros resumen. +- Reportes PDF y Excel. +- Resúmenes gerenciales. +- Alertas y análisis automáticos. + +La estrategia es comenzar pequeño y agregar capacidades mediante herramientas independientes. + +## Arquitectura + +```text + USUARIO + | + v + +-------------+ + | Chat Web UI | + | React/Vite | + +------+------+ + | + v + +-------------+ + | FastAPI | + | Backend | + +------+------+ + | + +---------+---------+ + | | + v v + +-----------+ +--------------+ + | Ollama | | Tool / Skill | + | Local LLM | | Engine | + +-----------+ +-------+------+ + | + +--------+--------+ + | | + v v + SAP HANA SAP Service Layer +``` + +### Principio fundamental + +El modelo de IA no debe tener acceso directo e irrestricto a SAP. + +El LLM debe solicitar herramientas (`tools`) que ejecuten consultas controladas. + +Ejemplo: + +```text +Usuario: ¿Cuánto vendimos este mes? + | + v + Ollama + | + v + ventas_mes() + | + v + Python / FastAPI + | + v + SAP HANA + | + v + Resultado + | + v + Ollama + | + v + Respuesta al usuario +``` + +Esto permite controlar permisos, consultas y calidad de los resultados. + +## Tecnologías + +### Frontend +- React +- Vite +- Interfaz tipo ChatGPT +- Tablas +- Gráficos +- Dashboards + +### Backend +- Python +- FastAPI +- Herramientas / Skills +- Control de acceso +- Gestión de conversaciones +- Generación de reportes + +### IA +- Ollama +- Modelos locales +- Candidatos iniciales: Qwen 3 8B, Qwen 3 14B, Mistral Small y Gemma 3 12B. +- La elección final dependerá del hardware y de pruebas reales. + +### Datos e integración +- SAP Business One +- SAP HANA +- Vistas HANA +- SQL controlado +- SAP Service Layer para operaciones que necesiten la lógica de SAP + +### Visualización y documentos +- Plotly para gráficos interactivos +- Matplotlib para imágenes/gráficos destinados a documentos +- ReportLab para PDF +- OpenPyXL para Excel + +# Fase 1: herramientas básicas + +Crear inicialmente un conjunto pequeño de funciones Python: + +```text +ventas_hoy() +ventas_mes() +top_clientes() +productos_mas_vendidos() +facturas_pendientes() +compras_mes() +stock_critico() +cuentas_por_cobrar() +cuentas_por_pagar() +utilidad_mes() +``` + +Cada herramienta ejecutará internamente una consulta SQL o utilizará una vista HANA. + +El usuario pregunta: + +```text +¿Cuánto vendimos este mes? +``` + +El agente determina: + +```text +tool = ventas_mes() +``` + +Obtiene el resultado y genera una respuesta en lenguaje natural. + +## Fase 2: herramientas con parámetros + +Agregar parámetros: + +```text +ventas_por_cliente(cliente) +ventas_por_fecha(desde, hasta) +compras_por_proveedor(proveedor, desde, hasta) +stock_almacen(almacen) +articulo(codigo) +``` + +Ejemplo: + +```text +¿Cuánto le hemos vendido a Alicorp este año? +``` + +Puede interpretarse como: + +```text +ventas_cliente( + cliente="ALICORP", + año=2026 +) +``` + +## Fase 3: capa semántica empresarial + +En lugar de hacer que el modelo conozca todas las tablas de SAP Business One, crear vistas orientadas al negocio: + +```text +VW_VENTAS +VW_COMPRAS +VW_STOCK +VW_CXC +VW_CXP +VW_CLIENTES +VW_PRODUCTOS +VW_VENDEDORES +VW_KPI_VENTAS +VW_KPI_COBRANZAS +``` + +Las vistas deben presentar información clara y consistente, por ejemplo: + +```text +Cliente +RUC +Vendedor +Línea +Ciudad +Total +Margen +Cantidad +Fecha +``` + +## Fase 4: SQL generado por IA + +Cuando el sistema básico sea estable, se puede permitir que el modelo genere SQL, pero únicamente sobre vistas analíticas autorizadas. + +Ejemplo: + +```text +Vista: VW_VENTAS + +Campos: +Fecha +Cliente +Ciudad +Total +Margen +Cantidad +Vendedor +``` + +Pregunta: + +```text +¿Cuánto vendimos por ciudad? +``` + +Consulta posible: + +```sql +SELECT + Ciudad, + SUM(Total) AS TotalVentas +FROM VW_VENTAS +GROUP BY Ciudad; +``` + +El backend debe validar el SQL antes de ejecutarlo. + +## Fase 5: conversación con contexto + +El agente debe mantener el contexto: + +```text +Usuario: Muéstrame las ventas de marzo. +Agente: ... + +Usuario: Ahora solo Lima. +Agente: ... + +Usuario: Compáralo con febrero. +Agente: ... + +Usuario: Haz un gráfico. +Agente: ... +``` + +## Fase 6: gráficos + +El agente podrá generar visualizaciones como: + +- Ventas por vendedor +- Ventas por ciudad +- Ventas mensuales +- Margen por línea +- Top 10 productos +- Top 10 clientes +- Evolución de cobranza +- Stock por almacén + +Flujo: + +```text +Pregunta -> Tool -> HANA -> Datos -> Motor de gráficos -> Gráfico -> Chat +``` + +## Fase 7: KPIs + +Crear un catálogo de indicadores. + +### Ventas +- Ventas del mes +- Ventas acumuladas +- Cumplimiento de meta +- Crecimiento vs. período anterior +- Ticket promedio +- Ventas por vendedor +- Ventas por cliente +- Ventas por producto + +### Rentabilidad +- Margen bruto +- Margen por producto +- Margen por línea +- Margen por vendedor + +### Inventario +- Stock disponible +- Stock crítico +- Rotación +- Productos sin movimiento +- Productos próximos a agotarse + +### Finanzas +- Cuentas por cobrar +- Cuentas por pagar +- Vencimientos +- Cobranza +- Antigüedad de saldos + +## Fase 8: reportes + +El usuario podrá solicitar: + +```text +Genera un resumen gerencial de junio. +``` + +El sistema: + +1. Consulta los datos. +2. Calcula KPIs. +3. Genera gráficos. +4. Utiliza el LLM para interpretar los resultados. +5. Genera conclusiones. +6. Crea un PDF. +7. Puede crear un Excel. + +Estructura posible: + +```text +REPORTE GERENCIAL + +Resumen ejecutivo +Ventas +Rentabilidad +Inventario +Cuentas por cobrar +Principales variaciones +Principales clientes +Principales productos +Conclusiones +``` + +## Fase 9: alertas automáticas + +Ejemplo de resumen diario: + +```text +Ventas: S/ 124,500 +Meta: 95% +Margen: 28% + +Top vendedor: Carlos +Productos sin stock: 14 +Clientes con deuda: 18 +``` + +El agente también podría detectar anomalías: + +```text +- Las ventas de Arequipa disminuyeron 15%. +- El producto X cayó 20% respecto al promedio. +- Las cobranzas aumentaron 12%. +- Tres clientes concentran una parte importante de la deuda vencida. +``` + +La IA debe aportar principalmente interpretación de datos reales, no inventar respuestas plausibles. + +## Seguridad + +Principios desde el inicio: + +- El LLM no debe tener credenciales directas de HANA. +- Las herramientas deben estar controladas por el backend. +- Separar consultas de lectura de operaciones de escritura. +- No permitir SQL arbitrario inicialmente. +- Validar parámetros. +- Registrar las consultas ejecutadas. +- Registrar usuario, herramienta y fecha. +- Controlar qué herramientas puede utilizar cada usuario. +- Utilizar Service Layer para operaciones que modifiquen SAP. +- No permitir que una pregunta de lenguaje natural ejecute operaciones destructivas. + +Arquitectura de lectura: + +```text +Usuario -> LLM -> Tool controlada -> Vista/Query HANA -> Resultado +``` + +Arquitectura de operaciones: + +```text +Usuario -> LLM -> Tool controlada -> Validación -> Service Layer -> SAP Business One +``` + +# Capa semántica empresarial + +Uno de los componentes más importantes será un catálogo que explique al agente qué significa cada dato. + +Ejemplo: + +```text +VW_VENTAS + +Descripción: +Información consolidada de documentos de venta. + +Campos: + +Fecha +Fecha del documento. + +Cliente +Código del cliente. + +NombreCliente +Nombre comercial. + +Vendedor +Vendedor responsable. + +Total +Importe total del documento. + +Margen +Margen bruto calculado. + +Cantidad +Cantidad vendida. +``` + +También se deben documentar reglas de negocio, por ejemplo: + +```text +"Ventas" significa documentos de venta contabilizados. + +"No considerar documentos cancelados." + +"Margen" se calcula utilizando el costo correspondiente. + +"Ventas del mes" utiliza DocDate salvo que se indique otra fecha. +``` + +Esto será más importante que intentar meter miles de tablas SAP en el contexto del LLM. + +# Estructura inicial del proyecto + +```text +agente_sap/ +| ++-- app/ +| +-- main.py +| +-- api/ +| | +-- chat.py +| | +-- reports.py +| +-- agent/ +| | +-- agent.py +| | +-- prompts.py +| | +-- tools.py +| +-- tools/ +| | +-- ventas.py +| | +-- compras.py +| | +-- stock.py +| | +-- clientes.py +| | +-- finanzas.py +| +-- database/ +| | +-- hana.py +| +-- sap/ +| | +-- service_layer.py +| +-- reports/ +| | +-- pdf.py +| | +-- excel.py +| +-- charts/ +| +-- charts.py +| ++-- frontend/ +| +-- ... +| ++-- sql/ +| +-- views/ +| +-- queries/ +| ++-- docs/ +| +-- semantic_layer/ +| ++-- tests/ +| ++-- .env ++-- requirements.txt ++-- README.md +``` + +# Primera versión recomendada + +No empezar con dashboards, agentes autónomos ni SQL generado por IA. + +La primera versión debería hacer solamente: + +```text +Chat + | + v +Ollama + | + v +Tools Python + | + v +HANA + | + v +Resultado + | + v +Ollama + | + v +Respuesta +``` + +Con cinco herramientas iniciales: + +```text +ventas_hoy() +ventas_mes() +top_clientes() +stock_critico() +cuentas_por_cobrar() +``` + +Y una interfaz web sencilla. + +# Evolución recomendada + +```text +FASE 1 +Chat + Ollama + 5 tools + | + v +FASE 2 +Tools con parámetros + | + v +FASE 3 +Vistas HANA / capa semántica + | + v +FASE 4 +SQL controlado sobre vistas + | + v +FASE 5 +Contexto conversacional + | + v +FASE 6 +Gráficos + | + v +FASE 7 +KPIs + | + v +FASE 8 +PDF / Excel + | + v +FASE 9 +Dashboards + | + v +FASE 10 +Alertas y análisis automáticos +``` + +# Objetivo final + +El asistente podrá responder preguntas como: + +```text +¿Cuánto vendimos este mes? + +¿Cuáles son nuestros 10 mejores clientes? + +¿Qué productos están cayendo en ventas? + +¿Qué vendedores no están alcanzando su meta? + +¿Cuánto tenemos pendiente de cobrar? + +¿Qué clientes tienen mayor deuda vencida? + +¿Cómo se comportaron las ventas frente al mes anterior? + +¿Cuál es nuestro margen promedio? + +Genera un reporte gerencial del mes. + +Genera un Excel con las ventas por vendedor. + +Muéstrame un gráfico de ventas de los últimos 12 meses. + +¿Qué problemas ves en los datos de este mes? +``` + +Posteriormente: + +```text +Analiza la situación comercial de la empresa +y dame las principales conclusiones. +``` + +Las conclusiones deben basarse en datos reales obtenidos de SAP, no en respuestas inventadas por el modelo. + +# Principio de diseño + +La arquitectura debe ser modular. + +Cada nueva capacidad debe incorporarse como una nueva herramienta: + +```text +Nueva necesidad + | + v +Nueva Tool + | + v +Consulta / Vista HANA + | + v +Documentación semántica + | + v +Disponible para el agente +``` + +Esto permite crecer sin rehacer toda la aplicación. + +# Conclusión + +La estrategia recomendada es construir primero un **asistente de consulta sobre SAP Business One**, no un sistema autónomo. + +La combinación: + +```text +React ++ +FastAPI ++ +Ollama ++ +Tools Python ++ +SAP HANA ++ +Service Layer +``` + +es suficiente para construir una primera versión sólida. + +La pieza más importante no será el modelo de IA, sino la **capa de herramientas y conocimiento empresarial** que conectará el lenguaje natural con los datos reales de SAP. + +El modelo puede cambiarse posteriormente. Las herramientas, vistas, reglas de negocio y capa semántica serán el verdadero activo del proyecto. diff --git a/005-Learn/Proyecto SAP B1 - FastAPI - React - Next.js.md b/005-Learn/Proyecto SAP B1 - FastAPI - React - Next.js.md deleted file mode 100644 index 8c6b675..0000000 --- a/005-Learn/Proyecto SAP B1 - FastAPI - React - Next.js.md +++ /dev/null @@ -1,587 +0,0 @@ -# Proyecto ERP Web Empresarial Integrado con SAP Business One Service Layer - -# Objetivo General - -Desarrollar una aplicación web empresarial para mantenimiento de datos maestros de Socios de Negocio similar al formulario estándar de SAP Business One. - -La solución utilizará: - -- Frontend: - - React.js - - Next.js - - TypeScript - -- Backend: - - Python - - FastAPI - -- Integración: - - SAP Business One Service Layer - ---- - -# Filosofía de Arquitectura - -La solución debe: - -- Ser escalable -- Ser desacoplada -- Tener arquitectura por capas -- Tener código mantenible -- Tener funciones pequeñas y reutilizables -- Aplicar principios SOLID -- Tener separación de responsabilidades -- Tener documentación técnica - ---- - -# Arquitectura General - -```mermaid -flowchart TD - -A[Frontend Next.js] --> B[Backend FastAPI] -B --> C[SAP Business One Service Layer] -C --> D[SAP Business One Database] -``` - ---- - -# Tecnologías - -# Frontend - -- React.js -- Next.js -- TypeScript -- React Hook Form -- Zod -- Axios -- Zustand -- TailwindCSS -- Shadcn UI - ---- - -# Backend - -- Python -- FastAPI -- Pydantic -- SQLAlchemy -- httpx -- passlib[bcrypt] -- JWT Authentication - ---- - -# Integración SAP - -- SAP Business One Service Layer -- Session Management -- B1SESSION -- ROUTEID - ---- - -# Estrategia de Desarrollo por Etapas - -# IMPORTANTE - -NO desarrollar frontend y backend simultáneamente. - -El proyecto debe ejecutarse por etapas para: -- minimizar errores -- facilitar pruebas -- mantener arquitectura limpia -- evitar acoplamiento prematuro - ---- - -# ETAPA 1 - Diseño de Arquitectura - -## Objetivo - -Definir completamente la arquitectura antes de programar. - ---- - -## Tareas - -### 1. Crear diagramas Mermaid - -Crear: - -- arquitectura general -- flujo login -- flujo CRUD -- flujo Service Layer -- arquitectura backend -- arquitectura frontend - ---- - -## Diagramas recomendados - -### Flujo Login - -```mermaid -sequenceDiagram - -Frontend->>Backend: Login usuario -Backend->>SAP Service Layer: Login técnico SAP -SAP Service Layer-->>Backend: B1SESSION -Backend->>SAP Service Layer: Consultar EmployeesInfo -SAP Service Layer-->>Backend: Datos usuario -Backend-->>Frontend: JWT -``` - ---- - -### Arquitectura Backend - -```mermaid -flowchart TD - -A[Routes] --> B[Services] -B --> C[Repositories] -C --> D[SAP Integration] -D --> E[Service Layer] -``` - ---- - -# Resultado esperado ETAPA 1 - -- Diagramas completos -- Arquitectura definida -- Carpetas definidas -- Responsabilidades definidas - ---- - -# ETAPA 2 - Backend Base - -# IMPORTANTE - -Primero construir backend. - -Razones: -- frontend depende APIs -- frontend depende autenticación -- frontend depende estructura JSON -- frontend depende validaciones - ---- - -# Objetivos ETAPA 2 - -Construir: -- estructura FastAPI -- autenticación -- integración SAP -- manejo sesiones -- JWT -- logging -- manejo errores - ---- - -# Estructura Backend - -```text -/app - /api - /services - /repositories - /schemas - /models - /validators - /middlewares - /core - /integrations - /sap - /utils - /queries -``` - ---- - -# Funcionalidades Backend Iniciales - -## 1. Login SAP técnico - -Endpoint: - -```text -POST /auth/login -``` - ---- - -## 2. Session Manager SAP - -Implementar: - -- login automático -- refresh automático -- manejo cookies -- timeout -- retry policy - ---- - -## 3. JWT propio - -Implementar: - -- access token -- refresh token -- expiración -- middleware autenticación - ---- - -## 4. Integración OHEM - -Usar: - -```text -EmployeesInfo -``` - -del Service Layer. - ---- - -# Usuarios - -Los usuarios funcionales estarán en: - -```text -OHEM -``` - -mediante Service Layer. - ---- - -# UDFs requeridos - -| Campo | Uso | -|---|---| -| U_APP_USERNAME | Usuario | -| U_APP_PASSWORD | Password hash | -| U_APP_ROLE | Rol | -| U_APP_ACTIVE | Estado | - ---- - -# Seguridad Passwords - -Usar: - -```text -bcrypt -``` - -Nunca guardar passwords en texto plano. - ---- - -# Resultado esperado ETAPA 2 - -- Backend funcionando -- Login funcionando -- JWT funcionando -- Integración SAP funcionando - ---- - -# ETAPA 3 - CRUD Socios de Negocio - -# Objetivo - -Implementar CRUD Business Partners. - ---- - -# Entidad principal - -```text -BusinessPartners -``` - ---- - -# Campos OCRD - -| Campo | Uso | -|---|---| -| CardCode | Código | -| CardName | Nombre | -| CardType | Tipo | -| LicTradNum | Documento | -| Phone1 | Teléfono | -| E_Mail | Correo | -| Currency | Moneda | -| GroupCode | Grupo | - ---- - -# Campos CRD1 - -| Campo | Uso | -|---|---| -| Address | Dirección | -| Country | País | -| Street | Calle | -| ZipCode | Código Postal | -| AdresType | Tipo | - ---- - -# Reglas de negocio - -## LicTradNum - -Debe: -- tener 8 caracteres -- ser numérico - ---- - -## CardCode - -Debe autogenerarse: - -```text -CardType + LicTradNum -``` - -Ejemplo: - -```text -C12345678 -``` - ---- - -# Operaciones CRUD - -| Operación | Método | -|---|---| -| Listar | GET | -| Obtener | GET | -| Crear | POST | -| Actualizar | PATCH | -| Eliminar | DELETE/PATCH | - ---- - -# Resultado esperado ETAPA 3 - -- CRUD completo -- Validaciones -- Integración real SAP - ---- - -# ETAPA 4 - Queries Optimizados - -# Objetivo - -Mejorar performance. - ---- - -# IMPORTANTE - -NO usar entidades completas SAP para listados masivos. - ---- - -# Estrategia - -## Escrituras - -Usar: -- Service Layer estándar - ---- - -## Lecturas masivas - -Usar: -- SQLQueries -- queries optimizados -- paginación - ---- - -# Resultado esperado ETAPA 4 - -- Listados rápidos -- Filtros -- Paginación - ---- - -# ETAPA 5 - Frontend Base - -# Objetivo - -Construir frontend luego de estabilizar backend. - ---- - -# Estructura Frontend - -```text -/src - /app - /components - /services - /hooks - /layouts - /store - /validators - /types - /utils -``` - ---- - -# Pantallas Iniciales - -## Login - -Campos: -- usuario -- password -- company db - ---- - -## Master Layout - -- sidebar -- header -- content - ---- - -## Socio de Negocio - -- formulario OCRD -- grid CRD1 -- CRUD -- validaciones - ---- - -# Resultado esperado ETAPA 5 - -- Login UI -- navegación -- consumo APIs - ---- - -# ETAPA 6 - Frontend Empresarial - -# Objetivo - -Mejorar experiencia usuario. - ---- - -# Funcionalidades - -- loading states -- toast notifications -- manejo errores -- tablas -- búsqueda -- debounce -- paginación -- responsive - ---- - -# ETAPA 7 - Seguridad y Performance - -# Objetivo - -Preparar entorno productivo. - ---- - -# Implementar - -- cache -- retry policy -- correlation ID -- logs -- auditoría -- middleware seguridad -- rate limiting -- circuit breaker - ---- - -# ETAPA 8 - DevOps y Despliegue - -# Backend - -- Docker -- Variables entorno -- Gunicorn/Uvicorn - ---- - -# Frontend - -- Build Next.js -- Reverse proxy - ---- - -# Infraestructura - -- HTTPS -- NGINX -- SSL -- monitoreo - ---- - -# Recomendaciones Arquitectónicas - -## NO hacer - -- acceso SQL directo escritura SAP -- passwords en texto plano -- lógica SAP en frontend -- consultas gigantes Service Layer - ---- - -# SI hacer - -- backend desacoplado -- funciones pequeñas -- validaciones separadas -- logs centralizados -- manejo global errores - ---- - -# Objetivo Final - -Construir una plataforma empresarial: -- mantenible -- escalable -- desacoplada -- compatible con SAP Business One -- optimizada para crecimiento futuro diff --git a/005-Learn/Roadmap Next.js.md b/005-Learn/Roadmap Next.js.md deleted file mode 100644 index d59408f..0000000 --- a/005-Learn/Roadmap Next.js.md +++ /dev/null @@ -1,746 +0,0 @@ -# Hoja de Ruta: Desarrollo de Aplicaciones Operacionales para SAP Business One con Next.js - -> Duración estimada: 4 a 5 meses -> Objetivo: Construir aplicaciones web operacionales simples, rápidas y mantenibles conectadas a SAP Business One mediante Service Layer. - ---- - -# Objetivo real del proyecto - -El objetivo NO es crear un ERP completo como SAP Business One. - -El objetivo es desarrollar: - -- formularios operacionales específicos -- módulos independientes -- validaciones empresariales -- procesos rápidos para usuarios internos - -Cada módulo tendrá: -- una funcionalidad específica -- su propia lógica -- su propio formulario -- integración con SAP Business One - ---- - -# Filosofía del sistema - -SAP Business One seguirá siendo: - -```text -Sistema maestro ERP -``` - -La aplicación web será: - -```text -Frontend operacional especializado - ↓ -Validaciones empresariales - ↓ -Integración con SAP Service Layer -``` - ---- - -# Ejemplos reales de módulos - -## Almacén -- Recepción de Orden de Compra -- Transferencias de almacén -- Validación de lotes -- Conteo de inventario - ---- - -## Compras -- Factura de gastos -- Factura de productos -- Distribución por centros de costo -- Validación SUNAT - ---- - -## Ventas -- Validación de pedidos -- Aprobaciones -- Seguimiento comercial - ---- - -# Arquitectura recomendada - -```text -Frontend -- Next.js -- TypeScript -- React Hook Form -- TanStack Table - -Backend Integración -- FastAPI - -ERP -- SAP Business One Service Layer -``` - ---- - -# Flujo típico de trabajo - -```text -1. Consultar información desde SAP -2. Mostrar información al usuario -3. Validar reglas operacionales -4. Permitir edición controlada -5. Enviar información final a SAP -``` - ---- - -# Principios de diseño UI - -## El sistema debe ser: - -- rápido -- minimalista -- estable -- predecible -- orientado a productividad - ---- - -## Evitar - -- animaciones -- dashboards innecesarios -- exceso de colores -- imágenes decorativas -- diseño tipo startup - ---- - -## Priorizar - -- velocidad -- teclado -- tabulación -- búsqueda rápida -- formularios densos -- tablas operacionales - ---- - -# Fase 1 — Fundamentos web modernos -Duración: ~3 semanas - ---- - -# JavaScript moderno - -## Aprender - -- let / const -- funciones -- arrays -- objetos -- async / await -- fetch API -- módulos - ---- - -## Objetivo ERP - -Consumir APIs y transformar datos empresariales. - -Ejemplos: -- obtener OC -- obtener proveedores -- listar artículos -- validar estados - ---- - -# HTML y CSS - -## Aprender - -- formularios -- tablas -- inputs -- layouts -- Flexbox -- CSS Grid -- responsive básico - ---- - -## Objetivo ERP - -Construir: -- formularios operacionales -- tablas densas -- layouts empresariales - ---- - -# TypeScript - -## Aprender - -- interfaces -- types -- arrays tipados -- objetos anidados -- generics -- Partial -- Pick -- Omit - ---- - -## Objetivo ERP - -Modelar: -- documentos -- líneas -- almacenes -- lotes -- centros de costo - ---- - -# Fase 2 — React para sistemas empresariales -Duración: ~3 semanas - ---- - -# Componentes - -## Aprender - -- componentes reutilizables -- props -- composición - ---- - -## Objetivo ERP - -Crear: -- inputs -- tablas -- formularios -- modales - ---- - -# Hooks React - -## Aprender - -- useState -- useEffect -- useMemo -- useCallback - ---- - -## Objetivo ERP - -Controlar: -- formularios -- búsquedas -- filtros -- cálculos - ---- - -# Formularios controlados - -## Aprender - -- eventos -- validaciones -- manejo errores - ---- - -## Objetivo ERP - -Validar: -- cantidades -- RUC -- fechas -- almacenes -- centros de costo - ---- - -# Fase 3 — Formularios empresariales modernos -Duración: ~2 semanas - -> Esta es una de las fases MÁS importantes. - ---- - -# React Hook Form - -## Aprender - -- useForm -- Controller -- FormProvider -- useFieldArray - ---- - -## Objetivo ERP - -Manejar: -- formularios grandes -- líneas dinámicas -- validaciones rápidas - ---- - -# Zod - -## Aprender - -- schemas -- validaciones -- refinements - ---- - -## Objetivo ERP - -Centralizar reglas empresariales. - -Ejemplos: -- cantidad > 0 -- RUC válido -- lote obligatorio -- centro de costo requerido - ---- - -# Fase 4 — Next.js moderno -Duración: ~4 semanas - ---- - -# App Router - -## Aprender - -- app/ -- layouts -- rutas dinámicas - ---- - -## Ejemplos - -```text -/recepcion-oc -/factura-gastos -/factura-productos -/transferencias -``` - ---- - -# Server Components y Client Components - -## Aprender - -- use client -- separación cliente/servidor - ---- - -## Objetivo ERP - -Separar: -- carga datos -- UI -- validaciones - ---- - -# API Routes - -## Aprender - -- GET -- POST -- PATCH - ---- - -## Objetivo ERP - -Comunicación: -- frontend -- FastAPI -- SAP - ---- - -# Autenticación - -## Aprender - -- sesiones -- middleware -- protección rutas - ---- - -## Escenario real - -Usuario: -- existe en OHEM -- usa login corporativo -- trabaja con usuario SAP indirecto - ---- - -# Fase 5 — Estado servidor y tablas -Duración: ~2 semanas - ---- - -# TanStack Query - -## Aprender - -- fetching -- cache -- invalidaciones -- mutations - ---- - -## Objetivo ERP - -Optimizar: -- búsquedas -- consultas SAP -- refresco de datos - ---- - -# TanStack Table - -## Aprender - -- filtros -- sorting -- paginación -- selección filas - ---- - -## Objetivo ERP - -Construir: -- líneas documento -- búsquedas -- listados operacionales - ---- - -# Fase 6 — Componentes ERP reutilizables -Duración: ~2 semanas - -> Esta fase define la calidad del sistema completo. - ---- - -# Componentes clave - -## ERPDataTable - -Tabla reutilizable: -- filtros -- búsqueda -- selección -- teclado - ---- - -# SearchModal - -Modal reutilizable para: -- artículos -- proveedores -- clientes -- órdenes -- almacenes - ---- - -# Inputs inteligentes - -Crear componentes: -- InputRUC -- InputCurrency -- InputDate -- InputQuantity -- InputWarehouse - ---- - -# Layouts reutilizables - -## Crear - -- FormLayout -- FilterLayout -- ModalLayout - ---- - -# Fase 7 — Backend integración FastAPI -Duración: ~2 semanas - ---- - -# FastAPI - -## Aprender - -- endpoints -- modelos Pydantic -- autenticación -- manejo errores - ---- - -# Objetivo ERP - -Centralizar: -- login SAP -- sesión Service Layer -- validaciones -- logs -- auditoría - ---- - -# Arquitectura recomendada - -```text -Next.js - ↓ -FastAPI - ↓ -SAP Service Layer -``` - ---- - -# Fase 8 — Integración SAP Business One -Duración: ~2 semanas - ---- - -# Aprender - -- login Service Layer -- cookies sesión -- GET -- POST -- PATCH - ---- - -# Escenarios reales - -## Recepción OC - -```text -1. Buscar OC -2. Mostrar pendientes -3. Registrar cantidades -4. Crear Entrada Mercancía -``` - ---- - -## Factura proveedor - -```text -1. Traer Entrada Mercancía -2. Completar datos contables -3. Distribuir gastos -4. Crear Factura Proveedor -``` - ---- - -# Validaciones reales - -## Manejar - -- sesión expirada -- errores SAP -- timeouts -- validaciones SUNAT -- concurrencia - ---- - -# Fase 9 — Seguridad y despliegue -Duración: ~1 semana - ---- - -# Seguridad - -## Aprender - -- HTTPS -- CORS -- middleware -- protección APIs - ---- - -# Deploy - -## Aprender - -- Docker -- Nginx -- Linux -- variables entorno - ---- - -# Estructura recomendada - -```text -/apps - /recepcion-oc - /factura-gastos - /factura-productos - /transferencias - -/shared-ui -/shared-api -/shared-types -``` - ---- - -# Filosofía modular - -Cada módulo: -- independiente -- simple -- mantenible -- desplegable - ---- - -# Proyecto inicial recomendado - -## Recepción de Orden de Compra - -Porque incluye: - -- filtros -- tablas -- modales -- líneas -- validaciones -- SAP Service Layer - ---- - -# Stack recomendado - -## Frontend - -- Next.js -- TypeScript -- Tailwind CSS -- shadcn/ui - ---- - -## Formularios - -- React Hook Form -- Zod - ---- - -## Tablas - -- TanStack Table - ---- - -## Estado servidor - -- TanStack Query - ---- - -## Backend - -- FastAPI - ---- - -# Recursos recomendados - -| Tema | Recurso | -|---|---| -| JavaScript | https://javascript.info | -| TypeScript | https://www.typescriptlang.org/docs | -| React | https://react.dev | -| Next.js | https://nextjs.org/learn | -| Tailwind CSS | https://tailwindcss.com | -| React Hook Form | https://react-hook-form.com | -| Zod | https://zod.dev | -| TanStack Query | https://tanstack.com/query | -| TanStack Table | https://tanstack.com/table | -| FastAPI | https://fastapi.tiangolo.com | - ---- - -# Resumen total - -| Fase | Tema | Semanas | -|---|---|---| -| 1 | Fundamentos web | 3 | -| 2 | React empresarial | 3 | -| 3 | Formularios modernos | 2 | -| 4 | Next.js | 4 | -| 5 | Estado y tablas | 2 | -| 6 | Componentes ERP reutilizables | 2 | -| 7 | FastAPI integración | 2 | -| 8 | SAP Business One | 2 | -| 9 | Seguridad y deploy | 1 | -| Total | | ~21 semanas | - ---- - -# Meta final - -Construir aplicaciones operacionales empresariales: -- rápidas -- simples -- mantenibles -- desacopladas -- conectadas a SAP Business One - -Sin intentar reinventar un ERP completo. La humanidad ya ha sufrido suficiente con eso. \ No newline at end of file diff --git a/005-Learn/Stack Tecnológico Recomendado.md b/005-Learn/Stack Tecnológico Recomendado.md deleted file mode 100644 index 841bb30..0000000 --- a/005-Learn/Stack Tecnológico Recomendado.md +++ /dev/null @@ -1,593 +0,0 @@ -## Aplicaciones Operacionales para SAP Business One - -> Objetivo: construir aplicaciones web empresariales simples, rápidas, mantenibles y desacopladas para procesos específicos conectados a SAP Business One mediante Service Layer. - ---- - -# Filosofía tecnológica - -El objetivo NO es crear: -- una plataforma compleja -- microservicios innecesarios -- interfaces visualmente exageradas - -El objetivo es construir: -- formularios operacionales rápidos -- tablas empresariales eficientes -- validaciones sólidas -- integración estable con SAP Business One - ---- - -# Arquitectura general recomendada - -```text -Frontend (Next.js) - ↓ -Backend Integración (FastAPI) - ↓ -SAP Business One Service Layer -``` - ---- - -# Lenguajes recomendados - -# 1. TypeScript - -## Uso principal -Frontend empresarial. - ---- - -## Se utilizará en: -- Next.js -- React -- Formularios -- Tablas -- Validaciones -- Componentes reutilizables - ---- - -## ¿Por qué usar TypeScript? - -Porque los sistemas ERP manejan: -- muchos datos -- documentos complejos -- estructuras anidadas -- validaciones empresariales - -TypeScript ayuda a: -- reducir errores -- mantener consistencia -- mejorar mantenimiento -- detectar problemas temprano - ---- - -## Ejemplo típico ERP - -```ts -interface PurchaseOrderLine { - itemCode: string - description: string - quantity: number - warehouseCode: string -} -``` - ---- - -# 2. Python - -## Uso principal -Backend de integración. - ---- - -## Se utilizará en: -- FastAPI -- integración SAP -- validaciones empresariales -- integración SUNAT -- logs -- auditoría -- automatizaciones -- procesos auxiliares - ---- - -## ¿Por qué Python? - -Porque: -- es rápido de desarrollar -- excelente para APIs -- ideal para integración empresarial -- muy compatible con automatización -- excelente ecosistema - ---- - -# IDE recomendado - -# Antigravity - -## IDE principal - -Antigravity puede ser muy útil para este proyecto debido a: -- generación acelerada de código -- asistencia IA -- productividad -- soporte moderno TypeScript y React - ---- - -# Uso recomendado de Antigravity - -## Excelente para generar: -- formularios -- CRUDs -- tablas -- hooks -- componentes -- validaciones -- clientes API -- schemas Zod - ---- - -## NO depender completamente de IA para: -- arquitectura -- seguridad -- lógica SAP -- reglas contables -- autorizaciones -- estructura del sistema - ---- - -# Filosofía correcta con IA - -```text -Arquitectura y lógica: -Manual - -Implementación repetitiva: -Asistida por IA -``` - ---- - -# Recomendación importante - -La IA debe: -- acelerar desarrollo -- reducir boilerplate -- mejorar productividad - -La IA NO debe: -- tomar decisiones arquitectónicas -- definir reglas empresariales -- controlar diseño de integración SAP - ---- - -# VS Code como respaldo - -## Recomendado instalar también: -Visual Studio Code. - ---- - -## Motivos -- estabilidad -- debugging excelente -- ecosistema enorme -- respaldo confiable -- herramientas empresariales - ---- - -# Extensiones recomendadas - -## Frontend - -- ES7+ React snippets -- Tailwind CSS IntelliSense -- ESLint -- Prettier -- Error Lens - ---- - -## Python - -- Python -- Pylance -- Ruff -- Black Formatter - ---- - -# Librerías Frontend - -# Next.js - -## Framework principal - -Se utilizará para: -- páginas -- layouts -- formularios -- módulos operacionales -- autenticación -- API routes - ---- - -## ¿Por qué Next.js? - -Porque: -- estructura moderna -- excelente soporte TypeScript -- arquitectura ordenada -- ideal para aplicaciones empresariales - ---- - -# React - -## Base UI - -React será utilizado para: -- componentes -- formularios -- tablas -- modales -- interacción usuario - ---- - -# Tailwind CSS - -## Framework CSS recomendado - -Ideal para: -- sistemas empresariales -- diseño minimalista -- formularios densos -- layouts rápidos - ---- - -## Ventajas - -- rápido -- consistente -- fácil mantenimiento -- poco CSS manual - ---- - -# shadcn/ui - -## Librería UI recomendada - -Ideal para: -- modales -- dialogs -- tablas -- formularios -- selects -- popovers - ---- - -## Ventaja principal - -Los componentes: -- son modificables -- quedan dentro del proyecto -- no dependen de librerías cerradas - ---- - -# Formularios - -# React Hook Form - -## Librería MÁS importante del frontend - -Se utilizará para: -- formularios complejos -- validaciones -- líneas dinámicas -- formularios ERP - ---- - -## Casos reales - -- facturas -- entradas mercancía -- transferencias -- gastos -- validaciones tributarias - ---- - -# Zod - -## Validaciones empresariales - -Se utilizará para: -- validar formularios -- validar payloads -- centralizar reglas - ---- - -## Ejemplos - -- RUC válido -- cantidad > 0 -- centro costo obligatorio -- lote requerido - ---- - -# Manejo de datos - -# TanStack Query - -## Manejo de estado servidor - -Se utilizará para: -- consultas SAP -- cache -- refresh -- sincronización datos - ---- - -## Ventajas - -- evita consultas repetidas -- mejora performance -- simplifica fetching - ---- - -# Tablas ERP - -# TanStack Table - -## Librería crítica ERP - -Se utilizará para: -- líneas documento -- listados -- filtros -- selección -- edición - ---- - -## Funcionalidades importantes - -- filtros -- sorting -- búsqueda -- navegación teclado -- paginación - ---- - -# Backend recomendado - -# FastAPI - -## Backend principal - -FastAPI será utilizado para: -- integración SAP -- autenticación -- validaciones -- logs -- auditoría -- APIs internas - ---- - -# Arquitectura recomendada - -```text -Next.js - ↓ -FastAPI - ↓ -SAP Service Layer -``` - ---- - -# ¿Por qué usar FastAPI? - -Porque: -- rápido -- limpio -- tipado -- excelente documentación -- ideal para APIs empresariales - ---- - -# SAP Business One - -## SAP seguirá siendo: - -```text -Sistema maestro ERP -``` - -La aplicación web: -- NO reemplaza SAP -- NO replica SAP completo - -La aplicación: -- simplifica procesos específicos -- mejora experiencia operacional -- agrega validaciones -- acelera tareas - ---- - -# Herramientas adicionales - -# Postman o Insomnia - -## Para pruebas API - -Utilizados para probar: -- SAP Service Layer -- FastAPI -- APIs SUNAT - ---- - -# Obsidian - -## Documentación técnica - -Ideal para: -- arquitectura -- flujos -- snippets -- documentación SAP - ---- - -# Git - -## Control versiones - -Recomendado: -- Git -- GitHub -- Gitea - ---- - -# Docker - -## Deploy empresarial - -Aprender: -- Docker -- Docker Compose -- Nginx - ---- - -# Organización recomendada - -```text -/apps - /recepcion-oc - /factura-gastos - /factura-productos - /transferencias - -/shared-ui -/shared-api -/shared-types -/shared-validations -``` - ---- - -# Filosofía modular - -Cada módulo debe ser: -- independiente -- simple -- mantenible -- desacoplado - ---- - -# Componentes reutilizables críticos - -## SearchModal - -Modal reutilizable para: -- artículos -- proveedores -- clientes -- órdenes compra - ---- - -# ERPDataTable - -Tabla reutilizable: -- filtros -- búsqueda -- selección -- teclado - ---- - -# Inputs inteligentes - -Crear: -- InputRUC -- InputCurrency -- InputDate -- InputQuantity -- InputWarehouse - ---- - -# Prioridades reales de aprendizaje - -# Prioridad máxima - -1. TypeScript -2. React Hook Form -3. TanStack Table -4. FastAPI -5. SAP Service Layer - ---- - -# Prioridad media - -6. Next.js -7. TanStack Query -8. Zod -9. Docker - ---- - -# Prioridad baja - -- Redux -- animaciones -- dashboards complejos -- SEO -- diseño visual avanzado - ---- - -# Objetivo final - -Construir aplicaciones empresariales: -- rápidas -- operacionales -- mantenibles -- desacopladas -- integradas con SAP Business One - -Sin intentar reinventar un ERP completo. La industria ya tiene suficientes cicatrices por eso. \ No newline at end of file diff --git a/005-Learn/gitea-tailscale-funnel.md b/005-Learn/gitea-tailscale-funnel.md new file mode 100644 index 0000000..55e6ba9 --- /dev/null +++ b/005-Learn/gitea-tailscale-funnel.md @@ -0,0 +1,384 @@ +# Gitea público con Tailscale Funnel en NAS UGREEN + +Guía para exponer Gitea (en Docker, NAS UGREEN con UGOS) por HTTPS a internet usando **Tailscale Funnel**, de modo que funcione desde cualquier equipo **sin instalar Tailscale**, en casa y fuera, con una sola URL. + +## Datos de esta instalación + +| Elemento | Valor | +|---|---| +| URL pública final | `https://unasgeorge.vaquita-hadar.ts.net` | +| Tailnet | `vaquita-hadar.ts.net` | +| Nombre del NAS en Tailscale | `unasgeorge` | +| IP Tailscale del NAS (contenedor) | `100.68.242.27` | +| IP local del NAS | `192.168.1.145` | +| Puerto de Gitea en el NAS (host) | `30000` (interno del contenedor: `3000`) | +| Puerta de enlace Docker (bridge) | `172.17.0.1` | +| Destino del proxy de Funnel | `http://172.17.0.1:30000` | +| Usuario Gitea | `george` | + +### Esquema + +``` +Cualquier equipo (con o sin Tailscale) + │ + ▼ +https://unasgeorge.vaquita-hadar.ts.net (puerto 443, HTTPS, Let's Encrypt) + │ + ▼ Tailscale Funnel (contenedor Tailscale en el NAS) +http://172.17.0.1:30000 (interno, nadie lo usa directamente) + │ + ▼ + Gitea +``` + +--- + +## 1. Preparar Tailscale (panel web) + +### 1.1 Activar certificados HTTPS + +1. Entrar a . +2. En **HTTPS Certificates**, pulsar **Enable HTTPS**. + +### 1.2 Permitir Funnel en la política de acceso + +1. Entrar a . +2. Verificar que exista este bloque (añadirlo si no está, respetando las comas): + +```json +"nodeAttrs": [ + { + "target": ["autogroup:member"], + "attr": ["funnel"] + } +] +``` + +3. Guardar (**Save**). + +> Alternativa: la primera vez que se ejecuta `tailscale funnel`, el comando muestra un enlace (`https://login.tailscale.com/f/funnel?node=...`) que añade este permiso automáticamente. + +**Validación:** después del paso 2, en debe aparecer la etiqueta **Funnel** junto a `unasgeorge`. + +--- + +## 2. Configurar Funnel en el contenedor de Tailscale + +### 2.1 Abrir la terminal del contenedor + +1. Entrar al panel del NAS (UGOS) → app **Docker** → **Contenedores**. +2. Abrir el contenedor de **Tailscale** → **Terminal** → añadir terminal. +3. En *Command* usar **`/bin/sh`** (la imagen de Tailscale no trae bash). + +> Si algún comando da *failed to connect to local tailscaled*, anteponer el socket: +> `tailscale --socket=/tmp/tailscaled.sock ` + +### 2.2 Comprobar que Tailscale está conectado + +```sh +tailscale status +tailscale version +``` + +Debe aparecer `unasgeorge` con IP `100.68.242.27`. Versión recomendada: 1.50 o superior. + +### 2.3 Encontrar por dónde ve el contenedor a Gitea + +El contenedor de Tailscale está en la red bridge de Docker: **no** llega a Gitea por la IP local del NAS ni por `127.0.0.1`. Hay que usar la puerta de enlace de Docker. + +```sh +ip route | head -1 +# Resultado esperado: default via 172.17.0.1 dev eth0 + +wget -qO- -T 5 http://172.17.0.1:30000 | head -c 200 +# Debe devolver HTML que empieza con +``` + +Referencia de lo que **no** funciona en esta instalación: + +```sh +wget -qO- -T 5 http://192.168.1.145:30000 | head -c 200 # download timed out +wget -qO- -T 5 http://127.0.0.1:30000 | head -c 200 # Connection refused +``` + +### 2.4 Activar Funnel + +```sh +tailscale serve reset +tailscale funnel --bg http://172.17.0.1:30000 +``` + +Salida esperada: + +``` +Available on the internet: + +https://unasgeorge.vaquita-hadar.ts.net/ +|-- proxy http://172.17.0.1:30000 + +Funnel started and running in the background. +``` + +### 2.5 Validar + +```sh +tailscale funnel status +``` + +Debe mostrar **un solo** destino: + +``` +https://unasgeorge.vaquita-hadar.ts.net (Funnel on) +|-- / proxy http://172.17.0.1:30000 +``` + +> `--bg` deja Funnel activo en segundo plano y sobrevive a reinicios del contenedor. Si el contenedor se **recrea** (no solo se reinicia) y su estado no está en un volumen, hay que repetir el paso 2.4. +> +> Para desactivar Funnel: `tailscale funnel --https=443 off` + +--- + +## 3. Configurar Gitea + +### 3.1 Variables de entorno del contenedor (prioritario) + +Las variables `GITEA__seccion__CLAVE` **tienen prioridad sobre `app.ini`** y lo reescriben en cada arranque. En esta instalación existía `GITEA__server__ROOT_URL = http://100.68.242.27:30000/`, que era la causa de que el botón *Clone* mostrara la URL antigua. + +1. App **Docker** de UGOS → contenedor de **Gitea** → **Detener**. +2. **Editar → Variables de entorno**. +3. Dejar los valores así (cambiar o añadir): + +``` +GITEA__server__ROOT_URL = https://unasgeorge.vaquita-hadar.ts.net/ +GITEA__server__DOMAIN = unasgeorge.vaquita-hadar.ts.net +GITEA__server__SSH_DOMAIN = 192.168.1.145 +GITEA__server__PUBLIC_URL_DETECTION = never +GITEA__service__DISABLE_REGISTRATION = true +``` + +4. Guardar e **Iniciar** el contenedor. Los repositorios no se pierden: están en el volumen. + +### 3.2 `app.ini` (si no se usan variables) + +Ruta habitual dentro del volumen: `.../gitea/gitea/conf/app.ini` (en el contenedor: `/data/gitea/conf/app.ini`). Se puede editar desde el **Gestor de archivos** de UGOS. + +```ini +[server] +DOMAIN = unasgeorge.vaquita-hadar.ts.net +ROOT_URL = https://unasgeorge.vaquita-hadar.ts.net/ +SSH_DOMAIN = 192.168.1.145 +PUBLIC_URL_DETECTION = never + +[service] +DISABLE_REGISTRATION = true +``` + +Reiniciar el contenedor de Gitea tras editar. + +> `PUBLIC_URL_DETECTION = never` hace que Gitea use siempre `ROOT_URL` para los enlaces, aunque se entre por otra dirección (IP de Tailscale, `ugdocker.link`, etc.). +> `SSH_DOMAIN` apunta a la IP local: SSH **no** pasa por Funnel, solo funciona en la red de casa. + +### 3.3 Validar + +- **Administración del sitio → Configuración → URL de la aplicación** debe ser `https://unasgeorge.vaquita-hadar.ts.net/`. +- En cualquier repo, el botón **Clone (HTTPS)** debe mostrar: + `https://unasgeorge.vaquita-hadar.ts.net/george/.git` +- Al cerrar sesión **no** debe aparecer la opción *Registrarse*. + +> El aviso *"The detected web site URL is ... unlikely matching the site config"* solo aparece cuando se entra por una dirección distinta de `ROOT_URL`. Desaparece al entrar por `https://unasgeorge.vaquita-hadar.ts.net`. + +### 3.4 Crear un token de acceso + +Git por HTTPS usa el token como contraseña. + +1. Gitea → avatar → **Configuración → Aplicaciones** → *Administrar tokens de acceso*. +2. Nombre: uno por equipo (ej. `macbook-air`, `serfactpro`). +3. Permisos: **repository → Read and Write** (y **user → Read** si lo pide). +4. **Generar token** y copiarlo (solo se muestra una vez). + +> No usar **Manage SSH Keys** para esto: las claves SSH no funcionan a través de Funnel. + +--- + +## 4. Validaciones de acceso + +### 4.1 Desde un equipo con Tailscale encendido + +```bash +curl -I https://unasgeorge.vaquita-hadar.ts.net +``` + +Esperado: + +``` +HTTP/2 200 +``` + +Si se queda colgado después de `Request completely sent off`, Funnel no llega a Gitea: revisar el paso 2.3 y el destino del proxy. + +### 4.2 DNS público (sin Tailscale) + +```bash +dig +short unasgeorge.vaquita-hadar.ts.net A @1.1.1.1 +dig +short unasgeorge.vaquita-hadar.ts.net A @8.8.8.8 +``` + +Esperado (IPs de los servidores de entrada de Funnel, pueden variar): + +``` +209.177.145.97 +209.177.145.192 +``` + +> Si sale vacío o `No answer`, el registro DNS público aún no se ha creado. Puede tardar desde 10 minutos hasta unas horas. No hay que cambiar nada, solo esperar. + +### 4.3 Desde un equipo o servidor **sin Tailscale** + +En el Mac: apagar Tailscale (icono de la barra de menú) y limpiar caché DNS: + +```bash +sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder +``` + +En Linux (si usa systemd-resolved): + +```bash +sudo resolvectl flush-caches +``` + +En Windows (PowerShell): + +```powershell +ipconfig /flushdns +``` + +Comprobaciones (válidas en macOS, Linux y Windows con curl/git): + +```bash +# 1. Resuelve por DNS público +nslookup unasgeorge.vaquita-hadar.ts.net 8.8.8.8 + +# 2. Responde por HTTPS +curl -I https://unasgeorge.vaquita-hadar.ts.net +# Esperado: HTTP/2 200 + +# 3. Git llega al repositorio (pedirá usuario y token si es privado) +git ls-remote https://unasgeorge.vaquita-hadar.ts.net/george/sap-legacy-webhook-emulator.git +``` + +### 4.4 Prueba desde una red totalmente externa + +En el iPhone (o cualquier móvil): desactivar Wi-Fi, desactivar Tailscale y abrir en el navegador: + +``` +https://unasgeorge.vaquita-hadar.ts.net +``` + +Debe cargar la página de Gitea. + +### 4.5 URLs de comprobación + +| Qué | URL | +|---|---| +| Gitea (pública) | | +| Repo de ejemplo | | +| Máquinas Tailscale (etiqueta Funnel) | | +| Política de acceso (nodeAttrs funnel) | | +| DNS / certificados HTTPS | | + +--- + +## 5. Cambiar el `origin` de los proyectos + +### 5.1 Un proyecto + +```bash +cd ruta/al/proyecto + +# Ver el remoto actual +git remote -v + +# Cambiarlo +git remote set-url origin https://unasgeorge.vaquita-hadar.ts.net/george/.git + +# Verificar +git remote -v +git ls-remote origin +git push +``` + +Credenciales en el primer `push`: + +- **Username:** `george` +- **Password:** el **token** (al pegarlo no se ve nada, es normal) + +### 5.2 Varios proyectos a la vez (macOS / Linux) + +Desde la carpeta que contiene todos los proyectos. Sustituye cualquiera de las URLs antiguas (IP Tailscale, IP local o `ugdocker.link`) por la nueva: + +```bash +for d in */; do + [ -d "$d/.git" ] || continue + old=$(git -C "$d" remote get-url origin 2>/dev/null) || continue + new=$(echo "$old" | sed -E 's#^https?://(100\.68\.242\.27|192\.168\.1\.145|app-30000-unasgeorge\.us15\.ugdocker\.link)(:30000)?#https://unasgeorge.vaquita-hadar.ts.net#') + if [ "$old" != "$new" ]; then + git -C "$d" remote set-url origin "$new" + echo "$d $old -> $new" + fi +done +``` + +### 5.3 Varios proyectos a la vez (Windows PowerShell) + +```powershell +Get-ChildItem -Directory | ForEach-Object { + if (Test-Path "$($_.FullName)\.git") { + $old = git -C $_.FullName remote get-url origin 2>$null + if ($old) { + $new = $old -replace '^https?://(100\.68\.242\.27|192\.168\.1\.145|app-30000-unasgeorge\.us15\.ugdocker\.link)(:30000)?', 'https://unasgeorge.vaquita-hadar.ts.net' + if ($old -ne $new) { + git -C $_.FullName remote set-url origin $new + Write-Host "$($_.Name) $old -> $new" + } + } + } +} +``` + +### 5.4 Guardar el token para no escribirlo cada vez + +| Sistema | Comando / comportamiento | +|---|---| +| macOS | Se guarda solo en el Llavero (`git config --global credential.helper osxkeychain`) | +| Windows | Git Credential Manager lo guarda automáticamente | +| Linux | `git config --global credential.helper store` (guarda en texto plano en `~/.git-credentials`) | + +### 5.5 Clonar en un equipo nuevo + +```bash +git clone https://unasgeorge.vaquita-hadar.ts.net/george/.git +``` + +--- + +## 6. Seguridad (Gitea queda público en internet) + +- [ ] Registro desactivado (`DISABLE_REGISTRATION = true`, verificado en variables de entorno **y** `app.ini`). +- [ ] 2FA activado: **Configuración → Seguridad**. +- [ ] Repositorios privados marcados como **privados**. +- [ ] Un token por equipo; revocar el de un equipo perdido en **Configuración → Aplicaciones**. +- [ ] Revisar que no exista otra variable `GITEA__...` que anule estos ajustes. + +--- + +## 7. Problemas encontrados y solución + +| Síntoma | Causa | Solución | +|---|---|---| +| `ssh` y `ping` a `100.68.242.27` hacen timeout | Esa IP es del contenedor de Tailscale, no del sistema del NAS | Usar la terminal del contenedor desde la app Docker de UGOS | +| `Funnel is not enabled on your tailnet` | Falta permiso Funnel | Abrir el enlace que muestra el comando y aceptar | +| `port 443 is not allowed for funnel` | El nodo aún no tiene el atributo `funnel` | Revisar `nodeAttrs` (paso 1.2) y reiniciar el contenedor de Tailscale | +| HTTPS conecta pero no responde (`Request completely sent off` y nada más) | Funnel apuntaba a un destino inalcanzable (`:3000` o `192.168.1.145:30000`) | `tailscale serve reset` y Funnel a `http://172.17.0.1:30000` | +| `Could not resolve host` sin Tailscale / `dig` vacío | DNS público de Funnel aún no publicado | Esperar (minutos a horas) y repetir `dig` | +| Clone muestra `http://100.68.242.27:30000/...` o `ugdocker.link` | Variable `GITEA__server__ROOT_URL` antigua anulaba `app.ini` | Cambiar la variable y añadir `PUBLIC_URL_DETECTION = never` | +| Aviso *detected web site URL ... unlikely matching* | Se entra por una dirección distinta de `ROOT_URL` | Informativo; entrar por la URL pública |