se agrega .md de tailscale para hacer gitea https
This commit is contained in:
1 parent
f915802fb4
commit
920a4a2d56
10 files changed
+2072
-2057
No files matched your search
Vendored
+33
-12
@@ -4,11 +4,11 @@
|
|||||||
"type": "split",
|
"type": "split",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "7eb63950e584c8c8",
|
"id": "74bf841407436ba6",
|
||||||
"type": "tabs",
|
"type": "tabs",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "52972da0bc9d4ad0",
|
"id": "0519cc60f14f90b9",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
@@ -41,7 +41,9 @@
|
|||||||
"type": "file-explorer",
|
"type": "file-explorer",
|
||||||
"state": {
|
"state": {
|
||||||
"sortOrder": "alphabetical",
|
"sortOrder": "alphabetical",
|
||||||
"autoReveal": false
|
"autoReveal": false,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
},
|
},
|
||||||
"icon": "lucide-folder-closed",
|
"icon": "lucide-folder-closed",
|
||||||
"title": "Files"
|
"title": "Files"
|
||||||
@@ -183,16 +185,38 @@
|
|||||||
"bases:Create new base": false
|
"bases:Create new base": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active": "52972da0bc9d4ad0",
|
"active": "0519cc60f14f90b9",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"005-Learn/Instructivo Git Gitea.md",
|
"005-Learn/Instructivo Entornos Virtuales Python.md",
|
||||||
"005-Learn/Instructivo Git Branches.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/Obsidian WorkingCopy Manual.md",
|
||||||
"005-Learn/Proyecto SAP B1 - FastAPI - React - Next.js.md",
|
"005-Learn/Instructivo launchd iOS.md",
|
||||||
"005-Learn/Roadmap Next.js.md",
|
"005-Learn/Guia_Entornos_Virtuales_Python.md",
|
||||||
"005-Learn/Stack Tecnológico Recomendado.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",
|
"005-Learn/roadmap_nextjs_erp.html",
|
||||||
"Instructivo Git Gitea.md",
|
|
||||||
"005-Learn",
|
"005-Learn",
|
||||||
"004-SDK-SAP",
|
"004-SDK-SAP",
|
||||||
"003-Hana",
|
"003-Hana",
|
||||||
@@ -200,9 +224,6 @@
|
|||||||
"001-Linux",
|
"001-Linux",
|
||||||
"Untitled.canvas",
|
"Untitled.canvas",
|
||||||
"Untitled.base",
|
"Untitled.base",
|
||||||
"Roadmap-nextjs-erp.md",
|
"roadmap_nextjs_erp.html"
|
||||||
"roadmap_nextjs_erp.html",
|
|
||||||
"2026-05-18.md",
|
|
||||||
"Welcome.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
|
||||||
|
```
|
||||||
@@ -1,192 +1,755 @@
|
|||||||
# 🌿 Guía Completa para Crear y Manejar un Branch en Git
|
# 🌿 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
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git status
|
## 🗺️ 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"]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Esto te mostrará:
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 1️⃣ Verifica el estado actual del proyecto
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
git status
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Esto te muestra:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- Archivos modificados
|
- Archivos modificados
|
||||||
|
|
||||||
- Archivos en stage
|
- Archivos en stage
|
||||||
|
|
||||||
- Archivos sin seguimiento
|
- 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
|
```bash
|
||||||
|
|
||||||
git add .
|
git add .
|
||||||
|
|
||||||
git commit -m "Version estable antes de nueva funcionalidad"
|
git commit -m "Version estable antes de nueva funcionalidad"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
✅ Esto crea un punto seguro al cual regresar.
|
✅ Esto crea un punto seguro al cual regresar.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 Alternativa: usar stash
|
|
||||||
|
### 📦 Alternativa: usar stash
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Si todavía no quieres hacer commit:
|
Si todavía no quieres hacer commit:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
git stash
|
git stash
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Luego podrás recuperarlos con:
|
Luego podrás recuperarlos con:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
git stash pop
|
git stash pop
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 3️⃣ Ve a la rama principal
|
|
||||||
|
|
||||||
|
## 3️⃣ Ve a la rama principal
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
git checkout main
|
git checkout main
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 4️⃣ Descarga lo último del repositorio
|
|
||||||
|
|
||||||
|
## 4️⃣ Descarga lo último del repositorio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
git pull
|
git pull
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Esto sincroniza tu proyecto local con el remoto.
|
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
|
```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
|
git branch
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
La rama actual aparecerá con un `*`
|
|
||||||
|
|
||||||
## 📌 Ejemplo
|
|
||||||
|
La rama actual aparecerá marcada con un `*`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 📌 Ejemplo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|
||||||
main
|
main
|
||||||
* agregar-dashboard-powerbi
|
|
||||||
|
* cliente-acme
|
||||||
|
|
||||||
|
cliente-globex
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 7️⃣ Trabaja normalmente y guarda cambios
|
|
||||||
|
|
||||||
|
## 7️⃣ Trabaja normalmente y guarda cambios
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
git add .
|
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
|
```bash
|
||||||
|
|
||||||
git checkout main
|
git checkout main
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 9️⃣ Une la nueva funcionalidad a main
|
|
||||||
|
|
||||||
|
## 9️⃣ Une la nueva funcionalidad a main
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```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
|
```bash
|
||||||
|
|
||||||
git push
|
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
|
```bash
|
||||||
git branch -d nueva-funcionalidad
|
|
||||||
|
git branch -d cliente-acme
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Si Git no te deja borrarla porque detecta cambios sin fusionar, y estás seguro de que quieres eliminarla de todos modos:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
git branch -D cliente-acme
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 🧠 Recomendaciones importantes
|
|
||||||
|
|
||||||
|
## 🧠 Recomendaciones importantes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
✅ Nunca trabajes directamente sobre `main`
|
✅ Nunca trabajes directamente sobre `main`
|
||||||
|
|
||||||
✅ Haz commits pequeños y claros
|
✅ Haz commits pequeños y claros
|
||||||
✅ Usa nombres descriptivos para tus branches
|
|
||||||
✅ Verifica siempre con `git status`
|
✅ 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"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 🚨 Comandos útiles extra
|
|
||||||
|
|
||||||
## Ver historial de commits
|
|
||||||
|
## ❓ ¿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
|
```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
|
git log --oneline
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ver diferencias de archivos
|
|
||||||
|
### Ver diferencias de archivos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
git diff
|
git diff
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Salir del visor de git diff
|
|
||||||
|
### Salir del visor de git diff / git log
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Presiona:
|
Presiona:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|
||||||
q
|
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
|
```text
|
||||||
|
|
||||||
main
|
main
|
||||||
└── nueva-funcionalidad
|
|
||||||
└── commits
|
├── 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
|
└── 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.
|
||||||
@@ -1,17 +1,30 @@
|
|||||||
# 🚀 Subir proyecto local a Gitea (Mac + Tailscale)
|
# 🚀 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
|
```bash
|
||||||
cd /Users/george/descarga_adjuntos_correos_cpe
|
cd /Users/george/descarga_adjuntos_correos_cpe
|
||||||
touch .gitignore
|
touch .gitignore
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. Editar `.gitignore`
|
### 3. Editar `.gitignore`
|
||||||
```bash
|
```bash
|
||||||
nano .gitignore
|
nano .gitignore
|
||||||
```
|
```
|
||||||
|
|
||||||
### Contenido recomendado
|
#### Contenido recomendado
|
||||||
```bash
|
```bash
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
@@ -23,100 +36,131 @@ secrets.yaml
|
|||||||
.idea/
|
.idea/
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. Si ya hiciste `git add` antes del `.gitignore`
|
> ⚠️ ¿Ya habías hecho `git add` antes de crear el `.gitignore`? → [[#Resolución: archivos que debían ignorarse siguen apareciendo]]
|
||||||
```bash
|
|
||||||
git rm -r --cached .
|
|
||||||
git add .
|
|
||||||
git commit -m "aplicar gitignore correctamente"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. Inicializar repositorio Git
|
### 4. Inicializar repositorio Git
|
||||||
```bash
|
```bash
|
||||||
cd /Users/george/descarga_adjuntos_correos_cpe
|
cd /Users/george/descarga_adjuntos_correos_cpe
|
||||||
git init
|
git init
|
||||||
```
|
```
|
||||||
|
|
||||||
## 5. Agregar archivos
|
### 5. Agregar archivos
|
||||||
```bash
|
```bash
|
||||||
git add .
|
git add .
|
||||||
```
|
```
|
||||||
|
|
||||||
## 6. Primer commit
|
> ⚠️ ¿Agregaste errores o archivos incorrectos? → [[#Resolución: quitar archivos del staging (deshacer git add)]]
|
||||||
|
|
||||||
|
### 6. Primer commit
|
||||||
```bash
|
```bash
|
||||||
git commit -m "primer commit"
|
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
|
```bash
|
||||||
git add ProyectoA/
|
git add ProyectoA/
|
||||||
git status
|
git status
|
||||||
git commit -m "mensaje commit para los archivos modificados del proyecto"
|
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
|
```bash
|
||||||
git add ProyectoA/FacturaNegociable.cs
|
git add ProyectoA/FacturaNegociable.cs
|
||||||
git status
|
git status
|
||||||
git commit -m "mensaje commit para el archivo especifico del proyecto"
|
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
|
## PARTE C — FLUJO DIARIO
|
||||||
```bash
|
|
||||||
git reset --soft HEAD~1
|
|
||||||
git reset
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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
|
```bash
|
||||||
git add .
|
git add .
|
||||||
git commit -m "mensaje claro"
|
git commit -m "mensaje claro"
|
||||||
git push
|
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
|
||||||
|
```
|
||||||
@@ -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
|
||||||
|
<!-- Comentario -->
|
||||||
|
```
|
||||||
|
|
||||||
|
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 <PID>
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
|
||||||
|
<key>Label</key>
|
||||||
|
<string>com.george.sap.sunat</string>
|
||||||
|
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/Users/george/services/sap_sunat/.venv/bin/python</string>
|
||||||
|
<string>/Users/george/services/sap_sunat/main.py</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>/Users/george/services/sap_sunat</string>
|
||||||
|
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>/Users/george/services/sap_sunat/logs/stdout.log</string>
|
||||||
|
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>/Users/george/services/sap_sunat/logs/stderr.log</string>
|
||||||
|
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
@@ -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
|
|
||||||
@@ -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.
|
|
||||||
@@ -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.
|
|
||||||
@@ -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 <https://login.tailscale.com/admin/dns>.
|
||||||
|
2. En **HTTPS Certificates**, pulsar **Enable HTTPS**.
|
||||||
|
|
||||||
|
### 1.2 Permitir Funnel en la política de acceso
|
||||||
|
|
||||||
|
1. Entrar a <https://login.tailscale.com/admin/acls>.
|
||||||
|
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 <https://login.tailscale.com/admin/machines> 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 <comando>`
|
||||||
|
|
||||||
|
### 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 <!DOCTYPE html>
|
||||||
|
```
|
||||||
|
|
||||||
|
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/<repo>.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) | <https://unasgeorge.vaquita-hadar.ts.net> |
|
||||||
|
| Repo de ejemplo | <https://unasgeorge.vaquita-hadar.ts.net/george/sap-legacy-webhook-emulator> |
|
||||||
|
| Máquinas Tailscale (etiqueta Funnel) | <https://login.tailscale.com/admin/machines> |
|
||||||
|
| Política de acceso (nodeAttrs funnel) | <https://login.tailscale.com/admin/acls> |
|
||||||
|
| DNS / certificados HTTPS | <https://login.tailscale.com/admin/dns> |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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/<repo>.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/<repo>.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 |
|
||||||
Reference in new issue
Block a user