revert(db): eliminar SecuenciaComprobante + SP de V013 — IMAC asigna numeros AFIP
SecuenciaComprobante, usp_ReservarNumeroComprobante y TipoComprobante no tienen propósito de negocio: IMAC/Infogestión asigna NumeroFactura+CAI externamente. V013 ahora solo gestiona PuntoDeVenta + temporal table + permiso AFIP. Sección 0 aplica drops idempotentes para limpiar SIGCM2_Test y reinstalaciones.
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
-- V013_ROLLBACK.sql
|
||||
-- Reversa de V013__create_puntos_de_venta.sql.
|
||||
--
|
||||
-- ADVERTENCIA: ejecutar ELIMINA PuntoDeVenta, SecuenciaComprobante, su historia temporal,
|
||||
-- el permiso 'administracion:puntos_de_venta:gestionar', sus asignaciones y el SP.
|
||||
-- ADVERTENCIA: ejecutar ELIMINA PuntoDeVenta, su historia temporal,
|
||||
-- el permiso 'administracion:puntos_de_venta:gestionar' y sus asignaciones.
|
||||
--
|
||||
-- Uso intended: ROLLBACK en entornos NO-productivos.
|
||||
-- Prerequisito: no deben existir FKs vivas apuntando a PuntoDeVenta (p.ej., comprobantes FAC-001).
|
||||
-- Si FAC-001 ya está aplicado, este rollback fallará — usar backup.
|
||||
--
|
||||
-- NOTA: SecuenciaComprobante y SP usp_ReservarNumeroComprobante ya no forman parte
|
||||
-- de V013 (eliminados en cirugía post-smoke Batch 9). Este rollback solo maneja PuntoDeVenta.
|
||||
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
SET ANSI_NULLS ON;
|
||||
@@ -14,52 +17,7 @@ SET NOCOUNT ON;
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 1. Drop SP
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF OBJECT_ID(N'dbo.usp_ReservarNumeroComprobante', N'P') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE dbo.usp_ReservarNumeroComprobante;
|
||||
PRINT 'SP dbo.usp_ReservarNumeroComprobante dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 2. Apagar SYSTEM_VERSIONING + remover PERIOD — SecuenciaComprobante primero (FK a PdV)
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.SecuenciaComprobante') AND temporal_type = 2)
|
||||
BEGIN
|
||||
ALTER TABLE dbo.SecuenciaComprobante SET (SYSTEM_VERSIONING = OFF);
|
||||
PRINT 'SecuenciaComprobante: SYSTEM_VERSIONING OFF.';
|
||||
END
|
||||
GO
|
||||
|
||||
IF EXISTS (SELECT 1 FROM sys.periods WHERE object_id = OBJECT_ID('dbo.SecuenciaComprobante'))
|
||||
BEGIN
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP PERIOD FOR SYSTEM_TIME;
|
||||
PRINT 'SecuenciaComprobante: PERIOD FOR SYSTEM_TIME dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
IF COL_LENGTH('dbo.SecuenciaComprobante', 'ValidFrom') IS NOT NULL
|
||||
BEGIN
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP CONSTRAINT IF EXISTS DF_SecuenciaComprobante_ValidFrom;
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP CONSTRAINT IF EXISTS DF_SecuenciaComprobante_ValidTo;
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP COLUMN ValidFrom, ValidTo;
|
||||
PRINT 'SecuenciaComprobante: ValidFrom/ValidTo dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SecuenciaComprobante_History', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
DROP TABLE dbo.SecuenciaComprobante_History;
|
||||
PRINT 'SecuenciaComprobante_History dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 3. Apagar SYSTEM_VERSIONING + remover PERIOD — PuntoDeVenta
|
||||
-- 1. Apagar SYSTEM_VERSIONING + remover PERIOD — PuntoDeVenta
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.PuntoDeVenta') AND temporal_type = 2)
|
||||
@@ -93,16 +51,9 @@ END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 4. Drop tablas (SecuenciaComprobante primero por FK)
|
||||
-- 2. Drop tabla PuntoDeVenta
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF OBJECT_ID(N'dbo.SecuenciaComprobante', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
DROP TABLE dbo.SecuenciaComprobante;
|
||||
PRINT 'Table dbo.SecuenciaComprobante dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.PuntoDeVenta', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
DROP TABLE dbo.PuntoDeVenta;
|
||||
@@ -111,7 +62,7 @@ END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 5. Remover permiso 'administracion:puntos_de_venta:gestionar' + RolPermiso
|
||||
-- 3. Remover permiso 'administracion:puntos_de_venta:gestionar' + RolPermiso
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
DELETE rp
|
||||
@@ -125,7 +76,6 @@ WHERE Codigo = 'administracion:puntos_de_venta:gestionar';
|
||||
GO
|
||||
|
||||
PRINT '';
|
||||
PRINT 'V013 rolled back. dbo.PuntoDeVenta, dbo.SecuenciaComprobante and their history removed.';
|
||||
PRINT 'SP dbo.usp_ReservarNumeroComprobante removed.';
|
||||
PRINT 'V013 rolled back. dbo.PuntoDeVenta and its history removed.';
|
||||
PRINT 'Permiso administracion:puntos_de_venta:gestionar removed.';
|
||||
GO
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
-- V013__create_puntos_de_venta.sql
|
||||
-- ADM-008 Puntos de Venta: DDL + SP de reserva atómica de número de comprobante.
|
||||
-- ADM-008 Puntos de Venta: DDL para dbo.PuntoDeVenta + permiso AFIP.
|
||||
--
|
||||
-- NOTA POST-SMOKE (Batch 9): SecuenciaComprobante, SP usp_ReservarNumeroComprobante
|
||||
-- y TipoComprobante fueron eliminados. SIG-CM2.0 NO genera números AFIP — IMAC
|
||||
-- (Plataforma Infogestión) los asigna externamente. Un worker futuro (INT-001)
|
||||
-- polleará la vista de Infogestión para asociar NumeroOrdenInterno ↔ NumeroFacturaAFIP + CAI.
|
||||
-- PuntoDeVenta.NumeroAFIP es config fija que se manda en el payload a IMAC.
|
||||
--
|
||||
-- Cambios:
|
||||
-- 1. dbo.PuntoDeVenta (FK→Medio, UNIQUE(MedioId,NumeroAFIP), SYSTEM_VERSIONING ON, retention 10Y).
|
||||
-- 2. dbo.SecuenciaComprobante (FK→PuntoDeVenta, PK(PuntoDeVentaId,TipoComprobante), SYSTEM_VERSIONING ON, retention 10Y).
|
||||
-- 3. Permiso 'administracion:puntos-de-venta:gestionar' + asignación a rol 'admin'.
|
||||
-- 4. SP dbo.usp_ReservarNumeroComprobante (SERIALIZABLE, UPDATE+OUTPUT, THROW 50001/50002/50003).
|
||||
-- 2. Drops idempotentes de artefactos de versión previa (SecuenciaComprobante + SP).
|
||||
-- 3. Permiso 'administracion:puntos_de_venta:gestionar' + asignación a rol 'admin'.
|
||||
--
|
||||
-- Patrón: V011 (Temporal Tables + Permiso MERGE + PAGE compression en history).
|
||||
-- Idempotente: seguro para re-ejecutar.
|
||||
@@ -18,7 +23,7 @@
|
||||
-- solo permite [a-z0-9_:] — se usa guion_bajo para cumplir la constraint existente.
|
||||
-- El backend y frontend deben usar el código con guion_bajo.
|
||||
--
|
||||
-- Covers: REQ-PDV-001, -003, -009, REQ-SEC-CMB-001, -002, -003, -004
|
||||
-- Covers: REQ-PDV-001, -003, -009
|
||||
-- Source of truth: Obsidian/02-ARQUITECTURA-y-TECH-STACK/2.10 ADM-008
|
||||
--
|
||||
-- NOTA T1.3 — Seeds: NO se seedean PuntoDeVenta.
|
||||
@@ -30,6 +35,39 @@ SET ANSI_NULLS ON;
|
||||
SET NOCOUNT ON;
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 0. Drops idempotentes de artefactos de versión previa
|
||||
-- (SecuenciaComprobante + SP — eliminados en cirugía post-smoke Batch 9)
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF OBJECT_ID(N'dbo.usp_ReservarNumeroComprobante', N'P') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE dbo.usp_ReservarNumeroComprobante;
|
||||
PRINT 'SP dbo.usp_ReservarNumeroComprobante dropped (cleanup).';
|
||||
END
|
||||
GO
|
||||
|
||||
IF EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.SecuenciaComprobante') AND temporal_type = 2)
|
||||
BEGIN
|
||||
ALTER TABLE dbo.SecuenciaComprobante SET (SYSTEM_VERSIONING = OFF);
|
||||
PRINT 'SecuenciaComprobante: SYSTEM_VERSIONING = OFF (cleanup).';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SecuenciaComprobante_History', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
DROP TABLE dbo.SecuenciaComprobante_History;
|
||||
PRINT 'SecuenciaComprobante_History dropped (cleanup).';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SecuenciaComprobante', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
DROP TABLE dbo.SecuenciaComprobante;
|
||||
PRINT 'Table dbo.SecuenciaComprobante dropped (cleanup).';
|
||||
END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 1. dbo.PuntoDeVenta
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
@@ -65,30 +103,7 @@ END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 2. dbo.SecuenciaComprobante
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF OBJECT_ID(N'dbo.SecuenciaComprobante', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SecuenciaComprobante (
|
||||
PuntoDeVentaId INT NOT NULL,
|
||||
TipoComprobante TINYINT NOT NULL,
|
||||
UltimoNumero INT NOT NULL CONSTRAINT DF_SecuenciaComprobante_UltimoNumero DEFAULT(0),
|
||||
FechaCreacion DATETIME2(3) NOT NULL CONSTRAINT DF_SecuenciaComprobante_FechaCreacion DEFAULT(SYSUTCDATETIME()),
|
||||
FechaModificacion DATETIME2(3) NULL,
|
||||
CONSTRAINT PK_SecuenciaComprobante PRIMARY KEY (PuntoDeVentaId, TipoComprobante),
|
||||
CONSTRAINT FK_SecuenciaComprobante_PuntoDeVenta FOREIGN KEY (PuntoDeVentaId) REFERENCES dbo.PuntoDeVenta(Id) ON DELETE NO ACTION,
|
||||
CONSTRAINT CK_SecuenciaComprobante_TipoComprobante CHECK (TipoComprobante BETWEEN 1 AND 6),
|
||||
CONSTRAINT CK_SecuenciaComprobante_UltimoNumero CHECK (UltimoNumero >= 0)
|
||||
);
|
||||
PRINT 'Table dbo.SecuenciaComprobante created.';
|
||||
END
|
||||
ELSE
|
||||
PRINT 'Table dbo.SecuenciaComprobante already exists — skip.';
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 3. SYSTEM_VERSIONING — PuntoDeVenta
|
||||
-- 2. SYSTEM_VERSIONING — PuntoDeVenta
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
IF COL_LENGTH('dbo.PuntoDeVenta', 'ValidFrom') IS NULL
|
||||
@@ -130,55 +145,7 @@ END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 4. SecuenciaComprobante — SIN SYSTEM_VERSIONING (decisión AD8 revisitada)
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- Razón: bajo reservas concurrentes (reportado 50 threads paralelos) el engine
|
||||
-- arroja "Data modification failed on system-versioned table because transaction
|
||||
-- time was earlier than period start" — UPDATEs repetidos sobre la misma fila
|
||||
-- en transacciones SERIALIZABLE concurrentes violan la invariante temporal.
|
||||
-- Ya anticipado en el design (AD8): la reserva es operacional, no configuracion.
|
||||
-- La auditoria del numero vigente no tiene valor de negocio: el estado actual
|
||||
-- (UltimoNumero) es la unica informacion relevante; cada comprobante emitido
|
||||
-- deja su propio rastro en AvisosCdo/CtaCte (modulos FAC-*).
|
||||
--
|
||||
-- Esta seccion es idempotente: si una version previa de la migracion dejo
|
||||
-- SYSTEM_VERSIONING = ON, lo desactiva y drop la history. En instalacion nueva
|
||||
-- no hace nada porque nunca se activo.
|
||||
|
||||
IF EXISTS (SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('dbo.SecuenciaComprobante') AND temporal_type = 2)
|
||||
BEGIN
|
||||
ALTER TABLE dbo.SecuenciaComprobante SET (SYSTEM_VERSIONING = OFF);
|
||||
PRINT 'SecuenciaComprobante: SYSTEM_VERSIONING = OFF (revisited AD8).';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SecuenciaComprobante_History', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
DROP TABLE dbo.SecuenciaComprobante_History;
|
||||
PRINT 'SecuenciaComprobante_History: dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
IF EXISTS (SELECT 1 FROM sys.periods WHERE object_id = OBJECT_ID('dbo.SecuenciaComprobante'))
|
||||
BEGIN
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP PERIOD FOR SYSTEM_TIME;
|
||||
PRINT 'SecuenciaComprobante: PERIOD FOR SYSTEM_TIME dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
IF COL_LENGTH('dbo.SecuenciaComprobante', 'ValidFrom') IS NOT NULL
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM sys.default_constraints WHERE name = 'DF_SecuenciaComprobante_ValidFrom' AND parent_object_id = OBJECT_ID('dbo.SecuenciaComprobante'))
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP CONSTRAINT DF_SecuenciaComprobante_ValidFrom;
|
||||
IF EXISTS (SELECT 1 FROM sys.default_constraints WHERE name = 'DF_SecuenciaComprobante_ValidTo' AND parent_object_id = OBJECT_ID('dbo.SecuenciaComprobante'))
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP CONSTRAINT DF_SecuenciaComprobante_ValidTo;
|
||||
ALTER TABLE dbo.SecuenciaComprobante DROP COLUMN ValidFrom, ValidTo;
|
||||
PRINT 'SecuenciaComprobante: ValidFrom/ValidTo + default constraints dropped.';
|
||||
END
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 5. Permiso: administracion:puntos-de-venta:gestionar
|
||||
-- 3. Permiso: administracion:puntos_de_venta:gestionar
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
MERGE dbo.Permiso AS t
|
||||
@@ -204,97 +171,9 @@ WHEN NOT MATCHED BY TARGET THEN
|
||||
INSERT (RolId, PermisoId) VALUES (s.RolId, s.PermisoId);
|
||||
GO
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- 6. SP: dbo.usp_ReservarNumeroComprobante
|
||||
-- ═══════════════════════════════════════════════════════════════════════
|
||||
-- Decisión AD1: SP con UPDATE+OUTPUT bajo SERIALIZABLE (lógica crítica en SP;
|
||||
-- permite validar PdV/Medio activos en DB; atómico sin race).
|
||||
-- Decisión AD2: patrón "UPDATE si existe, INSERT si @@ROWCOUNT=0" (lazy init;
|
||||
-- sin trigger; simple; no genera filas huérfanas).
|
||||
-- El retry ante deadlock (SqlException 1205) vive en el Application handler
|
||||
-- (ReservarNumeroCommandHandler), NO en este SP. Máx 3 intentos, 50/150/450ms.
|
||||
-- NO envolver la llamada en TransactionScope externo: el SP ya es atómico.
|
||||
-- Un TransactionScope externo con otra conexión escalaría a MSDTC innecesariamente.
|
||||
|
||||
IF OBJECT_ID(N'dbo.usp_ReservarNumeroComprobante', N'P') IS NOT NULL
|
||||
DROP PROCEDURE dbo.usp_ReservarNumeroComprobante;
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.usp_ReservarNumeroComprobante
|
||||
@PuntoDeVentaId INT,
|
||||
@TipoComprobante TINYINT,
|
||||
@NumeroReservado INT OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
|
||||
BEGIN TRAN;
|
||||
|
||||
-- Validar existencia y estado de PdV + Medio padre en una sola lectura.
|
||||
-- Con SERIALIZABLE, el lock de rango protege contra inserciones concurrentes
|
||||
-- de la misma fila de SecuenciaComprobante entre el SELECT y el UPDATE/INSERT.
|
||||
DECLARE @PdvActivo BIT;
|
||||
DECLARE @MedioActivo BIT;
|
||||
|
||||
SELECT
|
||||
@PdvActivo = p.Activo,
|
||||
@MedioActivo = m.Activo
|
||||
FROM dbo.PuntoDeVenta p
|
||||
JOIN dbo.Medio m ON m.Id = p.MedioId
|
||||
WHERE p.Id = @PuntoDeVentaId;
|
||||
|
||||
IF @PdvActivo IS NULL
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
THROW 50003, 'punto_de_venta_not_found', 1;
|
||||
END
|
||||
|
||||
IF @PdvActivo = 0
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
THROW 50001, 'punto_de_venta_inactivo', 1;
|
||||
END
|
||||
|
||||
IF @MedioActivo = 0
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
THROW 50002, 'medio_inactivo', 1;
|
||||
END
|
||||
|
||||
-- Intentar actualizar la fila existente y capturar el nuevo número.
|
||||
DECLARE @_out TABLE (n INT NOT NULL);
|
||||
|
||||
UPDATE dbo.SecuenciaComprobante
|
||||
SET
|
||||
UltimoNumero = UltimoNumero + 1,
|
||||
FechaModificacion = SYSUTCDATETIME()
|
||||
OUTPUT inserted.UltimoNumero INTO @_out(n)
|
||||
WHERE PuntoDeVentaId = @PuntoDeVentaId
|
||||
AND TipoComprobante = @TipoComprobante;
|
||||
|
||||
IF @@ROWCOUNT = 0
|
||||
BEGIN
|
||||
-- Primera reserva para este par (PdvId, TipoComprobante): inicialización lazy.
|
||||
INSERT INTO dbo.SecuenciaComprobante (PuntoDeVentaId, TipoComprobante, UltimoNumero)
|
||||
VALUES (@PuntoDeVentaId, @TipoComprobante, 1);
|
||||
SET @NumeroReservado = 1;
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
SELECT @NumeroReservado = n FROM @_out;
|
||||
END
|
||||
|
||||
COMMIT;
|
||||
END
|
||||
GO
|
||||
|
||||
PRINT '';
|
||||
PRINT 'V013 applied successfully.';
|
||||
PRINT ' - dbo.PuntoDeVenta (temporal, retention 10y, PAGE compression)';
|
||||
PRINT ' - dbo.SecuenciaComprobante (temporal, retention 10y, PAGE compression)';
|
||||
PRINT ' - Permiso administracion:puntos-de-venta:gestionar (asignado a admin)';
|
||||
PRINT ' - SP dbo.usp_ReservarNumeroComprobante';
|
||||
PRINT 'Next: Batch 2 — Domain (PuntoDeVenta entity + exceptions + TipoComprobante enum).';
|
||||
PRINT ' - Permiso administracion:puntos_de_venta:gestionar (asignado a admin)';
|
||||
PRINT ' - Artefactos de version previa (SecuenciaComprobante + SP) eliminados si existian';
|
||||
GO
|
||||
|
||||
Reference in New Issue
Block a user