From 58ff15a0c0548f113b7888307680111d3a36d805 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Fri, 17 Apr 2026 17:33:19 -0300 Subject: [PATCH] feat(adm-009): V014 create TipoDeIva + IngresosBrutos tables with SYSTEM_VERSIONING --- database/migrations/V014_ROLLBACK.sql | 141 +++++++++ .../V014__create_tablas_fiscales.sql | 292 ++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 database/migrations/V014_ROLLBACK.sql create mode 100644 database/migrations/V014__create_tablas_fiscales.sql diff --git a/database/migrations/V014_ROLLBACK.sql b/database/migrations/V014_ROLLBACK.sql new file mode 100644 index 0000000..8787e30 --- /dev/null +++ b/database/migrations/V014_ROLLBACK.sql @@ -0,0 +1,141 @@ +-- V014_ROLLBACK.sql +-- Reversa de V014__create_tablas_fiscales.sql. +-- +-- ADVERTENCIA: ejecutar ELIMINA TipoDeIva, IngresosBrutos, sus historiales temporales, +-- el permiso 'administracion:fiscal:gestionar' y sus asignaciones. +-- +-- Uso intended: ROLLBACK en entornos NO-productivos. +-- Prerequisito: no deben existir FKs vivas apuntando a estas tablas (FAC-001, etc.). +-- Si FAC-001 ya esta aplicado, este rollback fallara — usar backup. +-- +-- Idempotente: seguro para re-ejecutar (guards en cada paso). + +SET QUOTED_IDENTIFIER ON; +SET ANSI_NULLS ON; +SET NOCOUNT ON; +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 1. Apagar SYSTEM_VERSIONING — TipoDeIva +-- ═══════════════════════════════════════════════════════════════════════ + +IF EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.TipoDeIva') AND temporal_type = 2) +BEGIN + ALTER TABLE dbo.TipoDeIva SET (SYSTEM_VERSIONING = OFF); + PRINT 'TipoDeIva: SYSTEM_VERSIONING OFF.'; +END +GO + +IF EXISTS (SELECT 1 FROM sys.periods WHERE object_id = OBJECT_ID('dbo.TipoDeIva')) +BEGIN + ALTER TABLE dbo.TipoDeIva DROP PERIOD FOR SYSTEM_TIME; + PRINT 'TipoDeIva: PERIOD FOR SYSTEM_TIME dropped.'; +END +GO + +IF COL_LENGTH('dbo.TipoDeIva', 'ValidFrom') IS NOT NULL +BEGIN + ALTER TABLE dbo.TipoDeIva DROP CONSTRAINT IF EXISTS DF_TipoDeIva_ValidFrom; + ALTER TABLE dbo.TipoDeIva DROP CONSTRAINT IF EXISTS DF_TipoDeIva_ValidTo; + ALTER TABLE dbo.TipoDeIva DROP COLUMN ValidFrom, ValidTo; + PRINT 'TipoDeIva: ValidFrom/ValidTo dropped.'; +END +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 2. Apagar SYSTEM_VERSIONING — IngresosBrutos +-- ═══════════════════════════════════════════════════════════════════════ + +IF EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.IngresosBrutos') AND temporal_type = 2) +BEGIN + ALTER TABLE dbo.IngresosBrutos SET (SYSTEM_VERSIONING = OFF); + PRINT 'IngresosBrutos: SYSTEM_VERSIONING OFF.'; +END +GO + +IF EXISTS (SELECT 1 FROM sys.periods WHERE object_id = OBJECT_ID('dbo.IngresosBrutos')) +BEGIN + ALTER TABLE dbo.IngresosBrutos DROP PERIOD FOR SYSTEM_TIME; + PRINT 'IngresosBrutos: PERIOD FOR SYSTEM_TIME dropped.'; +END +GO + +IF COL_LENGTH('dbo.IngresosBrutos', 'ValidFrom') IS NOT NULL +BEGIN + ALTER TABLE dbo.IngresosBrutos DROP CONSTRAINT IF EXISTS DF_IIBB_ValidFrom; + ALTER TABLE dbo.IngresosBrutos DROP CONSTRAINT IF EXISTS DF_IIBB_ValidTo; + ALTER TABLE dbo.IngresosBrutos DROP COLUMN ValidFrom, ValidTo; + PRINT 'IngresosBrutos: ValidFrom/ValidTo dropped.'; +END +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 3. Drop FK self antes de DROP TABLE (para evitar constraint violation) +-- ═══════════════════════════════════════════════════════════════════════ + +IF OBJECT_ID('FK_TipoDeIva_Predecesor', 'F') IS NOT NULL +BEGIN + ALTER TABLE dbo.TipoDeIva DROP CONSTRAINT FK_TipoDeIva_Predecesor; + PRINT 'FK_TipoDeIva_Predecesor dropped.'; +END +GO + +IF OBJECT_ID('FK_IIBB_Predecesor', 'F') IS NOT NULL +BEGIN + ALTER TABLE dbo.IngresosBrutos DROP CONSTRAINT FK_IIBB_Predecesor; + PRINT 'FK_IIBB_Predecesor dropped.'; +END +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 4. Drop history tables → main tables +-- ═══════════════════════════════════════════════════════════════════════ + +IF OBJECT_ID(N'dbo.TipoDeIva_History', N'U') IS NOT NULL +BEGIN + DROP TABLE dbo.TipoDeIva_History; + PRINT 'TipoDeIva_History dropped.'; +END +GO + +IF OBJECT_ID(N'dbo.IngresosBrutos_History', N'U') IS NOT NULL +BEGIN + DROP TABLE dbo.IngresosBrutos_History; + PRINT 'IngresosBrutos_History dropped.'; +END +GO + +IF OBJECT_ID(N'dbo.TipoDeIva', N'U') IS NOT NULL +BEGIN + DROP TABLE dbo.TipoDeIva; + PRINT 'Table dbo.TipoDeIva dropped.'; +END +GO + +IF OBJECT_ID(N'dbo.IngresosBrutos', N'U') IS NOT NULL +BEGIN + DROP TABLE dbo.IngresosBrutos; + PRINT 'Table dbo.IngresosBrutos dropped.'; +END +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 5. Remover permiso 'administracion:fiscal:gestionar' + RolPermiso +-- ═══════════════════════════════════════════════════════════════════════ + +DELETE rp +FROM dbo.RolPermiso rp +JOIN dbo.Permiso p ON p.Id = rp.PermisoId +WHERE p.Codigo = 'administracion:fiscal:gestionar'; +GO + +DELETE FROM dbo.Permiso +WHERE Codigo = 'administracion:fiscal:gestionar'; +GO + +PRINT ''; +PRINT 'V014 rolled back.'; +PRINT ' - dbo.TipoDeIva and dbo.TipoDeIva_History removed.'; +PRINT ' - dbo.IngresosBrutos and dbo.IngresosBrutos_History removed.'; +PRINT ' - Permiso administracion:fiscal:gestionar removed.'; +GO diff --git a/database/migrations/V014__create_tablas_fiscales.sql b/database/migrations/V014__create_tablas_fiscales.sql new file mode 100644 index 0000000..60b58b6 --- /dev/null +++ b/database/migrations/V014__create_tablas_fiscales.sql @@ -0,0 +1,292 @@ +-- V014__create_tablas_fiscales.sql +-- ADM-009 Tablas Fiscales: DDL para dbo.TipoDeIva + dbo.IngresosBrutos + permisos. +-- +-- Patron: append-only versioned ref data. +-- Porcentaje/Alicuota son INMUTABLES post-creacion; cambiar el valor = nueva fila + cierre de predecesora. +-- PredecesorId (FK self) establece la cadena de versiones (historial de negocio). +-- SYSTEM_VERSIONING ON para historial tecnico (auditoria temporal de SQL Server). +-- +-- Idempotente: seguro para re-ejecutar. +-- Reversa: V014_ROLLBACK.sql. +-- Run on: SIGCM2 (dev) y SIGCM2_Test (integration tests). +-- +-- Covers: REQ-SEED-001, REQ-SEED-002, REQ-SEED-003, REQ-TEMPORAL-001, REQ-FISCAL-AUTH-002 + +SET QUOTED_IDENTIFIER ON; +SET ANSI_NULLS ON; +SET NOCOUNT ON; +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 1. dbo.TipoDeIva +-- ═══════════════════════════════════════════════════════════════════════ + +IF OBJECT_ID(N'dbo.TipoDeIva', N'U') IS NULL +BEGIN + CREATE TABLE dbo.TipoDeIva ( + Id INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_TipoDeIva PRIMARY KEY, + Codigo VARCHAR(32) NOT NULL, + Descripcion NVARCHAR(100) NOT NULL, + Porcentaje DECIMAL(5,2) NOT NULL, + AplicaIVA BIT NOT NULL, + Activo BIT NOT NULL CONSTRAINT DF_TipoDeIva_Activo DEFAULT(1), + VigenciaDesde DATE NOT NULL, + VigenciaHasta DATE NULL, + PredecesorId INT NULL, + FechaCreacion DATETIME2(3) NOT NULL CONSTRAINT DF_TipoDeIva_FechaCreacion DEFAULT(SYSUTCDATETIME()), + FechaModificacion DATETIME2(3) NULL, + CONSTRAINT CK_TipoDeIva_Porcentaje CHECK (Porcentaje >= 0 AND Porcentaje <= 100), + CONSTRAINT CK_TipoDeIva_Vigencia CHECK (VigenciaHasta IS NULL OR VigenciaHasta >= VigenciaDesde), + CONSTRAINT UQ_TipoDeIva_Codigo_Vigencia UNIQUE (Codigo, VigenciaDesde), + CONSTRAINT FK_TipoDeIva_Predecesor FOREIGN KEY (PredecesorId) REFERENCES dbo.TipoDeIva(Id) + ); + PRINT 'Table dbo.TipoDeIva created.'; +END +ELSE + PRINT 'Table dbo.TipoDeIva already exists — skip.'; +GO + +-- Indices TipoDeIva +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_TipoDeIva_Codigo_VigenciaDesde' AND object_id = OBJECT_ID('dbo.TipoDeIva')) +BEGIN + CREATE INDEX IX_TipoDeIva_Codigo_VigenciaDesde + ON dbo.TipoDeIva(Codigo, VigenciaDesde DESC); + PRINT 'Index IX_TipoDeIva_Codigo_VigenciaDesde created.'; +END +GO + +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_TipoDeIva_PredecesorId' AND object_id = OBJECT_ID('dbo.TipoDeIva')) +BEGIN + CREATE INDEX IX_TipoDeIva_PredecesorId + ON dbo.TipoDeIva(PredecesorId) + WHERE PredecesorId IS NOT NULL; + PRINT 'Index IX_TipoDeIva_PredecesorId created.'; +END +GO + +-- SYSTEM_VERSIONING — TipoDeIva +IF COL_LENGTH('dbo.TipoDeIva', 'ValidFrom') IS NULL +BEGIN + ALTER TABLE dbo.TipoDeIva + ADD + ValidFrom DATETIME2(3) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL + CONSTRAINT DF_TipoDeIva_ValidFrom DEFAULT(SYSUTCDATETIME()), + ValidTo DATETIME2(3) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL + CONSTRAINT DF_TipoDeIva_ValidTo DEFAULT(CONVERT(DATETIME2(3), '9999-12-31 23:59:59.999')), + PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo); + PRINT 'TipoDeIva: PERIOD FOR SYSTEM_TIME added.'; +END +GO + +IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.TipoDeIva') AND temporal_type = 2) +BEGIN + ALTER TABLE dbo.TipoDeIva + SET (SYSTEM_VERSIONING = ON ( + HISTORY_TABLE = dbo.TipoDeIva_History, + HISTORY_RETENTION_PERIOD = 10 YEARS + )); + PRINT 'TipoDeIva: SYSTEM_VERSIONING = ON (history: dbo.TipoDeIva_History, retention: 10 years).'; +END +ELSE + PRINT 'TipoDeIva: SYSTEM_VERSIONING already ON — skip.'; +GO + +IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'TipoDeIva_History' AND schema_id = SCHEMA_ID('dbo')) + AND NOT EXISTS ( + SELECT 1 FROM sys.partitions p + JOIN sys.tables t ON t.object_id = p.object_id + WHERE t.name = 'TipoDeIva_History' AND p.data_compression = 2 + ) +BEGIN + ALTER TABLE dbo.TipoDeIva_History REBUILD WITH (DATA_COMPRESSION = PAGE); + PRINT 'TipoDeIva_History: rebuilt with PAGE compression.'; +END +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 2. dbo.IngresosBrutos +-- ═══════════════════════════════════════════════════════════════════════ + +IF OBJECT_ID(N'dbo.IngresosBrutos', N'U') IS NULL +BEGIN + CREATE TABLE dbo.IngresosBrutos ( + Id INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_IngresosBrutos PRIMARY KEY, + Provincia VARCHAR(50) NOT NULL, + Descripcion NVARCHAR(100) NOT NULL, + Alicuota DECIMAL(5,2) NOT NULL, + Activo BIT NOT NULL CONSTRAINT DF_IIBB_Activo DEFAULT(1), + VigenciaDesde DATE NOT NULL, + VigenciaHasta DATE NULL, + PredecesorId INT NULL, + FechaCreacion DATETIME2(3) NOT NULL CONSTRAINT DF_IIBB_FechaCreacion DEFAULT(SYSUTCDATETIME()), + FechaModificacion DATETIME2(3) NULL, + CONSTRAINT CK_IIBB_Alicuota CHECK (Alicuota >= 0 AND Alicuota <= 100), + CONSTRAINT CK_IIBB_Vigencia CHECK (VigenciaHasta IS NULL OR VigenciaHasta >= VigenciaDesde), + CONSTRAINT UQ_IIBB_Provincia_Vigencia UNIQUE (Provincia, VigenciaDesde), + CONSTRAINT FK_IIBB_Predecesor FOREIGN KEY (PredecesorId) REFERENCES dbo.IngresosBrutos(Id) + ); + PRINT 'Table dbo.IngresosBrutos created.'; +END +ELSE + PRINT 'Table dbo.IngresosBrutos already exists — skip.'; +GO + +-- Indices IngresosBrutos +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_IIBB_Provincia_VigenciaDesde' AND object_id = OBJECT_ID('dbo.IngresosBrutos')) +BEGIN + CREATE INDEX IX_IIBB_Provincia_VigenciaDesde + ON dbo.IngresosBrutos(Provincia, VigenciaDesde DESC); + PRINT 'Index IX_IIBB_Provincia_VigenciaDesde created.'; +END +GO + +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_IIBB_PredecesorId' AND object_id = OBJECT_ID('dbo.IngresosBrutos')) +BEGIN + CREATE INDEX IX_IIBB_PredecesorId + ON dbo.IngresosBrutos(PredecesorId) + WHERE PredecesorId IS NOT NULL; + PRINT 'Index IX_IIBB_PredecesorId created.'; +END +GO + +-- SYSTEM_VERSIONING — IngresosBrutos +IF COL_LENGTH('dbo.IngresosBrutos', 'ValidFrom') IS NULL +BEGIN + ALTER TABLE dbo.IngresosBrutos + ADD + ValidFrom DATETIME2(3) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL + CONSTRAINT DF_IIBB_ValidFrom DEFAULT(SYSUTCDATETIME()), + ValidTo DATETIME2(3) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL + CONSTRAINT DF_IIBB_ValidTo DEFAULT(CONVERT(DATETIME2(3), '9999-12-31 23:59:59.999')), + PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo); + PRINT 'IngresosBrutos: PERIOD FOR SYSTEM_TIME added.'; +END +GO + +IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.IngresosBrutos') AND temporal_type = 2) +BEGIN + ALTER TABLE dbo.IngresosBrutos + SET (SYSTEM_VERSIONING = ON ( + HISTORY_TABLE = dbo.IngresosBrutos_History, + HISTORY_RETENTION_PERIOD = 10 YEARS + )); + PRINT 'IngresosBrutos: SYSTEM_VERSIONING = ON (history: dbo.IngresosBrutos_History, retention: 10 years).'; +END +ELSE + PRINT 'IngresosBrutos: SYSTEM_VERSIONING already ON — skip.'; +GO + +IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'IngresosBrutos_History' AND schema_id = SCHEMA_ID('dbo')) + AND NOT EXISTS ( + SELECT 1 FROM sys.partitions p + JOIN sys.tables t ON t.object_id = p.object_id + WHERE t.name = 'IngresosBrutos_History' AND p.data_compression = 2 + ) +BEGIN + ALTER TABLE dbo.IngresosBrutos_History REBUILD WITH (DATA_COMPRESSION = PAGE); + PRINT 'IngresosBrutos_History: rebuilt with PAGE compression.'; +END +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 3. Seed TipoDeIva — 4 filas canonicas (REQ-SEED-001) +-- MERGE garantiza idempotencia (REQ-SEED-003) +-- EXENTO y NO_GRAVADO no aplican IVA; IVA_105 e IVA_21 si aplican. +-- ═══════════════════════════════════════════════════════════════════════ + +MERGE dbo.TipoDeIva AS t +USING (VALUES + ('EXENTO', N'Exento de IVA', CAST(0 AS DECIMAL(5,2)), CAST(0 AS BIT), CAST('2020-01-01' AS DATE)), + ('NO_GRAVADO', N'No gravado', CAST(0 AS DECIMAL(5,2)), CAST(0 AS BIT), CAST('2020-01-01' AS DATE)), + ('IVA_105', N'IVA alicuota diferencial 10.5%', CAST(10.5 AS DECIMAL(5,2)), CAST(1 AS BIT), CAST('2020-01-01' AS DATE)), + ('IVA_21', N'IVA alicuota general 21%', CAST(21 AS DECIMAL(5,2)), CAST(1 AS BIT), CAST('2020-01-01' AS DATE)) +) AS s (Codigo, Descripcion, Porcentaje, AplicaIVA, VigenciaDesde) +ON t.Codigo = s.Codigo AND t.PredecesorId IS NULL +WHEN NOT MATCHED BY TARGET THEN + INSERT (Codigo, Descripcion, Porcentaje, AplicaIVA, Activo, VigenciaDesde, VigenciaHasta, PredecesorId) + VALUES (s.Codigo, s.Descripcion, s.Porcentaje, s.AplicaIVA, 1, s.VigenciaDesde, NULL, NULL); +GO + +PRINT 'TipoDeIva: 4 canonical rows seeded (EXENTO, NO_GRAVADO, IVA_105, IVA_21).'; +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 4. Seed IngresosBrutos — 24 filas (23 provincias INDEC + CABA) (REQ-SEED-002) +-- Alicuota=0 placeholder — el operador cargara las alicuotas reales via UI. +-- MERGE garantiza idempotencia (REQ-SEED-003). +-- Provincias almacenadas como nombre de enum ProvinciaArgentina (VARCHAR(50)). +-- DISCOVERY: spec dice 25 filas pero lista canonica del design tiene 24 entradas +-- (23 provincias INDEC + CABA). Implementado con 24. Ver apply-progress. +-- ═══════════════════════════════════════════════════════════════════════ + +MERGE dbo.IngresosBrutos AS t +USING (VALUES + ('BUENOS_AIRES', N'Ingresos Brutos - Buenos Aires'), + ('CABA', N'Ingresos Brutos - Ciudad Autonoma de Buenos Aires'), + ('CATAMARCA', N'Ingresos Brutos - Catamarca'), + ('CHACO', N'Ingresos Brutos - Chaco'), + ('CHUBUT', N'Ingresos Brutos - Chubut'), + ('CORDOBA', N'Ingresos Brutos - Cordoba'), + ('CORRIENTES', N'Ingresos Brutos - Corrientes'), + ('ENTRE_RIOS', N'Ingresos Brutos - Entre Rios'), + ('FORMOSA', N'Ingresos Brutos - Formosa'), + ('JUJUY', N'Ingresos Brutos - Jujuy'), + ('LA_PAMPA', N'Ingresos Brutos - La Pampa'), + ('LA_RIOJA', N'Ingresos Brutos - La Rioja'), + ('MENDOZA', N'Ingresos Brutos - Mendoza'), + ('MISIONES', N'Ingresos Brutos - Misiones'), + ('NEUQUEN', N'Ingresos Brutos - Neuquen'), + ('RIO_NEGRO', N'Ingresos Brutos - Rio Negro'), + ('SALTA', N'Ingresos Brutos - Salta'), + ('SAN_JUAN', N'Ingresos Brutos - San Juan'), + ('SAN_LUIS', N'Ingresos Brutos - San Luis'), + ('SANTA_CRUZ', N'Ingresos Brutos - Santa Cruz'), + ('SANTA_FE', N'Ingresos Brutos - Santa Fe'), + ('SANTIAGO_DEL_ESTERO', N'Ingresos Brutos - Santiago del Estero'), + ('TIERRA_DEL_FUEGO', N'Ingresos Brutos - Tierra del Fuego'), + ('TUCUMAN', N'Ingresos Brutos - Tucuman') +) AS s (Provincia, Descripcion) +ON t.Provincia = s.Provincia AND t.PredecesorId IS NULL +WHEN NOT MATCHED BY TARGET THEN + INSERT (Provincia, Descripcion, Alicuota, Activo, VigenciaDesde, VigenciaHasta, PredecesorId) + VALUES (s.Provincia, s.Descripcion, CAST(0 AS DECIMAL(5,2)), 1, CAST('2020-01-01' AS DATE), NULL, NULL); +GO + +PRINT 'IngresosBrutos: 24 canonical rows seeded (23 provincias INDEC + CABA, Alicuota=0 placeholder).'; +GO + +-- ═══════════════════════════════════════════════════════════════════════ +-- 5. Permiso: administracion:fiscal:gestionar (REQ-FISCAL-AUTH-002) +-- ═══════════════════════════════════════════════════════════════════════ + +MERGE dbo.Permiso AS t +USING (VALUES + ('administracion:fiscal:gestionar', N'Gestionar tablas fiscales', N'Gestionar tablas fiscales (IVA, IIBB)', 'administracion') +) AS s (Codigo, Nombre, Descripcion, Modulo) +ON t.Codigo = s.Codigo +WHEN NOT MATCHED BY TARGET THEN + INSERT (Codigo, Nombre, Descripcion, Modulo) + VALUES (s.Codigo, s.Nombre, s.Descripcion, s.Modulo); +GO + +MERGE dbo.RolPermiso AS t +USING ( + SELECT r.Id AS RolId, p.Id AS PermisoId + FROM (VALUES + ('admin', 'administracion:fiscal:gestionar') + ) AS x (RolCodigo, PermisoCodigo) + JOIN dbo.Rol r ON r.Codigo = x.RolCodigo + JOIN dbo.Permiso p ON p.Codigo = x.PermisoCodigo +) AS s ON t.RolId = s.RolId AND t.PermisoId = s.PermisoId +WHEN NOT MATCHED BY TARGET THEN + INSERT (RolId, PermisoId) VALUES (s.RolId, s.PermisoId); +GO + +PRINT ''; +PRINT 'V014 applied successfully.'; +PRINT ' - dbo.TipoDeIva (temporal, retention 10y, PAGE compression)'; +PRINT ' - dbo.IngresosBrutos (temporal, retention 10y, PAGE compression)'; +PRINT ' - TipoDeIva: 4 canonical rows (EXENTO, NO_GRAVADO, IVA_105, IVA_21)'; +PRINT ' - IngresosBrutos: 24 rows (23 provincias INDEC + CABA, Alicuota=0 placeholder)'; +PRINT ' - Permiso administracion:fiscal:gestionar (asignado a admin)'; +GO