Lo prometido es deuda (gracias)

// Programacion boton PROCESAR
// Te recuerdo que son 3 tablas, movexist,kardex,movacep
// Aqui vamos
// Inicializa variables
INTEGER TOT_LIN,I,BODORIG,BODDEST,LINCOMP
STRING TIPMOV,CODPROD,POCMOV,IDUSUARIO
LONG NUCOMP,CANTMOVI,PRECMOV
TOT_LIN=DW_2.ROWCOUNT()
FOR I=1 TO TOT_LIN
// Leo tabla movimientos
TIPMOV=DW_2.GetItemString(I,"movexist_tip_mov")
NUCOMP=DW_2.GetItemNumber(I,"movexist_nu_comp")
LINCOMP=DW_2.GetItemNumber(I,"movexist_lin_comp")
FEMOVI=DW_2.GetItemDate(I,"movexist_fe_movi")
BODORIG=DW_2.GetItemNumber(I,"movexist_bod_orig")
CODPROD=DW_2.GetItemString(I,"movexist_cod_prod")
CANTMOVI=DW_2.GetItemNumber(I,"movexist_cant_movi")
PRECMOV=DW_2.GetItemNumber(I,"movexist_prec_mov")
POCMOV=DW_2.GetItemString(I,"movexist_poc_mov")
BODDEST=DW_2.GetItemNumber(I,"movexist_bod_dest")
IDUSUARIO=DW_2.GetItemString(I,"movexist_id_usuario")
// Busco el producto en el kardex
SELECT BODEGA_1,BODEGA_2,BODEGA_3 INTO :BODEGA1,:BODEGA2,:BODEGA3
FROM KARDEX WHERE COD_PROD=:CODPROD;
// Sumo o resto segun bodega indicada en movimientos
CHOOSE CASE tipmov
CASE IS >"10" AND <"20"
// Suma a bodega
// ? Como se puede acortar la instruccion
// ya que podrian ser hasta 20 bodegas ??
CHOOSE CASE BODORIG
CASE IS = 1
BODEGA1=BODEGA1+CANTMOVI
CASE IS = 2
BODEGA2=BODEGA2+CANTMOVI
CASE IS = 3
BODEGA3=BODEGA3+CANTMOVI
END CHOOSE
CASE ELSE
// Resta a bodega
CHOOSE CASE BODORIG
CASE IS = 1
BODEGA1=BODEGA1-CANTMOVI
CASE IS = 2
BODEGA2=BODEGA2-CANTMOVI
CASE IS = 3
BODEGA3=BODEGA3-CANTMOVI
END CHOOSE
END CHOOSE
// Actualizo los campos bodegas del kardex
UPDATE KARDEX SET BODEGA_1=:BODEGA1 , BODEGA_2=:BODEGA2 , BODEGA_3=:BODEGA3
WHERE COD_PROD=:CODPROD USING SQLCA;
// Agrego el registro en movimientos aceptados
INSERT INTO MOVACEP(TIP_MOV,NU_COMP,LIN_COMP,FE_MOVI,BOD_ORIG,COD_PROD,CANT_MOVI,PREC_MOV,POC_MOV,BOD_DEST,ID_USUARIO)
VALUES (:TIPMOV,:NUCOMP,:LINCOMP,:FEMOVI,:BODORIG,:CODPROD,:CANTMOVI,:PRECMOV,:POCMOV,:BODDEST,:XUSER);
NEXT
// Eso es todo por ahora, lo iré poniendo más complejo en la medida que
vaya siendo corregido.
1

1 Respuesta

107.925 pts. clipper todas sus versiones (manejo total) power...
Perdón por la tardanza, espero aun no sea demasiado tarde.
He leído los scripts que me enviaste y asumo que el segundo es el correcto, por lo que mi respuesta va a estar centrado en este.
Con respecto a las instrucciones UPDATE e INSERT, me doy cuenta que cada una de ellas valida individualmente la posibilidad de asentar o rechazar la acción.
Por lo que te propongo utilices una variable del tipo BOOLEAN que permita definir esta acción.
Por ej.
BOOLEAN lb_commit
STRING ls_error
lb_commit = TRUE
// Actualizo los campos bodegas del kardex
UPDATE KARDEX
SET BODEGA_1=:ll_BODEGA1,
BODEGA_2=:ll_BODEGA2,
BODEGA_3=:ll_BODEGA3
WHERE COD_PROD=:ls_CODPROD USING SQLCA;
lb_commit = ((SQLCA.SQLCode = 0) AND (SQLCA.SQLDBCode = 0))
ls_error = SQLCA.SQLErrText
IF lb_commit THEN
INSERT INTO MOVACEP (TIP_MOV,NU_COMP,LIN_COMP,FE_MOVI,BOD_ORIG,COD_PROD,CANT_MOVI,PREC_MOV,POC_MOV,BOD_DEST,ID_USUARIO)
VALUES (:ls_TIPMOV,:ll_NUCOMP,:li_LINCOMP,:ld_FEMOVI,:li_BODORIG,:ls_CODPROD,:ll_CANTMOVI,:ll_PRECMOV,:ls_POCMOV,:li_BODDEST,:XUSER)
USING SQLCA;
lb_commit = ((SQLCA.SQLCode = 0) AND (SQLCA.SQLDBCode = 0))
ls_error = SQLCA.SQLErrText
END IF
IF lb_commit THEN
COMMIT USING SQLCA;
ELSE
messagebox("Aviso", "Ocurrio un error al insertar en la tabla MOVACEP.r" + ls_error)
EXIT //--> aborta el loop for
END IF
En esta porción modificada notaras que la variable lb_commit determina la acción de asentar la transacción, la cual esta formada de 2 acción una de un UPDATE y la otra de un INSERT.
En caso que existiera un error en el UPDATE, no ejecuta el INSERT, y si lo hace, depende de este para asentar la transacción.
Igualmente nota que utilizo SQLCA. SQLCode y SQLCA. SQLDBCode, para evaluar la transacción, lo que sucede es que uno me permite conocer los errores del sistema, y el otro los errores de la base de datos. Por lo que te recomiendo utilices este concepto.
También habrás notado que asigno el valor del SQLCA. SQLERRTEXT a una variable antes de hacer ROLLBACK, lo que sucede es que cuando este comando es ejecutado, es borrado el contenido del objeto de transacción, en este caso SQLCA.
Es recomendable que utilices en cualquier instrucción la sociacion del objeto de transacción por medio de la palabra USING, créeme que esto puede salvarte la vida en un momento determinado.
Con respecto a las bodegas.
Creo que el problema puede versar en que dependes del código de la bodega para determinar que hacer, si sumas o restas. Te propongo modificar tu tabla y añadir una nueva columna que por ejemplo podrías llamar signo, en donde coloques un signo + o - y por medio de este, evalúes que vas a hacer en la bodega según su código.
De esa forma puedes dar de alta las bodegas que quieras, sin tocar tu código.
Por ultimo.
Si estas manejando una base de datos transaccional, la lectura y la escritura no debe ser impedimento de bloqueo, a excepción que el mismo usuario este tratando de modificar un registro y al mismo tiempo leyéndolo, esto provoca un DEADLOCK, pero suele suceder muuuuuy de vez en cuando, casi te puedo asegurar que la propia base de datos va a evitarlo.
Creme que el procedimiento que estas proponiendo va a efectuarse tan rapido que nadie se va a dar cuenta, y los usuarios que leen tampoco.
La secuencia de actualización es la optima, pues es por cada registro ingresado
Solo ten en cuenta que cuando exista un error, seguramente el usuario va a querer actualizar de nuevo, y seguramente los datos estarán en pantalla, es posible que intente actualizar 2 veces el mismo registro, por lo que mi recomendación es que incluyas una columna que te indique que registros ya están actualizados, para que cuando vuelva a actualizar, solo tome en cuenta aquellos que no se encuentran marcados, la visibilidad de la marca la dejo a tu criterio.
Modifique el script de esta forma, pero no estoy seguro si están bien puestas las instrucciones que permiten dejar todo como estaba en caso de haber algún problema.
Gracias.
INTEGER li_TOT_LIN, I, li_BODORIG, li_BODDEST, li_LINCOMP
STRING ls_TIPMOV, ls_CODPROD, ls_POCMOV, ls_IDUSUARIO
LONG ll_NUCOMP, ll_CANTMOVI, ll_PRECMOV, ll_BODEGA1, ll_BODEGA2, ll_BODEGA3
DATE ld_FEMOVI
li_TOT_LIN = DW_2.ROWCOUNT()
sqlca.autocommit = False
FOR I = 1 TO li_TOT_LIN
// Leo tabla movimientos
ls_TIPMOV=DW_2.GetItemString(I,"movexist_tip_mov")
ll_NUCOMP=DW_2.GetItemNumber(I,"movexist_nu_comp")
li_LINCOMP=DW_2.GetItemNumber(I,"movexist_lin_comp")
ld_FEMOVI=DW_2.GetItemDate(I,"movexist_fe_movi")
li_BODORIG=DW_2.GetItemNumber(I,"movexist_bod_orig")
ls_CODPROD=DW_2.GetItemString(I,"movexist_cod_prod")
ll_CANTMOVI=DW_2.GetItemNumber(I,"movexist_cant_movi")
ll_PRECMOV=DW_2.GetItemNumber(I,"movexist_prec_mov")
ls_POCMOV=DW_2.GetItemString(I,"movexist_poc_mov")
li_BODDEST=DW_2.GetItemNumber(I,"movexist_bod_dest")
ls_IDUSUARIO=DW_2.GetItemString(I,"movexist_id_usuario")
// Busco el producto en el kardex
SELECT BODEGA_1,BODEGA_2,BODEGA_3
INTO :ll_BODEGA1,:ll_BODEGA2,:ll_BODEGA3
FROM KARDEX
WHERE COD_PROD=:ls_CODPROD;
// Sumo o resto segun bodega indicada en movimientos
CHOOSE CASE ls_tipmov
CASE IS >"10"
// Suma a bodega
// ? como se puede acortar la instruccion
// ya que podrian ser hasta 20 bodegas ??
CHOOSE CASE li_BODORIG
CASE 1
ll_BODEGA1 += ll_CANTMOVI
CASE IS < 2
ll_BODEGA2 += ll_CANTMOVI
CASE IS > 2
ll_BODEGA3 += ll_CANTMOVI
END CHOOSE
CASE ELSE
// Resta a bodega
CHOOSE CASE li_BODORIG
CASE 1
ll_BODEGA1 -= ll_CANTMOVI
CASE 2
ll_BODEGA2 -= ll_CANTMOVI
CASE 3
ll_BODEGA3 -= ll_CANTMOVI
END CHOOSE
END CHOOSE
// Actualizo los campos bodegas del kardex
UPDATE KARDEX
SET BODEGA_1=:ll_BODEGA1,
BODEGA_2=:ll_BODEGA2,
BODEGA_3=:ll_BODEGA3
WHERE COD_PROD=:ls_CODPROD USING SQLCA;
If SQLCA.SQLCode = -1 then
rollback;
messagebox("Aviso", "Ocurrio un error al actualizar la tabla KARDEX.~r" + SQLCA.SQLErrtext)
EXIT // Para salir del For... to
end if
// Agrego el registro en movimientos aceptados
INSERT INTO MOVACEP(TIP_MOV,NU_COMP,LIN_COMP,FE_MOVI,BOD_ORIG,COD_PROD,CANT_MOVI,PREC_MOV,POC_MOV,BOD_DEST,ID_USUARIO)
VALUES (:ls_TIPMOV,:ll_NUCOMP,:li_LINCOMP,:ld_FEMOVI,:li_BODORIG,:ls_CODPROD,:ll_CANTMOVI,:ll_PRECMOV,:ls_POCMOV,:li_BODDEST,:XUSER);
If SQLCA.SQLCode = -1 then
rollback;
messagebox("Aviso", "Ocurrio un error al insertar en la tabla MOVACEP.~r" + SQLCA.SQLErrtext)
EXIT // Para salir del For... to
end if
NEXT
// Al salir:
Commit;
Hola, mi pregunta es si cuando estoy ejecutando el script anterior, ¿las tablas involucradas pueden ser consultadas?, ¿O simplemente los demás usuarios deben esperar a que termine el proceso?
Gracias, y esta pendiente la pregunta anterior.
Disculpa las molestias.
Por supuesto que me sirvió, ahora voy de lleno a volcar lo que me enseñaste.
Muchas gracias, y con tu respuesta, no importa mucho la tardanza.
Saludos

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas