/* ============================================================================ MarmotechBI — Vistas para el Dashboard Ejecutivo de Presidencia ---------------------------------------------------------------------------- Autor : Juan F. Soto (jsoto) Fecha : 2026-08-26 Servidor : 192.168.40.8 (SQL Server 2016) Base : MarmotechBI (capa semantica; los datos viven en marmotech.dbo.*) Objetivo : Radiografia financiera para el Presidente, a partir del Mayor General Analitico (cgprrp008) y el Analisis de Gastos por Departamento (cgprrp009). Fuente de datos: marmotech.dbo.cgtb00004 = transacciones contables (debito/credito por cuenta/fecha) marmotech.dbo.cgtb00001 = catalogo de cuentas (nivel, descripcion) marmotech.dbo.prdtable = periodos contables (ano, mes -> rango de fechas) marmotech.dbo.mestable = nombres de meses marmotech.dbo.adtb00001 = departamentos (nom_dpto) Reglas de negocio (validadas contra cgprrp008 / cgprrp009): * Estado de Resultados por PRIMER DIGITO de la cuenta: 4 = VENTAS NETA (naturaleza credito) 5 = COSTO DE VENTAS (naturaleza debito) 7 = GASTOS (naturaleza debito) 8 = OTROS INGRESOS Y GASTOS (incluye 88 = IMPUESTO S/RENTA) * resultado (aporte a la utilidad) = credito - debito -> Ventas suma positivo; Costo/Gastos/ISR restan; la suma de todas las lineas = Utilidad Neta del periodo. * Solo transacciones activas: status_t IS NULL. * Se EXCLUYE el asiento de cierre anual (ref 'ED.99-001/12YY' y 'ED.99-002/12YY'); de lo contrario cada ano cerrado netearia a 0 porque el cierre revierte las cuentas de resultado contra Utilidades Retenidas. (2026 aun no tiene cierre, por eso muestra saldo operativo real.) Seguridad (requisito): estas vistas solo deben ser legibles por jsoto. Se crean en el esquema [presidencia] y se hace DENY SELECT a [public]. jsoto (MARMOTECH\jsoto y login SQL jsoto) es sysadmin/db_owner, por lo que ignora el DENY y conserva acceso; el resto del equipo (db_datareader) queda bloqueado a nivel de esquema. ============================================================================ */ USE MarmotechBI; GO /* ---- 1. Esquema dedicado ------------------------------------------------- */ IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = 'presidencia') EXEC('CREATE SCHEMA presidencia AUTHORIZATION dbo;'); GO /* ---- 2. Estado de Resultados mensual (cgprrp008) ------------------------- */ /* Grano: ano x mes x cuenta. Un renglon por cuenta contable de resultado. */ IF OBJECT_ID('presidencia.vwPLMensual','V') IS NOT NULL DROP VIEW presidencia.vwPLMensual; GO CREATE VIEW presidencia.vwPLMensual AS WITH mov AS ( SELECT p.ano, p.mes AS numero_mes, b.cuenta_no, SUM(b.debito) AS debito, SUM(b.credito) AS credito FROM marmotech.dbo.cgtb00004 b INNER JOIN marmotech.dbo.prdtable p ON b.fecha BETWEEN p.fecha_inicio AND p.fecha_corte WHERE b.status_t IS NULL AND LEFT(b.cuenta_no,1) IN ('4','5','7','8') AND b.ref NOT LIKE 'ED.99-001/12%' -- asiento de cierre anual AND b.ref NOT LIKE 'ED.99-002/12%' -- asiento de cierre anual (variante) GROUP BY p.ano, p.mes, b.cuenta_no ) SELECT m.ano, m.numero_mes, ms.descrip AS mes, RIGHT('0000'+CONVERT(varchar(4),m.ano),4) + '-' + RIGHT('00'+CONVERT(varchar(2),m.numero_mes),2) AS AnoMes, DATEFROMPARTS(m.ano, m.numero_mes, 1) AS fecha_mes, LEFT(m.cuenta_no,1) AS grupo, CASE LEFT(m.cuenta_no,1) WHEN '4' THEN 1 WHEN '5' THEN 2 WHEN '7' THEN 3 WHEN '8' THEN CASE WHEN m.cuenta_no LIKE '88%' THEN 5 ELSE 4 END END AS orden_linea, CASE LEFT(m.cuenta_no,1) WHEN '4' THEN 'Ventas Netas' WHEN '5' THEN 'Costo de Ventas' WHEN '7' THEN 'Gastos Operativos' WHEN '8' THEN CASE WHEN m.cuenta_no LIKE '88%' THEN 'Impuesto sobre la Renta' ELSE 'Otros Ingresos y Gastos' END END AS linea, LEFT(m.cuenta_no,2) AS subgrupo_cod, sg.descripcion AS subgrupo_desc, m.cuenta_no AS cuenta, ct.descripcion AS cuenta_desc, ct.nivel, m.debito, m.credito, CAST(m.credito - m.debito AS decimal(19,2)) AS resultado, -- + = aporta utilidad CAST(m.debito - m.credito AS decimal(19,2)) AS costo_gasto -- + = costo/gasto FROM mov m LEFT JOIN marmotech.dbo.cgtb00001 ct ON ct.cuenta_no = m.cuenta_no LEFT JOIN marmotech.dbo.cgtb00001 sg ON sg.cuenta_no = LEFT(m.cuenta_no,2) LEFT JOIN marmotech.dbo.mestable ms ON ms.mes = m.numero_mes; GO /* ---- 3. Analisis de Gastos por Departamento (cgprrp009) ------------------ */ /* Grano: ano x mes x departamento x cuenta. Solo grupo 7 (GASTOS). */ IF OBJECT_ID('presidencia.vwGastosDepto','V') IS NOT NULL DROP VIEW presidencia.vwGastosDepto; GO CREATE VIEW presidencia.vwGastosDepto AS WITH mov AS ( SELECT p.ano, p.mes AS numero_mes, ISNULL(b.departamento,0) AS departamento, b.cuenta_no, SUM(b.debito) AS debito, SUM(b.credito) AS credito FROM marmotech.dbo.cgtb00004 b INNER JOIN marmotech.dbo.prdtable p ON b.fecha BETWEEN p.fecha_inicio AND p.fecha_corte WHERE b.status_t IS NULL AND LEFT(b.cuenta_no,1) = '7' AND b.ref NOT LIKE 'ED.99-001/12%' AND b.ref NOT LIKE 'ED.99-002/12%' GROUP BY p.ano, p.mes, ISNULL(b.departamento,0), b.cuenta_no ) SELECT m.ano, m.numero_mes, ms.descrip AS mes, RIGHT('0000'+CONVERT(varchar(4),m.ano),4) + '-' + RIGHT('00'+CONVERT(varchar(2),m.numero_mes),2) AS AnoMes, DATEFROMPARTS(m.ano, m.numero_mes, 1) AS fecha_mes, LEFT(CONVERT(varchar(4),m.departamento),1) AS gerencia_cod, CASE LEFT(CONVERT(varchar(4),m.departamento),1) WHEN '1' THEN 'Gerencia General' WHEN '2' THEN 'Administracion y Materiales' WHEN '3' THEN 'Gestion Humana' WHEN '4' THEN 'Ventas y Mercadeo' WHEN '5' THEN 'Canteras' WHEN '6' THEN 'Planta / Produccion' WHEN '7' THEN 'Planta Agregados' WHEN '8' THEN 'Marmotech en Caribbean' ELSE 'Sin Departamento' END AS gerencia, m.departamento, ISNULL(ad.nom_dpto,'SIN DEPARTAMENTO') AS depto_nombre, LEFT(m.cuenta_no,2) AS subgrupo_cod, sg.descripcion AS subgrupo_desc, m.cuenta_no AS cuenta, ct.descripcion AS cuenta_desc, m.debito, m.credito, CAST(m.debito - m.credito AS decimal(19,2)) AS gasto -- + = gasto neto FROM mov m LEFT JOIN marmotech.dbo.cgtb00001 ct ON ct.cuenta_no = m.cuenta_no LEFT JOIN marmotech.dbo.cgtb00001 sg ON sg.cuenta_no = LEFT(m.cuenta_no,2) LEFT JOIN marmotech.dbo.adtb00001 ad ON ad.departamento = m.departamento LEFT JOIN marmotech.dbo.mestable ms ON ms.mes = m.numero_mes; GO /* ---- 4. Balance General / Estructura financiera (saldo acumulado) -------- */ /* Grano: ano x mes x cuenta, grupos 1 (Activos) 2 (Pasivos) 3 (Capital). */ /* saldo_acumulado = saldo contable al cierre del mes (deb-cred acumulado). */ IF OBJECT_ID('presidencia.vwBalanceMensual','V') IS NOT NULL DROP VIEW presidencia.vwBalanceMensual; GO CREATE VIEW presidencia.vwBalanceMensual AS WITH mov AS ( SELECT p.ano, p.mes AS numero_mes, b.cuenta_no, SUM(b.debito - b.credito) AS movimiento FROM marmotech.dbo.cgtb00004 b INNER JOIN marmotech.dbo.prdtable p ON b.fecha BETWEEN p.fecha_inicio AND p.fecha_corte WHERE b.status_t IS NULL AND LEFT(b.cuenta_no,1) IN ('1','2','3') GROUP BY p.ano, p.mes, b.cuenta_no ), acum AS ( SELECT m.*, SUM(m.movimiento) OVER (PARTITION BY m.cuenta_no ORDER BY m.ano, m.numero_mes ROWS UNBOUNDED PRECEDING) AS saldo_acumulado FROM mov m ) SELECT a.ano, a.numero_mes, ms.descrip AS mes, RIGHT('0000'+CONVERT(varchar(4),a.ano),4) + '-' + RIGHT('00'+CONVERT(varchar(2),a.numero_mes),2) AS AnoMes, DATEFROMPARTS(a.ano, a.numero_mes, 1) AS fecha_mes, LEFT(a.cuenta_no,1) AS grupo, CASE LEFT(a.cuenta_no,1) WHEN '1' THEN 'Activos' WHEN '2' THEN 'Pasivos' WHEN '3' THEN 'Capital' END AS grupo_desc, LEFT(a.cuenta_no,2) AS subgrupo_cod, sg.descripcion AS subgrupo_desc, a.cuenta_no AS cuenta, ct.descripcion AS cuenta_desc, CAST(a.movimiento AS decimal(19,2)) AS movimiento_mes, CAST(a.saldo_acumulado AS decimal(19,2)) AS saldo_natural, -- deb-cred /* Presentacion: Activos positivos por debito; Pasivos/Capital por credito */ CAST(CASE WHEN LEFT(a.cuenta_no,1) = '1' THEN a.saldo_acumulado ELSE -a.saldo_acumulado END AS decimal(19,2)) AS saldo_presentacion FROM acum a LEFT JOIN marmotech.dbo.cgtb00001 ct ON ct.cuenta_no = a.cuenta_no LEFT JOIN marmotech.dbo.cgtb00001 sg ON sg.cuenta_no = LEFT(a.cuenta_no,2) LEFT JOIN marmotech.dbo.mestable ms ON ms.mes = a.numero_mes; GO /* ---- 5. Seguridad: solo jsoto ------------------------------------------- */ DENY SELECT ON SCHEMA::presidencia TO [public]; GO /* Concesion explicita (documenta la intencion; jsoto ya es db_owner/sysadmin) */ IF EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'MARMOTECH\jsoto') GRANT SELECT ON SCHEMA::presidencia TO [MARMOTECH\jsoto]; GO IF EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'jsoto') GRANT SELECT ON SCHEMA::presidencia TO [jsoto]; GO