feat: Funcion de sistema tenants
This commit is contained in:
238
scripts/seed_data.py
Normal file
238
scripts/seed_data.py
Normal file
@@ -0,0 +1,238 @@
|
||||
"""
|
||||
Script de datos iniciales (seed) para ServiceManagerWeb.
|
||||
Crea categorías, sistemas, y usuarios de prueba en el tenant aduanasoft-demo.
|
||||
Ejecutar desde dentro del contenedor: python /scripts/seed_data.py
|
||||
"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy import select
|
||||
|
||||
# Configurar path para importar el app
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.core.config import get_settings
|
||||
|
||||
settings = get_settings()
|
||||
from app.core.security import security
|
||||
from app.models.tenant import Tenant
|
||||
from app.models.category import Category
|
||||
from app.models.system import System
|
||||
from app.models.user import User, UserRole
|
||||
|
||||
TENANT_SLUG = "aduanasoft-demo"
|
||||
|
||||
CATEGORIES = [
|
||||
{
|
||||
"name": "Soporte Técnico",
|
||||
"description": "Problemas técnicos con sistemas y aplicaciones empresariales",
|
||||
"color": "#EF4444",
|
||||
"sla_response_hours": 2,
|
||||
"sla_resolution_hours": 24,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Facturación",
|
||||
"description": "Consultas y problemas relacionados con facturación y pagos",
|
||||
"color": "#F59E0B",
|
||||
"sla_response_hours": 4,
|
||||
"sla_resolution_hours": 48,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Incidentes Críticos",
|
||||
"description": "Fallas graves que afectan la operación del negocio",
|
||||
"color": "#DC2626",
|
||||
"sla_response_hours": 1,
|
||||
"sla_resolution_hours": 8,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Consultas Generales",
|
||||
"description": "Preguntas generales sobre productos y servicios",
|
||||
"color": "#3B82F6",
|
||||
"sla_response_hours": 8,
|
||||
"sla_resolution_hours": 72,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Capacitación",
|
||||
"description": "Solicitudes de entrenamiento y capacitación en sistemas",
|
||||
"color": "#8B5CF6",
|
||||
"sla_response_hours": 24,
|
||||
"sla_resolution_hours": 96,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Infraestructura",
|
||||
"description": "Problemas de red, servidores y componentes de infraestructura",
|
||||
"color": "#06B6D4",
|
||||
"sla_response_hours": 2,
|
||||
"sla_resolution_hours": 16,
|
||||
"is_active": True,
|
||||
},
|
||||
]
|
||||
|
||||
SYSTEMS = [
|
||||
{
|
||||
"name": "ERP Aduanero",
|
||||
"description": "Sistema principal de gestión aduanera y comercio exterior",
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Portal Web",
|
||||
"description": "Portal de autogestión y consultas en línea para clientes",
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Gestión Documental",
|
||||
"description": "Sistema de administración y archivo de documentos aduaneros",
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "App Móvil",
|
||||
"description": "Aplicación móvil para seguimiento de trámites en tiempo real",
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"name": "Reportes y BI",
|
||||
"description": "Plataforma de inteligencia de negocio y generación de reportes",
|
||||
"is_active": True,
|
||||
},
|
||||
]
|
||||
|
||||
USERS = [
|
||||
{
|
||||
"email": "agente@aduanasoft.com",
|
||||
"password": "agente123",
|
||||
"first_name": "Carlos",
|
||||
"last_name": "Agente",
|
||||
"role": UserRole.AGENT,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"email": "manager@aduanasoft.com",
|
||||
"password": "manager123",
|
||||
"first_name": "Laura",
|
||||
"last_name": "Gerente",
|
||||
"role": UserRole.SUPPORT_MANAGER,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"email": "cliente@empresa-demo.com",
|
||||
"password": "cliente123",
|
||||
"first_name": "Roberto",
|
||||
"last_name": "Cliente",
|
||||
"role": UserRole.CLIENT_USER,
|
||||
"is_active": True,
|
||||
},
|
||||
{
|
||||
"email": "admin-cliente@empresa-demo.com",
|
||||
"password": "clienteadmin123",
|
||||
"first_name": "Ana",
|
||||
"last_name": "Admin",
|
||||
"role": UserRole.CLIENT_ADMIN,
|
||||
"is_active": True,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
engine = create_async_engine(settings.DATABASE_URL, echo=False)
|
||||
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
async with async_session() as session:
|
||||
# 1. Obtener tenant
|
||||
result = await session.execute(
|
||||
select(Tenant).where(Tenant.slug == TENANT_SLUG)
|
||||
)
|
||||
tenant = result.scalar_one_or_none()
|
||||
|
||||
if not tenant:
|
||||
print(f"ERROR: Tenant '{TENANT_SLUG}' no encontrado. Ejecuta el seed de tenants primero.")
|
||||
return
|
||||
|
||||
tenant_id = tenant.id
|
||||
print(f"✅ Tenant: {tenant.name} (id={str(tenant_id)[:8]}...)")
|
||||
|
||||
# 2. Categorías
|
||||
print("\n📁 Creando categorías:")
|
||||
# Eliminar la categoría "Infraestructura" duplicada creada previamente si existe
|
||||
existing_cats = (await session.execute(
|
||||
select(Category).where(Category.tenant_id == tenant_id)
|
||||
)).scalars().all()
|
||||
existing_names = {c.name for c in existing_cats}
|
||||
|
||||
created = 0
|
||||
for cat_data in CATEGORIES:
|
||||
if cat_data["name"] in existing_names:
|
||||
print(f" ⏭ Ya existe: {cat_data['name']}")
|
||||
continue
|
||||
cat = Category(
|
||||
tenant_id=tenant_id,
|
||||
**cat_data,
|
||||
)
|
||||
session.add(cat)
|
||||
print(f" ✓ {cat_data['name']} (resp={cat_data['sla_response_hours']}h, resol={cat_data['sla_resolution_hours']}h)")
|
||||
created += 1
|
||||
|
||||
await session.flush()
|
||||
print(f" → {created} categorías creadas, {len(existing_names)} ya existían")
|
||||
|
||||
# 3. Sistemas
|
||||
print("\n🖥 Creando sistemas:")
|
||||
existing_sys = (await session.execute(
|
||||
select(System).where(System.tenant_id == tenant_id)
|
||||
)).scalars().all()
|
||||
existing_sys_names = {s.name for s in existing_sys}
|
||||
|
||||
created_sys = 0
|
||||
for sys_data in SYSTEMS:
|
||||
if sys_data["name"] in existing_sys_names:
|
||||
print(f" ⏭ Ya existe: {sys_data['name']}")
|
||||
continue
|
||||
sys_obj = System(
|
||||
tenant_id=tenant_id,
|
||||
**sys_data,
|
||||
)
|
||||
session.add(sys_obj)
|
||||
print(f" ✓ {sys_data['name']}")
|
||||
created_sys += 1
|
||||
|
||||
await session.flush()
|
||||
print(f" → {created_sys} sistemas creados")
|
||||
|
||||
# 4. Usuarios
|
||||
print("\n👤 Creando usuarios:")
|
||||
existing_users = (await session.execute(
|
||||
select(User).where(User.tenant_id == tenant_id)
|
||||
)).scalars().all()
|
||||
existing_emails = {u.email for u in existing_users}
|
||||
|
||||
created_users = 0
|
||||
for user_data in USERS:
|
||||
if user_data["email"] in existing_emails:
|
||||
print(f" ⏭ Ya existe: {user_data['email']}")
|
||||
continue
|
||||
pwd = user_data.pop("password")
|
||||
hashed_pwd = security.hash_password(pwd)
|
||||
user = User(
|
||||
tenant_id=tenant_id,
|
||||
password_hash=hashed_pwd,
|
||||
**user_data,
|
||||
)
|
||||
session.add(user)
|
||||
print(f" ✓ {user_data['email']} [{user_data['role'].value}] pwd={pwd}")
|
||||
created_users += 1
|
||||
|
||||
await session.commit()
|
||||
print(f" → {created_users} usuarios creados")
|
||||
|
||||
await engine.dispose()
|
||||
print("\n🎉 Seed completado exitosamente.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user