PDA

Ver la Versión Completa : Problema con Stored Procedure para actualizar tabla con datos de otra tabla.


Adrian Murua
04-02-2012, 01:39:08
Estimados Amigos:

Tengo dos tablas de una base de datos MySQL, una de ellas tiene datos sobre las cuotas sociales de un afiliado a una mutual, y la otra tiene un registro de pagos de estas cuotas sociales. Ej:

Tabla CuotasSociales.


ID Fecha pura saldo interes importepag Pagada Mes Af_Id
1 27/01/2012 0.000 0.000 0.000 59.000 1 Dec 2
2 27/01/2012 0.000 34.910 0.000 24.090 2 Dec 3


Tabla Planillas.

Af_ID Valor Periodo

2 59.000 Dec
3 24.090 Dec


Aproximadamente son 2000 registros en ambas tablas.

Lo que necesito hacer es actualizar los datos de la tabla CuotasSociales con los datos de la tabla planilla, Pues anteriormente se inserto los registros mediante un procedimiento almacenado que inserta un valor (59,000 pesos, valor de la cuota social) en el campo importepag y un '1' en el campo pagada, valor que representa el pago total de la cuota(reg. N°1), la otra posibilidad es como se muestra en el reg. N°2, si el pago fue menor a 59 pesos, se inserta el valor pagado(24.090 pesos ) en el campo importepag y la diferencia respecto a 59 se ingresa en el campo saldo, se coloca un '2' en el campo pagada que representa un pago parcial.
Los valores de la tabla planillas son extraidos de los descuentos por planillas de los afiliados.



CREATE DEFINER = 'root'@'localhost' PROCEDURE `cuotasmutual828`()
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
#Routine body goes here...
DECLARE dni VARCHAR(8);
DECLARE control VARCHAR(15);
declare importe DECIMAL(18,3);
DECLARE operacion int;
DECLARE afiliado int;
DECLARE diff DECIMAL(18,3);
DECLARE done INT DEFAULT 0;
DECLARE cuotasocial DECIMAL(18,3);

DECLARE bPlanillas CURSOR FOR SELECT
planillas.dni,
planillas.control,
planillas.importe,
afiliados.id as afiliado
FROM
planillas
INNER JOIN afiliados ON (planillas.dni = afiliados.dni)order by dni;

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN bPlanillas;

set operacion = 1680;

SELECT cuota_social INTO cuotasocial FROM parametros WHERE id = 1;

REPEAT

FETCH bPlanillas INTO dni, control, importe, afiliado;
IF NOT done THEN
if importe >= cuotasocial THEN
INSERT INTO cuotassociales (fecha,pura,saldo,interes,importepag,pagada,mespagado,anopagado,operacion,afiliados_id,modocobranzas _id)
VALUES ( curdate(),0,0,0,importe,'1','Dec','2012',operacion,afiliado,'1');
ELSE
set diff = cuotasocial - importe;
INSERT INTO cuotassociales (fecha,pura,saldo,interes,importepag,pagada,mespagado,anopagado,operacion,afiliados_id,modocobranzas _id)
VALUES ( curdate(),0,diff,0,importe,'2','Dec','2012',operacion,afiliado,'1');

END IF;
set operacion = operacion + 1;
END IF;
UNTIL done END REPEAT;

CLOSE bPlanillas;

END;


Este procedimiento almacenado funciona bien, aunque demora en promedio 43seg. aprox., pero funciona.

Despues de correr este procedimiento , se limpia la tabla planilla y se cargan nuevos datos que representan descuentos por otras modalidades por ej. descuentos por CBU, obviamente dentro del mismo periodo.

Como dije arriba debo actualizar la tabla cuotassociales con estos nuevos datos de la tabla planillas. y aqui recide el problema que se me presenta.

La logica de la actualizacion seria la siguiente:

1. tomar un registro de la tabla planillas, ver si existe el afiliado en la tabla cuotassociales.
2. si existe comprobar que el saldo sea mayor que cero ( es decir que este parcialmente pagada la cuota). actualizar el importepag y el campo pagada en '1' si la suma es igual a 59 o seguir con el valor '2' si aun es menor que 59.
3. Seguir los pasos 1 y 2 hasta el ultimo registro de la tabla planillas.


Este es el procedimiento almacenado que intentar hacer esto.



CREATE DEFINER = 'root'@'localhost' PROCEDURE `cuotasmutual964`()
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
#Routine body goes here...
#Routine body goes here...
DECLARE dni VARCHAR(8);
DECLARE control VARCHAR(15);
DECLARE importe DECIMAL(18,3);
DECLARE operacion int;
DECLARE afiliado int;
DECLARE diff DECIMAL(18,3);
DECLARE done INT DEFAULT 0;
DECLARE diff_ DECIMAL(18,3);

DECLARE cid int;
DECLARE cfecha VARCHAR(10);
DECLARE cpura DECIMAL(18,3);
DECLARE csaldo DECIMAL(18,3);
DECLARE cinteres DECIMAL(18,3);
DECLARE cimportepag DECIMAL(18,3);
DECLARE cpagada int ;
DECLARE cmespagado VARCHAR(3);
DECLARE canopagado VARCHAR(4);
DECLARE coperacion INT;
DECLARE cafiliados_id INT;
DECLARE cmodocobranzas_id INT;
DECLARE cdni VARCHAR(8);


DECLARE bPlanillas CURSOR FOR SELECT
planillas.dni,
planillas.control,
planillas.importe,
afiliados.id as afiliado
FROM
planillas
INNER JOIN afiliados ON (planillas.dni = afiliados.dni)order by dni;


DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN bPlanillas;


REPEAT

FETCH bPlanillas INTO dni, control, importe, afiliado;
IF NOT done THEN

SELECT
cuotassociales.id,
cuotassociales.pura,
cuotassociales.saldo,
cuotassociales.interes,
cuotassociales.importepag,
cuotassociales.pagada,
cuotassociales.afiliados_id,
cuotassociales.modocobranzas_id,
afiliados.dni
INTO
cid,
cpura,
csaldo,
cinteres,
cimportepag,
cpagada,
cafiliados_id,
cmodocobranzas_id,
cdni

FROM
cuotassociales
INNER JOIN afiliados ON afiliados.id = cuotassociales.afiliados_id
WHERE afiliados.dni = dni limit 1;

IF csaldo > 0 THEN

IF importe >= csaldo THEN

SET diff = importe - csaldo;
UPDATE cuotassociales SET
/* pura = 0,
saldo = 0,
interes = 0,*/
importepag = cimportepag + csaldo,
pagada = '5'
WHERE id = cid;

ELSE

SET diff = 0;
SET diff_ = csaldo - importe;
UPDATE cuotassociales SET
/* pura = 0,*/
saldo = diff_,
interes = 0,
importepag = cimportepag + importe,
pagada = '9'
WHERE id = cid;


END IF;



END IF;

END IF;
UNTIL done END REPEAT;

CLOSE bPlanillas;

END;


pero me actualiza solo un registro. lo que he notado es que cuando el select dentro del repeat es nulo, directamente la variable done se pone a 1 y sale del bucle y termina el procedimiento.

Uso como lenguaje anfitrion el PHP 5.3, pero hice ejecutar estos procedimiento con los clientes de MySQL: Navicat y EMS mysqlmanager.

Sinceramente no se como modificar este procedimiento para que actualice todos los registro que correspondan.

Gracias por su tiempo.

Saludos.

Caral
04-02-2012, 01:46:34
Hola
Primera vez que veo algo tan complicado para llevar una simple cuenta por Cobrar.:o:p
Saludos

Adrian Murua
04-02-2012, 02:13:08
Pues, eso , como se prodria hacer para hacerlo menos complicado. :cool:

Caral
04-02-2012, 02:30:14
Hola
No se como se hara menos complicado, eso dependera del punto de vista de cada quien.
Como hago estas cosas:
1-Tabla cuentas por cobrar.
En esta se tienen los datos del cliente y se tiene el balance de su cuenta con el dato inicial, los pagos realizados y los saldos.
Esta tabla se actualiza de acuerdo al ID del cliente.
No se cambian los datos, simpleente se insertan, el programa es el que hace los calculos.
2- Tabla cuentas por cobrar detalle.
En esta se hace un detalle de todas las transacciones efectuadas a la cuenta de cada cliente.
3- Tabla clientes.
Es evidente, los datos del cliente.

No me parece muy logico dejar todo a la BD, me parece que los datos los tiene que generar el programa.
Saludos
PD: Por algun lado deje un programa completo para cuentas por cobrar y pagar, podrias buscar en el FTP del club por ahi debe de estar, creo que te daria alguna idea de como hacer estas cosas, NO mas eficientemente (eso se lo dejo a los Maestros) si no mas sencillo.

Adrian Murua
04-02-2012, 02:54:49
Gracias, por tu ayuda .

He intentado hacer que el programa haga los calculos pertinentes, pero tarda bastante tiempo, por supuesto que no debe ser la mejor rutina, por eso estaba probando realizarlo con procedimientos almacenados , voy a echar un vistazo a lo que tu me dices para guiarme , gracias por tu respuesta.

Saludos.