IF OBJECT_ID('dbo.sp_Api5_pvtMovCajaEncAperturaCreate','P') IS NOT NULL
    DROP PROCEDURE dbo.sp_Api5_pvtMovCajaEncAperturaCreate;
GO
CREATE PROCEDURE dbo.sp_Api5_pvtMovCajaEncAperturaCreate
    @correlativo        BIGINT,
    @tipo               INT,
    @tipomovimiento     INT,
    @caja               INT,              -- ? INT (tabla pvtCajas.codigo es INT)
    @sucursal           INT,              -- ? INT (tabla pvtCajas.sucursal es INT)
    @cajero             INT,
    @fechainicio        DATETIME     = NULL,
    @montocaja          DECIMAL(18,2),
    @monto              DECIMAL(18,2) = NULL,
    @fechacierre        DATETIME     = NULL,
    @correlativocierre  BIGINT       = NULL,
    @comentario         NVARCHAR(500) = NULL,
    @estado             INT          = 0,
    @login_id           NVARCHAR(100),
    @host               NVARCHAR(100) = NULL,
    @unineg             NVARCHAR(50)  = NULL,
    @tipdoc             INT           = NULL,
    @numdoc             INT           = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @now DATETIME = GETDATE();
    DECLARE @fi  DATETIME = ISNULL(@fechainicio, @now);
    DECLARE @rowsMovEnc   INT = 0;
    DECLARE @rowsCajas    INT = 0;
    DECLARE @rowsRegCajas INT = 0;
    DECLARE @existed      BIT = 0;

    -- ?? Menos fenómenos de carrera: serializa lectura/actualización por clave
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

    BEGIN TRY
        BEGIN TRAN;

        ----------------------------------------------------------------------
        -- 1) pvtMovCajaEnc: idempotencia por (tipo, correlativo)
        --    Si existe, actualiza campos clave; si no, inserta.
        ----------------------------------------------------------------------
        IF EXISTS (
            SELECT 1
            FROM dbo.pvtMovCajaEnc WITH (UPDLOCK, HOLDLOCK)
            WHERE tipo = @tipo AND correlativo = @correlativo
        )
        BEGIN
            SET @existed = 1;

            UPDATE E
               SET E.tipomovimiento   = @tipomovimiento,
                   E.caja             = CONVERT(NVARCHAR(20), @caja),
                   E.sucursal         = CONVERT(NVARCHAR(20), @sucursal),
                   E.cajero           = @cajero,
                   E.fechainicio      = ISNULL(E.fechainicio, @fi),
                   E.montocaja        = @montocaja,
                   E.monto            = ISNULL(@monto, E.monto),
                   E.comentario       = COALESCE(@comentario, E.comentario),
                   E.estado           = ISNULL(@estado, E.estado),
                   E.logmod           = @login_id,
                   E.fecmod           = @now,
                   E.unineg           = COALESCE(@unineg, E.unineg),
                   E.tipdoc           = COALESCE(@tipdoc, E.tipdoc),
                   E.numdoc           = COALESCE(@numdoc, E.numdoc)
            FROM dbo.pvtMovCajaEnc AS E WITH (UPDLOCK, HOLDLOCK)
            WHERE E.tipo = @tipo AND E.correlativo = @correlativo;

            SET @rowsMovEnc = @@ROWCOUNT;
        END
        ELSE
        BEGIN
            INSERT INTO dbo.pvtMovCajaEnc
            (
                correlativo, tipo, tipomovimiento, caja, sucursal, cajero,
                fechainicio, montocaja, monto, fechacierre, correlativocierre,
                comentario, estado, loging, logmod, unineg, tipdoc, numdoc
            )
            VALUES
            (
                @correlativo, @tipo, @tipomovimiento,
                CONVERT(NVARCHAR(20), @caja),
                CONVERT(NVARCHAR(20), @sucursal),
                @cajero,
                @fi, @montocaja, ISNULL(@monto,0), NULL, @correlativocierre,
                @comentario, ISNULL(@estado,0), @login_id, @login_id,
                @unineg, @tipdoc, @numdoc
            );

            SET @rowsMovEnc = @@ROWCOUNT;
        END

        ----------------------------------------------------------------------
        -- 2) pvtRegistroCajas: registra evento (evita duplicado evidente)
        ----------------------------------------------------------------------
        INSERT INTO dbo.pvtRegistroCajas (sucursal, caja, idcierre, host, loging, logmod)
        SELECT CONVERT(NVARCHAR(20),@sucursal),
               CONVERT(NVARCHAR(20),@caja),
               0,
               ISNULL(@host, @login_id),
               @login_id,
               @login_id
        WHERE NOT EXISTS (
            SELECT 1
            FROM dbo.pvtRegistroCajas WITH (UPDLOCK, HOLDLOCK)
            WHERE sucursal = CONVERT(NVARCHAR(20),@sucursal)
              AND caja     = CONVERT(NVARCHAR(20),@caja)
              AND idcierre = 0
              AND host     = ISNULL(@host, @login_id)
        );

        SET @rowsRegCajas = @@ROWCOUNT;

        ----------------------------------------------------------------------
        -- 3) pvtCajas: marcar “en uso” (indice=0). 
        --    Nota: en tu diseño, 'cierre' ? boolean: guardas el correlativo.
        ----------------------------------------------------------------------
        UPDATE C WITH (ROWLOCK)
           SET C.cajero           = @cajero,
               C.cierre           = @correlativo,                 -- ? marca en uso
               C.host             = LEFT(ISNULL(@host,@login_id),50),
               C.ultimaoperacion  = 'APERTURA',
               C.logmod           = @login_id,
               C.fecmod           = @now
        FROM dbo.pvtCajas AS C WITH (UPDLOCK, HOLDLOCK)
        WHERE C.sucursal = @sucursal
          AND C.codigo   = @caja
          AND C.indice   = 0;

        SET @rowsCajas = @@ROWCOUNT;

        COMMIT TRAN;

        ----------------------------------------------------------------------
        -- 4) Resultado (compatible con ExecuteScalar: 1a col = correlativo)
        ----------------------------------------------------------------------
        SELECT
            @correlativo  AS correlativo,
            @existed      AS existed,        -- 1 = ya existía en MovEnc (se actualizó)
            @rowsMovEnc   AS rowsMovEnc,     -- filas afectadas en pvtMovCajaEnc
            @rowsRegCajas AS rowsRegCajas,   -- filas insertadas en pvtRegistroCajas (0/1)
            @rowsCajas    AS rowsCajas;      -- filas actualizadas en pvtCajas (0 o 1)
    END TRY
    BEGIN CATCH
        IF XACT_STATE() <> 0 ROLLBACK TRAN;

        DECLARE @Msg NVARCHAR(4000) = ERROR_MESSAGE(),
                @Num INT = ERROR_NUMBER(),
                @Sev INT = ERROR_SEVERITY(),
                @Sta INT = ERROR_STATE();

        RAISERROR('sp_Api5_pvtMovCajaEncAperturaCreate failed (%d): %s', @Sev, @Sta, @Num, @Msg);
        RETURN;
    END CATCH
END
GO
