PDA

Ver la Versión Completa : Problemas al grabar Facturas o Pedidos?


FelipeDiaz
08-01-2008, 16:50:22
Hola a todos,

Antes que todo me perrdonan si tal ves soy algo extenso en la explicacion o si mios tres inquietudes podrian hacerse en tres hilos, pero en aras de no explicar la situacion tres veces los resum aqui...

Se me presenta la siguiente inquietud y requiero algo de orientación, agradezco de antemano quien me pueda ayudar.

Ando trabajando una aplicación comercial con DELPHI, FIREBIRD y componentes FIBPLUS, y llegué al punto donde tengo que trabajar las ventanas o forms tipo “Pedidos” o “Facturas”.

Tengo algunos inconvenientes que se me han presentado y aún no se, si es causado por la forma en que trabajo o hay algo que estoy dejando de hacer:

Son tres inquietudes, pero antes tratare de definir como lo estoy haciendo.

Capturar por ejemplo Un pedido:

Trabajo un form con controles vinculados directamente con las tablas Maestra (encabezado del pedido) y Detalle (relación de artículos).

Teniendo en cuenta que , internamente la aplicación ejecuta un Dataset.Post y luego un Dataset.Edit, (de tal forma que queda definida la Primary Key de la tabla maestra) en el momento mismo en que el usuario intenta crear un nuevo registro para los detalles ( y habiendo ingresado antes todos los datos de encabezado).

La anterior es la forma en que lo recomienda el autor de la cara oculta de Delphi.

Volviendo al tema…

Inicialmente se presenta la ventana con los DB controles para la tabla maestra y un DBGrid para los detalles, adicionalmente 4 botones ( “Buscar”, “Nuevo”, ”Eliminar”, y “Cancelar”)

Cuando el usuario desea crear un nuevo pedido, presiona el Boton “Nuevo” (aquí inicio un Database.Startransaction ) y los controles de encabezado le permiten la edición.

Para agregar detalles al pedido, Existen otros dos botones “Agregar Producto” y “Eliminar Producto”, el usuario debe presionar el de agregar, que le presenta una segunda ventana de donde puede escoger los productos (desde otro DBGrid) y agregarlos al DBGrid de la ventana inicial, (creo que esta forma es la mas ordenada).
Para cada registro agrego los campos mediante instrucciones desde una tabla a la otra y haciendo Insert al inicio y post al final del grupo.

Como imaginaran el boton Eliminar Producto, es para eliminar registros del DBGrid de la primera Ventana, es decir si el usuario desea borrar un registro previamente agregado.

Al final el usuario confirma o graba el pedido mediante un Boton Guardar, (que en mi caso es el mismo “Nuevo”, el cual alterno). Y aquí es donde realizo el Database.Commit.

Bueno, si hasta aquí no hay confusión alguna… mis inquietudes son las siguientes:


El StarTransaction, lo estoy realizando al presionar el boton “NUEVO” mientras que la ejecusion del Commit o el Rollback, sucede al presionar el Grabar o Cancelar , es decir que las instrucciones no estan en forma secuencial o continua dentro del codigo, esto permite que entre la ejecución de las dos intruciones el usuario pueda abrir otra ventana y tome otras decisiones, como cancelar la transacción con el boton cancelaro salir de la ventana.Tengo la ligera impresión que esta mal como lo hago, aunque me funciona así.
Ademas tengo entendido que el StarTransaction va antes de una instrucicon INSERT o EDIT, y lo peor es que no puedo proteger el codigo con una instrucción TRY Except por no estar continuo.


En este caso en que hablo de pedidos o facturas, sabemos bien que es importante que se conserve el consecutivo del Numero del documento. Es decir aquí la opcion de un generador y un triger, no serian una solucion adecuada. Para este punto mi aplicacion realiza una consulta de cual es el mayor numero asignado (Select MAX) y le sumo 1. y ese valor se presenta y se almacena en el nuevo registro con el post que se realiza sobre la cabecera del archivo justo luego del startransaction y cuando aun no se ha cerrado la transacción.El problema que noté cuando estaba haciendo pruebas, es que cuando se produce un error antes de cerrar la transacción, es decir antes de ejecutar un commit o un Rollback,……….. al reinicar la aplicación, encuentro que el registro fue almacenado, (como si hubiese ocurrido un Commit o como si el solo Post hubiese sido suficiente e ignorando la transacción). Previamente me asegure que las propiedades AutoCommit de los dataset, estuviesen en False. No se que ocurre, tenia entendido que cuando no se cierra una transacción, ningun cambio es tenido en cuenta.


Cuando uso el boton eliminar…. O elimino con Control + Delete, los registros visualmente de borran de los controles (DBGrid), pero luego que el usuario decide grabar cambios, resulta que los registros que no debian aparecer en detalles, aparecen como si la accion de borrado no fuese tenido en cuenta.Es decir lo que debe hacer ese boton “Eliminar producto” en realidad no funciona.



Gracias por la colaboración.

Felipe Diaz

waly2k1
08-01-2008, 17:03:55
Muchooooo rollo, lo q te aconsejo o al menos yo lo hago así, es:
Tener una tabla temporal donde cargas todos los items de facturas/Pedidos (detalles) y cuando confirma recién inicias la transacción y almacenas los datos. De esta forma te avitas todos los problemas de claves que en entorno multiusuario pueden generarte varios dolores de cabeza y no te preocupas por nada. La tabla la creas para cada factura/pedido y la borras cuando cancela o acepta y el nombre debe ser aleatorio o como quieras pero no un nombre fijo que pueda causar conflictos con otro usuario y listo, no more problem.

Saludos y espero te sirva de algo mi consejo
Walter

Edito:
El botón eliminar: Yo borraría directamente de la tabla: 'DELETE FROM Pedido WHERE Campo=' + Variable1 + ' AND Campo2=' + Variable2
y despues refrescas la tabla o consulta, con lo cual el DBGRID se actualiza solo.-

juanelo
08-01-2008, 17:09:39
Que tal,
Porque no usas clientDatasets.
Saludos

Lepe
09-01-2008, 09:32:12
Estoy con juanelo.

Una duda dudosa :p .... Si trabajas en Firebird ¿por qué has puesto la duda en el foro conexión con bases de datos? ;)

Si acaso trabajas con Firebird 2, recuerda que una sql de inserción puede devolver la clave primaría recien insertada:

insert into tabla (campoLLave, nombre) values (null, 'pepe')
returning_value campollave
(lo digo de memoria, espero no equivocarme).

Saludos

FelipeDiaz
14-01-2008, 21:14:28
Hola que pena la demora, ando en vacaciones y no dispongo d einternet en casa.

Si uso Firebird, y bueno el tema lo coloque aqui porque el problema que planteo es independiente del sistema de Base de Datos.

Por otro lado, estuve leyendo el capitulo 32 de la cara Oculta de Delphi, y plantean el uso de Alamacenamiento en cache, lo cual y sin mas codigo que tres lineas extras, me permite resilver los problemas anteriores.

No hay necesidad de tablas temporales pues la propiedad CacheUpdates, permite que Delphi haga el juego de tabla temporal, y solo la utilizas con las tablas que desees.

Les recomiendo ojear este capitulo y dos mas que siguen.

Un abrazo a todos y gracias por la colaboracion.

Felipe Diaz