--Hash:17E4E997BFDAE9878D6B8CEAEBB7F457

-- Bloqueo exclusivo por base de datos
--//
SET NOCOUNT ON;

DECLARE @__ZiurDbScriptLockResource NVARCHAR(200) = N'ZiurSoft:DbScriptLock:' + CAST(DB_ID() AS NVARCHAR(20));
DECLARE @__ZiurDbScriptLockResult INT;
EXEC @__ZiurDbScriptLockResult = sp_getapplock
    @Resource = @__ZiurDbScriptLockResource,
    @LockMode = N'Exclusive',
    @LockOwner = N'Session',
    @LockTimeout = 600000; -- 10 min

IF (@__ZiurDbScriptLockResult < 0)
BEGIN
    RAISERROR(N'No se pudo obtener el bloqueo exclusivo de actualizacion para esta base de datos.', 16, 1);
    SET NOEXEC ON;
END

/* Idempotencia a nivel de script: si la version ya existe, no ejecutar nada. */
IF EXISTS (SELECT 1 FROM dbo.ZiurVersiones WHERE NumVersion = 974)
BEGIN
    PRINT N'Scripts_974.sql: la version 974 ya esta aplicada. Se omite ejecucion.';
    EXEC sp_releaseapplock @Resource = @__ZiurDbScriptLockResource, @LockOwner = N'Session';
    SET NOEXEC ON;
END

SET XACT_ABORT ON;

GO

SET DATEFORMAT mdy;

--Validar que no existan scripts que no se hayan ejecutado
--//
IF EXISTS
(
	SELECT a.NumVersion + 1 AS HuecoInicio
	FROM ZiurVersiones a
	LEFT JOIN ZiurVersiones b ON a.NumVersion + 1 = b.NumVersion
	WHERE a.NumVersion>830 AND b.NumVersion IS NULL
	AND a.NumVersion + 1 < 974
)
RAISERROR('Error : hay un script que no se ejecuto , debe ejecutarlo manualmente.', 20, -1) with log
--//

--Colocar contenido de script diferencial aqui (Ziur.Database.publish.sql)

GO
/*
 Plantilla de script anterior a la implementación							
--------------------------------------------------------------------------------------
 Este archivo contiene instrucciones de SQL que se ejecutarán antes del script de compilación	
 Use la sintaxis de SQLCMD para incluir un archivo en el script anterior a la implementación			
 Ejemplo:      :r .\miArchivo.sql								
 Use la sintaxis de SQLCMD para hacer referencia a una variable en el script anterior a la implementación		
 Ejemplo:      :setvar TableName miTabla							
               SELECT * FROM [$(TableName)]					
--------------------------------------------------------------------------------------
*/

GO
GO

GO
PRINT N'Quitando Clave externa [dbo].[FK_DocElectronicos_Equivalencias_Clientes_TiposIdent]...';


GO
IF OBJECT_ID(N'dbo.DocElectronicos_Equivalencias', N'U') IS NOT NULL
AND EXISTS (
    SELECT 1
    FROM sys.foreign_keys
    WHERE name = N'FK_DocElectronicos_Equivalencias_Clientes_TiposIdent'
      AND parent_object_id = OBJECT_ID(N'dbo.DocElectronicos_Equivalencias')
)
    ALTER TABLE [dbo].[DocElectronicos_Equivalencias] DROP CONSTRAINT [FK_DocElectronicos_Equivalencias_Clientes_TiposIdent];


GO
PRINT N'Modificando Tabla [dbo].[DocElectronicos_Equivalencias]...';


GO
ALTER TABLE [dbo].[DocElectronicos_Equivalencias] ALTER COLUMN [Identificacion] NVARCHAR (100) NULL;

ALTER TABLE [dbo].[DocElectronicos_Equivalencias] ALTER COLUMN [IdTipoIdent] INT NULL;


GO
IF OBJECT_ID(N'dbo.DocElectronicos_Equivalencias', N'U') IS NOT NULL
AND COL_LENGTH(N'dbo.DocElectronicos_Equivalencias', N'ValorIva') IS NULL
BEGIN
    ALTER TABLE [dbo].[DocElectronicos_Equivalencias]
        ADD [ValorIva] NUMERIC (28, 6) NULL;
END


GO
PRINT N'Creando Clave externa [dbo].[FK_DocElectronicos_Equivalencias_Clientes_TiposIdent]...';


GO
IF OBJECT_ID(N'dbo.DocElectronicos_Equivalencias', N'U') IS NOT NULL
AND NOT EXISTS (
    SELECT 1
    FROM sys.foreign_keys
    WHERE name = N'FK_DocElectronicos_Equivalencias_Clientes_TiposIdent'
      AND parent_object_id = OBJECT_ID(N'dbo.DocElectronicos_Equivalencias')
)
BEGIN
    ALTER TABLE [dbo].[DocElectronicos_Equivalencias] WITH NOCHECK
        ADD CONSTRAINT [FK_DocElectronicos_Equivalencias_Clientes_TiposIdent] FOREIGN KEY ([IdTipoIdent]) REFERENCES [dbo].[Clientes_TiposIdent] ([IdTipoIdent]);
END


GO
PRINT N'Modificando Procedimiento [dbo].[GenerarDocumentos]...';

IF OBJECT_ID(N'dbo.GenerarDocumentos', N'P') IS NULL
    EXEC(N'CREATE PROCEDURE dbo.GenerarDocumentos AS BEGIN SET NOCOUNT ON; RETURN 0; END');


GO
ALTER PROCEDURE GenerarDocumentos
    @IdDoc INT,
    @IdEncabNew INT OUTPUT,
    @Exito INT = 0 OUTPUT,
    @MensajeError NVARCHAR(200) OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        DECLARE @IdEncab INT;
        DECLARE @XML XML;
        DECLARE @NumeroFactura VARCHAR(50);
        DECLARE @FechaFactura DATE;
        DECLARE @ValorTotal DECIMAL(18,2);
        DECLARE @TipoDocumento VARCHAR(100);
        DECLARE @Mensaje VARCHAR(500);
        DECLARE @ResponseID VARCHAR(50);
        DECLARE @FacturaRef VARCHAR(50);
        
        -- Variables para datos del XML
        DECLARE @NitProveedor VARCHAR(50);
        DECLARE @NombreProveedor VARCHAR(200);
        DECLARE @CodigoMoneda VARCHAR(10);
        DECLARE @TipoFactura VARCHAR(10);
        DECLARE @UnidadMedida VARCHAR(10);
        DECLARE @TipoIdentProveedor VARCHAR(10);
        
        -- Variables para dirección del cliente
        DECLARE @DireccionCliente VARCHAR(500);
        DECLARE @TelefonoCliente VARCHAR(50);
        DECLARE @EmailCliente VARCHAR(100);
        DECLARE @IdCiudadCliente VARCHAR(20);
        DECLARE @IdFormaPago VARCHAR(10);
        DECLARE @PlazoCliente INT;
        DECLARE @Vence DATE;
        
        -- Variables para cálculos
        DECLARE @Cantidad DECIMAL(18,6);
        DECLARE @BaseImpuesto DECIMAL(18,2);
        DECLARE @ValorImpuesto DECIMAL(18,2);
        DECLARE @ValorIva DECIMAL(18,2);
        DECLARE @SubTotal DECIMAL(18,2);
        DECLARE @DescuentoTotal DECIMAL(18,2);
        DECLARE @FactorDescuento DECIMAL(18,6);

        -- Variables para datos del XML
        DECLARE @NitEmpresa VARCHAR(50);
        DECLARE @CiudadBodega VARCHAR(50);
        DECLARE @CodigoCiudad VARCHAR(10);

        DECLARE @IdTipoIdent INT;
        DECLARE @TaxLevelCode VARCHAR(200);
        DECLARE @IdTipoRegimen INT;

        -- Obtenemos el XML
        SELECT @XML = CAST(PR.Recurso AS XML)
        FROM dbo.DocElectronicos DE 
        INNER JOIN dbo.DocElectronicos_DocRecursos DR ON DE.IdDoc = DR.IdDoc 
        INNER JOIN dbo.Parametros_Recursos PR ON DR.IdRecurso = PR.IdRecurso
        WHERE DE.IdDoc = @IdDoc
        AND DR.IdTipo = 0;

        IF @XML IS NULL
        BEGIN
            RAISERROR('No se encontró el documento XML para el ID especificado.', 16, 1);
            RETURN;
        END;

        -- Verificamos el tipo de documento
        SET @TipoDocumento = @XML.value('local-name(/*[1])', 'varchar(100)');
        
        IF @TipoDocumento = 'ApplicationResponse'
        BEGIN
            WITH XMLNAMESPACES (
                'urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2' as ar,
                'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' as cbc,
                'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' as cac
            )
            SELECT 
                @ResponseID = @XML.value('(/ar:ApplicationResponse/cbc:ID)[1]', 'varchar(50)'),
                @FacturaRef = @XML.value('(/ar:ApplicationResponse/cac:DocumentResponse/cac:DocumentReference/cbc:ID)[1]', 'varchar(50)');

            SET @Mensaje = 'Este documento es un ApplicationResponse (ID: ' + ISNULL(@ResponseID, 'N/A') + 
                          ') que hace referencia a la factura: ' + ISNULL(@FacturaRef, 'N/A');
            RAISERROR(@Mensaje, 16, 1);
            RETURN;
        END;

        IF @TipoDocumento != 'Invoice'
        BEGIN
            SET @Mensaje = 'El documento no es una factura válida. Tipo de documento: ' + ISNULL(@TipoDocumento, 'Desconocido');
            RAISERROR(@Mensaje, 16, 1);
            RETURN;
        END;

        -- Extraemos todos los datos relevantes del XML
        WITH XMLNAMESPACES (
            'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2' as inv,
            'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' as cbc,
            'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' as cac
        )
        SELECT 
            -- Datos básicos del documento
            @NumeroFactura = @XML.value('(/inv:Invoice/cbc:ID)[1]', 'varchar(50)'),
            @FechaFactura = @XML.value('(/inv:Invoice/cbc:IssueDate)[1]', 'date'),
            @TipoFactura = @XML.value('(/inv:Invoice/cbc:InvoiceTypeCode)[1]', 'varchar(10)'),
            @CodigoMoneda = @XML.value('(/inv:Invoice/cbc:DocumentCurrencyCode)[1]', 'varchar(10)'),
            
            -- Datos de la empresa receptora (para determinar IdEmpresa)
            @NitEmpresa = @XML.value('(/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID)[1]', 'varchar(50)'),
            
            -- Datos de ubicación (para determinar bodega)
            @CiudadBodega = @XML.value('(/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CityName)[1]', 'varchar(50)'),
            @CodigoCiudad = @XML.value('(/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:ID)[1]', 'varchar(10)'),
            
            -- Datos del proveedor
            @NitProveedor = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID)[1]', 'varchar(50)'),
            @NombreProveedor = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name)[1]', 'varchar(200)'),
            @TipoIdentProveedor = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID/@schemeName)[1]', 'varchar(10)'),
            
            -- Datos del producto/servicio
            @UnidadMedida = @XML.value('(/inv:Invoice/cac:InvoiceLine/cbc:InvoicedQuantity/@unitCode)[1]', 'varchar(10)'),
            
            -- Datos del proveedor y su dirección
            @DireccionCliente = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:AddressLine/cbc:Line)[1]', 'varchar(500)'),
            @TelefonoCliente = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:Telephone)[1]', 'varchar(50)'),
            @EmailCliente = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:ElectronicMail)[1]', 'varchar(100)'),
            @IdCiudadCliente = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:ID)[1]', 'varchar(20)'),
            @IdFormaPago = @XML.value('(/inv:Invoice/cac:PaymentMeans/cbc:ID)[1]', 'varchar(10)'),
            
            -- Cantidades y valores
            @Cantidad = @XML.value('(/inv:Invoice/cac:InvoiceLine/cbc:InvoicedQuantity)[1]', 'decimal(18,6)'),
            --@ValorUnitarioItem = @XML.value('(/inv:Invoice/cac:InvoiceLine/cac:Price/cbc:PriceAmount)[1]', 'decimal(18,2)'),
            @BaseImpuesto = @XML.value('(/inv:Invoice/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount)[1]', 'decimal(18,2)'),
            @ValorImpuesto = @XML.value('(/inv:Invoice/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount)[1]', 'decimal(18,2)'),
            @SubTotal = @XML.value('(/inv:Invoice/cac:LegalMonetaryTotal/cbc:LineExtensionAmount)[1]', 'decimal(18,2)'),
            @DescuentoTotal = @XML.value('(/inv:Invoice/cac:LegalMonetaryTotal/cbc:AllowanceTotalAmount)[1]', 'decimal(18,2)'),
            @ValorTotal = @XML.value('(/inv:Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount)[1]', 'decimal(18,2)'),

            @IdTipoIdent = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID/@schemeName)[1]', 'int'),
            @TaxLevelCode = @XML.value('(/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode)[1]', 'varchar(50)'),
           
            @IdTipoRegimen =
            CASE
                WHEN @IdTipoIdent = 42 THEN 9 -- Tercero del Exterior
                WHEN @IdTipoIdent = 13 AND @TaxLevelCode LIKE '%O-15%' THEN 10 -- Gran Contribuyente Persona Natural
                WHEN @IdTipoIdent = 13 AND @TaxLevelCode = 'R-99-PN' THEN 6 -- Persona Natural No Responsable de IVA
                WHEN @IdTipoIdent = 13 THEN 2 -- Persona Natural Responsable de IVA
                WHEN @IdTipoIdent = 31 AND @TaxLevelCode LIKE '%O-15%' THEN 4 -- Gran Contribuyente
                WHEN @IdTipoIdent = 31 THEN 3 -- Persona Jurídica
                ELSE 6
            END

        -- Validamos que tengamos los datos mínimos necesarios
        IF @NumeroFactura IS NULL OR @FechaFactura IS NULL OR @ValorTotal IS NULL OR @NitProveedor IS NULL
        BEGIN
            RAISERROR('No se pudieron extraer todos los datos necesarios de la factura.', 16, 1);
            RETURN;
        END;

        --crea una equivalencia generica cuando no existe ninguna definida
        --//
        IF NOT EXISTS (SELECT 1 FROM DocElectronicos_Equivalencias WHERE IdTipoIdent = @IdTipoIdent AND Identificacion = @NitProveedor)
        BEGIN
            INSERT INTO DocElectronicos_Equivalencias (IdTipoIdent, Identificacion, NombreCompleto)
            VALUES (@IdTipoIdent, @NitProveedor, @NombreProveedor);
            RAISERROR('Doc %s, No tiene definida la contabilización en caso de que se cree un producto nuevo.', 16, 1, @NumeroFactura);
            RETURN;
        END
        --//

        -- Validamos que el documento no exista
        --//
        IF EXISTS (SELECT 1 FROM Encabezados WHERE NumDocumentoExt = @NumeroFactura)
        BEGIN
            RAISERROR('El documento %s ya existe en el sistema.', 16, 1, @NumeroFactura);
            RETURN;
        END;
        --//

        --Se inicia aqui la transaccion para que se haga el insert de DocElectronicos_Equivalencias
        BEGIN TRANSACTION;

        -- Buscamos o creamos el proveedor si no existe
        DECLARE @IdCliente INT;
        SELECT TOP 1 @IdCliente = IdCliente FROM Clientes WHERE Identificacion = @NitProveedor;

        -- Si el cliente no existe, lo creamos junto con su dirección
        IF @IdCliente IS NULL
        BEGIN
            -- Calculamos el DV
            DECLARE @DVCliente VARCHAR(2) = NULL;
            IF @TipoIdentProveedor=31
                SET @DVCliente = dbo.GetDigitoVerificacion(@NitProveedor);

            -- Insertamos el cliente
            INSERT INTO Clientes (
                Identificacion,
                Nombre1,
                EsActivo,
                IdTipoIdent,
                DVCliente,
                IdTipoRegimen,
                TarifaIca,
                CupoCreditoPlazo,
                ComisionTiene,
                IdPais,
                FechaCreacion,
                FechaUltModificacion
            )
            VALUES (
                @NitProveedor,
                @NombreProveedor,
                1,
                @IdTipoIdent,
                @DVCliente,
                @IdTipoRegimen,
                NULL,
                NULL,
                NULL,
                48,
                GETDATE(),
                GETDATE()
            );
            
            SET @IdCliente = SCOPE_IDENTITY();

            -- Obtenemos el IdTipoDir mínimo
            DECLARE @IdTipoDir INT;
            SELECT @IdTipoDir = MIN(IdTipoDir) FROM Clientes_TiposDireccion;

            -- Insertamos la dirección del cliente
            INSERT INTO Clientes_Direcciones (
                IdCliente,
                IdTipoDir,
                Direccion,
                DireccionFormato1,
                DireccionFormato2,
                Telefonos,
                Celular,
                Email,
                IdCiudad,
                Nota,
                EsDirPrincipal,
                Subdivision,
                CodigoPostal
            )
            VALUES (
                @IdCliente,
                @IdTipoDir,
                @DireccionCliente,
                @DireccionCliente,
                @DireccionCliente,
                @TelefonoCliente,
                @TelefonoCliente,
                @EmailCliente,
                @IdCiudadCliente,
                NULL,
                1,
                NULL,
                NULL
            );

            -- Insertamos las asociaciones del cliente
            INSERT INTO Clientes_Asociacion (IdCliente, IdTipo) VALUES (@IdCliente, 5);
            INSERT INTO Clientes_Asociacion (IdCliente, IdTipo) VALUES (@IdCliente, 8);
        END;

        -- Obtenemos el IdClienteDir principal
        DECLARE @IdClienteDir INT;
        SELECT @IdClienteDir = MAX(idclientedir) 
        FROM Clientes_Direcciones 
        WHERE EsDirPrincipal = 1 AND IdCliente = @IdCliente;

        -- Obtenemos el plazo del cliente
        SELECT @PlazoCliente = ISNULL(CupoCreditoPlazo, 0) 
        FROM Clientes 
        WHERE IdCliente = @IdCliente;

        -- Buscamos el ID de la moneda
        DECLARE @IdMoneda INT;
        IF @CodigoMoneda = 'COP'
            SET @IdMoneda = 1; -- Asumimos que 1 es el ID para COP
        ELSE
        BEGIN
            SELECT TOP 1 @IdMoneda = IdMoneda
            FROM Monedas
            WHERE Abrev = @CodigoMoneda
            OR NomMoneda1 = @CodigoMoneda;

            IF @IdMoneda IS NULL
                SET @IdMoneda = 1; -- Default a COP si no se encuentra
        END;

        -- Buscamos el tipo de documento basado en el código DIAN
        DECLARE @IdDocumento INT;
        SELECT TOP 1 @IdDocumento = IdDocumento
        FROM Documentos
        WHERE FeIdDocumentoDian = @TipoFactura;

        IF @IdDocumento IS NULL
            SET @IdDocumento = 13; -- Default a Comprobante de Egreso si no se encuentra

        SET @FactorDescuento=0

        -- Calculamos el factor de descuento
        --SET @FactorDescuento = CASE 
        --    WHEN @SubTotal > 0 THEN (@DescuentoTotal / @SubTotal) * 100
        --    ELSE 0
        --END;

        -- Buscamos la empresa por su NIT
        DECLARE @IdEmpresa INT;
        SELECT TOP 1 @IdEmpresa = IdEmpresa
        FROM Empresas
        WHERE EmpresaNit = @NitEmpresa;

        IF @IdEmpresa IS NULL
        BEGIN
            RAISERROR('No se encontró la empresa con NIT: %s', 16, 1, @NitEmpresa);
            RETURN;
        END;

        -- Bodega principal predterminada
        DECLARE @IdBodega INT = 1; -- Valor por defecto
        SET @Vence = DATEADD(day, @PlazoCliente, @FechaFactura)

        -- Insertar en Encabezados
        INSERT INTO Encabezados (
            IdEmpresa,
            IdDocumento,
            NumDocumentoExt,
            Fecha,
            IdCliente1,
            IdCliente1_IdDir,
            IdMoneda,
            ValorTRM,
            ValorPago,
            Nota,
            IdFormaPago,
            Vence,
            FechaCreacion,
            FechaUltModificacion
        )
        VALUES (
            @IdEmpresa,
            CASE 
                WHEN EXISTS (SELECT 1 FROM DocElectronicos WHERE IdDoc = @IdDoc AND TipoDoc = 'Factura electrónica')
                THEN 1
                ELSE @IdDocumento
            END,
            @NumeroFactura,
            @FechaFactura,
            @IdCliente,
            @IdClienteDir,
            @IdMoneda,
            0,                  -- ValorTRM siempre 0
            0,
            'Importado automáticamente',
            @IdFormaPago,
            @Vence,
            GETDATE(),
            GETDATE()
        );

        SET @IdEncab = SCOPE_IDENTITY();


        --*************************************************************************
		--ITERAR ITEMS
        DECLARE @TotalItems INT
        DECLARE @Index INT = 1
        DECLARE @IdInventario INT;
        DECLARE @IdUnidad INT = 1; -- Valor por defecto
        DECLARE @CodInventario VARCHAR(50);
        DECLARE @CodInventario2 VARCHAR(50);
        DECLARE @NomInventario VARCHAR(500);
        DECLARE @ValorUnitario NUMERIC(18,2);

        --Equivalencias
        DECLARE @EqSenFind                 BIT;
        DECLARE @EqIdEquiv                 INT;
        DECLARE @EqIdInventario            INT;
        DECLARE @EqIdTipoInv               INT;
        DECLARE @EqIdContab               INT;
        DECLARE @EqCodInventario_Pref      NVARCHAR(50);

        -- Contar cuántos nodos hay
		WITH XMLNAMESPACES (
			'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2' AS inv,
			'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' AS cac,
			'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' AS cbc
		)
		SELECT @TotalItems = @XML.value('count(/inv:Invoice/cac:InvoiceLine)', 'int')
        PRINT '@TotalItems: ' + CONVERT(VARCHAR, @TotalItems)


        -- Bucle para procesar cada uno
        WHILE @Index <= @TotalItems
        BEGIN
            -- Inicializar
            SET @EqSenFind                 = 0;
            SET @EqIdEquiv                 = NULL;
            SET @EqIdInventario            = NULL;
            SET @EqIdTipoInv               = NULL;
            SET @EqIdContab                = NULL;
            SET @EqCodInventario_Pref      = NULL;

            -- Extraer valores del XML
            WITH XMLNAMESPACES (
                'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2' AS inv,
                'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' AS cac,
                'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' AS cbc
            )
            SELECT
                @CodInventario = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cbc:ID)[1]', 'varchar(20)'),
                @CodInventario2 = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cac:Item/cac:StandardItemIdentification/cbc:ID)[1]', 'varchar(20)'),
                @NomInventario = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cac:Item/cbc:Description)[1]', 'varchar(500)'),
                @Cantidad = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cbc:InvoicedQuantity)[1]', 'decimal(18,2)'),
                @ValorTotal = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cbc:LineExtensionAmount)[1]', 'decimal(18,2)'),
                @ValorUnitario = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cac:Price/cbc:PriceAmount )[1]', 'numeric(18,2)'),
                @ValorIva = @XML.value('(//inv:Invoice/cac:InvoiceLine[position()=sql:variable("@Index")]/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent)[1]', 'decimal(18,2)');

            -- Revisa si tiene el codigo personalizado o uno generico
            SET @CodInventario = COALESCE(@CodInventario2, @CodInventario);
            SET @ValorIva = COALESCE(@ValorIva, 0);

            --Caso Equivalencias NomInventario
            --//
            IF (@EqSenFind=0)
            BEGIN
                SELECT @EqIdEquiv = IdEquiv , @EqIdInventario = IdInventario,  @EqIdTipoInv = IdTipoInv, @EqIdContab= IdContab, @EqCodInventario_Pref = CodInventario_Pref
                FROM DocElectronicos_Equivalencias 
                WHERE 
                (IdTipoIdent = @IdTipoIdent AND Identificacion=@NitProveedor) AND 
                (NomInventario_Operador IS NOT NULL AND NomInventario IS NOT NULL) AND 
                (
                    (NomInventario_Operador = 0 AND @NomInventario = NomInventario ) OR
                    (NomInventario_Operador = 1 AND @NomInventario LIKE '%' + NomInventario + '%') OR
                    (NomInventario_Operador = 2 AND @NomInventario LIKE NomInventario + '%') OR
                    (NomInventario_Operador = 3 AND @NomInventario LIKE '%' + NomInventario)
                ) AND
                (ValorIva = @ValorIva OR ValorIva IS NULL)
                ORDER BY CASE WHEN ValorIva = @ValorIva THEN 1 WHEN ValorIva IS NULL THEN 2 END;

                IF @EqIdEquiv IS NOT NULL
                    SET @EqSenFind = 1
            END
            --//

            --Caso Equivalencias CodInventario
            --//
            IF (@EqSenFind=0)
            BEGIN
                SELECT @EqIdEquiv = IdEquiv , @EqIdInventario = IdInventario,  @EqIdTipoInv = IdTipoInv, @EqIdContab= IdContab, @EqCodInventario_Pref = CodInventario_Pref
                FROM DocElectronicos_Equivalencias 
                WHERE 
                (IdTipoIdent = @IdTipoIdent AND Identificacion=@NitProveedor) AND 
                (CodInventario_Operador IS NOT NULL AND CodInventario IS NOT NULL) AND 
                (
                    (CodInventario_Operador = 0 AND @CodInventario = CodInventario ) OR
                    (CodInventario_Operador = 1 AND @CodInventario LIKE '%' + CodInventario + '%') OR
                    (CodInventario_Operador = 2 AND @CodInventario LIKE CodInventario + '%') OR
                    (CodInventario_Operador = 3 AND @CodInventario LIKE '%' + CodInventario)
                ) AND
                (ValorIva = @ValorIva OR ValorIva IS NULL)
                ORDER BY CASE WHEN ValorIva = @ValorIva THEN 1 WHEN ValorIva IS NULL THEN 2 END;

                IF @EqIdEquiv IS NOT NULL
                    SET @EqSenFind = 1
            END
            --//

            --Caso Equivalencias General por TipoIdent y Proveedor
            --//
            IF (@EqSenFind=0)
            BEGIN
                SELECT TOP 1 @EqIdEquiv = IdEquiv , @EqIdInventario = IdInventario,  @EqIdTipoInv = IdTipoInv, @EqIdContab= IdContab, @EqCodInventario_Pref = CodInventario_Pref
                FROM DocElectronicos_Equivalencias 
                WHERE 
                (IdTipoIdent = @IdTipoIdent AND Identificacion=@NitProveedor) AND
                (ValorIva = @ValorIva OR ValorIva IS NULL)
                ORDER BY CASE WHEN ValorIva = @ValorIva THEN 1 WHEN ValorIva IS NULL THEN 2 END;

                IF @EqIdEquiv IS NOT NULL
                    SET @EqSenFind = 1
            END
            --//

            --Caso Equivalencias General
            --//
            IF (@EqSenFind=0)
            BEGIN
                SELECT TOP 1 @EqIdEquiv = IdEquiv , @EqIdInventario = IdInventario,  @EqIdTipoInv = IdTipoInv, @EqIdContab= IdContab, @EqCodInventario_Pref = CodInventario_Pref
                FROM DocElectronicos_Equivalencias 
                WHERE 
                (ValorIva = @ValorIva OR ValorIva IS NULL)
                ORDER BY CASE WHEN ValorIva = @ValorIva THEN 1 WHEN ValorIva IS NULL THEN 2 END;

                IF @EqIdEquiv IS NOT NULL
                    SET @EqSenFind = 1
            END
            --//

            IF (@EqSenFind =0)
            BEGIN
                DECLARE @NomTipoIdent NVARCHAR(100);
                SELECT @NomTipoIdent = NomTipoIdent FROM Clientes_TiposIdent WHERE IdTipoIdent = @IdTipoIdent;

                RAISERROR('Doc %s : No se encontró configuración de equivalencia con TipoIdent: %s y Número: %s', 16, 1, @NumeroFactura, @NomTipoIdent, @NitProveedor);
                RETURN;
            END;

            --Obtener el id del inventario
            --//
            DECLARE @CodInventarioFull NVARCHAR(50);
            DECLARE @tIdTipoInv INT = NULL;

            SET @CodInventarioFull = COALESCE(@EqCodInventario_Pref, '') + @CodInventario;

            IF (@EqIdInventario IS NULL)
            BEGIN
                SELECT TOP 1 @IdInventario = IdInventario, @tIdTipoInv = IdTipoInv FROM Inventarios WHERE CodInventario = @CodInventarioFull;

                --Validar si es un producto o gasto (1,5)
                --//
                IF (@IdInventario IS NOT NULL) AND @tIdTipoInv NOT IN (1, 5)
                BEGIN
                    RAISERROR('Doc %s : El inventario relacionado con el código %s no es un producto o gasto', 16, 1, @NumeroFactura, @CodInventarioFull);
                    RETURN;
                END
                --//

                --Validar si toca crear un producto y no tiene una contabilizacion definida
                --//
                IF (@IdInventario IS NULL) AND (@EqIdContab IS NULL)
                BEGIN
                    RAISERROR('Doc %s : No existe una contabilización definida, para la creación del producto %s', 16, 1, @NumeroFactura, @CodInventarioFull);
                    RETURN;
                END
                --//

                IF @IdInventario IS NULL
                BEGIN
                    -- Aquí deberíamos insertar el nuevo producto
                    INSERT INTO Inventarios 
                    (
                        CodInventario,
                        NomInventario,
                        EsActivo,
                        CantMaxima,
                        CantMinima, 
                        PuntoReorden,
                        IdUnidad,
                        ValorIva,
                        IdTipoInv,
                        IdContab,
                        ValorImptoConsumo,
                        ValorUtilidadEst,
                        TipoVentaKit,
                        FechaCreacion,
                        FechaUltModificacion
                    )
                    VALUES (
                        @CodInventarioFull,
                        @NomInventario,
                        1,
                        NULL,
                        NULL,
                        NULL,
                        1,
                        @ValorIva,
                        COALESCE(@EqIdTipoInv,1),
                        @EqIdContab,
                        NULL,
                        NULL,
                        NULL,
                        GETDATE(),
                        GETDATE()
                    );
            
                    SET @IdInventario = SCOPE_IDENTITY();
                END;
            END;
            ELSE
            BEGIN
                SET @IdInventario = @EqIdInventario;
            END;
            --//

            --Verificar si el producto tiene contabilizacion
            --//
            DECLARE @tIdContab INT = NULL
            SELECT @tIdContab = IdContab from Inventarios where IdInventario = @IdInventario
            IF (@tIdContab IS NULL)
            BEGIN
                RAISERROR('Doc %s : No se encontró una contabilización para el inventario : %s', 16, 1, @NumeroFactura, @CodInventarioFull);
                RETURN;
            END
            --//

            -- Insertar movimiento inventario
            INSERT INTO Encabezados_Mov (
                IdEncab,
                IdInventario,
                IdBodega,
                IdLote,
                Cantidad,
                CantidadFisica,
                IdUnidad,
                FactorCantidad,
                FactorMovim,
                ValorUnitario,
                ValorUnitarioExt,
                ValorIva,
                ValorImptoConsumo,
                TotalMov,
                IdCliente,
                IdMoneda,
                Nota,
                Vence,
                IdCentroCosto,
                Dcto,
                FechaCreacion,
                FechaUltModificacion
            )
            VALUES (
                @IdEncab,
                @IdInventario,     -- Ya era dinámico
                @IdBodega,         -- Ahora dinámico basado en la ubicación
                NULL,              -- IdLote
                @Cantidad,         -- Ya era dinámico
                NULL,              -- CantidadFisica
                @IdUnidad,         -- Ya era dinámico
                @Cantidad,         -- Ya era dinámico
                1,                 -- FactorMovim
                @ValorUnitario,    -- Ya era dinámico
                NULL,              -- ValorUnitarioExt
                @ValorIva, -- Ya era dinámico
                0.000000,          -- ValorImptoConsumo
                NULL,       -- Ya era dinámico
                @IdCliente,        -- Ya era dinámico
                1,
                'Factura XML: ' + @NumeroFactura + ' - ' + @NomInventario,
                @Vence,              -- Vence
                NULL,              -- IdCentroCosto
                @FactorDescuento,   -- Ya era dinámico
                GETDATE(),
                GETDATE()
            );

            SET @Index = @Index + 1
        END

        -- Retornamos el ID del encabezado creado
        SELECT @IdEncab as IdEncabezado;
        SET @IdEncabNew = @IdEncab;

        --Contabilizar Documento
        --//
        EXEC [dbo].[ContabilizarDoc] @IdEncab = @IdEncab, @Exito = @Exito OUTPUT, @InfoUsuario = N'0,--BASEDATOS--';
        --//

        SET @Exito = NULL

        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        --si hay error hace rollback de la transacción
        IF XACT_STATE() <> 0    
            ROLLBACK TRANSACTION;

        DECLARE @ErrorMsg NVARCHAR(4000) = ERROR_MESSAGE();
        RAISERROR(@ErrorMsg, 16, 1);
    END CATCH;
END;
GO
	/*
	Plantilla de script posterior a la implementación							
	--------------------------------------------------------------------------------------
	 Este archivo contiene instrucciones de SQL que se anexarán al script de compilación.		
	 Use la sintaxis de SQLCMD para incluir un archivo en el script posterior a la implementación.			
	 Ejemplo:      :r .\miArchivo.sql								
	 Use la sintaxis de SQLCMD para hacer referencia a una variable en el script posterior a la implementación.		
	 Ejemplo:      :setvar TableName miTabla							
				   SELECT * FROM [$(TableName)]					
	--------------------------------------------------------------------------------------
	*/

	
GO

GO
PRINT N'Comprobando los datos existentes con las restricciones recién creadas';





GO
IF OBJECT_ID(N'dbo.DocElectronicos_Equivalencias', N'U') IS NOT NULL
AND EXISTS (
    SELECT 1
    FROM sys.foreign_keys
    WHERE name = N'FK_DocElectronicos_Equivalencias_Clientes_TiposIdent'
      AND parent_object_id = OBJECT_ID(N'dbo.DocElectronicos_Equivalencias')
)
    ALTER TABLE [dbo].[DocElectronicos_Equivalencias] WITH CHECK CHECK CONSTRAINT [FK_DocElectronicos_Equivalencias_Clientes_TiposIdent];


GO
PRINT N'Actualización completada.';


GO


--Actualizar datos de la version

IF NOT EXISTS (SELECT 1 FROM dbo.ZiurVersiones WHERE NumVersion = 974)
BEGIN
    INSERT INTO dbo.ZiurVersiones (IdVersion, NumVersion, Descripcion)
    VALUES (384, 974, 'Implementar Valor IVA');
END
GO


/* Liberar bloqueo exclusivo por base de datos */
DECLARE @__ZiurDbScriptLockResourceEnd NVARCHAR(200) = N'ZiurSoft:DbScriptLock:' + CAST(DB_ID() AS NVARCHAR(20));
EXEC sp_releaseapplock
    @Resource = @__ZiurDbScriptLockResourceEnd,
    @LockOwner = N'Session';
GO
