-- =============================================================================
-- Dashboard V2 — catálogo de indicadores
-- Base: asercolg_po (conexión `mysql`) · MariaDB 10.6
-- Ver specs/SPEC_Dashboard_V2.MD §6
-- =============================================================================
--
-- Unifica `graficos_dashboard` + `graficos_kpi` y absorbe la parametrización de
-- `asercol.graficos` (websimex, solo lectura).
--
-- El cambio de fondo respecto a la V1: aquí NO se guarda SQL. Cada fila describe
-- QUÉ medir; el CÓMO vive en las clases de app/Services/Dashboard/Fuentes/.
-- Sin texto SQL en base de datos no hay nada que interpolar (D-01) ni `GROUP BY`
-- que auditar (D-29).
--
-- CLAUDE.md §3: el esquema se administra fuera del repositorio. Este script se
-- aplica a mano; NO se crea migración.
--
-- Es idempotente: se puede volver a correr sin duplicar nada.
--
-- =============================================================================
-- ORDEN DE EJECUCIÓN
-- =============================================================================
--
--   1º  specs/sql/dashboard_v2_catalogo.sql      <- ESTE archivo
--   2º  specs/sql/dashboard_v2_catalogo_ans.sql
--
-- El 2º depende de las tablas que crea el 1º: si se invierte, falla con
-- «Table 'indicadores' doesn't exist» y no escribe nada.
--
-- specs/sql/graficos_dashboard.sql NO SE EJECUTA. Es el volcado de la V1 que
-- sirve de línea base para comparar cifras; ejecutarlo no haría nada útil.
--
-- Ambos se corren sobre la conexión `mysql` (base asercolg_po) con un usuario
-- con permiso de CREATE TABLE. Sólo escriben en las tres tablas nuevas: no tocan
-- `graficos_dashboard`, `graficos_kpi`, `indicadores_kpi` ni ninguna otra.
--
-- =============================================================================
-- `indicadores_kpi` SE COPIA, NO SE MUEVE (decisión M, 2026-09-11)
-- =============================================================================
--
-- Al verificar colisiones de nombre apareció `indicadores_kpi` (26 filas) con
-- `indicadores_kpi_empresas` (14 filas): un catálogo DECLARATIVO de indicadores
-- de tiempo con meta, que ya vive en esta misma base, con CRUD en producción
-- (menú 128 «Def. de KPI») y SIN motor de cálculo que lo consuma.
--
-- Es, en lo esencial, el modelo que propone §6 — y con dos columnas que a §6 le
-- faltaban: `unidad_medida` (DIAS HABILES / DIAS CALENDARIO / HORAS) y
-- `condicion_cumplimiento` (el operador de comparación). Ya están absorbidas.
--
-- El PASO 4 lo copia al catálogo nuevo. NO borra ni modifica una sola fila de
-- `indicadores_kpi` ni de `indicadores_kpi_empresas`: ambas tablas y su CRUD
-- siguen operando igual. `indicadores.id_indicador_kpi` guarda la trazabilidad.
--
-- Consecuencia a vigilar: durante la convivencia el catálogo queda DUPLICADO.
-- Editar un indicador en el menú 128 no se refleja en el Dashboard V2. Mientras
-- la V2 esté en piloto eso es aceptable —las 14 asignaciones existentes son del
-- importador 2656 (YARA), que está inactivo— pero hay que resolverlo antes de
-- que el menú 128 vuelva a usarse en serio.
--
-- =============================================================================
-- PASO 0 — Estado antes (ejecutar y guardar la salida)
-- =============================================================================

SELECT TABLE_NAME, TABLE_ROWS
  FROM information_schema.TABLES
 WHERE TABLE_SCHEMA = DATABASE()
   AND TABLE_NAME IN ('indicadores', 'indicador_visualizacion', 'indicador_asignacion');

-- =============================================================================
-- PASO 1 — Tablas
-- =============================================================================

CREATE TABLE IF NOT EXISTS `indicadores` (
  `id`                  INT(11)      NOT NULL AUTO_INCREMENT,
  `codigo`              VARCHAR(60)  NOT NULL                  COMMENT 'identificador estable en código, ej. imp_tamano_unidad_carga',
  `nombre`              VARCHAR(150) NOT NULL,
  `descripcion`         VARCHAR(255) DEFAULT NULL              COMMENT 'explicación de negocio; en ANS viene de asercol.graficos.descreporte',
  `bloque`              VARCHAR(40)  NOT NULL                  COMMENT 'cabecera|series|participacion|mapa|ans|operativo',
  `regimen`             CHAR(1)      DEFAULT NULL              COMMENT 'I importación, E exportación, NULL ambos',
  `id_proceso_ws`       INT(11)      DEFAULT NULL              COMMENT 'FK lógica a websimex.reportes.procesos.idproceso',
  `fuente`              VARCHAR(20)  NOT NULL                  COMMENT 'operaciones|hitos|geografia',
  `parametros`          LONGTEXT     DEFAULT NULL              COMMENT 'JSON: qué medir (campo de corte, dimensión, hitos). NUNCA SQL',
  `unidad`              VARCHAR(20)  NOT NULL DEFAULT 'operaciones' COMMENT 'operaciones|dias|contenedores|porcentaje',
  `meta_defecto`        DECIMAL(20,2) DEFAULT NULL             COMMENT 'objetivo, expresado en `unidad_medida`',
  `unidad_medida`       VARCHAR(20)  DEFAULT NULL              COMMENT 'DIAS HABILES|DIAS CALENDARIO|HORAS — de indicadores_kpi',
  `condicion_cumplimiento` VARCHAR(10) DEFAULT NULL            COMMENT 'operador contra la meta: <=, >=, = — de indicadores_kpi',
  `umbral_cumplimiento` DECIMAL(5,2) DEFAULT NULL              COMMENT '% mínimo de operaciones en meta para considerar cumplido',
  `id_grafico_v1`       VARCHAR(40)  DEFAULT NULL              COMMENT 'trazabilidad: ids de graficos_dashboard que absorbe',
  `id_grafica_ws`       INT(11)      DEFAULT NULL              COMMENT 'trazabilidad: asercol.graficos.idgrafica',
  `id_indicador_kpi`    INT(11)      DEFAULT NULL              COMMENT 'trazabilidad: indicadores_kpi.id',
  `orden`               INT(11)      NOT NULL DEFAULT 0,
  `estado`              TINYINT(4)   NOT NULL DEFAULT 1,
  `created_at`          TIMESTAMP    NULL DEFAULT NULL,
  `updated_at`          TIMESTAMP    NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_indicadores_codigo` (`codigo`),
  KEY `ix_indicadores_bloque` (`bloque`, `estado`, `orden`),
  KEY `ix_indicadores_proceso` (`id_proceso_ws`, `estado`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Una medición se puede dibujar de más de una forma sin repetir la consulta:
-- es la fusión de los pares column+pie de la V1 expresada en el esquema (§2.3).
CREATE TABLE IF NOT EXISTS `indicador_visualizacion` (
  `id`           INT(11)      NOT NULL AUTO_INCREMENT,
  `id_indicador` INT(11)      NOT NULL,
  `tipo`         VARCHAR(30)  NOT NULL COMMENT 'columna_apilada|barra_participacion|tabla|mapa|tarjeta',
  `titulo`       VARCHAR(200) NOT NULL,
  -- 255 para que quepa `indicadores`.`descripcion` completa: la del indicador
  -- ANS «INICIO-LEVANTE» tiene 207 caracteres.
  `subtitulo`    VARCHAR(255) DEFAULT NULL,
  `titulo_eje`   VARCHAR(200) DEFAULT NULL,
  `ancho`        TINYINT(4)   NOT NULL DEFAULT 1 COMMENT '1 = media fila, 2 = fila completa',
  `orden`        INT(11)      NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `ix_indicador_visualizacion_indicador` (`id_indicador`, `orden`),
  CONSTRAINT `fk_visualizacion_indicador`
    FOREIGN KEY (`id_indicador`) REFERENCES `indicadores` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Trae de graficos_kpi la personalización por grupo empresarial (que
-- graficos_dashboard no tiene) y de asercol.graficos la meta (que
-- graficos_dashboard tampoco tiene).
CREATE TABLE IF NOT EXISTS `indicador_asignacion` (
  `id`                   INT(11)      NOT NULL AUTO_INCREMENT,
  `id_indicador`         INT(11)      NOT NULL,
  `id_grupo_empresarial` INT(11)      DEFAULT NULL COMMENT 'NULL = aplica a todos los clientes',
  `id_importador`        INT(11)      DEFAULT NULL COMMENT 'NULL = todo el grupo. Granularidad de indicadores_kpi_empresas',
  `ids_terceros`         VARCHAR(255) DEFAULT NULL COMMENT 'CSV de terceros a los que aplica — de indicadores_kpi_empresas',
  `meta_override`        DECIMAL(20,2) DEFAULT NULL COMMENT 'NULL = usa indicadores.meta_defecto',
  `umbral_override`      DECIMAL(5,2) DEFAULT NULL COMMENT 'NULL = usa indicadores.umbral_cumplimiento',
  `orden`                INT(11)      NOT NULL DEFAULT 0,
  `estado`               TINYINT(4)   NOT NULL DEFAULT 1,
  `created_at`           TIMESTAMP    NULL DEFAULT NULL,
  `updated_at`           TIMESTAMP    NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_asignacion_indicador_destino` (`id_indicador`, `id_grupo_empresarial`, `id_importador`),
  KEY `ix_asignacion_grupo` (`id_grupo_empresarial`, `estado`),
  KEY `ix_asignacion_importador` (`id_importador`, `estado`),
  CONSTRAINT `fk_asignacion_indicador`
    FOREIGN KEY (`id_indicador`) REFERENCES `indicadores` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- -----------------------------------------------------------------------------
-- PASO 1b — Ajuste para instalaciones que ya corrieron una versión anterior
-- -----------------------------------------------------------------------------
--
-- `CREATE TABLE IF NOT EXISTS` no modifica una tabla que ya existe, así que esta
-- línea es la que lleva `subtitulo` de 200 a 255 donde el script se aplicó antes
-- de la corrección. Ensanchar una columna nunca pierde datos y se puede repetir.

ALTER TABLE `indicador_visualizacion`
  MODIFY COLUMN `subtitulo` VARCHAR(255) DEFAULT NULL;

-- =============================================================================
-- PASO 2 — Carga inicial · bloques de volumen (traducción de graficos_dashboard)
-- =============================================================================
--
-- 21 gráficos activos de la V1 se convierten en 13 indicadores: ocho de ellos
-- eran cuatro mediciones dibujadas dos veces (barras de volumen mensual + dona de
-- participación anual). El diseño las resuelve en una sola tarjeta con leyenda,
-- así que el agregado anual se suma en PHP desde la serie mensual. Ver §2.3.
--
-- `parametros` queda NULL a propósito: se llena en la Etapa 1, junto con la clase
-- Fuentes/FuenteOperaciones que lo consume. Fijar el contrato JSON antes de
-- escribir su único consumidor sería adivinar. La identidad, la fusión y el orden
-- de presentación —que es lo que hay que revisar ahora— sí quedan definidos.

INSERT INTO `indicadores`
  (`codigo`, `nombre`, `descripcion`, `bloque`, `regimen`, `fuente`, `unidad`, `id_grafico_v1`, `orden`, `estado`, `created_at`, `updated_at`)
VALUES
  ('imp_modo_transporte',     'Importaciones',                    'Operaciones de importación con levante, desglosadas por medio de transporte', 'cabecera',     'I', 'operaciones', 'operaciones',   '1,2',   10, 1, NOW(), NOW()),
  ('exp_modo_transporte',     'Exportaciones',                    'Operaciones de exportación zarpadas, desglosadas por medio de transporte',    'cabecera',     'E', 'operaciones', 'operaciones',   '8',     20, 1, NOW(), NOW()),
  ('imp_tamano_unidad_carga', 'Tamaño de unidad de carga',        'Unidades de carga arribadas con levante',                                     'series',       'I', 'operaciones', 'contenedores',  '3,4',   30, 1, NOW(), NOW()),
  ('imp_tipos_carga',         'Tipos de carga marítima',          'Contenedorizada, suelta y granel',                                            'series',       'I', 'operaciones', 'operaciones',   '9,10',  40, 1, NOW(), NOW()),
  ('imp_tipos_declaracion',   'Tipos de declaración',             'Declaraciones de importación anticipadas e iniciales',                        'series',       'I', 'operaciones', 'operaciones',   '11,14', 50, 1, NOW(), NOW()),
  ('imp_selectividad',        'Tipo de selectividad',             'Declaraciones por resultado de selectividad',                                 'series',       'I', 'operaciones', 'operaciones',   '49,50', 60, 1, NOW(), NOW()),
  ('imp_agentes_transporte',  'Agentes transportadores',          'Participación por número de contenedores',                                    'participacion','I', 'operaciones', 'contenedores',  '36',    70, 1, NOW(), NOW()),
  ('imp_aduanas',             'Aduanas de nacionalización',       'Operaciones por aduana donde se nacionaliza',                                 'participacion','I', 'operaciones', 'operaciones',   '16,17', 80, 1, NOW(), NOW()),
  ('imp_pais_origen',         'Importaciones por país de origen', 'Países origen de las importaciones',                                          'mapa',         'I', 'geografia',   'operaciones',   '38',    90, 1, NOW(), NOW()),
  ('exp_tamano_unidad_carga', 'Tamaño de unidad de carga',        'Unidades de carga zarpadas',                                                  'series',       'E', 'operaciones', 'contenedores',  '12,13', 100, 1, NOW(), NOW()),
  ('exp_navieras',            'Líneas navieras',                  'Participación por número de contenedores',                                    'participacion','E', 'operaciones', 'contenedores',  '35',    110, 1, NOW(), NOW()),
  ('exp_aduanas',             'Aduanas de exportación',           'Operaciones por sucursal comercial',                                          'participacion','E', 'operaciones', 'operaciones',   '5,6',   120, 1, NOW(), NOW()),
  ('exp_pais_destino',        'Exportaciones por país destinatario', 'Países a los que se ha exportado',                                         'mapa',         'E', 'geografia',   'operaciones',   '7',     130, 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE
  `nombre`      = VALUES(`nombre`),
  `descripcion` = VALUES(`descripcion`),
  `bloque`      = VALUES(`bloque`),
  `orden`       = VALUES(`orden`),
  `updated_at`  = NOW();

-- Gráficos de la V1 que NO se migran, y por qué:
--   26, 27, 28, 37  -> `estado = 0` desde antes de la V2. Si el negocio los
--                      quiere de vuelta se replantean sobre MovimientoDo y
--                      DiasDevolucionContenedor (Dashboard.MD §11.5).
--   "Tipos de carga · exportación" del diseño NO existe en la V1: no hay gemelo
--                      expo del gráfico 9. Pendiente de decisión (§12 · P4).

-- =============================================================================
-- PASO 3 — Visualizaciones de los bloques de volumen
-- =============================================================================

INSERT INTO `indicador_visualizacion` (`id_indicador`, `tipo`, `titulo`, `subtitulo`, `ancho`, `orden`)
SELECT i.`id`, v.`tipo`, v.`titulo`, v.`subtitulo`, v.`ancho`, v.`orden`
  FROM (
    SELECT 'imp_modo_transporte'     AS codigo, 'tarjeta'             AS tipo, 'Importaciones'                       AS titulo, 'Operaciones con levante en el periodo'   AS subtitulo, 1 AS ancho, 10 AS orden UNION ALL
    SELECT 'exp_modo_transporte',           'tarjeta',             'Exportaciones',                       'Operaciones zarpadas en el periodo',      1, 20 UNION ALL
    SELECT 'imp_tamano_unidad_carga',       'columna_apilada',     'Tamaño de unidad de carga',           'Unidades de carga arribadas con levante', 1, 30 UNION ALL
    SELECT 'imp_tipos_carga',               'columna_apilada',     'Tipos de carga marítima',             'Contenedorizada, suelta y granel',        1, 40 UNION ALL
    SELECT 'imp_tipos_declaracion',         'columna_apilada',     'Tipos de declaración',                'Volumen mensual · participación anual',   1, 50 UNION ALL
    SELECT 'imp_selectividad',              'columna_apilada',     'Tipo de selectividad',                'Declaraciones por resultado',             1, 60 UNION ALL
    SELECT 'imp_agentes_transporte',        'barra_participacion', 'Agentes transportadores · importación', 'Participación por número de contenedores', 1, 70 UNION ALL
    SELECT 'imp_aduanas',                   'tabla',               'Aduanas de nacionalización',          'Operaciones por mes · participación anual', 1, 80 UNION ALL
    SELECT 'imp_pais_origen',               'mapa',                'Importaciones por país de origen',    NULL,                                      1, 90 UNION ALL
    SELECT 'exp_tamano_unidad_carga',       'columna_apilada',     'Tamaño de unidad de carga',           'Unidades de carga zarpadas',              1, 100 UNION ALL
    SELECT 'exp_navieras',                  'barra_participacion', 'Líneas navieras · exportación',       'Participación por número de contenedores', 1, 110 UNION ALL
    SELECT 'exp_aduanas',                   'tabla',               'Aduanas de exportación',              'Operaciones por sucursal comercial',      1, 120 UNION ALL
    SELECT 'exp_pais_destino',              'mapa',                'Exportaciones por país destinatario', NULL,                                      1, 130
  ) v
  JOIN `indicadores` i ON i.`codigo` = v.`codigo`
  LEFT JOIN `indicador_visualizacion` iv ON iv.`id_indicador` = i.`id`
 WHERE iv.`id` IS NULL;

-- =============================================================================
-- PASO 4 — Copia de `indicadores_kpi` al catálogo nuevo (decisión M)
-- =============================================================================
--
-- SOLO LECTURA sobre `indicadores_kpi` e `indicadores_kpi_empresas`. Nada se
-- borra ni se modifica allí: la operación actual del sistema no se toca.
--
-- 11 de los 26 indicadores no tienen `etapa_inicial` y `etapa_final`: no se
-- pueden calcular por hitos. Entran con `fuente = 'pendiente'` para que el motor
-- los ignore y queden visibles como trabajo por definir, en vez de aparecer
-- siempre en cero.

INSERT INTO `indicadores`
  (`codigo`, `nombre`, `descripcion`, `bloque`, `regimen`, `fuente`, `parametros`,
   `unidad`, `meta_defecto`, `unidad_medida`, `condicion_cumplimiento`, `umbral_cumplimiento`,
   `id_indicador_kpi`, `orden`, `estado`, `created_at`, `updated_at`)
SELECT
  CONCAT('kpi_', k.`id`),
  k.`nombre`,
  LEFT(COALESCE(k.`explicacion`, ''), 255),
  'ans',
  NULLIF(k.`proceso`, ''),
  CASE WHEN COALESCE(k.`etapa_inicial`, '') <> '' AND COALESCE(k.`etapa_final`, '') <> ''
       THEN 'hitos' ELSE 'pendiente' END,
  CONCAT('{"actividad_inicial":',
         CASE WHEN COALESCE(k.`etapa_inicial`, '') = '' THEN '[]'
              ELSE CONCAT('["', k.`etapa_inicial`, '"]') END,
         ',"actividad_final":',
         CASE WHEN COALESCE(k.`etapa_final`, '') = '' THEN '[]'
              ELSE CONCAT('["', k.`etapa_final`, '"]') END,
         ',"tipo_kpi":"', COALESCE(k.`tipo`, ''), '"',
         ',"abreviacion":"', COALESCE(k.`abreviacion`, ''), '"',
         ',"excluir_interrupciones":true}'),
  'dias',
  k.`meta`,
  k.`unidad_medida`,
  COALESCE(NULLIF(k.`condicion_cumplimiento`, ''), '<='),
  90,
  k.`id`,
  1000 + k.`id`,
  k.`estado`,
  NOW(), NOW()
FROM `indicadores_kpi` k
ON DUPLICATE KEY UPDATE
  `nombre`                 = VALUES(`nombre`),
  `descripcion`            = VALUES(`descripcion`),
  `parametros`             = VALUES(`parametros`),
  `meta_defecto`           = VALUES(`meta_defecto`),
  `unidad_medida`          = VALUES(`unidad_medida`),
  `condicion_cumplimiento` = VALUES(`condicion_cumplimiento`),
  `updated_at`             = NOW();

-- Asignaciones por importador. `indicadores_kpi_empresas` asigna a ID_IMPORTADOR,
-- no a grupo empresarial: por eso `id_grupo_empresarial` queda NULL.
--
-- Va con NOT EXISTS y NO con ON DUPLICATE KEY: en MariaDB los NULL no colisionan
-- en un índice único, así que `uk_asignacion_indicador_destino` no protege
-- mientras `id_grupo_empresarial` sea NULL, y una segunda corrida duplicaría.
INSERT INTO `indicador_asignacion`
  (`id_indicador`, `id_grupo_empresarial`, `id_importador`, `ids_terceros`, `orden`, `estado`, `created_at`, `updated_at`)
SELECT i.`id`, NULL, e.`id_importador`, NULLIF(e.`ids_terceros`, ''), 0, e.`estado`, NOW(), NOW()
  FROM `indicadores_kpi_empresas` e
  JOIN `indicadores` i ON i.`id_indicador_kpi` = e.`id_indicador_kpi`
 WHERE NOT EXISTS (
       SELECT 1 FROM `indicador_asignacion` a
        WHERE a.`id_indicador`  = i.`id`
          AND a.`id_importador` = e.`id_importador`
          AND a.`id_grupo_empresarial` IS NULL
 );

-- Visualización de los indicadores copiados.
INSERT INTO `indicador_visualizacion` (`id_indicador`, `tipo`, `titulo`, `subtitulo`, `ancho`, `orden`)
SELECT i.`id`, 'tabla', i.`nombre`, i.`descripcion`, 1, i.`orden`
  FROM `indicadores` i
  LEFT JOIN `indicador_visualizacion` v ON v.`id_indicador` = i.`id`
 WHERE i.`id_indicador_kpi` IS NOT NULL AND v.`id` IS NULL;

-- =============================================================================
-- PASO 5 — Carga inicial · bloque ANS
-- =============================================================================
--
-- Los 52 indicadores activos de `asercol.graficos` (websimex). Se copian en vez
-- de leerse en vivo porque están en otro servidor y porque la V2 necesita poder
-- añadirles umbral y asignación por cliente, cosa que el ERP no soporta.
--
-- `meta_defecto` va en DÍAS HÁBILES de 8 horas laborales (decisión N). El cálculo
-- lo hace App\Support\CalendarioLaboral con los festivos de websimex.dias_festivos.
--
-- `umbral_cumplimiento` se carga en 90 para todos, a la espera de la decisión del
-- negocio (§12 · P3). `asercol.graficos` no tiene esa columna.
--
-- Las sentencias van en el archivo adjunto, generado desde el ERP:
--   specs/sql/dashboard_v2_catalogo_ans.sql
--
-- Se aplica DESPUÉS de este script, porque depende de las tablas de arriba.

-- =============================================================================
-- PASO 6 — Verificación
-- =============================================================================

SELECT `bloque`, COUNT(*) AS indicadores
  FROM `indicadores`
 WHERE `estado` = 1
 GROUP BY `bloque`
 ORDER BY `bloque`;

-- Esperado tras aplicar este script y el de ANS:
--   ans            78   (52 de asercol.graficos + 26 de indicadores_kpi)
--   cabecera        2
--   mapa            2
--   participacion   4
--   series          5
--                  --
--                  91
--
-- De los 78 del bloque ANS, 11 entran con `fuente = 'pendiente'` por no tener
-- etapa inicial y final. Comprobarlo:
--
--   SELECT `fuente`, COUNT(*) FROM `indicadores` WHERE `bloque`='ans' GROUP BY `fuente`;

SELECT i.`codigo`, i.`bloque`, COUNT(v.`id`) AS visualizaciones
  FROM `indicadores` i
  LEFT JOIN `indicador_visualizacion` v ON v.`id_indicador` = i.`id`
 WHERE i.`estado` = 1 AND i.`bloque` <> 'ans'
 GROUP BY i.`codigo`, i.`bloque`
HAVING visualizaciones = 0;

-- Esperado: 0 filas. Todo indicador de volumen debe tener su visualización.
