-
+
-
-
+
+
-
-
-
-
INTERNAL_ACCESS_V2
+
+
+
+
INTERNAL_ACCESS_V2
-
-
- Panel de Administración
-
+
+
Panel de Administración
- Plataforma de gestión de servicios, monitoreo de tickets y administración de usuarios. Acceso restringido únicamente a personal autorizado.
+ Plataforma de gestión de servicios, monitoreo de tickets y administración de usuarios.
+ Acceso restringido únicamente a personal autorizado.
-
- System Status: Operational
+
+ System Status: Operational
-
- 256-bit Encryption Enabled
+
+ 256-bit Encryption Enabled
@@ -106,106 +112,129 @@
-
-
-
-
Iniciar Sesión
-
Acceso al sistema central
-
+
+
+
Iniciar Sesión
+
Acceso al sistema central
+
-
-
-
-
-
Aduanasoft Internal Systems © 2024
-
+
+
+ {#if isLoading}
+
+ Autenticando...
+ {:else}
+ {showTwoFactor ? 'Verificar Token' : 'Entrar al Panel'}
+ {/if}
+
+
+
+
+
+
+
+ Aduanasoft Internal Systems © 2024
+
+
diff --git a/scripts/README-powershell.md b/scripts/README-powershell.md
new file mode 100644
index 0000000..392df30
--- /dev/null
+++ b/scripts/README-powershell.md
@@ -0,0 +1,43 @@
+# Scripts PowerShell en ServiceManagerWeb
+
+## security-test-data.ps1
+- **Propósito:** Genera o limpia datos de prueba para análisis de seguridad.
+- **Uso:**
+ - `. ools\security-test-data.ps1 generar` → Genera datos de prueba.
+ - `. ools\security-test-data.ps1 limpiar` → Limpia los datos de prueba.
+- **Funcionamiento:** Verifica que el contenedor backend esté corriendo y ejecuta el script Python correspondiente dentro del contenedor.
+
+## test_critical_sync.ps1
+- **Propósito:** Verifica la sincronización de incidentes críticos entre Auditoría y Seguridad.
+- **Pasos:**
+ 1. Login como admin y obtiene token.
+ 2. Consulta estadísticas del módulo Auditoría.
+ 3. Consulta estadísticas del módulo Seguridad.
+- **Resultado:** Muestra si los incidentes críticos están sincronizados.
+
+## test_tenant_update.ps1
+- **Propósito:** Prueba el endpoint de actualización de tenants.
+- **Pasos:**
+ 1. Login como admin.
+ 2. Obtiene lista de tenants.
+ 3. Actualiza el tenant (ejemplo: teléfono y status).
+- **Resultado:** Verifica que la actualización funcione correctamente.
+
+## test_manual.ps1
+- **Propósito:** Pruebas manuales de endpoints clave.
+- **Pasos:**
+ 1. Login y obtención de token.
+ 2. Listar categorías.
+ 3. Crear ticket con SLA automático.
+- **Resultado:** Permite validar manualmente el flujo de API.
+
+## test_frontend_integration.ps1
+- **Propósito:** Verifica la integración entre frontend y backend.
+- **Pasos:**
+ 1. Verifica servicios Docker.
+ 2. Login y obtención de token.
+ 3. Verifica tickets con SLA.
+- **Resultado:** Confirma que el frontend puede consumir correctamente el backend.
+
+---
+**Recomendación:** Conserva estos scripts para testing e integración. Documenta cualquier script nuevo siguiendo este formato.
\ No newline at end of file
diff --git a/scripts/README-uso-rapido.md b/scripts/README-uso-rapido.md
new file mode 100644
index 0000000..ed3a1aa
--- /dev/null
+++ b/scripts/README-uso-rapido.md
@@ -0,0 +1,29 @@
+# Guía rápida de scripts esenciales
+
+## 1. setup-dev.sh
+Configura el entorno de desarrollo completo (servicios, dependencias).
+
+## 2. seed_data.py
+Inicializa categorías, sistemas y usuarios demo.
+
+## 3. seed_tickets.py
+Genera tickets de prueba (requiere seed_data.py ejecutado).
+
+## 4. run_tests.sh
+Ejecuta la suite de tests de integración.
+
+## 5. reset_passwords.py
+Resetea contraseñas de usuarios demo para pruebas de login.
+
+## 6. generate_sla_test_data.py
+Crea tickets con diferentes estados de SLA.
+
+## 7. generate_security_test_data.py
+Genera logs de auditoría de prueba.
+
+## 8. check_tenants.py
+Lista y audita los tenants existentes.
+
+---
+
+**Recomendación:** Ejecuta los scripts en este orden para tener un entorno funcional y datos de prueba completos. Elimina los scripts de debugging/manuales si no los necesitas para troubleshooting avanzado.
\ No newline at end of file
diff --git a/scripts/check_relations.py b/scripts/check_relations.py
deleted file mode 100644
index 6c5e636..0000000
--- a/scripts/check_relations.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from app.models.ticket import Ticket
-from app.models import relationships # ensure relationships are loaded
-from sqlalchemy import inspect
-
-mapper = inspect(Ticket)
-print("Relationships:", [r.key for r in mapper.relationships])
-print("Columns:", [c.key for c in mapper.columns])
diff --git a/scripts/check_sla.py b/scripts/check_sla.py
deleted file mode 100644
index babd89a..0000000
--- a/scripts/check_sla.py
+++ /dev/null
@@ -1,40 +0,0 @@
-"""Check SLA state of tickets and categories"""
-import asyncio
-import os
-import sys
-
-sys.path.insert(0, '/app')
-os.chdir('/app')
-
-from sqlalchemy.ext.asyncio import create_async_engine
-from sqlalchemy import text
-
-
-async def run():
- database_url = os.environ.get('DATABASE_URL', 'postgresql+asyncpg://postgres:postgres@db:5432/servicemanager')
- engine = create_async_engine(database_url)
-
- async with engine.connect() as c:
- print("=== CATEGORIES SLA HOURS ===")
- r = await c.execute(text(
- "SELECT name, sla_response_hours, sla_resolution_hours "
- "FROM ticket_categories "
- "ORDER BY name"
- ))
- for row in r.fetchall():
- print(f" {row[0]}: response={row[1]}h, resolution={row[2]}h")
-
- print("\n=== TICKETS SLA DATES ===")
- r2 = await c.execute(text(
- "SELECT ticket_number, category_id, sla_response_due, sla_resolution_due "
- "FROM tickets "
- "ORDER BY created_at "
- "LIMIT 10"
- ))
- for row in r2.fetchall():
- print(f" {row[0]}: cat={str(row[1])[:8] if row[1] else 'None'}, sla_resp={row[2]}, sla_res={row[3]}")
-
- await engine.dispose()
-
-
-asyncio.run(run())
diff --git a/scripts/debug_category.py b/scripts/debug_category.py
deleted file mode 100644
index 4bd5a8e..0000000
--- a/scripts/debug_category.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""Debug: check if ticket's category_id maps to a valid category and what tenant it belongs to"""
-import asyncio
-import os
-import sys
-
-sys.path.insert(0, '/app')
-os.chdir('/app')
-
-from sqlalchemy.ext.asyncio import create_async_engine
-from sqlalchemy import text
-
-
-async def run():
- database_url = os.environ.get('DATABASE_URL', 'postgresql+asyncpg://postgres:postgres@db:5432/servicemanager')
- engine = create_async_engine(database_url)
-
- async with engine.connect() as c:
- # Check tickets and their category names via direct JOIN
- r = await c.execute(text("""
- SELECT t.ticket_number, t.category_id,
- cat.name as category_name, cat.tenant_id as cat_tenant,
- t.tenant_id as ticket_tenant
- FROM tickets t
- LEFT JOIN ticket_categories cat ON cat.id = t.category_id
- WHERE t.category_id IS NOT NULL
- LIMIT 10
- """))
- print("=== TICKET -> CATEGORY JOIN ===")
- for row in r.fetchall():
- match = "✓ SAME TENANT" if row[3] == row[4] else "✗ DIFFERENT TENANT"
- print(f" {row[0]}: cat_id={str(row[1])[:8]}, cat_name={row[2]}, {match}")
-
- # Check what tenant aduanasoft-demo is
- r2 = await c.execute(text("SELECT id, slug FROM tenants WHERE slug='aduanasoft-demo'"))
- tenant = r2.fetchone()
- print(f"\nTenant aduanasoft-demo: {tenant[0] if tenant else 'NOT FOUND'}")
-
- await engine.dispose()
-
-
-asyncio.run(run())
diff --git a/scripts/debug_orm.py b/scripts/debug_orm.py
deleted file mode 100644
index d85af5f..0000000
--- a/scripts/debug_orm.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""Debug: check SQLAlchemy ORM category loading"""
-import asyncio
-import os
-import sys
-
-sys.path.insert(0, '/app')
-os.chdir('/app')
-
-from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
-from sqlalchemy.orm import sessionmaker, selectinload
-from sqlalchemy import select
-from app.models.ticket import Ticket
-from app.models.category import Category
-
-
-async def run():
- database_url = os.environ.get('DATABASE_URL', 'postgresql+asyncpg://postgres:postgres@db:5432/servicemanager')
- engine = create_async_engine(database_url, echo=True)
- async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
-
- async with async_session() as session:
- # Test selectinload
- result = await session.execute(
- select(Ticket)
- .options(selectinload(Ticket.category))
- .where(Ticket.category_id != None)
- .limit(3)
- )
- tickets = result.scalars().all()
-
- print(f"\n=== ORM RESULTS ({len(tickets)} tickets) ===")
- for t in tickets:
- print(f" {t.ticket_number}: category_id={t.category_id}, category={t.category}")
- if t.category:
- print(f" -> category.name={t.category.name}")
- else:
- print(f" -> category is None!")
-
- # Check if Category model can be queried directly
- r2 = await session.execute(select(Category).limit(3))
- cats = r2.scalars().all()
- print(f"\n=== DIRECT CATEGORY QUERY ({len(cats)} categories) ===")
- for c in cats:
- print(f" id={c.id}, name={c.name}")
-
- await engine.dispose()
-
-
-asyncio.run(run())
diff --git a/scripts/reset-fabrica.sh b/scripts/reset-fabrica.sh
new file mode 100644
index 0000000..090d205
--- /dev/null
+++ b/scripts/reset-fabrica.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Script para resetear datos a estado de fábrica (solo datos, no afecta estructura ni funcionalidad)
+
+set -e
+
+echo "🧹 Reseteando datos del sistema..."
+
+# 1. Eliminar datos de tickets, comentarios, logs, auditoría, uploads
+# (Ejemplo: usando comandos SQL directos desde el contenedor)
+docker-compose exec backend psql -U servicemanager -d servicemanager -c "TRUNCATE tickets, ticket_comments, audit_logs, uploads RESTART IDENTITY CASCADE;"
+
+echo "✅ Datos eliminados."
+
+# 2. Volver a poblar datos demo
+
+docker-compose exec backend python scripts/seed_data.py
+docker-compose exec backend python scripts/seed_tickets.py
+docker-compose exec backend python scripts/generate_sla_test_data.py
+docker-compose exec backend python scripts/generate_security_test_data.py
+docker-compose exec backend python scripts/reset_passwords.py
+
+echo "🎉 Sistema restaurado a estado de fábrica demo."