Saltar a contenido

Autor: Adalberto González

Fecha creacion: 2026-04-20
Estado: desarrollo
Tipo: vista

Vista: Portafolio

Selector: app-portafolio
Ubicación: src/app/views/tienda/portafolio
Acceso: Autenticado | Rol: Todos (eliminación restringida a CEO y Desarrollador)


¿Qué hace?

Catálogo de gestión de productos de la tienda. Permite al usuario listar, buscar, filtrar por texto, tienda, categoría, proveedor, tipo y estado; crear productos individuales o en lote, editar y eliminar. Muestra estadísticas de inventario en tiempo real.


Ruta

Ruta Guard Parámetros de URL
/tienda/portafolio AuthGuard

Decoradores (eliminar si no tiene)

Decorador Nombre Tipo Descripción
@HostListener document:click Cierra todos los menús desplegables de los filtros al hacer clic fuera de ellos.

Propiedades clave

Propiedad Tipo Descripción
productos Producto[] Lista completa cargada desde el backend.
filteredProducts Producto[] Lista resultado de aplicar todos los filtros activos.
selectedEstadoFiltro string Estado activo en los tabs (Activo, Inactivo o vacío para Todos).
isCreProdModalOpen boolean Visibilidad del modal de creación individual.
isCreProdMasiModalOpen boolean Visibilidad del modal de carga masiva.
modalActualizarAbierto boolean Visibilidad del modal de edición.
productoParaEditar Producto \| null Producto seleccionado para editar.
rolesUsuario string[] Roles del usuario leídos de sessionStorage → roles_asignados.
buscarTienda / buscarCategoria / buscarProveedor string Texto del buscador en cada dropdown de filtro.
tiendasFiltradas / categoriasFiltradas / proveedoresFiltrados any[] Opciones filtradas para cada dropdown searchable.

Servicios y endpoints

Servicio Método Endpoint Cuándo
ConsumoGenericoService consultarGenerico() GET metodoGenerico?coleccion=Productos&Tienda={tiendas} Al inicializar y tras crear/editar/eliminar
ConsumoGenericoService eliminarGenerico() DELETE metodoGenerico?coleccion=Productos&_id={_id} Al eliminar un producto
DecompressionService decompressGzip() Descomprime la respuesta del backend
GetObjectService obtenerObjeto() S3 imagenes-productos-logigho Al generar el catálogo PDF

Flujo principal

ngOnInit()
  → Lee roles_asignados de sessionStorage
  → fetchTableData()
      → Lee tiendas_asignadas de sessionStorage
      → GET metodoGenerico?coleccion=Productos&Tienda=...
      → decompressGzip(data.Resultado)
      → this.productos = resultado
      → this.filteredProducts = [...this.productos]
  → Construye dropdowns de tienda, categoría y proveedor (valores únicos de productos)

── Filtros ──
aplicarFiltros()
  → combina: searchTerm + tienda + categoría + proveedor + tipo + estado
  → filteredProducts = resultado
  → currentPage = 1

── Creación individual ──
openCreProdModal() → isCreProdModalOpen = true
onProductoCreado() → fetchTableData() + reconstruye dropdowns

── Carga masiva ──
openCreProdMasiModal() → isCreProdMasiModalOpen = true
onProductoCreadoMasivo() → fetchTableData() + reconstruye dropdowns

── Edición ──
abrirModalActualizar(producto) → productoParaEditar = producto, modalActualizarAbierto = true
despuesDeActualizar() → fetchTableData() + resetearFiltros()

── Eliminación ──
eliminarProducto(producto)
  → verifica rol CEO / Desarrollador
  → Swal confirmación
  → eliminarGenerico(_id)
  → fetchTableData() + reconstruye dropdowns + resetearFiltros()

Historial de cambios

Fecha Autor Cambio
2026-04-20 Adalberto González Corrección race condition en generación de IDs al crear productos en lote.
2026-04-20 Adalberto González fetchTableData() refrescada al inicio de cada submit para reducir ventana de colisión.
2026-04-20 Adalberto González Adición de onProductoCreado() para refrescar tabla y dropdowns tras creación exitosa.
2026-04-20 Adalberto González .trim() en nombre de tienda al crear productos para evitar inconsistencias de filtro.
2026-05-20 Adalberto González Integración del modal de carga masiva (app-creaciones-masiva-productos) con stepper de 3 pasos.
2026-05-20 Adalberto González Patrón Template Method en portafolio/importacion-template-method/: ImportacionMasivaBase y ProductoImportacionValidator.
2026-05-20 Adalberto González Validación de columnas del Excel antes de procesar filas; error descriptivo con columnas faltantes.
2026-05-20 Adalberto González Columna NombreCategoria en Excel: el usuario elige por nombre, el sistema resuelve al ID internamente.
2026-05-20 Adalberto González Regla 1 activa: precioventa > precioproveedor. Regla 2 activa: IdTienda en tiendas asignadas al usuario.
2026-05-20 Adalberto González Race condition en IDs corregida: id e idproducto se recalculan con datos frescos de la BD antes de insertar cada producto.
2026-05-20 Adalberto González Reemplazo de ngx-select-dropdown por searchable dropdowns propios en la barra de filtros.
2026-05-20 Adalberto González Filtro por estado (Activo / Inactivo) con tabs visuales y contadores en la barra de filtros.
2026-05-20 Adalberto González Reset visual automático de los tres searchable dropdowns al crear, actualizar o eliminar (resetearFiltros()).
2026-05-20 Adalberto González Cierre de los tres modales (creación, edición, masivo) al hacer clic fuera del contenido.
2026-05-20 Adalberto González Bloqueo del botón "Actualizar" si no hay cambios — snapshot JSON.stringify con getter haycambios.
2026-05-20 Adalberto González Botón "Limpiar archivo" en modal masivo: permite reiniciar el paso 1 para corregir el Excel y volver a subir.

Observaciones

  • Inconsistencia de conteo: Productos con Tienda con espacios extra ("Nombre tienda ") no son retornados por el filtro exacto del backend. El .trim() al crear previene nuevos casos, pero los registros existentes requieren migración en el backend.
  • Race condition de IDs (mitigada en frontend): La reconsulta a la BD antes de cada inserción reduce la ventana de colisión, pero la solución definitiva es que el backend genere y garantice los IDs atómicamente.
  • Template Method en portafolio/importacion-template-method/: Para agregar una nueva regla de negocio, editar solo validarNegocio() en ProductoImportacionValidator. Ver ADR-001-template-method-importacion-masiva.md.