Base de datos:
Cambios y mejoras:
Se crearon los siguientes SPs:
- SP_ReciboDeComprobanteSelect: SP el cual recibe un comprobante de pago y selecciona todos los recibos que corresponden al comprobante de pago con el id recibido
CREATE PROC [dbo].[SP_ReciboDeComprobanteSelect]
@inIdComprobantePago INT
SELECT *
FROM [dbo].[Recibos] R
INNER JOIN [dbo].[ReciboPagado] RP ON RP.id_Recibo = R.id
WHERE RP.id_Comprobante = @inIdComprobantePago
- SP_ComprobantePagoSelect: SP el cual recibe un id de recibo y retorna su comprobante de pago correspondiente
CREATE PROC [dbo].[SP_ComprobantePagoSelect]
@inIdRecibo INT
SELECT CP.id,CP.fecha, CP.total
FROM [dbo].[ComprobantePago] CP
INNER JOIN [dbo].[ReciboPagado] RP ON RP.id_Comprobante = CP.id
INNER JOIN [dbo].[Recibos] R ON R.id = RP.id_Recibo
WHERE R.id = @inIdRecibo
- SP_ComprobantePagoPorPropiedadSelect: SP que recibe un numero de finca y retorna los comprobantes de pago correspondientes a esta propiedad
CREATE PROC [dbo].[SP_ComprobantePagoPorPropiedadSelect]
@inNumFinca INT
SELECT DISTINCT CP.id,CP.fecha, CP.total
FROM [dbo].[ComprobantePago] CP
INNER JOIN [dbo].[ReciboPagado] RP ON RP.id_Comprobante = CP.id
INNER JOIN [dbo].[Recibos] R ON R.id = RP.id_Recibo
INNER JOIN [dbo].[Propiedad] P ON P.id = R.id_Propiedad
WHERE P.numFinca = @inNumFinca
- SP_ProcesaConsumo: recibe una tabla diaria que trae los consumos e itera en ella para guardar el movimiento de consumo que se realizo y actualizar los datos de M3acumuladosAgua:
DECLARE @idMenor INT, @idMayor INT
SELECT @idMenor = min([id]), @idMayor=max([id]) FROM @inConsumo
BEGIN TRAN
WHILE @idMenor<=@idMayor
BEGIN
INSERT INTO [dbo].[MovConsumo] (fecha,montoM3,lecturaConsumo,nuevoM3Consumo,id_Propiedad,idTipoMov)
SELECT
C.Fecha,
CASE WHEN (C.idTipo = 1) THEN C.LecturaM3- P.M3acumuladosAgua
ELSE C.LecturaM3
END,
CASE WHEN (C.idTipo = 1) THEN C.LecturaM3
ELSE NULL
END,
CASE WHEN (C.idTipo = 1) THEN C.LecturaM3
WHEN (C.idTipo = 2) THEN P.M3acumuladosAgua-C.LecturaM3
ELSE P.M3acumuladosAgua+C.LecturaM3
END,
P.id,
C.idTipo
FROM [dbo].[Propiedad] P
INNER JOIN @inConsumo C ON C.numFinca = P.[numFinca]
WHERE C.id = @idMenor
UPDATE [Propiedad]
SET M3acumuladosAgua = CASE WHEN (C.idTipo = 1) THEN C.LecturaM3
WHEN (C.idTipo = 2) THEN M3acumuladosAgua-C.LecturaM3
ELSE M3acumuladosAgua+C.LecturaM3
END
FROM [Propiedad] P
INNER JOIN @inConsumo C ON C.numFinca = P.[numFinca]
WHERE C.id = @idMenor
SET @idMenor = @idMenor+1
END
COMMIT
- SP_ProcCortaAgua: recibe una fecha la cual viene del xml para realizar los cortes de agua de acuerdo con la simulacion de fechas, busca todas las propiedades que tienen mas de un recibo de agua sin pagar y aun no se les ha hecho un corte de agua, itera sobre estas propiedades para generar recibo de reconexion, y corte de agua:
DECLARE @idPropiedades TABLE(id INT IDENTITY(1,1),idPropiedad int,idCC INT,c int)
DECLARE @idMenor INT, @idMayor INT, @id int
BEGIN TRAN
INSERT INTO @idPropiedades(idPropiedad,idCC,c)
SELECT R.id_Propiedad,R.id_CC, COUNT(*)
FROM [dbo].[Recibos] R
WHERE R.estado = 0 AND R.id_CC = 1
AND NOT EXISTS (SELECT id FROM [dbo].[Recibos] WHERE id_CC = 10 AND id_Propiedad = R.id_Propiedad)
GROUP BY id_Propiedad,R.id_CC
HAVING COUNT(*) > 1
SELECT @idMenor = MIN(id), @idMayor = MAX(id) FROM @idPropiedades
WHILE @idMenor<=@idMayor
BEGIN
INSERT INTO [dbo].[Recibos] (id_CC,monto,estado,id_Propiedad,fecha,fechaVence)
SELECT 10,CC.monto,0,P.idPropiedad,@inFecha,DATEADD(D,CC.diasParaVencer,@inFecha)
FROM @idPropiedades P
INNER JOIN [dbo].[ConceptoDeCobro] CC ON CC.id = 10
WHERE P.id = @idMenor
SET @id = IDENT_CURRENT('[dbo].[Recibos]')
INSERT INTO [dbo].[ReciboReconexion](id)
SELECT @id
INSERT INTO [dbo].[Corte](fecha,id_Propiedad,recRecon)
SELECT @inFecha,idP.idPropiedad,@id
FROM @idPropiedades idP
WHERE idP.id = @idMenor
SET @idMenor = @idMenor+1
END
COMMIT
- Para insertar las entidades: Propietario, usuario, propietarioVsPropiedad y Usuario vsPropiedad desde el archivo xml a la base de datos se implementaron SPs los cuales reciben una tabla con todas las entidades mencionada anteriormente correspondientes al dia de operacion, y el SP las procesa de manera iterativa para asi poder guardar los cambios en la bitacora de cambios, ejemplo:
declare @jsonDespues varchar(500), @idMenor int, @idMayor int, @idModified int, @insertedAt DATE
SELECT @idMenor = min([id]), @idMayor=max([id]) FROM @inPropiedadDelPropietario
SET @insertedAt = (SELECT Fecha FROM @inPropiedadDelPropietario WHERE id = @idMenor)
BEGIN TRAN
WHILE @idMenor<=@idMayor
BEGIN
--INSERTA LA RELACION
INSERT INTO [dbo].[PropiedadDelPropietario] ([id_Propietario], [id_Propiedad])
SELECT idPropietario,idPropiedad
FROM @inPropiedadDelPropietario
WHERE id = @idMenor
--GUARDA EL ID
SET @idModified = IDENT_CURRENT('[dbo].[PropiedadDelPropietario]')
--GUARDA EL JSON DEL ROW DE LA RELACION DESPUES
SET @jsonDespues = (SELECT [id], [id_Propiedad], [id_Propietario]
FROM [dbo].[PropiedadDelPropietario] WHERE [id] = @idModified
FOR JSON PATH)
--INSERTA EL CAMBIO
EXEC [dbo].[SP_BitacoraCambioInsert] @inIdEntityType = 4,@inEntityID = @idModified, @inJsonAntes = NULL,
@inJsonDespues = @jsonDespues, @inInsertedBy = 'usuario1',
@inInsertedIn = 123, @inInsertedAt = @insertedAt
SET @idMenor = @idMenor+1
END
COMMIT
- SP_ProcActualizarValProp: Recibe una tabla con los cambios de valor que indica el xml y hace los cambios en la tabla de propiedades:
UPDATE [dbo].[Propiedad]
SET [dbo].[Propiedad].[valor] = NVP.nuevoValor,
[dbo].[Propiedad].[fechaDeIngreso] = @inFecha
FROM [dbo].[Propiedad] P
INNER JOIN @inNuevosValProp NVP ON NVP.numFinca = P.numFinca
- SP_ProcGeneraRecibos: Recibe una fecha del xml y genera recibos a todas las propiedades de acuerdo con los conceptos de cobro que tienen asociados, actualiza tambien el valor de M3AcumuladosUltimoRecibo de la propiedad:
SET @dia = DAY(@inFecha)
BEGIN TRAN
INSERT INTO [dbo].[Recibos] (id_CC,monto,estado,id_Propiedad,fecha,fechaVence)
SELECT
CC.id,
CASE WHEN (CC.esFijo = 'Si' AND CC.id != 1) THEN CC.monto
WHEN (CC.esImpuesto = 'Si') THEN P.valor/100*CCPo.valorPorcentual
WHEN (CC.id = 1) THEN
CASE WHEN (P.M3acumuladosAgua-P.M3AcumuladosUltimoRecibo)*CCC.valorPorM3>CCC.montoMinimoRecibo
THEN (P.M3acumuladosAgua-P.M3AcumuladosUltimoRecibo)*CCC.valorPorM3
ELSE CCC.montoMinimoRecibo END
END,
0,
P.id,
@inFecha,
DATEADD(d,CC.diasParaVencer,@inFecha)
FROM [dbo].[CCDePropiedad] CCP
INNER JOIN [dbo].[ConceptoDeCobro] CC ON CCP.id_CC = CC.id
INNER JOIN [dbo].[Propiedad] P ON CCP.id_Propiedad = P.id
FULL OUTER JOIN [dbo].[CCPorcentaje] CCPo ON CCPo.id = CC.id
FULL OUTER JOIN [dbo].[CCConsumo] CCC ON CCC.id = CC.id
WHERE CC.diaDeCobro = @dia
UPDATE [dbo].[Propiedad]
SET M3AcumuladosUltimoRecibo = M3acumuladosAgua
FROM [dbo].[Propiedad] P
INNER JOIN [dbo].[CCDePropiedad] CCP ON CCP.id_Propiedad = P.id
INNER JOIN [dbo].[ConceptoDeCobro] CC ON CC.id = CCP.id_CC
WHERE CC.id = 1 AND CC.diaDeCobro = @dia AND P.M3AcumuladosUltimoRecibo != P.M3acumuladosAgua
COMMIT
- SP_ProcesarPagos: El sp que mas nos costo, recibe una tabla de pagos la cual contiene el numero de finca y el concepto de cobro entonces, antes buscabamos el recibo de esta propiedad con ese concepto de cobro mas viejo, y pagabamos ese, con la version final entonces lo que hacemos es guardar en una tabla temporal todos los recibos de esa propiedad que tengan que ver con ese concepto de cobro, iteramos sobre esta tabla y creamos los pagos, verificamos si ya existe un comprobante de pago, y verificamos si es necesario crera un recibo moratorio al final le asinamos al comprobante de pago todos los montos que se pagaron.
DECLARE @idMenor INT, @idMayor INT, @fechaVence DATE, @fechaOperacion DATE, @montoMoratorio MONEY, @contador INT,
@idComprobante INT, @tasaMoratoria FLOAT, @montoRecibo MONEY, @tipoCC int, @idPropiedad INT
--TABLA DE IDS DE RECIBOS POR CONCEPTO DE COBRO DE CADA PROPIEDAD
DECLARE @idRecibosPagar TABLE(id INT IDENTITY(1,1),idRecibo INT)
--CONTADOR PARA ITERAR TABLA DE RECIBOS DE CADA PROPIEDAD Y SABER DONDE QUEDE LA ULTIMA VEZ
SET @contador = 1
SELECT @idMenor = min([id]), @idMayor=max([id]) FROM @Pagos--SACA ID MAYOR Y MENOR PARA ITERAR LA TABLA
BEGIN TRAN
--RECORRE LOS PAGOS DE FINCAS
WHILE @idMenor<=@idMayor
BEGIN
SET @montoMoratorio = 0 --MONTO MORATORIO SE CAMBIA SI ES QUE HAY RECIBO MORATORIO, SINO ES 0
SET @fechaOperacion = (SELECT fechaOperaciones FROM @Pagos WHERE id = @idMenor)
SET @tipoCC = (SELECT idTipoRecibo FROM @Pagos WHERE id = @idMenor)--TIPO CC EN EL PAGO
SET @idPropiedad = (SELECT pr.id FROM [dbo].[Propiedad] PR -- PROPIEDAD A LA QUE SE LE HACE EL PAGO
INNER JOIN @Pagos P ON P.numFinca = PR.numFinca
WHERE P.id = @idMenor)
--VERIFICA SI EXISTE EL COMPROBANTE DE PAGO PARA ESA PROPIEDAD, ESE MISMO DIA
SET @idComprobante = (SELECT CC.id FROM [dbo].[ComprobantePago] CC
INNER JOIN [dbo].[ReciboPagado] RP ON RP.id_Comprobante = CC.id
INNER JOIN [dbo].[Recibos] R ON R.id = RP.id_Recibo
WHERE R.id_Propiedad = @idPropiedad AND CC.fecha = @fechaOperacion)
--SI NO EXISTE ENTONCES LO CREA
IF @idComprobante IS NULL
BEGIN
INSERT INTO [dbo].[ComprobantePago](fecha,total)
SELECT @fechaOperacion,0
SET @idComprobante = IDENT_CURRENT('[dbo]. [ComprobantePago]')
END
--SE INSERTAN LOS RECIBOS DE LA PROPIEDAD EN LA TABLA VARIABLE, Y SE VAN ACUMULANDO, PARA ESO SE USA EL CONTADOR
--SI ES CONCEPTO DE COBRO 10 (RECONEXION)
IF @tipoCC = 10
BEGIN
INSERT INTO @idRecibosPagar(idRecibo)
SELECT R.id
FROM @Pagos P
INNER JOIN [dbo].[Propiedad] PR ON PR.numFinca = P.numFinca
INNER JOIN [dbo].[Recibos] R ON R.id_Propiedad = PR.id
WHERE P.id = @idMenor AND R.[estado] = 0
AND (R.[id_CC] = 1 --GUARDA TODOS LOS RECIBOS DE AGUA PENDIENTES (1)
OR R.[id_CC] = 11 --GUARDA TODOS LOS RECIBOS MORATORIOS PENDIENTES (11)
OR R.[id_CC] = 10)--GUARDA TODOS LOS RECIBOS DE RECONEXION PENDIENTES (10)
END
ELSE--SI ES OTRO CONCEPTO DE COBRO
BEGIN
INSERT INTO @idRecibosPagar(idRecibo)
SELECT R.id
FROM @Pagos P
INNER JOIN [dbo].[Propiedad] PR ON PR.numFinca = P.numFinca
INNER JOIN [dbo].[Recibos] R ON R.id_Propiedad = PR.id
WHERE P.id = @idMenor AND R.[estado] = 0
AND (R.[id_CC] = 11 --GUARDA TODOS LOS RECIBOS MORATORIOS PENDIENTES (11)
OR R.[id_CC] = @tipoCC)--GUARDA TODOS LOS RECIBOS DE DE ESE CONCEPTO DE COBRO PENDIENTES (@TIPOCC)
END
--MIENTRAS EXISTA UN CONCEPTO DE COBRO SIN PAGAR, RECORRA LOS RECIBOS
WHILE EXISTS(SELECT idRP.id FROM @idRecibosPagar idRP INNER JOIN [dbo].[Recibos] R ON R.id = idRP.idRecibo WHERE R.estado = 0)
BEGIN
--ESTABLECE EL MONTO DEL RECIBO
SET @montoRecibo = (SELECT R.monto FROM [dbo].[Recibos] R
INNER JOIN @idRecibosPagar idRP ON R.id = idRP.idRecibo
WHERE idRP.id = @contador)
--INSERTA UNA RELACION ENTRE RECIBO Y COMPROBANTE DE PAGO
INSERT INTO [dbo].[ReciboPagado](id_Comprobante,id_Recibo)
SELECT @idComprobante,idRP.idRecibo
FROM @idRecibosPagar idRP
WHERE idRP.id = @contador
--PAGA EL RECIBO ACTUALIZANDO SU ESTADO A PAGADO
UPDATE [dbo].[Recibos]
SET [estado] = 1
FROM @idRecibosPagar idRP
WHERE idRP.idRecibo = [dbo].[Recibos].[id] AND idRP.id = @contador
--VERIFICA SI SE DEBE CREAR RECIBO MORATORIO
--SACA LA FECHA EN LA QUE VENCE EL RECIBO
SET @fechaVence = (SELECT fechaVence FROM [dbo].[Recibos] R
INNER JOIN @idRecibosPagar idRP ON idRP.idRecibo = R.id
WHERE @contador = idRP.id)
--SI LA FECHA EN LA QUE VENCE ES MENOR A LA FECHA EN LA QUE SE ESTA PAGANDO EL RECIBO
IF @fechaVence < @fechaOperacion
BEGIN
--SACA LA TASA MORATORIA DE ESE RECIBO
SET @tasaMoratoria = (SELECT CC.tasaImpuestoMoratorio FROM [dbo].[ConceptoDeCobro] CC
INNER JOIN [dbo].[Recibos] R ON R.id_CC = CC.id
INNER JOIN @idRecibosPagar idRP ON idRP.idRecibo = R.id
WHERE idRP.id = @contador)
--AQUI CAMBIA EL MONTO MORATORIO YA QUE SI SE DEBE CREAR RECIBO MORATORIO
SET @montoMoratorio = (@montoRecibo*@tasaMoratoria/365)*ABS(DATEDIFF(d,@fechaVence,@fechaOperacion))
--CREA UN RECIBO RE TIPO MORATORIO Y LO PAGA
INSERT INTO [dbo].[Recibos] (id_CC,monto,estado,id_Propiedad,fecha,fechaVence)
SELECT CC.id,@montoMoratorio,1,@idPropiedad,@fechaOperacion,
DATEADD(d,CC.diasParaVencer,@fechaOperacion)
FROM [dbo].[ConceptoDeCobro] CC
WHERE CC.id = 11
--INSERTAR UNA RELACION ENTRE EL RECIBO MORATORIO PAGADO Y EL COMPROBANTE DE PAGO
INSERT INTO [dbo].[ReciboPagado](id_Comprobante,id_Recibo)
SELECT @idComprobante,IDENT_CURRENT('[dbo].[Recibos]')
END
--AL FINAL ACTUALIZA EL MONTO DEL COMPORBANTE DE PAGO
UPDATE [dbo].[ComprobantePago]
SET [total] = [total]+@montoRecibo+@montoMoratorio--SI NO HUBO RECIBO MORATORIO SUMA 0 MAS EL MONTO POR LOS DEMAS RECIBOS
WHERE id = @idComprobante
SET @contador = @contador+1--INCREMENTA EL CONTADOR
END
SET @idMenor = @idMenor+1
END
COMMIT
- SP_BitacoraSelect: Recibe dos fechas y un tipo de entidad y retorna los cambios que hubieron entre esas fechas a esa entidad:
CREATE PROC [dbo].[SP_BitacoraSelect] @inFechaDesde VARCHAR(30), @inFechaHasta VARCHAR(30), @inIdEntidad INT
SELECT [jsonAntes],[jsonDespues],[insertedAt],U.nombre,[insertedIn]
FROM [dbo].[BitacoraCambio] BC
INNER JOIN [dbo].[Usuario] U ON U.id = BC.insertedBy
WHERE (insertedAt BETWEEN @fechaDesde AND @fechaHasta)
AND (idEntityType = @inIdEntidad)
ORDER BY [insertedAt] ASC
- trigger_cambiosPropiedad: Se activa cuando se genera algun insert o update en la tabla de propiedades y se usa para guardar los cambios en bitacora, es iterativo ya que le pueden llegar 200 records por lo que hay que ir uno por uno creando los jsons:
declare @jsonAntes varchar(500), @jsonDespues varchar(500), @idMenor int, @idMayor int, @insertedAt DATE
SELECT @idMenor = min([id]), @idMayor=max([id]) FROM inserted
SET @insertedAt = (SELECT fechaDeIngreso FROM inserted WHERE [id] = @idMenor)
WHILE @idMenor<=@idMayor
BEGIN
IF @idMenor IN (SELECT id FROM inserted) OR @idMenor IN (SELECT id FROM deleted)
BEGIN
SET @jsonAntes = (SELECT [id], [valor], [direccion], [numFinca], [fechaDeIngreso],[M3acumuladosAgua],[M3AcumuladosUltimoRecibo]
FROM deleted WHERE [id] = @idMenor AND activo = 1
FOR JSON PATH)
SET @jsonDespues = (SELECT [id], [valor], [direccion], [numFinca], [fechaDeIngreso],[M3acumuladosAgua],[M3AcumuladosUltimoRecibo]
FROM inserted WHERE [id] = @idMenor AND activo = 1
FOR JSON PATH)
EXEC [dbo].[SP_BitacoraCambioInsert]
@inIdEntityType = 1,
@inEntityID = @idMenor,
@inJsonAntes = @jsonAntes,
@inJsonDespues = @jsonDespues,
@inInsertedBy = 'usuario1',
@inInsertedIn = '1.1787.0289',
@inInsertedAt = @insertedAt
END
SET @idMenor = @idMenor+1
END
Tablas nuevas:
- BitacoraCambio: almacena los cambios que se hacen en las entidades. (id,idEntityType,entityID,jsonAntes,jsonDespues,insertedAt,insertedBy,insertedIn)
- Corte: almacena los cote que se hacen a las propiedades. (id,fecha,id_propiedad,recRecon)
- MovConsumo: Almacena los movimientos de consumo que se le realizna a una propiedad.(id,fecha,montoM3,lecturaConsumo,nuevoM3Consumo,id_Propiedad,idTipoMov)
- ReciboPagado: esta tabla se agrego ya que teniamos un problema con los comprobantes de pago y los recibo, el problema era que los recibos tenian el id del comprobante pero los comprobantes de pago se generaban hasta que los ecibos fueran pagados por lo que implementamos esta tabla la cual tiene el id del recibo y su comprobante de pago.
- ReciboReconexion: es un tipo de recibo por lo que hereda de la tabla de recibos. (id y es el mismo que el recibo)
- Reconexion: Cada vez que se le genera una reconexion a una propiedad queda almacenada aqui. (id,fecha,id_Propiedad,recRecon)
- TipoEntidad: Es un catalogo con los id de las entidades. (id,nombre,activo)
- TipoMov: catalogo con los tipos de movimiento.(id,nombre)
Se complemento:
- Transactions y commits cuando un SP trae mas de una transacción es decir mas de un update o mas de un insert
declare y sets...
BEGIN TRAN
nada mas transacciones....
COMMIT
- Para devolver todas las transacciones que se hicieron se implemento el siguiente codigo el cual realiza un rollback de la transaccion en caso de que se realizaran mas de una transaccion:
If @@TRANCOUNT > 0
ROLLBACK TRAN;
- Cuando se hace CRUD de las entidades: Propietario, usuario, propietarioVsPropiedad y Usuario vsPropiedad, se agrego el siguiente codigo para guardar los cambios en la bitacora, tambien se implemento que ahora reciben dos parametros mas(@inUsuarioACargo, @inIPusuario):
--GUARDA EL ID y fecha
SET @insertedAt = GETDATE()
SET @idModified = (SELECT [id] FROM [dbo].[Usuario] WHERE [nombre] = @inNombreOriginal)
----GUARDA EL JSON DEL ROW DE USUARIO ANTES
SET @jsonAntes = (SELECT [id], [nombre], [password], [tipoDeUsuario], [fechaDeIngreso]
FROM [dbo].[Usuario] WHERE [id] = @idModified
FOR JSON PATH)
--GUARDA EL JSON DEL ROW DE USUARIO DESPUES
SET @jsonDespues = (SELECT [id], [nombre], [password], [tipoDeUsuario], [fechaDeIngreso]
FROM [dbo].[Usuario] WHERE [id] = @idModified
FOR JSON PATH)
--INSERTA EL CAMBIO
EXEC [dbo].[SP_BitacoraCambioInsert] @inIdEntityType = 3,
@inEntityID = @idModified, @inJsonAntes = @jsonAntes,
@inJsonDespues = @jsonDespues, @inInsertedBy= @inUsuarioACargo,
@inInsertedIn = @inIPusuario, @inInsertedAt = @insertedAt
Problemas:
- Al tener tantas acciones en la lógica de la segunda parte era un poco confuso como trabajar con todo, sin embargo al trabajar con iteracion y leer bien lo que había que hacer se logro entender y conseguir terminar todo de la mejor manera.
- Al llamar al trigger con procesos masivos, no ns estaba realizando la función que era generar json y dejarlos almacenado por lo que tuvimos que hacer que le trigger fuera iterativo para conseguir esto.
- Se investigo bastante ya que algunas funciones nos simplificaran bastante seleccionar los objetos que necesitábamos, por ejemplo cuando se buscan las propiedades que tiene mas de un recibo pendiente para generar un recibo de corte, esto se podía hacer con un solo select y buscando e investigando lo conseguimos.
- Era necesario hacer muchos inner joins para consultas por lo que había que mantener bastante el orden y estar atento a que no faltara ninguna condición.
- Al necesitar tablas variables, nos enteramos que las tablas no se reinician hasta que se salga del scope del SP por lo que en el SP de pago tuvimos que agregar un contador e iterar de otra manera, la manera que utilizamos para iterar normalmente es sacar el mínimo y el máximo sin embargo en este iteramos hasta que estén todos los recibos pagados, para la ietracion por día lo que hacemos es borra todos los elementos de las tablas después de usarlas.
Para esta segunda parte los procedimientos eran mas pesados, habían que hacer mas de un a transacción y ademas tuvimos que trabajar con recursividad para así poder trabajar con cada objeto de manera individual, trabajar de manera iterativa es bastante funcional y es mas fácil a la hora de realizar diferentes acciones a un solo objeto.
Se trabajo por 58 horas en total aproximadamente
Parte Web
- ¿Qué se implementó?
- Sitio web para el cliente, el cual permite al usuario ver la información de las propiedades con que cuenta permiso.
- Cuando el usuario cliente ingresa al sitio web, se le despliega un grid con las propiedades. Este grid tiene cuatro link buttons, cada uno para una distinta consulta que puede realizar el usuario. Estas consultas son: ver los conceptos de cobro de la propiedad, ver los recibos pagados, ver los recibos pendientes y ver todos los comprobantes de pago de la propiedad.
- Se añadió una nueva consulta al sitio web del administrador que permite ver todos los cambios que se dieron en un tipo de entidad en un rango de fechas. La interfaz de para realizar esta consulta es parecida a las otras, cuenta con una lista que permite seleccionar la entidad, la diferencia es que los otros dos campos son inputs que al dar click muestran un calendario para que el usuario puede elegir una fecha de inicio y una de fin. Esto se implemento usando la librería jQuery, la cual ya cuenta con una función que convierte el input en un DatePicker.
- Esta consulta obtiene de la base de datos una tabla con el usuario que hizo el cambio, su ip, y dos json que muestran el estado antes y después del cambio. Para mostrar esta información se decidió utilizar tres gridView, el primero muestra una lista de todos los cambios por fecha, junto con el usuario, la ip, y un botón para ver la información contenida en los json. Al seleccionar un cambio en especifico se muestra una o dos tablas, dependiendo del tipo de cambio, la cuales muestran el json antes y el json después del cambio.
- Ahora cuando se carga la pagina de login, lo primero que se hace es guardar la ip del usuario, y en el momento que inicia sesión se guarda también su nombre de usuario. Esta se guarda en una variable de sesión usando el siguiente codigo:
- string userIp = Request.UserHostAddress;
if (Request.UserHostAddress != null)
{
HttpContext.Current.Session["userIp"] = userIp;
}
- El nombre de usuario de usuario también se guarda en una variable de sesión cuando el usuario ingresa sus datos correctamente.
- String user = usernameTextBox.Text;
- Session["userName"] = user;
- El nombre de usuario y la ip se tuvieron que agregar como parámetros cuando se realiza un crud de propietario, usuario, propiedad vs propietario, usuario vs propiedad. Esto no era necesario en el crud de propiedades, esto dado que la tabla propiedades usa un trigger para guardar los datos en la bitácora. Solo se tuvieron que agregar las siguientes dos líneas de código en cada SP que necesitaba los parámetros:
- cmd.Parameters.Add("@inUsuarioACargo", SqlDbType.VarChar).Value = Session["userName"];
- cmd.Parameters.Add("@inIPusuario", SqlDbType.VarChar).Value = Session["userIp"];
- Problemas encontrados
- A la hora de mostrar los json inicialmente se hizo un código ineficiente el cual lo que hacía era tomar uno de los dos json, el que no estuviera nulo, y se utilizaban las llaves para crear las columnas de las tablas que muestran los dos json, luego cada uno se tomaba por separado y se usaban los valores para formar una fila en cada tabla. Estas dos tablas se asignaban a dos gridView en la pagina del cliente y de esta manera se mostraba el json. Tras investigar un poco se encontró que la misma instrucción que convierte el json en un diccionario, arreglo, etc, también era capaz de convertirlo directamente a una tabla, por esto se decidió cambiar el código para que ambos json sean convertidos directamente a una tabla, las cuales luego solo se asignan sus respectivos grids y se muestran en la pagina web. En caso de que uno de los json sea nulo el grid respectivo simplemente no se muestra.
string[] ambosJson = cambiosPorFecha[rowIndex];
DataTable antes = (DataTable)JsonConvert.DeserializeObject(ambosJson[0], (typeof(DataTable)));
DataTable despues = (DataTable)JsonConvert.DeserializeObject(ambosJson[1], (typeof(DataTable)));
GridJsonAntes.DataSource = antes;
GridJsonAntes.DataBind();
GridJsonAntes.Visible = true;
DivJsonAntes.Visible = true;
GridJsonDespues.DataSource = despues;
GridJsonDespues.DataBind();
GridJsonDespues.Visible = true;
DivJsonDespues.Visible = true;
- El código anterior muestra como se convierte el json a un objeto DataTable, el cual luego solo se asigna a un grid y se muestra este.
- No se sabia como crear un datePicker en asp por lo que se tuvo que investigar un poco sobre el tema. La solución que se encontró fue usar la librería de JQuery y JQuery UI junto con una pequeña función de javascript.
<p style="color:white">Fecha inicio: <input type="text" name="fromDate" id="fromDate1"> Fecha final <input type="text" name="toDate" id="toDate1"></p>
<script>
$(function () {
$("#fromDate1").datepicker();
$("#toDate1).datepicker();
});
</script>
- Este script solo se debe agregar al final del archivo que contiene ambos inputs y se encarga de convertirlos en DatePickers. La función "datepicker" es de Jquery, por esto es necesario incluir la librería.
<link rel="stylesheet" href="/css/jquery-ui.min.css">
<script src="/Js/jquery-3.5.1.min.js" type="text/javascript"></script>
<script src="/Js/jquery-ui.min.js" type="text/javascript"></script>
- La tres líneas de código se deben añadir al head del archivo para incluir Jquery, Jquery ui, el respectivo archivo css.
- Se trabajo aproximadamente 20 horas.
No hay comentarios:
Publicar un comentario