miércoles, 15 de febrero de 2012

Creación de Procedimientos Almacenados.

Esta es la tercera entrega de la primera parte, que son los procedimientos almacenados, aquí es donde viene la programación pura y la lógica de negocio, tratare de ser lo más claro posible en la explicación de la creación de los procedimientos almacenados. Si existe alguna duda en alguno de ellos pueden contactarme o dejarla en sus comentarios.








Comenzaremos explicando, que es un procedimiento almacenado, aquí una definición:


Procedimiento almacenado:


(stored OF procedure en inglés) es un programa (o procedimiento) el cual es almacenado físicamente en una base de datos. Su implementación varía de un gestor de bases de datos a otro. La ventaja de un procedimiento almacenado es que al ser ejecutado, en respuesta a una petición de usuario, es ejecutado directamente en el motor de bases de datos, el cual usualmente corre en un servidor separado. Como tal posee acceso directo a los datos que necesita manipular y sólo necesita enviar sus resultados de regreso al usuario, deshaciéndose de la sobrecarga resultante de comunicar grandes cantidades de datos salientes y entrantes. [es.wikipedia.org/]


La definición de los procedimientos almacenados en SQL Server 2008 son mediante Transact-SQL

La Sintaxis es la siguiente:

CREATE PROCEDURE <nombre_del_procedimiento>
      -- cometarios se hacen con dos guiones seguidos "--"
     @<nombre_parametro1><tipo>(<tamaño>)
      ,@<nombre_parametro2><tipo>(<tamaño>)

AS
BEGIN --indica el inicio del codigo
      -- SET NOCOUNT ON Evita que se devuelva el recuento del número de filas afectadas
      -- en la sentencias SELECT
      SET NOCOUNT ON;

  --Aqui va el codigo del procedimiento
  ...
  ...
END
GO

Cuando hacemos varias modificaciones en un procedimiento como inserciones, eliminaciones, actualizaciones, etc. condicionadas entre ellas, es decir, si se realiza una venta de algún artículo se debe hacer la inserción de la venta y la eliminación del artículo en el almacén, para evitar una inconsistencia en los datos por causa de un error al momento de realizar alguna de las dos modificaciones como la falla de la conexión o error en una de estas, debemos cerciorarnos que se realicen ambas transacciones o ninguna. Existe un método para hacer esto y crear una sola transacción que englobe todas las modificaciones y verifica si existe algún error entonces se cancelan o se revierten todas las modificaciones de datos, podemos combinarlas en los procedimientos almacenados y esas son las transacciones las cuales tiene, se confirman con la sentencia COMMIT(para confirmar) o ROLLBACK (para revertir). 

De esta manera se pueden combinar:

CREATE PROCEDURE <nombre_del_procedimiento>
      -- cometarios se hacen con dos guiones seguidos "--"
      @<nombre_parametro1><tipo>(<tamaño>)
      ,@<nombre_parametro2><tipo>(<tamaño>)
AS
      -- SET NOCOUNT ON Evita que se devuelva el recuento del número de filas afectadas
      -- en la sentencias SELECT
      SET NOCOUNT ON;
BEGIN TRAN --indica el inicio de las transacciones

  --Aqui va el codigo del procedimiento
  ...
  ...
IF @@ERROR = 0 --llamamos a la funcion del sistema @@ERROR
                        --evaluamos si nos devuelve un cero
                       
      BEGIN       --apertura del bloque de sentecias
     
            COMMIT TRAN -- si devuelve un cero comprometemos o realizamos la transaccion
           
      END               --cierre del bloque de sentencias
     
ELSE -- en caso contrario (si no)

      BEGIN --apertura del bloque de sentecias
     
            RAISERROR('HA OCURRIDO UN ERROR (intente de nuevo)',16,1) --generamos un error.
            ROLLBACK --  revertimos todos los cambios
           
      END --cierre del bloque de sentencias

--no lleva cierre del procedimiento Almacenado



Aquí tenemos la posibilidad con la función RAISERROR de crear y capturar un error para poder manejar una cadena de texto en Visual Studio y darle información al usuario sobre el error. La función RAISERROR recibe 3 parámetros,el mensaje del error, la severidad y el estado. 

La severidad indica el grado de criticidad del error. Admite valores de 0 al 25, pero solo podemos asignar valores del 0 al 18. Los errores el 20 al 25 son considerados fatales por el sistema, y cerraran la conexión que ejecuta el comando RAISERROR. Para asignar valores del 19 al 25 necesitares ser miembros de la función de SQL Server sysadmin. 

El estado es un valor para permitir que el programador identifique el mismo error desde diferentes partes del código, admite valores entre 1 al 127 y permite tratar. Si desean más información les dejo aquí un link de uno excelentes tutoriales que me ayudaron mucho. [devjoker.com]


Creación de una función. 

Nuestro sistema tendrá la necesidad de crear llaves primarias para la venta de cada boleto y para el número de venta por eso crearemos una función que nos cree llaves únicas. Esta función recibirá dos parámetros uno tipo int,y otro tipo nvarchar, nos devolverá un nvarchar de tamaño 50, esta función convertirá el int en nvarchar y lo concatenara con el segundo parámetro para hacer una llave única.
CREATE FUNCTION nvoNumeroTer(@pasaSemilla int,@ident nvarchar(50))
--funcion para obtener convertir un numero entero a cadena de caracteres
--agregandole un identificador al inicio de la cadena

RETURNS
nvarchar(50)
--retornamos una cadena de longitud maxima de 50

AS
BEGIN
--declaramos una variable que retornaremos
DECLARE @dato nvarchar(50)

--primero convertimos la variable entera con la funcion CAST a
--nvarchar despues la concatenamos con el identificador inicial
--que llevara la cadena y la asignamos a la variable @dato
SET @dato=(@ident+(CAST(@pasaSemilla AS nvarchar)))

--al final retornamos la variable @dato
RETURN @dato
END
GO


Creación de Procedimientos almacenados.


Comprobación de cuenta

Crearemos un procedimiento para comprobar la contraseña y el nombre de usuario de la base de datos, pasándole al procedimiento almacenado dos parámetros de entrada que son el nombre de usuario y la contraseña, por ultimo tendrá un parámetro de salida o “output” tipo bit o booleano este servirá para evaluar si la contraseña fue correcta o no.

CREATE PROCEDURE compruebaCuenta
@NombUsuarioCC nvarchar(50), -- parametro de entrada para recibir el nombre de usuario
@NumPinCC nvarchar(50), -- parametro de entrada papara recibir la contraseña
@pinCorrecto bit output -- parametro de salida para saber si es correcta la contraseña

--procedimiento para comprobar el pin de una cuenta
--pedimos el nombre de la cuenta y su pin
--tenemos una variable de output para dar uan respuesta
--si el pin es correcto o no
AS
     
SET NOCOUNT ON;
           
BEGIN TRAN

--primero comprobamos si el nombre de usuario existe
-- la funcion NOT EXISTS retorna true si no encuentra filas
IF NOT EXISTS(SELECT nombUsuario FROM Usuarios WHERE nombUsuario = @nombUsuarioCC)
      BEGIN
            RAISERROR('EL NOMBRE DE USUARIO NO EXISTE (intente de nuevo)',16,1)
            ROLLBACK
      END
ELSE
      BEGIN
     
      --despues verificamos si la cuenta esta habilitada
      --cuentaHabilitada es tipo bit si es true sera 1 lo compraramos y si nos retorna
      --un true es por que esta habilitada
      IF((SELECT cuentaHabilitada FROM Usuarios WHERE nombUsuario =@nombUsuarioCC)=1)        
            BEGIN      
           
            --ahora comprobamos si el pin es correcto y asignamos true
            --a la variable output      
            IF((SELECT contraseña FROM Usuarios WHERE nombUsuario=@nombUsuarioCC)=@NumPinCC)
                  BEGIN
                 
                        SET @pinCorrecto=1
                       
                  END
                 
            ELSE
            --si no asignamos false
                  BEGIN
                 
                        SET @pinCorrecto=0
                       
                  END
                 
                  --si no hay errores comprometemos la transaccion
                  IF @@ERROR=0
                        BEGIN
                             COMMIT TRAN
                        END
                  ELSE
                        BEGIN
                             RAISERROR('HA OCURRIDO UN ERROR (intente de nuevo)',16,1)
                             ROLLBACK
                        END

                 
            END
      ELSE
      --si la cuenta esta deshabilitada arrojamos el error
            BEGIN
                  RAISERROR('EL USUARIO ESTA DESHABILIDADO',16,1)
                  ROLLBACK
            END
      END
GO


Inicio de caja.

Al iniciar caja el campo abierta” tipo bit cambiara a true, y se le asignara el “idCaja“ al usuario que abrió la caja en el campo cajaAsignada
CREATE PROCEDURE IniciaCaja
@efectivoIC money,
@idSucursalIC nvarchar(50),
@idCajaIC nvarchar(50),
@nomUsuarioIC nvarchar(50)

--el procedimiento almacenado
--inica caja y se la asigna a un usuario
AS
SET NOCOUNT ON
BEGIN TRAN

--Verificamos si la caja que queremos iniciar ya esta abierta o no
IF((SELECT abierta FROM Cajas WHERE idCaja=@idCajaIC)=0)
      BEGIN

--si el valor es 0 indica que esta cerrada
--ingresamos la apertura
            INSERT INTO inicioCaja
                           (idCaja
                           ,idSucursal
                           ,nombUsuario
                           ,fechaApertura
                           ,efectivoApertura)
                   VALUES
                           (@idCajaIC
                           ,@idSucursalIC
                           ,@nomUsuarioIC
                           ,GETDATE()     ---Esta funcion retorna la fecha del sistema de BD
                           ,@efectivoIC)


--actualizamos el valor de caja abierta a verdadero
            UPDATE Cajas
               SET abierta =1
             WHERE idCaja = @idCajaIC
             
--le asignamos la caja al usuario
                  UPDATE Usuarios
                  SET cajaAsignada=@idCajaIC
                  WHERE nombUsuario=@nomUsuarioIC
--comprobamos errores
            IF @@ERROR=0
                  COMMIT TRAN
            ELSE
            BEGIN
            RAISERROR('HA OCURRIDO UN ERROR (intente de nuevo)',16,1)
            ROLLBACK
            END

      END
ELSE
      BEGIN
      --si no indicamos que la caja esta abierta o iniciada
            RAISERROR('ESTA CAJA YA SE HA INICIADO (SELECCIONE OTRA)',16,1)
            ROLLBACK
      END
GO


Venta de Boletos


Crearemos una nueva tabla con las mismas columnas de la tabla Boletos además de un campo auto-incrementable de uno en uno tipo identity llamado semilla el cual será para crear las llaves primarias, esta tabla nos servirá para guardar los boletos que se deseen en una sola venta, sin importar si son a diferentes destinos y para evitar que se guarden datos en las tablas relacionadas del sistema hasta que se finalice y confirme la venta los copiaremos a las tablas reales

CREATE TABLE ref_Boletos(
      idBoleto nvarchar(50) NOT NULL,
      idCorrida nvarchar(50) NOT NULL,
      lugarDestino nvarchar(50) NOT NULL,
      lugarSalida nvarchar(50) NOT NULL,
      nombCliente nvarchar(50) NOT NULL,
      edad int NULL,
      idVenta nvarchar(50) NOT NULL,
      fechaSalida datetime NOT NULL,
      precio money NOT NULL,
      clase nvarchar(50) NOT NULL,
      numAsiento int NOT NULL,
      idAutobus nvarchar(50) NOT NULL,
      idSucursal nvarchar(50) NOT NULL,
      semilla int IDENTITY(1,1) NOT NULL
)

También modificaremos la tabla ventas agregándole una columna más llamada semilla también tipo IDENTITY para las llaves primarias de ventas , con la siguiente instrucción lo hacemos.

ALTER TABLE Ventas ADD semilla INT IDENTITY(1,1) NOT NULL


Pueden aprender un poco más sobre los campos IDENTITY, en este link que está bastante claro su explicación y funciones [grimpidev.wordpress.com]
El siguiente procedimiento almacenado es para agregar un boleto a la venta, por medio de uno de los parámetros de entrada, llamado @nuevaVenta tipo bit, lo utilizaremos para saber si se ejecuta este procedimiento para agregar otro boleto a la misma venta, o si es una nueva venta, de ser una nueva venta eliminaremos todas las filas que existan de la tabla ref_Boletos para agregar nuevos datos y no copiar los datos de los boletos de ventas anteriores.

CREATE PROCEDURE NuevoBoleto      
           @CorridaNB nvarchar(50)
           ,@lugarDestinoNB nvarchar(50)
           ,@lugarSalidaNB nvarchar(50)
           ,@NomClienteNB nvarchar(50)
           ,@edadNB int
           ,@precioNB money
           ,@claseNB nvarchar(50)
           ,@numAsientoNB int          
           ,@idSucursalNB nvarchar(50)
           ,@nuevaVenta bit
AS
     
SET NOCOUNT ON;
           
      BEGIN TRAN
--Verificamos si es una nueva venta eliminamos todos los datos de la tabla anteriores
IF(@nuevaVenta=1)
BEGIN
--Eliminamos todo loq eu tenga la tabla de ref para evitar errores    
DELETE FROM ref_Boletos
END

--hacemos la insercion de los datos ee la tabla ref_Boletos

INSERT INTO ref_Boletos
           (idBoleto
           ,idCorrida
           ,lugarDestino
           ,lugarSalida
           ,nombCliente
           ,edad
           ,idVenta
           ,fechaSalida
           ,precio
           ,clase
           ,numAsiento
           ,idAutobus
           ,idSucursal)
     VALUES
           ((SELECT dbo.nvoNumeroTer( (SELECT IDENT_CURRENT('ref_Boletos'))+1,'BT'))
           ,@CorridaNB
           ,@lugarDestinoNB
           ,@lugarSalidaNB
           ,@NomClienteNB
           ,@edadNB
           ,(SELECT dbo.nvoNumeroTer( (SELECT IDENT_CURRENT('VENTAS'))+1,'VT'))
           ,(SELECT fechaSalida FROM Corridas WHERE idCorrida = @CorridaNB)
           ,@precioNB
           ,@claseNB
           ,@numAsientoNB
           ,(SELECT idAutobus FROM Corridas WHERE idCorrida = @CorridaNB)
           ,@idSucursalNB)

--Comprobamos errores y conformamos la transaccion                         
      IF @@ERROR = 0
      BEGIN
                        COMMIT TRAN
      END
                  ELSE
                        BEGIN
                        RAISERROR('HA OCURRIDO UN ERROR (intente de nuevo)',16,1)
                        ROLLBACK
                        END
GO


La función IDENT_CURRENT('Nombre_Tabla'), nos retorna el ultimo valor autogenerado del campo IDENTITY de la tabla que se le pasa como una cadena de caracteres.


Al finalizar y confirmar la venta se ejecutara el siguiente procedimiento para ingresar y dar de alta la venta en la base de datos, en este paso aun podemos copiar los boletos de esta venta a la tabla Boletos aun, debido a que el idVenta de la misma no existe hasta que se termina de ejecutar este procedimiento almacenado, asi que la mejor opcion para copiar los boletos sera un trigger que se ejecute despues de insertar una columna en la tabla ventas.

CREATE PROCEDURE NuevaVentaBoleto
           @nomUsuarioNV nvarchar(50)
           ,@idCaja nvarchar(50)
          
AS   
SET NOCOUNT ON;                                  
           
      BEGIN TRAN
--hacemos la insercion de la venta
INSERT INTO Ventas
           (idVenta
           ,nombUsuario
           ,idCaja
           ,importeVenta
           ,fechaVenta
           ,numBoletos)
     VALUES
           ((SELECT DISTINCT idVenta FROM ref_Boletos) --tomamos el id venta de los boletos
           ,@nomUsuarioNV
           ,@idCaja
           ,(SELECT SUM(precio) FROM ref_Boletos) --sumamos todos los precios de los boletos
           ,GETDATE()
           ,(SELECT COUNT(idBoleto) FROM ref_Boletos)) --contamos todos los boletos

--Comprobamos errores y conformamos la transaccion                         
IF @@ERROR = 0
      BEGIN
                        COMMIT TRAN
      END
ELSE
      BEGIN
            RAISERROR('HA OCURRIDO UN ERROR (intente de nuevo)',16,1)
            ROLLBACK
      END
GO



Trigger de la Venta

Una vez que se aya insertado una fila en la tabla Ventas, se copiaran los boletos de esta venta a la tabla relacionada de la base de datos, si por alguna cuestión llega a fallar por algun error de conexion o cualquier otro el sistema revierte todos los cambios que se hacen desde este trigger hasta el procedimiento donde se creo la insercion de la tabla venta.

CREATE TRIGGER CopiaBoletosVendidos

ON Ventas

AFTER INSERT

AS

BEGIN
BEGIN TRAN

    -- SET NOCOUNT ON impide que se generen mensajes de texto

    -- con cada instrucción
    SET NOCOUNT ON;
   
   
 --copiamos los boletos que vendimos a la tabla de boletos  
INSERT INTO Boletos
           (idBoleto
           ,idCorrida
           ,lugarDestino
           ,lugarSalida
           ,nombCliente
           ,edad
           ,idVenta
           ,fechaSalida
           ,precio
           ,clase
           ,numAsiento
           ,idAutobus
           ,idSucursal)
    SELECT ref_Boletos.idBoleto
           ,ref_Boletos.idCorrida
           ,ref_Boletos.lugarDestino
           ,ref_Boletos.lugarSalida
           ,ref_Boletos.nombCliente
           ,ref_Boletos.edad
           ,ref_Boletos.idVenta
           ,ref_Boletos.fechaSalida
           ,ref_Boletos.precio
           ,ref_Boletos.clase
           ,ref_Boletos.numAsiento
           ,ref_Boletos.idAutobus
           ,ref_Boletos.idSucursal
           FROM ref_Boletos
   

---------------------------------------------------------------
---------si no ocurre un error finalizamos la tranzaccion
IF @@ERROR=0
      BEGIN                          
           COMMIT TRAN
    END
   ---si no la cancelamos---------------------------------------
ELSE
      BEGIN
      RAISERROR ('HA OCURRIDO UN ERROR INTENTELO DE NUEVO', 16,  1 )
      ROLLBACK
      END
END

GO



Procedimiento para la cancelación.

En este caso al ser un boleto el cual creamos a partir de ningún inventario podemos simplemente eliminarlo, en este caso también agregaremos un campo a la tabla de cancelaciones para guardar algunos datos de la cancelación, en la tabla de cancelaciones podemos agregar más datos del boleto si es que se necesitan.

CREATE PROCEDURE CancelaBoleto          
          @idBoletoCB nvarchar(50),
          @idCajaCB nvarchar(50),
          @nomUsuarioCB nvarchar(50),
          @devolucionBoleto money output
AS
     
SET NOCOUNT ON;
           
      BEGIN TRAN
     
IF NOT EXISTS(SELECT idBoleto FROM Boletos WHERE idBoleto=@idBoletoCB)
BEGIN
            RAISERROR('EL BOLETO NO EXISTE (verifique el numero)',16,1)
            ROLLBACK
END
ELSE
      BEGIN
            --declaramos las variables que utilizaremos en para guardar
            --el numero de boletos vendidos, y el numero de la venta
            DECLARE @numBoletosCB int,@numVentaCB nvarchar(50),@precioboleto money

            ---guardamos la devolucion del boleto para saber cuanto es lo que devolveremos
            SET @precioboleto= (SELECT precio FROM Boletos WHERE idBoleto = @idBoletoCB)

            --Obtenemos el numero de venta para saber cual es el que actualizaremos
            SET @numVentaCB=(SELECT idVenta FROM Boletos WHERE idBoleto=@idBoletoCB)
            DELETE FROM Boletos WHERE idBoleto=@idBoletoCB


            SET @numBoletosCB=(SELECT numBoletos FROM Ventas WHERE idVenta=@numVentaCB)

            IF(@numBoletosCB=1)
                  BEGIN
                        DELETE FROM Ventas WHERE idVenta = @numVentaCB
                  END
            ELSE
                  BEGIN
                  UPDATE Ventas SET numBoletos=(numBoletos-1)
                  ,importeVenta=(importeVenta-@precioboleto)
                  WHERE idVenta = @numVentaCB
                  END
                 
            INSERT INTO Cancelaciones
           (idBoleto
           ,importe
           ,fechaCancelacion
           ,idCaja
           ,nombUsuario)
     VALUES
           (@idBoletoCB
           ,@precioboleto
           ,GETDATE()
           ,@idCajaCB
           ,@nomUsuarioCB)



            --si no hay errores comprometemos la transaccion
                  IF @@ERROR=0
                        BEGIN
                        SET @devolucionBoleto=@precioboleto
                             COMMIT TRAN
                        END
                  ELSE
                        BEGIN
                             RAISERROR('HA OCURRIDO UN ERROR (intente de nuevo)',16,1)
                             ROLLBACK
                        END


      END
GO



Corte de caja.

Para realizar el corte de caja basta con simples consultas del total de ventas y cancelaciones, crearemos un procedimiento almacenado para enviar los datos con parámetros de “output” a la aplicación en Visual Studio antes de cerrar la caja, solo como información para el usuario y pueda verificar el efectivo de caja con lo que marca el sistema.

CREATE PROCEDURE VerificaCorteCaja
@idCajaVC nvarchar(50),
@EfectivoIni money output,
@totalVentas money output,
@totalEfectivo money output,
@numVentasVC int output,
@boletosVendido int output,
@boletosCancelado int output,
@totalCancelaciones money output

AS
SET NOCOUNT ON
BEGIN TRAN

IF((SELECT abierta FROM Cajas WHERE idCaja=@idCajaVC)=1)
      BEGIN
            DECLARE @fechaAperturaMax datetime

            SET @fechaAperturaMax=(SELECT MAX(fechaApertura)
                                   FROM inicioCaja WHERE idCaja=@idCajaVC)

            IF NOT EXISTS(SELECT efectivoApertura FROM inicioCaja
                         WHERE idCaja=@idCajaVC and fechaApertura=@fechaAperturaMax)
                  BEGIN
                        SET @EfectivoIni=0
                  END
            ELSE
                  BEGIN
                        SET @EfectivoIni=(SELECT efectivoApertura FROM inicioCaja
                         WHERE idCaja=@idCajaVC and fechaApertura=@fechaAperturaMax)
                  END
            IF NOT EXISTS(SELECT importeVenta FROM Ventas
                                   WHERE idCaja=@idCajaVC and fechaVenta>=@fechaAperturaMax)
                  BEGIN
                  SET @totalVentas=0
                  END
            ELSE
                  BEGIN
                        SET @totalVentas=(SELECT SUM(importeVenta) FROM Ventas
                                   WHERE idCaja=@idCajaVC and fechaVenta>=@fechaAperturaMax)     
                  END
                 

            SET @totalEfectivo=@EfectivoIni+@totalVentas

            SET @numVentasVC=(SELECT COUNT(idVenta)FROM Ventas
                        WHERE idCaja=@idCajaVC and fechaVenta>=@fechaAperturaMax)
                       
            IF NOT EXISTS(SELECT numBoletos FROM Ventas
                        WHERE idCaja=@idCajaVC and fechaVenta>=@fechaAperturaMax)
                  BEGIN
                        SET @boletosVendido=0
                  END
            ELSE
                  BEGIN
                            
                        SET @boletosVendido=(SELECT SUM(numBoletos)FROM Ventas
                                   WHERE idCaja=@idCajaVC and fechaVenta>=@fechaAperturaMax)
                  END

            SET @boletosCancelado=(SELECT COUNT(idBoleto)FROM Cancelaciones
                                               WHERE fechaCancelacion>=@fechaAperturaMax )
                                              
            IF NOT EXISTS(SELECT idBoleto FROM Cancelaciones
                                               WHERE fechaCancelacion>=@fechaAperturaMax )
                  BEGIN
                        SET  @totalCancelaciones=0
                  END
            ELSE
                  BEGIN
                        SET @totalCancelaciones=(SELECT SUM(importe) FROM Cancelaciones
                                               WHERE fechaCancelacion>=@fechaAperturaMax )
                  END

            IF @@ERROR =0
            COMMIT TRAN
            ELSE
            BEGIN
                  RAISERROR('HA OCURRIDO UN ERROR EN CARGAR LOS DATOS INTENTE DE NUEVO',16,1)
                  ROLLBACK
            END

      END
ELSE
      BEGIN
                  RAISERROR('LA CAJA ESTA CERRADA',16,1)
                  ROLLBACK
      END
GO



Por ultimo creamos el procedimiento para realizar el corte de caja, cerrar la caja y actualizaremos al usuario que realizo la apertura de caja.

CREATE PROCEDURE RealizaCorte
@idCajaRC nvarchar(50),
@nomUsuarioRC nvarchar(50)

AS
SET NOCOUNT ON
BEGIN TRAN

IF((SELECT abierta FROM Cajas WHERE idCaja=@idCajaRC)=1)
      BEGIN
     
DECLARE
@fechaApeMax datetime,
@EfectivoIniRC money ,
@totalVentasRC money ,
@totalEfectivoRC money ,
@numVentasRC int ,
@boletosVendidoRC int ,
@boletosCanceladoRC int ,
@totalCancelacionesRC money


            SET @fechaApeMax=(SELECT MAX(fechaApertura)
                                   FROM inicioCaja WHERE idCaja=@idCajaRC)

            IF NOT EXISTS(SELECT efectivoApertura FROM inicioCaja
                         WHERE idCaja=@idCajaRC and fechaApertura=@fechaApeMax)
                  BEGIN
                        SET @EfectivoIniRC=0
                  END
            ELSE
                  BEGIN
                        SET @EfectivoIniRC=(SELECT efectivoApertura FROM inicioCaja
                         WHERE idCaja=@idCajaRC and fechaApertura=@fechaApeMax)
                  END
            IF NOT EXISTS(SELECT importeVenta FROM Ventas
                                   WHERE idCaja=@idCajaRC and fechaVenta>=@fechaApeMax)
                  BEGIN
                  SET @totalVentasRC=0
                  END
            ELSE
                  BEGIN
                        SET @totalVentasRC=(SELECT SUM(importeVenta) FROM Ventas
                                   WHERE idCaja=@idCajaRC and fechaVenta>=@fechaApeMax)
                  END
                 

            SET @totalEfectivoRC=@EfectivoIniRC+@totalVentasRC

            SET @numVentasRC=(SELECT COUNT(idVenta)FROM Ventas
                        WHERE idCaja=@idCajaRC and fechaVenta>=@fechaApeMax)
                       
            IF NOT EXISTS(SELECT numBoletos FROM Ventas
                        WHERE idCaja=@idCajaRC and fechaVenta>=@fechaApeMax)
                  BEGIN
                        SET @boletosVendidoRC=0
                  END
            ELSE
                  BEGIN
                            
                        SET @boletosVendidoRC=(SELECT SUM(numBoletos)FROM Ventas
                                   WHERE idCaja=@idCajaRC and fechaVenta>=@fechaApeMax)
                  END

            SET @boletosCanceladoRC=(SELECT COUNT(idBoleto)FROM Cancelaciones
                                               WHERE fechaCancelacion>=@fechaApeMax )
                                              
            IF NOT EXISTS(SELECT idBoleto FROM Cancelaciones
                                               WHERE fechaCancelacion>=@fechaApeMax )
                  BEGIN
                        SET  @totalCancelacionesRC=0
                  END
            ELSE
                  BEGIN
                        SET @totalCancelacionesRC=(SELECT SUM(importe) FROM Cancelaciones
                                               WHERE fechaCancelacion>=@fechaApeMax )
                  END


     
      INSERT INTO Cortes
           (idCaja
           ,nombUsuario
           ,numVentas
           ,numCancelaciones
           ,importeVentas
           ,importeCancelaciones
           ,efectivoTotal
           ,fechaCorte)
     VALUES
           (@idCajaRC
           ,@nomUsuarioRC
           ,@numVentasRC
           ,@boletosCanceladoRC
           ,@totalVentasRC
           ,@totalCancelacionesRC
           ,@totalEfectivoRC
           ,GETDATE())
          
       --se actualiza el usuario
             UPDATE Usuarios
             SET cajaAsignada=''
             WHERE nombUsuario=@nomUsuarioRC
          
       --se actualiza el estado de la caja
         UPDATE Cajas
         SET abierta=0
         WHERE idCaja=@idCajaRC
        
        
            IF @@ERROR =0
            COMMIT TRAN
            ELSE
            BEGIN
                  RAISERROR('HA OCURRIDO UN ERROR EN CARGAR LOS DATOS INTENTE DE NUEVO',16,1)
                  ROLLBACK
            END

     
     
     
      END
ELSE
      BEGIN
      RAISERROR('LA CAJA ESTA CERRADA',16,1)
      END
GO



Estos son los procedimientos almacenados que utilizaremos para crear nuestro sistema de 3 capas, la primera capa está terminada con los procedimientos almacenado los podemos probarlos ejecutándolos con el manejador de base de datos. Para todos aquellos que deseen aprender más sobre el lenguaje Transact-SQL les sugiero visitar esta excelente página con muy buenos tutoriales de varios lenguajes.[devjoker.com]

Gracias por seguirnos y les agradezco cualquier aporte y comentario ;) los espero en la próxima entrega. 

No hay comentarios:

Publicar un comentario