Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Actualizar inventario desde DbGridEh (https://www.clubdelphi.com/foros/showthread.php?t=88855)

Camilo 14-08-2015 16:55:22

Actualizar inventario desde DbGridEh
 
Hola Amigos del Club.
uso Delphi XE y BD - Firebird
Mi pregunta es la Siguiente:
Tengo una tabla que se llama Inventarios. Dentro de ella hay un campo que se llama Codigo_Producto este campo es la llave primaria. y entre otros tengo un campo que se llama cantidad.
Necesito actualizar la cantidad de los productos desde un DbGrideh. esto lo lo gro bien. es decir con el procedimiento que pongo a continuacion me actualiza correctamente el problema es que no me suma lo que hay en el inventario con el parametro que le doy. Ejemplo:
Tengo un producto cuya codigo es 100 y la cantidad en inventarios es 500. Cuando lo actualizo con una cantidad de 100 (Deberia darme 600) entonces lo que hace es reemplazar la cantidad de 500 por la de 100 es decir actualiza con el parametro pero no lo suma.
Por favor me puden guiar en esta inquietud; de antemano mil gracias.
Código Delphi [-]
procedure TFCargaFactura.BitBtn1Click(Sender: TObject);
begin
DBGridEh1.DataSource.DataSet.First;
While not (DBGridEh1.DataSource.DataSet.Eof) do
  begin
      with IBQActualizaInventario do
       begin
       IBQActualizaInventario.Close;
             ParamByName('CODIGO_PRODUCTO').AsString:= DbGrideH1.Columns[0].Field.AsString;
               ParamByName('NOMBRE_PRODUCTO').AsString:= DbGrideH1.Columns[1].Field.AsString;
                 ParamByName('CANTIDAD').AsInteger:= DbGrideH1.Columns[2].Field.AsInteger;
                  ParamByName('PRECIO').AsFloat:= DbGrideH1.Columns[3].Field.AsFloat;
                  
       IBQActualizaInventario.Open;

      DBGridEh1.DataSource.DataSet.Next;
       end;
       end;
       DataModule1.IBT1.CommitRetaining;
       DataModule1.IBTInventario.close;
       DataModule1.IBTInventario.Open;
       Showmessage('EL INVENTARIO SE ACTUALIZO CON EXITO');
end;

El Query desde el cual se hace la actualizacion es el siguiente
Código SQL [-]
UPDATE OR INSERT INTO Inventario
(Codigo_Producto, Cantidad, Precio, Nombre_Producto )
VALUES (:Codigo_Producto, :Cantidad, :Precio, :Nombre_Producto)

ecfisa 14-08-2015 21:45:32

Hola Camilo.

Es que la declaración INSERT OR UPDATE hace solamente eso. Es decir verifica que la clave primaria (o la columna especificada en la cláusula MATCHING) existan. Si alguna de las anteriores no existe, realiza una inserción de modo contrario una modificación.

Pero según entiendo, estas intentando incrementar el valor de una determinada columna y la instrucción solo está diseñada para insertar o modificar de acuerdo a si existe o no el valor especificado.

Saludos :)

Camilo 15-08-2015 00:53:40

Hola Ecfisa. Gracias por tu tiempo, experiencia y sobre todo la voluntad de colaboración.
Sobre el tema te cuento que tienes razón yo intento ademas sumar la cifra de la nueva compra. posteriormente restar la cifra de la venta. en fin.
Me puedes orientar en mi pregunta por fa. Sera que hay que hacer un ciclo, sera que debo calcular un campo inicialmente y luego si subirlo?.
Entonces me toca hacer otro procedimiento? me puedes orientar un poco sobre cual hacer. Mil Gracias.

ecfisa 15-08-2015 06:10:35

Hola Camilo.

Creo que podrías hacerte un procedimiento similar a este ejemplo:
Código Delphi [-]
procedure UpdateInventory(qy: TIBQuery; const Cod: string;
  const Cant: Integer; const Prec: Currency);
begin
  qy.Close;
  qy.SQL.Clear;
  qy.SQL.Add('UPDATE INVENTARIO');
  qy.SQL.Add('SET CANTIDAD = CANTIDAD + COALESCE(:CANTIDAD, 0),');
  qy.SQL.Add('PRECIO = PRECIO + COALESCE(:PRECIO, 0)');
  qy.SQL.Add('WHERE CODIGO_PRODUCTO = :CODIGO');
  qy.ParamByName('CODIGO').AsString    := Cod;
  qy.ParamByName('CANTIDAD').AsInteger := Cant;
  qy.ParamByName('PRECIO').AsCurrency  := Prec;
  qy.ExecSQL;
end;

Ejemplos de llamada,

Agrega 4 unidades e incrementa 15.5 el precio del producto código '1':
Código Delphi [-]
  UpdateInventory(IBQueryTmp, '1', 4, 15.5);

Decrementa 4 unidades y decrementa 15.5 el precio del producto código '1':
Código Delphi [-]
  UpdateInventory(IBQueryTmp, '1', -4, -15.5);

Saludos :)

Camilo 15-08-2015 18:09:46

Hola Ecfisa.
El código lo implemento y no pasa nada. es decir no bota error pero no actualiza nada tampoco. por otro lado tengo la duda de ese "IBQueryTmp". de que se trata?
Una aclaración que me parece pertinente:
los campos cantidad y precio (integer y DoublePresicion) respectivamente los actualizo con base en los registros de una factura que se refleja en el DbGridEh1. si esta factura contiene 5 registros de productos comprados y en el inventario hay 4 de los 5 productos entonces el comportamiento seria actualizar los 4 que existen en los dos campos e insertar el 5. por eso el recorrido que hago del grid.
mi problema esta en que los parámetros no están tomando las cantidades y precios del inventario sino que toman solo las nuevas y (o) no hace nada o las duplica.

Camilo 15-08-2015 20:29:14

Hola recapitulo para ubicarnos en donde voy.

Si hago esto entonces me inserta o me actualiza bien la primera vez pero si ya existe el registro entonces me actualiza sin sumarme los nuevos valores de cantidad y precio.
Código Delphi [-]
procedure TFCargaFactura.Button1Click(Sender: TObject);
begin
  DBGridEh1.DataSource.DataSet.First;
  while not (DBGridEh1.DataSource.DataSet.Eof) do
  begin
    with IBQActualizaInventarios do
    begin
      UpdateInventory(IBQueryTmp, DbGrideH1.Columns[0].Field.AsString,
        DbGrideH1.Columns[2].Field.AsInteger, DbGrideH1.Columns[3].Field.AsFloat);
      IBQActualizaInventarios.Close;
      ParamByName('CODIGO_PRODUCTO').AsString:= DbGrideH1.Columns[0].Field.AsString;
      ParamByName('CATEGORIA').AsString:= DbGrideH1.Columns[4].Field.AsString;
      ParamByName('NOMBRE_PRODUCTO').AsString:= DbGrideH1.Columns[1].Field.AsString;
      ParamByName('REFERENCIA_PRODUCTO').AsString:= DbGrideH1.Columns[5].Field.AsString;
      ParamByName('CANTIDAD').AsInteger:= DbGrideH1.Columns[2].Field.AsInteger;
      ParamByName('PRECIO').AsFloat:= DbGrideH1.Columns[3].Field.AsFloat;
      ParamByName('Auditoria').AsString:=Edit1.Text;
      ParamByName('Fecha_Auditoria').AsDateTime:= StrToDate(MaskEdit1.Text);
      IBQActualizaInventarios.Open;
      DBGridEh1.DataSource.DataSet.Next;
    end;
  end;
  DataModule1.IBT1.CommitRetaining;
  DataModule1.IBTInventario.close;
  DataModule1.IBTInventario.Open;
  Showmessage('EL INVENTARIO SE ACTUALIZO CON EXITO');
end;

Y si hago esto entonces me acrtualia perfecto pero si el registro ya existe si no existe no lo inserta.
Código Delphi [-]
procedure TFCargaFactura.BitBtn1Click(Sender: TObject);
begin
  DBGRidEh1.DataSource.DataSet.First;
  while not DBGridEh1.Eof do
  begin
    UpdateInventory(IBQueryTmp, DbGrideH1.Columns[0].Field.AsString,
      DbGrideH1.Columns[2].Field.AsInteger,DbGrideH1.Columns[3].Field.AsFloat);
    DBGridEh1.DataSource.DataSet.Next;
  end;
  DataModule1.IBT1.CommitRetaining;
end;

Este el el llamado de la funcion que ecfisa expone arriba.

Entonces necesito combinar las dos. es decir si no esta el registro entonces creelo pero si esta entonces actualice los valores cantidad y precio.

Gracias por la ayuda que pueda recibir.

ecfisa 15-08-2015 21:32:35

Hola Camilo.
Cita:

Empezado por Camilo (Mensaje 495552)
Hola Ecfisa.
El código lo implemento y no pasa nada. es decir no bota error pero no actualiza nada tampoco. por otro lado tengo la duda de ese "IBQueryTmp". de que se trata?

El código incrementa o decrementa las columnas cantidad y precio en base al valor enviado en sus respectivos parametros: Cant y Prec y puedo asegurarte que lo hace (a menos que realizes un Rollback o RollbackRetaining).
También podría suceder que esté realizando la modificación y no la veas reflejada por que no actualizaste el TDataSet asociado al TDBGrid...


"IBQueryTmp", es otro TIBQuery qualquiera, de uso general, pero también podría haberlo escrito de este modo:
Código Delphi [-]
procedure UpdateInventory(const Cod: string; const Cant: Integer; const Prec: Currency);
var
  qy: TIBQuery;
begin
  qy := TIBQuery.Create(nil);
  try
    qy.Database    := Tu_DataModule.Tu_IBDatabase;
    qy.Transaction := Tu_DataModule.Tu_IBTransaction;
    qy.Close;
    qy.SQL.Clear;
    qy.SQL.Add('UPDATE INVENTARIO');
    qy.SQL.Add('SET CANTIDAD = CANTIDAD + COALESCE(:CANTIDAD, 0),');
    qy.SQL.Add('PRECIO = PRECIO + COALESCE(:PRECIO, 0)');
    qy.SQL.Add('WHERE CODIGO_PRODUCTO = :CODIGO');
    qy.ParamByName('CODIGO').AsString    := Cod;
    qy.ParamByName('CANTIDAD').AsInteger := Cant;
    qy.ParamByName('PRECIO').AsCurrency  := Prec;
    qy.ExecSQL;
  finally
    qy.Free;
  end;
end;
Si no deseas complicarte, una buena alternativa es el uso del TIBDataSet, un componente que conjuga las virtudes de una tabla y una consulta, te recomiendo que revises estos enlaces que tratan sobre él:
Saludos :)

Camilo 15-08-2015 22:50:52

hola. tienes toda la razón el procedimiento si funciona correctamente es que no lo veía actuar pero.......Escribí otro mensaje en que aclaro que las dos cosas funcionan perfectamente pero independientes. me gustaria saber como (por que no pude solo) hacer para esto leí los documentos y son interesantes pero confieso mi bloqueo mental y no fui capaz de hacer esto. Le echas una miradita al mensaje No. 6 por fa.

Camilo 17-08-2015 20:11:25

Señores del Club este tema ha quedado resuelto hice unas modificaciones no tanto al código como si al concepto. y el código aportado por ecfisa en sus respuestas 4 y 7 me vino como anillo al dedo. Puedo decir que prescindí del método Update Or insert por lo que bien explican los textos y aportes.
Amigo Ecfisa Eres muy amable y "Calidoso" en tus conocimientos.
Mil Gracias.


La franja horaria es GMT +2. Ahora son las 22:33:50.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi