PDA

Ver la Versión Completa : Actualizar datos de un StringGrid desde DB


BlackDaemon
21-03-2007, 06:16:01
Buenas a todos.
como verán no suelo postear mucho por que con la info que hay en ClubDelphi creo que no es necesário hacerlo :D ya que está "casi" todo lo que uno necesita para poder realizar "casi" cualquier cosa, estoy aprendiendo muchísimo gracias a este foro y a sus foreros que siempre me han ayudado hasta el momento ( saludos Caral, Lepe, Roman.. y alguno que se me escapa ) que me resolvieron las dudas hasta el momento.. pero bueno al grano xDD

Resulta que estoy haciendo un sistema de facturación y ahora estoy en la parte de ventas, que es donde mas problemas he tenido y los superé como dije gracias al foro.. pero ahora este problema que tengo ahora me mata!!!
No pude resolverlo es mas. creo que parte de mi por no saber plantearme bién que es lo que necesito o COMO necesito hacerlo.

Bueno lo que quiero hacer es ACTUALIZAR una COLUMNA de un StringGrid con datos de una DB ( MySQL ) que conecto con ZEOS
no tengo problemas para insertar datos.. eliminarlos, etc.

Ahora el problema es que para los que estoy haciendo el programa manejan 6 Precios diferentes de cada producto que se los agrega el momento de agregar el respectivo producto o "Item", bueno ahora cada cliente el momento de darle de alta se le asigna una lista de precio ( cualquiera de los precios )

Ya hasta este punto bién.. ahora lo que pretengo hacer es lo siguiente.

CUando abro el módulo ventas lo primero que me sale es esto
(si, si ya se que está feo pero quiero que sea funcinal xD )

[img=http://img187.imageshack.us/img187/4128/preciosow0.th.jpg] (http://img187.imageshack.us/my.php?image=preciosow0.jpg)

ahora cuando busco un cliente tiene que cambiar el ComboBox que ven a la derecha el que está encerrado con en un óvalo :D

Bueno luego de eso comienzo la búqueda del producto por código de producto o código de barras lo encuentro y lo agrego el StringGrid
OJO.- el precio lo toma desde el ComboBox según el número que esté

Bueno y todo lo demás sin problemas.. pero ahora que pasaría si el Cliente quiere que le den con la lista de precio 4 ( precio4 ) por ej y siendo que el tenía la lista de precio 3 ( precio3 ) pues si como se lo imaginaban.. hay que precionar el botón LIMPIAR TODO :D y comensar a agregar de nuevo con la nueva lista de precios escojida en el ComboBOx perooooooooo como se darán cuenta es una pérdida de tiempo y además el programa no sería efisciente.. daría malos ratos al que lo usa y no me gusta eso, si hago algo lo quiero hacer bién.

Ya ahora lo quiera es que el que usa la app pueda cambiar el item en el COmboBox y automaticamente se ACTUALIZEN TODOS los precios de la respectiva columna :)

Pero no se como hacer..
Por el momento lo que analicé es hacer con una consulta SQL a la tabla Productos de mi Base de Datos.

TABLA PRODUCTOS.

CREATE TABLE `productos` (
`ID_producto` int(10) unsigned NOT NULL auto_increment,
`CodProducto` varchar(10) NOT NULL,
`CodigoBarra` varchar(15) NOT NULL default '0',
`Descripcion` varchar(30) NOT NULL default '',
`Categoria` varchar(20) NOT NULL default '',
`SubCategoria` varchar(20) NOT NULL default '',
`Unidad` varchar(5) NOT NULL,
`Cantidad` int(11) NOT NULL default '0',
`Proveedor` varchar(20) NOT NULL default '',
`UnidadPrecio` varchar(5) NOT NULL default '',
`PrecioCompraBs` float default '0',
`PrecioCompraSus` float default '0',
`Costo` float default '0',
`Precio1` float NOT NULL default '0',
`Precio2` float default NULL,
`Precio3` float default NULL,
`Precio4` float default NULL,
`Precio5` float default NULL,
`Precio6` float default NULL,
`FechaActualizacion` date NOT NULL default '0000-00-00',
PRIMARY KEY (`ID_producto`),
UNIQUE KEY `CodProducto` (`CodProducto`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1


luego de eso pensé primer lugar en buscar el producto ya sea por codProducto o por CodigoBarra que si o si tienen que tenerlo una ves encontrado el producto de la primera columna ( vamos la horizontal, estoy tan confundido que no recuerdo cual es fila y columna en el StringGrid )
una ves buscaod el producto por codproducto o codigobarra y buscar el campo precio pienso que sería una variable que contenga de acuerdo al ComboBox el respectivo precio ( precio1, precio2,.... )
Luego de eso una ves encontrado el producto por su código y su campo precio con la variable precio hacer que ACTUALIZE el precio que tiene insertado en el StringGrid... por ej si estaba un producto:

SIlla de madera precio1

que me lo actualice a :

Silla de madera precio2 ( dependiendo de que items tengan en el ComboBox )

y eso hacer con tooooodos los productos que tenga en el StringGrid
:D

Bueno se que sería con unos 2 bucles pero vamos.. soy pura teoría que no se como hacerlo

ajunto una chapucera que intenté pero se que está mal xDD
por lo menos intenté :)

procedure TFrmVentas.CBListaPrecioChange(Sender: TObject);
var
i : Integer;
Precio : String;
begin
DM.ZQAgregarItems.Close;
DM.ZQAgregarItems.SQL.Text := 'Select * FROM productos';
DM.ZQAgregarItems.Open;

case CBListaPrecio.ItemIndex of
0:Precio := DM.ZQAgregarItems.FieldByName('Precio1').Value;
1:Precio := DM.ZQAgregarItems.FieldByName('Precio2').Value;
2:Precio := DM.ZQAgregarItems.FieldByName('Precio3').Value;
3:Precio := DM.ZQAgregarItems.FieldByName('Precio4').Value;
4:Precio := DM.ZQAgregarItems.FieldByName('Precio5').Value;
5:Precio := DM.ZQAgregarItems.FieldByName('Precio6').Value;
end;

For i:=0 to SGListaProductos.RowCount-1 Do
Begin
DM.ZQActualizaListaPrecio.Close;
DM.ZQActualizaListaPrecio.SQL.Clear;
DM.ZQActualizaListaPrecio.SQL.Add('SELECT :precio FROM productos');
DM.ZQActualizaListaPrecio.SQL.Add('Where CodProducto = :codigo');
DM.ZQActualizaListaPrecio.ParamByName('precio').AsString := Precio;
DM.ZQActualizaListaPrecio.ParamByName('codigo').AsInteger := StrToInt(SGListaProductos.Cells[3,i]);
DM.ZQActualizaListaPrecio.Open;
End;

Bueno eso lo puse en el evento OnChange del CBListaPrecio que así se llama el ComboBox que dependen de el las listas de precios,
Bueno que datos mas ??

Pues uso un query para agregar los items ahí que se llama
ZQAgregarItems :D

el código que uso para agregar los items es el siguiente por si a alguien le sirve..

AGREGAR ITEMS A STRINGGRID DESDE BASE DE DATOS MySQL

if (CBListaPrecio.Text <> '') then
begin

FrmAgregarItems := TFrmAgregarItems.Create(self);

try
FrmAgregarItems.ShowModal;
finally
If FrmAgregarItems.Cancela = False then
Begin
If Cuenta > 1 then SGListaProductos.RowCount := SGListaProductos.RowCount + 1;
SGListaProductos.Cells[1,cuenta] := FrmAgregarItems.ECantidad.Text;
SGListaProductos.Cells[2,cuenta] := DM.ZQAgregarItems.FieldByName('unidad').AsString;
SGListaProductos.Cells[3,cuenta] := DM.ZQAgregarItems.FieldByName('codproducto').AsString;
SGListaProductos.Cells[4,cuenta] := DM.ZQAgregarItems.FieldByName('codigobarra').AsString;
SGListaProductos.Cells[5,cuenta] := DM.ZQAgregarItems.FieldByName('descripcion').AsString;
SGListaProductos.Cells[6,cuenta] := DM.ZQAgregarItems.FieldByName('unidadprecio').AsString;
case CBListaPrecio.ItemIndex of
0:Precio := DM.ZQAgregarItems.FieldByName('Precio1').Value;
1:Precio := DM.ZQAgregarItems.FieldByName('Precio2').Value;
2:Precio := DM.ZQAgregarItems.FieldByName('Precio3').Value;
3:Precio := DM.ZQAgregarItems.FieldByName('Precio4').Value;
4:Precio := DM.ZQAgregarItems.FieldByName('Precio5').Value;
5:Precio := DM.ZQAgregarItems.FieldByName('Precio6').Value;
end;
SGListaProductos.Cells[7,cuenta] := Precio; //DM.ZQAgregarItems.FieldByName('precio1').AsString;
SGListaProductos.Cells[8,cuenta] := Format('%8.2f',[StrToFloat(Precio) * StrToFloat(SGListaProductos.Cells[1,cuenta])]);

Cuenta := Cuenta +1;
SortGrid(SGListaProductos,0,0);
CalculaTotales;
end;
FrmAgregarItems.Free;
end;
end;


Bueno creo que he sido muy claro en mi duda..

saludos y gracias por adelantado foreros.. y disculpen por aumentar el tamaño de su DB del foro xDD

salud!!!

Lepe
21-03-2007, 12:07:29
Pues si, has sido muy claro y conciso :).

Creo que vas bien. La SQL que necesitas para actualizar el precio según la lista elegida sería:

For i:=0 to SGListaProductos.RowCount-1 Do
Begin
DM.ZQActualizaListaPrecio.SQL.Add('UPDATE productos');
DM.ZQActualizaListaPrecio.SQL.Add(' SET Precio = :precio');
DM.ZQActualizaListaPrecio.SQL.Add('Where CodProducto = :codigo');
DM.ZQActualizaListaPrecio.ParamByName('precio').AsCurrency:= strToCur(Precio);
DM.ZQActualizaListaPrecio.ParamByName('codigo').AsInteger := StrToInt(SGListaProductos.Cells[3,i]);
DM.ZQActualizaListaPrecio.ExecSql; // ejecutamos la consulta.
end;



Aunque yo, en lugar de guardar los 4 precios en la tabla productos, hubiera creado una nueva tabla llamada tarifas, donde a cada producto le pondría los precios:
tabla tarifas:

codProducto Tipo_Tarifa Precio
21 Precio_Bajo 10 €
21 Precio_Medio 15 €
21 Precio_Alto 30 €
1 Precio_Bajo 10 €
1 Precio_Alto 30 €


La clave primaria la conformaría los dos primeros campos, de esa forma no se permitirían inchoherencias (poner 2 precios a un mismo producto con el mismo Tipo_Tarifa).

Después, para presentar la lista en el combo haría algo así:

select * from tarifas where codigo = 1

En el combo podría presentar el campo Tipo_Tarifa, y el usuario elije la que quiere aplicar.

Saludos

BlackDaemon
21-03-2007, 16:36:11
Hola lepe... muy interesante y clara tu respuesta y muchas gracias por dármela.
Pero hay un problema. creo que me expliqué un poco mal o entendiste un poco mal.
la cosa va asi.. tu me das este código :

For i:=0 to SGListaProductos.RowCount-1 Do
Begin
DM.ZQActualizaListaPrecio.SQL.Add('UPDATE productos');
DM.ZQActualizaListaPrecio.SQL.Add(' SET Precio = :precio');
DM.ZQActualizaListaPrecio.SQL.Add('Where CodProducto = :codigo');
DM.ZQActualizaListaPrecio.ParamByName('precio').AsCurrency:= strToCur(Precio);
DM.ZQActualizaListaPrecio.ParamByName('codigo').AsInteger := StrToInt(SGListaProductos.Cells[3,i]);
DM.ZQActualizaListaPrecio.ExecSql; // ejecutamos la consulta.
end;

el cual con el UPDATE lo que haría escribir en mi base de datos y por el momento NO necesito eso.. creo que eso tendría que ir en la parte final cual el usuario precioa un botón, por ej: EJECUTAR o VENDER como sea :p y que descuente las cantidades ... osea osar ese pedaso de código para UPDATEAR las CANTIDADES no los precios.. por que para podificar los precios está otro Form donde también pueden modificar el nombre, código de barra, descripción, etc.

Bueno y lo que yo necesito solo es ACTUALIZAR la mi STRINGGRID con otros precios de mi TABLA

espero ahora haber podío ser mas claro.

AHora respecto al otro punto.. me parece una exelente idéa de hacer una nueva tabla para los precios.. por que me será mas fácil manejar ya que son 6 precios :mad: , ya suponiendo que tengo mi NUeva tabla TARIFAS y podría hacer lo que me dices.
Hacer un SELECT peroooooooo lo que no entiendo es que como hacer para saber el código del producto.. osea buscar el el producto que está en el StringGrid luego hacer el select, escojer el nuevo precio de acuerdo al COmboBox y reemplazar al que está en el StringGrid, eso hacer para toda la lista del StringGrid supongo que es con un bucle pero no me doy idea de como mesclar las 2 consultas.. me refiero a una BUSCA PRODUCTO POR CODIGO , una ves encontrado BUSCA PRECIO DE ACUERDO AL COMBOBOX, una ves que tengo el nuevo precio REEMPLAZARLO AL PRECIO QUE TENGO EN EL STRINGGRID

Bueno por el momento estaré haciendo la nueva tabla con los precios

saludos y gracias Lepe tus respuestas siempre me ayudan :D

salud!!

Lepe
21-03-2007, 17:51:43
En el stringGrid tienes la columna 3 con el código del producto. Teniendo la tabla tarifas, te sale más fácil, ya que en esa tabla tienes el código del producto y el tipo de tarifa:


DM.ZQActualizaListaPrecio.Close;
DM.ZQActualizaListaPrecio.SQL.Clear;
DM.ZQActualizaListaPrecio.SQL.Add('SELECT precio FROM Tarifas');
DM.ZQActualizaListaPrecio.SQL.Add('Where CodProducto = :codigo');
DM.ZQActualizaListaPrecio.SQL.Add('and Tipo_Tarifa = :Tarifa');
DM.ZQActualizaListaPrecio.prepare;

with DM.ZQActualizaListaPrecio DO
For i:=0 to SGListaProductos.RowCount-1 Do
Begin
ParamByName('codigo').AsInteger := StrToInt(SGListaProductos.Cells[3,i]);
ParamByName('Tarifa').AsString = combobox1.items[combobox1.Itemindex];
Open; // abrimos la consulta
if not IsEmpty then

SGListaProductos.Cells[7,i] := Fieldbyname('Precio').AsString;
//solo debería existir un registro para esta tarifa y este producto.
else
begin
ShowMessage('No existe El tipo de tarifa para el producto' + StrToInt(SGListaProductos.Cells[3,i]));
SGListaProductos.Cells[7,i] := '<< Error >>';
end;
Close; // cerramos la consulta para la próxima iteración del bucle.
End;

Edito:
Como ahora el usuario es el que creará los "tipos de tarifas", en el combobox1 (el combo de precios) tendrás que cargarlo dinámicamente, por ejemplo al crear la ventana, usando un TZQuery convenientemente preparado:

select distinct Tipo_Tarifa from Tarifas

y ya en el Oncreate de la ventana:

qryTiposTarifas.Open;
Combobox1.items.Clear;
qryTiposTarifas.DisableControls; // agilizar las iteraciones por la consulta.
combobox1.items.BeginUpdate; // agilizar las adiciones al combo.
while not qryTiposTarifas.eof do
begin
Combobox1.Items.Add(qrytiposTarifas.Fields[0].AsString;
qryTiposTarifas.Next;
end;

qryTiposTarifas.Close;
qryTiposTarifas.EnableControls; // dejar las cosas como estaban.
combobox1.Items.EndUpdate;


Saludos

BlackDaemon
21-03-2007, 20:56:18
jojojo ahora si creo que esto es lo que necesitaba :) Lepe :D

bueno en este mismo momento estoy probando el código :cool:
de 10 minutos te digo el resultado.. se que este post no tiene sentido pero te agradesco por tu respuesta

saludos pues !!

BlackDaemon
22-03-2007, 01:39:51
Bueno pues.. he estado toda la tarde en esto y lo que avancé fue hacer la tabla respectiva para los precios.. ya que manejan 6 precios distintos hice mi tabla de esta manera.. agregué un campo para Código de Barras.. por que con el tiempo creo que se manejarán así todo.

TABLA DE TARIFAS

CREATE TABLE `tarifas` (
`CodigoBarra` varchar(20) NOT NULL,
`CodProducto` varchar(20) NOT NULL,
`TipoTarifa` varchar(20) NOT NULL,
`Precio` double NOT NULL,
KEY `CodigoBarra` (`CodigoBarra`),
KEY `CodProducto` (`CodProducto`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Bueno una ves creeada la tabla tuve que modificar la parte de AGREGAR PRODUCTOS .. donde antes ahí se ponían los precios y era con una simple tabla de conectar unos DBEdits a cada campo de la tabla PRODUCTOS.. los DBEdits correspondían a cada precio.. osea eran 6.
Ahora.. los precios los agrego de esta forma..
A mi parecer esta una chapucera.. por que soy nuevo en esto pero me andá bién y eso me hace sentir bién.. pero creo que se podría mejorar..
Aquí les dejo el código del botón que agrega los los precios en la nueva TABLA

procedure TFrmAgregarProductos.SBGuardarClick(Sender: TObject);
begin
with DM.ZQPrecios do
begin
Close;
SQL.Clear;

SQL.Add('INSERT INTO `tarifas` ( `CodigoBarra` , `CodProducto` , `TipoTarifa` , `Precio` )');
SQL.Add('VALUES (:CB, :CP, :TT1, :P1), ');
SQL.Add('(:CB, :CP, :TT2, :P2), ');
SQL.Add('(:CB, :CP, :TT3, :P3), ');
SQL.Add('(:CB, :CP, :TT4, :P4), ');
SQL.Add('(:CB, :CP, :TT5, :P5), ');
SQL.Add('(:CB, :CP, :TT6, :P6)');

// Si, asignamos los parámetros xDD
ParamByName('CB').AsString := ECodigoBarra.Text;
ParamByName('CP').AsString := ECodProducto.Text;
ParamByName('TT1').AsString := 'Precio1';
ParamByName('TT2').AsString := 'Precio2';
ParamByName('TT3').AsString := 'Precio3';
ParamByName('TT4').AsString := 'Precio4';
ParamByName('TT5').AsString := 'Precio5';
ParamByName('TT6').AsString := 'Precio6';

ParamByName('P1').AsString := EPrecio1.Text;
ParamByName('P2').AsString := EPrecio2.Text;
ParamByName('P3').AsString := EPrecio3.Text;
ParamByName('P4').AsString := EPrecio4.Text;
ParamByName('P5').AsString := EPrecio5.Text;
ParamByName('P6').AsString := EPrecio6.Text;
// Ejecutamos e insertamos todos los valores asignados
ExecSQL;

end;

DM.ZTAlmacen.Post; --> Este agrega las demas descripciones pero a la tabla PRODUCTOS.. lo de arriba a la nueva tabla TARIFAS

end;


Bueno.. esa parte ya la arreglé con eso.. PERO tengo unas dudas ahora.. cuando se realize una búqueda de un producto y quiero que me lo muestre en un DBGrid como lo tendría que hacer ?? por ej

SELECT * FROM productos WHERE codproducto = :codigo

Bueno en primer lugar no tendré para hacer búsquedas por Código de producto ni por Codigo de barras.. por que ya esos datos los guardo en otra tabla.. ahora podría buscar por CATEGORIA o DESCRIPCION del produto.. peroooo ya no me mostraría el codigo de barras, código de producto NI los precios :S por que estarán en otra tabla.
Y si realizo la búsqueda en la tabla TARIFAS, ahí podré buscar por códigos pero tampoco me mostrarán las descripciones ni las cantidades disponibles que eso se guarda en la TABLA productos.. en fin son dudas que tengo y que con eso ya se fregó gran parte de mi programa.. pero si es por el BIEN estoy de acuerdo en solucionar esas partes ... de las búsquedas etc.
o para hacer las búsquedas tendría que llamar a las 2 TABLAS ?? a la PRODUCTOS y TARIFAS ?? como sería eso son SQL ?

SELECT * FROM productos, tarifas

si es así no habrá problemas.. :D

Ahora seguiré probando el código para actualizar toda la fila de PRECIOS

pero hasta el momento como voy ?? está bién lo que hago ??

ahh una cosa mas.. que he estado pensando cuando uno agrega un producto indicas que si es Und, Pza, Doc == Unidad, Pieza, Docena
bueno eso donde cumple su función sería a la hora de agregar los produtos al StringGrid verdad ?? si es Docena pues multiplicar el precio de la Unidad por 12 supongo.. pero creo que mes estoy pasando a otro punto, pero igual quería saber por si puedo hacer algo ahora o eso luego.

bueno saludos

salud!!

BlackDaemon
22-03-2007, 03:50:47
Bueno pues el motivo de este post es el siguiente.. dejando aparte el anterior problema .. que ya estoy por sulicionarlo pero al solucionar ese surgieron muchos problemas mas.. bueno para mi :confused:
el primero es este.

http://img301.imageshack.us/img301/8769/productosfu0.jpg

como podrán ver antes usaba esos DBEdits que estaban enlasados a cada campo de mi TABLA PRODUCTOS pero ahora agregué esos Edits normales para hacer la inserción de los precios en la tabla nueva TARIFAS.. que lo hago sin problemas.. pero antes cuando hacian clic en el botón NET o PRIOR, LAST, etc.. este recorria la TTable y se visualizaban en los DBEdits para así poder EDITAR o ELIMINAR.. pero ahora como los EDITS normales no están enlasados a ninguna TABLA no es posible hacer eso.. y quedan con el TEXTO que se le escribe la primera vés que uno hace un registro..
además que cuando elimino con TTable.delete; no me borrará de la tabla TARIFAS los precios correspondientes a esa descripción..ya que no estarán en la mis TABLA.. bueno es un problema grave para mi por que no se como resolverlo.. y si no lo resulevo eso no puedo pasar el otro punto de mi problema que es el primer post de este tema.

Aquí les pongo el código con el que registraba un nuevo producto.

procedure TFrmAgregarProductos.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
FrmAgregarProductos := nil;
Action := caFree;
FrmAgregarProductos.Free;
end;

procedure TFrmAgregarProductos.SBNuevoClick(Sender: TObject);
begin
modoEditar(True);
DM.ZTAlmacen.Append;
DBECodigoProducto.SetFocus;
DateTimePicker1.DateTime := Now;
DateTimePicker1.BringToFront;
end;

procedure TFrmAgregarProductos.SBEditarClick(Sender: TObject);
begin
DM.ZTAlmacen.Edit;
modoEditar(True);
DBECodigoProducto.SetFocus;
end;

procedure TFrmAgregarProductos.SBGuardarClick(Sender: TObject);
begin
with DM.ZQTarifas do
begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO `tarifas` ( `CodigoBarra` , `CodProducto` , `TipoTarifa` , `Precio` )');
SQL.Add('VALUES (:CB, :CP, :TT1, :P1), ');
SQL.Add('(:CB, :CP, :TT2, :P2), ');
SQL.Add('(:CB, :CP, :TT3, :P3), ');
SQL.Add('(:CB, :CP, :TT4, :P4), ');
SQL.Add('(:CB, :CP, :TT5, :P5), ');
SQL.Add('(:CB, :CP, :TT6, :P6)');

// Si, asignamos los parámetros xDD
ParamByName('CB').AsString := ECodigoBarra.Text;
ParamByName('CP').AsString := ECodProducto.Text;
ParamByName('TT1').AsString := 'Precio1';
ParamByName('TT2').AsString := 'Precio2';
ParamByName('TT3').AsString := 'Precio3';
ParamByName('TT4').AsString := 'Precio4';
ParamByName('TT5').AsString := 'Precio5';
ParamByName('TT6').AsString := 'Precio6';

ParamByName('P1').AsString := EPrecio1.Text;
ParamByName('P2').AsString := EPrecio2.Text;
ParamByName('P3').AsString := EPrecio3.Text;
ParamByName('P4').AsString := EPrecio4.Text;
ParamByName('P5').AsString := EPrecio5.Text;
ParamByName('P6').AsString := EPrecio6.Text;
// Ejecutamos e insertamos todos los valores asignados
ExecSQL;

end;
DM.ZTAlmacen.FieldByName('FechaActualizacion').AsDateTime := DateTimePicker1.Date;
DM.ZTAlmacen.Post;
ModoEditar(False);
end;

procedure TFrmAgregarProductos.SBEliminarClick(Sender: TObject);
var
resp : Integer;
begin
if Editando then begin
DM.ZTAlmacen.Cancel;
modoEditar(False);
end
else begin
resp := Application.MessageBox(Pchar('¿Desea eliminar el código '+DBECodigoProducto.Text+'?'),'Eliminar un registro',MB_YESNO+MB_ICONERROR);
if resp = ID_YES then begin
DM.ZTAlmacen.Delete;
modoEditar(False);
end;
end;
end;

procedure TFrmAgregarProductos.FormShow(Sender: TObject);
begin
try
DM.ZTUnidad.Active := True;
DM.ZTUnidadPrecio.Active := True;
DM.ZTAlmacen.Active := True;
DM.ZTProveedores.Active := True;
DM.ZTCategorias.Active := True;
DM.ZTSubCategorias.Active := True;
except
Application.MessageBox(Pchar('Error de conexión a la base de datos:'+#13+#13+'Verifique si la ruta es correcta'),'Error de conexión',MB_ICONWARNING);
Application.Terminate;
end;
ModoEditar(False);
end;

procedure TFrmAgregarProductos.SBPrimeroClick(Sender: TObject);
begin
DM.ZTAlmacen.First;
end;

procedure TFrmAgregarProductos.SBAnteriorClick(Sender: TObject);
begin
DM.ZTAlmacen.Prior;
end;

procedure TFrmAgregarProductos.SBSiguienteClick(Sender: TObject);
begin
DM.ZTAlmacen.Next;
end;

procedure TFrmAgregarProductos.SBUltimoClick(Sender: TObject);
begin
DM.ZTAlmacen.Last;
end;

procedure TFrmAgregarProductos.DBEPrecio1KeyPress(Sender: TObject;
var Key: Char);
var precio : Integer;
begin
if Key = #13 then begin
Key := #0; //quitamos el sonido
precio := (StrToInt(DBEPrecio1.Text) * 16 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio2.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 25 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio3.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 35 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio4.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 40 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio5.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 8 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio6.Text := IntToStr(precio);

end;
end;

end.


Disculpen por poner un código tan largo.. pero espero así ser lo mas claro posible

cual sería la solución para este caso ?? ( pueden ver la imagen para tener una idea mas clara )

Bueno.. creo que son esas todas mis dudas tontas que tengo y no puedo resolverlas solo :o

Bueno pues según yo tendré que hacerlo TODO con SQL no ??? ya no usaré una TTabla para eso verdad ?

Saludos y gracias por leeme.

Lepe
22-03-2007, 12:22:12
Antes de nada te recomiendo un manual de sql, avanzarás más rápido, éste (http://programatium.com/tutoriales/cursos/mysql/index.htm)es uno de tantos, pero busca un poco, los hay de todo tipo.

Lo de borrar un producto y que se borren las tarifas, se llama integridad referencial, en el caso de mysql no sé la respuesta, pero básicamente hay que decirle a la base de datos que el campo CodProductos de la tabla tarifas es una clave ajena (foreign key) de la tabla productos, y en caso de borrado de un producto, se borre todos las filas de ese producto en la tabla tarifas (ON DELETE CASCADE). Aqui viene (http://www.mysql-hispano.org/page.php?id=27&pag=9)

Saludos

BlackDaemon
22-03-2007, 16:02:00
Gracias Lepe y si, si tengo un manual de SQL a mano siempre que necesito algo.. pero como esto de integridad referenciál no sabía osea que no tenía idea de como buscar.. gracias por darte la molestia de ponerme los link .. en este momento estoy en el trabajo, cuando llegue a casa lo probaré y luego comento que pasó y seguro que tendré otro problema..

gracias

salud!!

sierraja
22-03-2007, 18:25:52
Saludos, creo que mi intervencion es un poco tardia, pero si te sirve de algo, yo estoy desarrollando un sistema de facturacion y ya pase por la parte de ventas, y si efectivamente maneje solo tres precios y el detalle de la lista de productos coloque una tabla temporal donde agregaba, eliminaba y modificaba cualquier producto, tambien al momento de agregar cada producto tiene la posibilidad de escoger el precio que quieras para ese producto solamente y me ha funcionado muy bien. Tambien observe que estas utilizando Bs. quiere decir que estas en Venezuela. De todas maneras podriamos intercambiar informacion ya que yo manejo la misma moneda. Saludos. :D

BlackDaemon
22-03-2007, 19:31:07
Pues que información podríamos intercambiar ?? Si tu ya lo tienes todo listo, además no soy de Venezuela :D , soy de Bolivia como dice en la parte superior-izquierda de cada mensaje en el foro :)
y por lo que me dices veo que usas un DBGrid para eso verdad ??
o estás usando un stringGrid ? si sería eso podrías pastear tu código ??
ya que no quisiera repetir las mas de 1000 líneas que puse en los anteriores post, con los que te darás cuenta de cual es mi problema.

saludos.

PD lo siento pero soy nuevo en esto y no creo que pueda servirte de mucha ayuda ;) y tu si a mi :cool: jiji

BlackDaemon
22-03-2007, 23:51:58
Hola Lepe he estado leyendo http://www.mysql-hispano.org/page.php?id=27&pag=9

le entendí todo y es inetresante la forma como manejan las tablas de esa forma.. ya había leido antes sobre eso, pero algo superficial y ahora entendí mejor y comprendí todo, ahora me parece un poco mas complicado hacer todo eso de

mysql> ALTER TABLE venta DROP FOREIGN KEY 0_26;
Query OK, 2 rows affected (0.22 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> ALTER TABLE venta ADD FOREIGN KEY(id_cliente)
-> REFERENCES cliente(id_cliente) ON DELETE RESTRICT ON UPDATE CASCADE;
Query OK, 2 rows affected (0.22 sec)
Records: 2 Duplicates: 0 Warnings: 0

es un ejemplo.

hacer eso cada ves que quiero UPDATEAR o EDITAR un precio..
Bueno no es que es difícil.. pero no sería una mejor idea de mantener una sola tabla PRODCUTOS como la tenía en mi primer post, y de ahi leer los valores de los precios correspondientes ???

Bueno solo pienso eso.. por que no lo se hacer :D
Si es que es mejor de esta forma pues seguiré adelante de esta forma aunque me cueste un hue** ;)

Si sería de mantener mi anterior tabla PRODUCTOS con los campos ahí mismo como sería para poder actualizar un StringGrid con una lista de precios seleccionada por el usuario en en ComboBox ??

Creo que solo sería cambiar en este código algo no ??

DM.ZQActualizaListaPrecio.Close;
DM.ZQActualizaListaPrecio.SQL.Clear;
DM.ZQActualizaListaPrecio.SQL.Add('SELECT precio FROM Tarifas');
DM.ZQActualizaListaPrecio.SQL.Add('Where CodProducto = :codigo');
DM.ZQActualizaListaPrecio.SQL.Add('and Tipo_Tarifa = :Tarifa');
DM.ZQActualizaListaPrecio.prepare;

with DM.ZQActualizaListaPrecio DO
For i:=0 to SGListaProductos.RowCount-1 Do
Begin
ParamByName('codigo').AsInteger := StrToInt(SGListaProductos.Cells[3,i]);
ParamByName('Tarifa').AsString = combobox1.items[combobox1.Itemindex];
Open; // abrimos la consulta
if not IsEmpty then

SGListaProductos.Cells[7,i] := Fieldbyname('Precio').AsString;
//solo debería existir un registro para esta tarifa y este producto.
else
begin
ShowMessage('No existe El tipo de tarifa para el producto' + StrToInt(SGListaProductos.Cells[3,i]));
SGListaProductos.Cells[7,i] := '<< Error >>';
end;
Close; // cerramos la consulta para la próxima iteración del bucle.
End;

Bueno creo que cambiando esta parte :

DM.ZQActualizaListaPrecio.Close;
DM.ZQActualizaListaPrecio.SQL.Clear;
DM.ZQActualizaListaPrecio.SQL.Add('SELECT precio FROM Tarifas');
DM.ZQActualizaListaPrecio.SQL.Add('Where CodProducto = :codigo');
DM.ZQActualizaListaPrecio.SQL.Add('and Tipo_Tarifa = :Tarifa');
DM.ZQActualizaListaPrecio.prepare;

se podría leer de mi tabla PRODUCTOS donde tengo los las tarifas ??

Bueno si no es posible o se complicaría mas aún.. seguiré tu consejo, lo que acabo de poner es solo una idea mia

salud!!

Lepe
23-03-2007, 00:09:44
ALTER TABLE venta ADD FOREIGN KEY(id_cliente)
-> REFERENCES cliente(id_cliente) ON DELETE RESTRICT ON UPDATE CASCADE;

No hombre no....

Si en lugar de ON DELETE RESTRICT pones ON DELETE CASCADE, cuando borras un cliente, automáticamente se borrarán todas las ventas que tenga ese cliente en la base de datos, TODAS.

El hecho de poner ALTER TABLE (alterar la estructura de la tabla), es para indicar que MySql tenga este tipo de comportamiento. Lo defines una sola vez, y servirá para todos los registros.

Aplicándolo a la tabla productos y tarifas: Si borras un producto, porque no lo vas a utilizar más, MySql borraría todas las tarifas que existiesen de ese producto:
ALTER TABLE tarifas ADD FOREIGN KEY(Codproducto)
-> REFERENCES Productos(CodProducto) ON DELETE CASCADE ON UPDATE CASCADE;

Ahora piensa "a lo grande": Tienes un proveedor, ese proveedor te da muchos productos, productos que a su vez estarán en facturas que vendes a tus Clientes, clientes con sus datos personales. Bien definido el sistema, podrías hacer que al borrar un proveedor, se borraran todos los registros asociados, es decir, productos, facturas, clientes, etc. Todo con un simple borrado de un registro en la tabla proveedores.

¿Peligroso? puede, por eso mismo tienes que pararte a pensar si poner ON DELETE CASCADE o bien ON DELETE NULL o bien ON DELETE RESTRICT

¿Potente? por supuesto, puedes desencadenar el borrado en 10, 20 o 100 tablas con solo borrar 1 registro ¡¡ sin escribir ni una sola línea de código delphi!!

Saludos

BlackDaemon
23-03-2007, 01:35:23
ahhhhhhh bueno Lepe ahora si entendí bién.. y tienes toda la razón en esos puntos del final de tu post, en eso de peligroso, potente :D
Es la verdad.. creo que aprenderé a usar así mis tablas de ahora en adelante ya que creo que te libra de muchos problemas :)

Bueno Lepe muchas gracias por la info, he estado todo el día sentado a ver si alguien respondía el tema jeje :) y ahora que ya lo sé y lo tengo mas claro lo pondré a la práctica, mañana tendré algunos resultados malos o buenos, eso ya se verá en la practica.. jeje muchas gracias de nuevo
Es que pensé que eso lo tennía que hacer cada ves que un registro o elimine o modifique, pero ahora me doy cuenta que solo se hace una ves y luego es normal..


salud pues!

BlackDaemon
23-03-2007, 06:59:21
Hola,
tengo problemas al poner esto.

mysql> ALTER TABLE tarifas ADD FOREIGN KEY(Id_producto)
-> REFERENCES Productos(id_producto) ON DELETE CASCADE ON UPTADE CASCADE;

me da este error :

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'UPTAD
E CASCADE' at line 2

Bueno no se por que es si modifiqué mis 2 tablas y quedaron así.

mysql> SHOW CREATE TABLE tarifas;
tarifas | CREATE TABLE `tarifas` (
`Id_producto` int(11) NOT NULL,
`CadigoBarra` bigint(20) NOT NULL,
`CodProducto` varchar(20) NOT NULL,
`TipoTarifa` varchar(10) NOT NULL,
`Precio` double NOT NULL,
PRIMARY KEY (`CadigoBarra`),
KEY `id_producto` (`Id_producto`)
ENGINE=InnoDB DEFAULT CHARSET=utf8

y mi tabla PRODUCTOS asi

mysql> SHOW CREATE TABLE productos;
productos | CREATE TABLE `productos` (
`ID_producto` int(10) unsigned NOT NULL auto_increment,
`CodProducto` varchar(10) NOT NULL,
`CodigoBarra` bigint(20) NOT NULL default '0',
`Descripcion` varchar(30) NOT NULL default '',
`Categoria` varchar(20) NOT NULL default '',
`SubCategoria` varchar(20) NOT NULL default '',
`Unidad` varchar(5) NOT NULL,
`Cantidad` int(11) NOT NULL default '0',
`Proveedor` varchar(20) NOT NULL default '',
`UnidadPrecio` varchar(5) NOT NULL default '',
`PrecioCompraBs` float default '0',
`PrecioCompraSus` float default '0',
`Costo` float default '0',
`Precio1` float NOT NULL default '0',
`Precio2` float default NULL,
`Precio3` float default NULL,
`Precio4` float default NULL,
`Precio5` float default NULL,
`Precio6` float default NULL,
`FechaActualizacion` date NOT NULL default '0000-00-00',
PRIMARY KEY (`ID_producto`)
ENGINE=InnoDB DEFAULT CHARSET=latin1

Bueno los prcios no los quité todavía de aquí y tampoco pienso quitarlos xDD
Ahora que lo pensé esos serán los que se visualicen al momento de hacer un Table.next; o last; etc. Pero claro.. no afectarán en nada.. y los otros serán de donde leere los valores.. al momento de agregar un producto tendría que INSERTAR los precios tanto a la tabla PRODUCTOS como a la tabla TARIFAS pero eso no es problema por que con mi código que tenía se puede hcer eso.

Bueno ahora cual es el problema ?? no veo ningún problema que esté comentiendo pero me da ese error
Será por que los tipos de campos no son compatibles? ??
Pero si por lo que veo si son.. BIGINT los 2 :) y el otro INT

Ya ahora si que no se cual es el error.

salud!!

Lepe
23-03-2007, 11:28:11
Tú lo has dicho, uno lo defines como Int(10) y el otro como int(11) deben ser iguales, porque se guardará el mismo número. Además uno es unsigned y el otro no.

Saludos

Lepe
23-03-2007, 16:50:28
he estado todo el día sentado a ver si alguien respondía el tema jeje :)

:(, Por eso mismo se comenta que en los foros no hay "urgencias", ya ves, tenemos 7 horas de diferencia entre Bolivia y España :(, sin contar que yo tenga un rato libre para entrar al foro.

Saludos peninsulares (15:49 ;))

BlackDaemon
23-03-2007, 18:23:00
Hola hola..

óh! que tondo he sido al no darme cuenta en eso y yo me me cuidaba en ese aspecto.. y se me fué :(
Bueno ahora aquí con buenas notícias.. he tenía "creo" buenos avances con respecto a esto de la integridad referencial en MySQL y comprendí todo, me quedó todo muy claro Lepe ahora implenté tus ideas y sugerencias y aquí traigo los resultados en código.

Primero Mi tabla PRODUCTOS tengo de clave primaria el campo y es autoincrementable, aunque leyendo sobre ese tipo de campo no era posible en versiones anteriores aquí explican un poco mejor sobre el tema para alguien que tenga ganas de aprender
http://dev.mysql.com/doc/refman/5.0/es/innodb-auto-increment-column.html
http://dev.mysql.com/doc/refman/5.0/es/innodb-restrictions.html

Ahora como les decía que este es mi campo en la tabla PRODUCTOS

Id_productos


Mi tabla TARIFAS la mentení tal y como estaba solo cambiando los valores de int(11) y quité el autoincrement y también quité que el campo CodigoBarra sea la llave primaria.. por que al serlo no permite que se repitan y yo SI necesito que se repitan cada Codigo de barra.. es mas.. se repetirían 6 veces de acuerdo a la cantidad de lista de precios para cada producto,

Luego de eso con este código en mi boton guardar de mi form donde agrego y modifíco los precios, nombres, códigos, etc

procedure TFrmAgregarProductos.SBGuardarClick(Sender: TObject);
begin
DM.ZTAlmacen.FieldByName('FechaActualizacion').AsDateTime := DateTimePicker1.Date;
DM.ZTAlmacen.Post;
with DM.ZQTarifas do
begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO `tarifas` (`Id_producto`, `CodigoBarra` , `CodProducto` , `TipoTarifa` , `Precio` )');
SQL.Add('VALUES (:IDP, :CB, :CP, :TT1, :P1), ');
SQL.Add('(:IDP, :CB, :CP, :TT2, :P2), ');
SQL.Add('(:IDP, :CB, :CP, :TT3, :P3), ');
SQL.Add('(:IDP, :CB, :CP, :TT4, :P4), ');
SQL.Add('(:IDP, :CB, :CP, :TT5, :P5), ');
SQL.Add('(:IDP, :CB, :CP, :TT6, :P6)');

// Si, asignamos los parámetros xDD
ParamByName('IDP').AsInteger := DM.ZTAlmacen.FieldByname('id_producto').AsInteger;
ParamByName('CB').AsString := DBECodigoBarra.Text;
ParamByName('CP').AsString := DBECodigoProducto.Text;
ParamByName('TT1').AsString := 'Precio1';
ParamByName('TT2').AsString := 'Precio2';
ParamByName('TT3').AsString := 'Precio3';
ParamByName('TT4').AsString := 'Precio4';
ParamByName('TT5').AsString := 'Precio5';
ParamByName('TT6').AsString := 'Precio6';

ParamByName('P1').AsString := DBEPrecio1.Text;
ParamByName('P2').AsString := DBEPrecio2.Text;
ParamByName('P3').AsString := DBEPrecio3.Text;
ParamByName('P4').AsString := DBEPrecio4.Text;
ParamByName('P5').AsString := DBEPrecio5.Text;
ParamByName('P6').AsString := DBEPrecio6.Text;
// Ejecutamos e insertamos todos los valores asignados
ExecSQL;

end;

ModoEditar(False);
end;


ahora explico.

DM.ZTAlmacen.Post; esto lo que hace es guardar TODOS los datos que están en los diferentes DBEdits de mi form.. y ahora como podrán ver guardo los precios y codigos en 2 tablas si en la tabla productos y tarifas
eso es debido a que me resultará mas fácil mostrar resultados PERO creo que para hacer un UPDATE tendré que hacer a las 2 tablas claro está... no se si esto sea bueno o no, pero no encuentro otra colución para mostrar las tarifas en un FORM con un simple TTable.next; o de esta forma recorrer fila por fila de un campo para ir mostrando en los diferentes DBEdits.. vamos como lo hacía antes yo pero eso se podía por que estaban en una misma tabla las características, , tarífas, y códigos, bueno si alguien me dice como puedo hacer como un simple TTable.Next estaría muy agradecido...

Puedo hacer es tener una TTTarifas y conectarlo a mis DBEPrecio1, DBEPrecio2, etc.. luego llenar la tabla TARIFAS con un query.. pero para recorrer los campo de uno a uno hacerlo con la TTTarifa.Next ???
Pero claro.. solo serviría para eso. por que no pienso usar el TTable.appent, open, y POST.. solo serviria para lo antes dicho, recorrer una fila

Por ej tengo un totón que es SIGUIENTE y lo que tiene es:

procedure TFrmAgregarProductos.SBSiguienteClick(Sender: TObject);
begin
DM.ZTAlmacen.Next;
end;

entonces con mi nueva tabla quedaría

procedure TFrmAgregarProductos.SBSiguienteClick(Sender: TObject);
begin
DM.ZTAlmacen.Next;
DM:ZTTarifas.Next;
end;

eso irá sincronizado ??? osea las descripciones, unidaddes de precio, etc con las tarífas que están en la tabla TARIFAS ???

si es que no habrá problemas cuando elimine un producto creo que sería una idea, ademas como ahora trabajo con innoDB al aleminar un producto se eliminará también en la tabla TARIFAS todos los 6 precios incluyendo el id_producto, osea TODO.

bueno voy a comer..

salud!


Oh!! que mala suerte yo que pensaba que todo estaba bién ocurre siempre un problema :(
resulta que ahora cuando edito un producto me escribe en la tabla TARIFAS de nuevo los precios osea 6 filas mas.. cada ves que edito algo.. claro por que en mi código está así, y tendré que ver que hacer para poder saber si está un producto con el mismo id_producto para que lo edite. pero creo que tendré que hacer puro SQL y olvidarme de mi TABLA y usar puros QUERYS

asludos

Lepe
23-03-2007, 20:49:35
Te estas complicando la vida mucho.

Estudia las Formas Normales o Normalización de tablas, es todo un concepto basado en muchos años de experiencias en diseños de Bases de datos; son las normas para crear una base de datos eficiente, fácil de mantener y ampliar.

Lo que pides es muy muy fácil, ahora no puedes usar DBEdits, porque no vas a tener 6 precios, al tener la tabla tarifas el usuario podrá crear 10 o 100 precios distintos.... por tanto usa un grid atado a un Query:

Yo no uso MySql, pero seguro que tiene un componente llamado MyDataset que tiene 4 sqls:
- Delete
- Insert
- Update
- Select

Rellenando cada una de ellas, puedes mostrar en el grid todas las tarifas y precios y que se puedan modificar desde el mismo grid. En el MyDataset puedes asignarle su propiedad MasterSource al DataSource de Productos, de esa forma al cambiar de producto, se muestran en el grid las tarifas del nuevo Producto elegido.

Los precios de la tabla productos... sobran, debes eliminarlos.

Necesitas urgentemente dejar de programar y pararte a estudiar los conceptos de la tecnología Cliente/Servidor, Diseños de Bases de datos y Normalización de tablas.

Saludos

BlackDaemon
23-03-2007, 22:00:19
Oh!! que mala suerte yo que pensaba que todo estaba bién ocurre siempre un problema :(
resulta que ahora cuando edito un producto me escribe en la tabla TARIFAS de nuevo los precios osea 6 filas mas.. cada ves que edito algo.. claro por que en mi código está así, y tendré que ver que hacer para poder saber si está un producto con el mismo id_producto para que lo edite. pero creo que tendré que hacer puro SQL y olvidarme de mi TABLA y usar puros QUERYS

saludos


**************************Table.Edit;*********************************

Bueno edito por que justamente cuando postee tu también lo hiciste.. y tendré que seguir tus consejos, voy a eliminar de mi tabla PRODUCTOS todos los precios y trabajar como deve ser, así no se hará una chapucera todo jejeje

ahh una cosa mas.. pero es que los 6 precios son fijos, no habrán mas de esos, ademas que tiene que ser en edits o DBEdits por que si te fija en esta parte de mi código del Form VENTAS tengo esto.

procedure TFrmAgregarProductos.DBEPrecio1KeyPress(Sender: TObject;
var Key: Char);
var precio : Integer;
begin
if Key = #13 then begin
Key := #0; //quitamos el sonido
precio := (StrToInt(DBEPrecio1.Text) * 16 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio2.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 25 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio3.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 35 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio4.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 40 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio5.Text := IntToStr(precio);
precio := (StrToInt(DBEPrecio1.Text) * 8 Div 100 + StrToInt(DBEPrecio1.Text));
DBEPrecio6.Text := IntToStr(precio);

end;
end;


que calcula automaticamente con un porcetaje relacionado al primer precio
alguna otra forma de hacerlo ??


bueno luego cuento que tal

salud !

BlackDaemon
24-03-2007, 00:43:22
Hola Lepe ahora si que estoy perdido :( no se ni que hacer.. o no te entendí bién esta frase:

Lo que pides es muy muy fácil, ahora no puedes usar DBEdits, porque no vas a tener 6 precios, al tener la tabla tarifas el usuario podrá crear 10 o 100 precios distintos....

Pues te diré que solo serán 6 precios.. ademas el problema principal no es ese, si no que tiene que calcularse los porcentaje tanbién, y eso lo hacía como muestro en mi anterior POST :)

por tanto usa un grid atado a un Query:

Yo no uso MySql, pero seguro que tiene un componente llamado MyDataset que tiene 4 sqls:
- Delete
- Insert
- Update
- Select

Rellenando cada una de ellas, puedes mostrar en el grid todas las tarifas y precios y que se puedan modificar desde el mismo grid. En el MyDataset puedes asignarle su propiedad MasterSource al DataSource de Productos, de esa forma al cambiar de producto, se muestran en el grid las tarifas del nuevo Producto elegido.

Pues no entiendo a que se refiere con MyDataSet.. tal vés se que es pero no con ese nombre.. por que soy nuevo en esto. perdón por no comprender.

Los precios de la tabla productos... sobran, debes eliminarlos.

Si señor, ya están eliminados los precios. y los manejaré en la otra tabla.

Necesitas urgentemente dejar de programar y pararte a estudiar los conceptos de la tecnología Cliente/Servidor, Diseños de Bases de datos y Normalización de tablas.

Creo que mi problema en este momento es delphi no MySQL.. por que ya probé mi base de datos y si está todo en orden cuando hago un

DELETE FROM productos WHERE id_producto = 1

me elimina todos los datos del id_producto 1 como debe ser, y además elimina de la tabla TARIFAS todos las listas de precios que tienen el id_producto = 1

Osea que esta funcionando bién, ahora mi problema sería con delphi que no se como enlazar los componentes Zquery, Z,Table, DataSource uno con otros para soluionar mi problema.. bueno espero poder haber sido claro, y creo que estoy a punto de superar este mi problema.. se que es algo fácil pero que no puedo darme cuenta, necesito un empujoncito Lepe

saludos

Lepe
24-03-2007, 05:03:22
Los cálculos de porcentajes deberías hacerlos antes de guardar, ya que al presionar una tecla, si usa retroceso para borrar todos los caracteres, cuando no quede ninguno, obtendrás un bonito " '' is not a valid float".

El cálculo, igual pero más simple:
precio := (StrToInt(DBEPrecio1.Text) * 1.16 ;

Incluso podría hacerse en un trigger before update y before Insert, los cálculos los haría el servidor y no tú desde delphi. Esta idea no viene de la nada, viene de haber leído los manuales de Interbase 6 y Firebird, de ahí que te sugiera estudiar lo propio en MySql. Sabiendo de antemano que es un trigger, como funciona, como se implementa, cuando se ejecuta, etc, tendrás tu mente "más abierta" para solucionar los problemas que te lleguen.

La verdad es que me he confundido con el tema de "MyDataset". Si usas los componentes Zeos, tendrás un ZTable, ZQuery, ZDataset (éste último es al que me refiero), en cliente servidor jamás debería usarse un ZTable, ese componente yo lo veo ahí por compatibilidad y migración, pero no para usarlo en aplicaciones nuevas. Deberías usar un ZDataset y traer solo el registro que desees modificar.

Por mi desconocimiento de los componentes Zeos, no sé si existirá el componente "ZDataset" con ese nombre, puede que tenga otro nombre... a ver si alguien que trabaje con Zeos puede ser más específico.

Para el problema de "unir querys con Grids y demás" mira en la cara oculta de delphi 4, las relaciones Maestro-Detalle es lo que necesitas.

Saludos

BlackDaemon
24-03-2007, 07:57:55
Bueno pues según lo que ví en las componentes ZEOS tengo esto en las paletas

ZConnection: TZConnection
ZReadOnlyQuery: ZDataSet
ZQuery: ZDataSet
ZTable : ZDataSet
ZUpdateSQL: ZsqlUpdate
ZStoredProc: ZstoredProcedure
ZSQLMetadata: ZSQLMetadata
ZSQLProcessor: ZSQLProcessor
ZSQLMonitor : ZSQLMonitor
ZSequence : ZSequence

Bueno supongo que alos que te refieres don ZDataSet es a los 3 componentes no ?? pero mas seguro solo el ZQUERY por que me dijiste que decarte el STable, bueno eso es lo que haré entonces..

ahora con respecto al porcentaje pues lo tendré que hacer de tu modo por que como dices avees me daba el No is valid integer :D pero no era bonito era feo xDD

y ahora sobre los tigers me pondré mañana mismo a leer sobre eso tenloo por seguro :) al igual que lo hice con la integridad referencial que me lo aprendí muy bién y ahora se algo nuevo :D

ahora sobre el maestro detalle, eso es lo que quería saber.. no sabía con que nombre buscar eso, ahora que lo se tambien tenlo por seguro que lo leere, ya que tengo aquí la cara oculta de delphi 4 y otros manuales en pdf muy buenos. ademas de un libro de anaya que esta bién nomas..

bueno pues Lepe muchas gracias por las recomendaciones y consejos, se que me servirán de ahora en delante para hacer mas sencillas las cosas

saludos y gracias nuevamente.

PD mañana posteo algunas dudas xDD

BlackDaemon
27-03-2007, 01:06:15
Bueno aquí vendo despuies de 2 días haber escrito mi último post
Lepe mira, he estado leyendo todos estos días el foro-.. buscando sobre maetro/detalle y encontré vários temas pero no logro entender su funcionamiento.. vamos me doy cuenta de lo que se devería hacer un maestro/detalle, aquí encontré un post explican algo de eso y logré entender algo
http://www.clubdelphi.com/foros/showthread.php?t=39668&highlight=maestro+detalle

Pero no es suficiente para poder hacer lo que yo quiero.. en primer lugar NO quiero poner ningún DBGrid en mi form.. con DBEdits me bastaría, tu dices que me olvide de los DBEdits y las ZTAbles, entonces como guardaría un producto ??
SI ya se que se podría hacer con SQL y no es difícil, pero tendría que tomar los datos de Edits verdad ?? o de donde mas lo tomaría ?? ahora.. mi problema esta en querer actualizar un producto y sus 6 precios que tengo en la otra base de datos, podría ser con puro SQL pero SE que no es lo correcto hacerlo, creo que debe haber alguna manéra de hacerlo mas sencillo
Lo único que pretendo hacer es esto:

Agregar un nuevo producto llenando unos DBEdits o EDits, luego llenar tambien unos DBEdits o Edits con los 6 precios que se alamcenarán en la otra tabla TARIFAS, bueno eso lo hice con SQL y copié el id_producto a la tabla TARIFAS por cada producto, cosa que quedaría así
Un producto con todas las descripciones en la tabla PRODCUTOS y los 6 precios y sus códigos en la tabla TARIFAS, bueno hasta haý no hay problema, por que cuando elimino un producto tam,bién se eliminar los 5 precios, PERO el problema está al editar un producto no edita en la tabla TARIFAS con mi código que puse en los anteriores post, lo único que hace es editar los campor de la tabla PRODCUTOS pero NO edita los 6 precios y códigos de la tabla TARIFAS, lo que hace es agregarme los mismos 6 precios ( en el caso de que no modificaron los precios ) con el mismo id_producto, osea serían 12 precios para el id_producto y si otra ves actualizo me graba 6 precios mas xDD osea 18 ya serían.. lo único que quiero es que UPDATE los precios y códigos en la tabla TARIFAS.. eso es lo que quiero saber.. si tendría que hacerlo puro SQL ?? o hay algún componete como el ZUpdateQUery ???? he estado leyendo tambien sobre en en este tema
http://www.clubdelphi.com/foros/showthread.php?p=3802#post3802

o se si me serviría pero bueno.. para que no digan que no busco o que no leo :o la verdad es que me frustra no poder hacer algo tan secillo que parece.. y se que cuando aprenda diré : oh he sido un tonto al no poder hacer algo tan sencillo

Y otra cosa.. que acreo que aquí viene lo de master/detail es que quiero mostrar los datos de los productos todo en uno, osea descripciones del producto que leere de la tabla PRODCUTOS y sus precios y códigos que leeré de la tabla TARIFAS, bueno ahora eso lo tengo que hacer puro SQL también ?? o con master/detail solo tengo que escojer los campos de las tablas ?? no entiendo muy bién que inutil que soy :confused:

Bueno creo que lo mejor me vendría es un pequeño ejemplo de lo que pretendo hacer,

aquí les dejo una pequeña base de datos relacionales.

-- Base de datos: `test`

CREATE TABLE `cliente` (
`id_cliente` int(11) NOT NULL,
`nombre` varchar(30) default NULL,
PRIMARY KEY (`id_cliente`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `venta` (
`id_factura` int(11) NOT NULL,
`id_cliente` int(11) NOT NULL,
`cantidad` int(11) default NULL,
PRIMARY KEY (`id_factura`),
KEY `id_cliente` (`id_cliente`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


--
-- Filtros para la tabla `venta`
--
ALTER TABLE `venta`
ADD CONSTRAINT `venta_ibfk_1` FOREIGN KEY (`id_cliente`) REFERENCES `cliente` (`id_cliente`) ON DELETE CASCADE ON UPDATE CASCADE;


Bueno a ver si alguien TAN amable me hace un ejemplo con esa pequeña base de datos.. como poder agregar 6 catidades para un mismo id_cliente y luego poder editarlo esto,,, además un master/detail con eso :)
La verdad es que solo con eso creo que aprenderé o mejor dicho me daré cuenta en que es lo que fallo y que conceptos tengo mal definidos de lo que leí

saludos y gracias por la ayuda :)

Lepe
27-03-2007, 11:37:11
Como ya te dije, usa un ZDataset, es lo que necesitas para editar, insertar, borrar y seleccionar de una tabla.

Mira en este hilo (http://www.clubdelphi.com/foros/showthread.php?t=41695)los mensajes 7 y 8

Saludos

BlackDaemon
31-03-2007, 23:33:39
Como ya te dije, usa un ZDataset, es lo que necesitas para editar, insertar, borrar y seleccionar de una tabla.

Mira en este hilo (http://www.clubdelphi.com/foros/showthread.php?t=41695)los mensajes 7 y 8

Saludos

Me he leido todos los mensajes.. y lo que aún no entiendo es que me mandas a usar un ZDataset pero sigo sin saber que es eso.. lo que se es que es un componente, pero te refieres al ZQuery ?? o el ZQUptadeSQL ??
Y me mandas a al mensaje 7, 8 donde claramente tu recomiendas unos componentes diferentes a los que suo, yo uso ZEOSlib + MYSQL y los que aconsejas con para Firebird

http://www.clubdelphi.com/foros/showpost.php?p=191065&postcount=7

Esos componentes pueden que tengas uno llamado MDODataset pero aquí no tengo alguno que se parece pero es obvio puesto que uso los ZEOS, ahora mi pregunta es.. ese ZDataset al que te refieres es el ZUpdateSQL que tienen las ZEOS ??? y en el aterior post te puse los componentes que tengo en esa paleta, pero te las pongo de nuevo por si no las viste.

ZConnection: TZConnection
ZReadOnlyQuery: ZDataSet
ZQuery: ZDataSet
ZTable : ZDataSet
ZUpdateSQL: ZsqlUpdate
ZStoredProc: ZstoredProcedure
ZSQLMetadata: ZSQLMetadata
ZSQLProcessor: ZSQLProcessor
ZSQLMonitor : ZSQLMonitor
ZSequence : ZSequence

Bueno yo ahora estoy usando ZQuery para insertar registros pero la verdad es que es un lio.. por que tengo que usar 2 para cada tabla :eek: se que lo hago mal. pero así funciona, la cosa es a la hora de actualizar, no tengo la menos idea de como hacerlo con unos Edits, puesto que ya no uso los DBEdits, lo que estaba haciendo es hacer una busqueda del producto a editar luego llenar los campos Edits, pero tengo problemas al llenar unos DBLookComboBox :confused: que son los que llenan sus Items leyendo de otra tabla, bueno creo que estoy muy perdido o es que me he confundido demasiado y quiero salir de esto :(
Este es el código que estoy usando para agregar las descripciones de los productos a la tabla PRODUCTOS y códigos, precios, y listaprecios a la tabla TARIFAS

if (ECodigoBarra.Text = '') then
begin
ShowMessage('Ingresa un valor para el Código de barra.');
end
else
begin
//Armamos el query (INSERT) para agregar los datos del producto.
DM.ZQProductos.Close;
DM.ZQProductos.SQL.Clear;
DM.ZQProductos.SQL.Add('INSERT INTO productos (Descripcion, Categoria, SubCategoria, Unidad, Cantidad, Proveedor, ');
DM.ZQProductos.SQL.Add('UnidadPrecio, PrecioCompraBs, PrecioCompraSus, Costo, FechaActualizacion)');
DM.ZQProductos.SQL.Add('VALUES (:Des, :Cat, :SubCat, :Uni, :Cant, :Prov, :UniPre, :PCB, :PCS, :Cos, :FechAct)');
//Asignamos los parámetros tomados de los edits.text
DM.ZQProductos.ParamByName('Des').AsString := MDescripcion.Text;
DM.ZQProductos.ParamByName('Cat').AsString := DBLCBCategoria.Text;
DM.ZQProductos.ParamByName('SubCat').AsString := DBLCBSubCategoria.Text;
DM.ZQProductos.ParamByName('Uni').AsString := DBLCBUnidad.Text;
DM.ZQProductos.ParamByName('Cant').AsString := ECantidad.Text;
DM.ZQProductos.ParamByName('Prov').AsString := DBLCBProveedor.Text;
DM.ZQProductos.ParamByName('UniPre').AsString := DBLCBUnidadPrecio.Text;
DM.ZQProductos.ParamByName('PCB').AsString := EPrecioCompraBs.Text;
DM.ZQProductos.ParamByName('PCS').AsString := EPrecioCompraSus.Text;
DM.ZQProductos.ParamByName('Cos').AsString := ECosto.Text;
DM.ZQProductos.ParamByName('FechAct').AsDateTime := DateTimePicker1.Date;
DM.ZQProductos.ExecSQL;
//DM.ZQProductos.Open;
//DM.ZQProductos.Refresh;
//DM.ZQProductos.Last;
DM.ZTProductos.Refresh;
DM.ZTProductos.Last;

with DM.ZQTarifas do
begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO tarifas (Id_producto, CodigoBarra , CodProducto , TipoTarifa , Precio)');
SQL.Add('VALUES (:IDP, :CB, :CP, :TT1, :P1), ');
SQL.Add('(:IDP, :CB, :CP, :TT2, :P2), ');
SQL.Add('(:IDP, :CB, :CP, :TT3, :P3), ');
SQL.Add('(:IDP, :CB, :CP, :TT4, :P4), ');
SQL.Add('(:IDP, :CB, :CP, :TT5, :P5), ');
SQL.Add('(:IDP, :CB, :CP, :TT6, :P6)');

// Si, asignamos los parámetros xDD
ParamByName('IDP').AsInteger := DM.ZTProductos.FieldByname('Id_producto').AsInteger;
ParamByName('CB').AsString := ECodigoBarra.Text;
ParamByName('CP').AsString := ECodProducto.Text;

ParamByName('TT1').AsString := 'Precio1';
ParamByName('TT2').AsString := 'Precio2';
ParamByName('TT3').AsString := 'Precio3';
ParamByName('TT4').AsString := 'Precio4';
ParamByName('TT5').AsString := 'Precio5';
ParamByName('TT6').AsString := 'Precio6';

ParamByName('P1').AsString := EPrecio1.Text;
ParamByName('P2').AsString := EPrecio2.Text;
ParamByName('P3').AsString := EPrecio3.Text;
ParamByName('P4').AsString := EPrecio4.Text;
ParamByName('P5').AsString := EPrecio5.Text;
ParamByName('P6').AsString := EPrecio6.Text;
// Ejecutamos e insertamos todos los valores asignados
ExecSQL;
end;

end;
end;


bueno por lo que verán es demasiado largo ;) y se que se puede hacerlo mas fácil pero no lo se,

saludos y espero me ayuden :)

Lepe
01-04-2007, 02:15:18
Lo siento, como ves no uso esos componentes. Los ví cuando lo pusiste la primera vez, pero como no los conozco, no respondí, estuve esperando que otra persona que use Zeos pudiera afirmarlo.

Deber... debe exister ese componente, o quizás no lo hayan creado aún... en definitiva, no puedo asegurarte nada.

Siento mi última intervención.

Saludos

BlackDaemon
01-04-2007, 03:08:25
Lepe pero tengo un componente que se llama ZsqlUpdate.. tiene esas 3 propiedades.. insert, delete, update creo que es a ese que te refieres no ??
no me abandones xDDDD


saludos, a ver si álguien mas me echa una mano que tengo ganas de aprender :)

salud!

Lepe
01-04-2007, 11:33:07
Es que, no lo sé.

Yo tengo un MDODataset y un MDOUpdateSql, y son componentes distintos, el segundo no se usa igual que el primero. No tengo ni idea si en Zeos le han cambiado el nombre.

Saludos

BlackDaemon
02-04-2007, 00:48:25
jeje bueno Lepe, pero tranquilo, no te enojes xDD (broma)

Ya, ahora a esperar que álguien sepa o seguir buscando info, no creo que nadie haya necesitado alguna vés estos componentes con MySQL y tablas relacionales


saludos y gracias :D

d-hugo
10-04-2007, 04:14:22
Algunas observaciones (disculpa el atrevimiento):
Para dinero en lugar de utilizar un campo FLOAT usa NUMERIC que guarda un valor exacto, el float redondea cada vez que se usa por lo que usarlo para dinero no es recomendable.
Ten presente que si borras un producto, proveedor, cliente o cualquier otro nomenclador que hayas usado en documentos comerciales, perderás el historial. En el lugar donde trabajo esto es inaceptable, por lo que yo suelo usar un campo boolean para definir si el nomenclador está activo o no.
No veo el objetivo de tener 6 precios en la base de datos si 5 siempre se van a calcular de la misma manera a partir del primero. Bien puedes calcular los valores en el momento en que vayas a mostrarlos en el formulario. Pero bueno, si vas a usar la tabla de precios, por qué mejor no usar solo el foreign key a id_producto y así no solo te ahorras ambos códigos, sino que puedes realizar joins y mostrar los campos que quieras?
Otra cosa es que en vez de usar un stringgrid quizás sería mejor usar un clientdataset para así poder hacer updates más comodamente, creo que de hecho te simplificaría más las cosas porque podrías usar controles db-aware y usar instrucciones SQL que son más sencillas.
En fin, suerte.

BlackDaemon
10-04-2007, 09:54:39
Hola gracias por los consejos, me servirán de mucho y tendré muy en cuenta sobre los precios, pues no lo sabía, ahora sobre los precios ya lo he discutido con mi jefe, yo quiería hacer así, tener un precios _base_ y a este asignarle 6 porcentajes diferentes para calcular el resto de los precios al momento de ponerlos al StringGrid Por ej, pero bueno jeje hay que hacer caso a los jafes :D y mas aún siendo este mi primer jefe xD
Ahora ya lo tengo todo listo.. he echo todo una chapucera, pero funciona :)
ahora mismo son las 3:00 am en mi País y mañana pienso poner el código para que a alguien mas le sirva, aunque es mucho pero igual xD

saludos d-hugo

PD ahh es que ya tengo casi todo en mi stringGrind, sería como comenzar casi de nuevo con lo mucho que me esta costando :(

d-hugo
10-04-2007, 10:50:13
ahh es que ya tengo casi todo en mi stringGrind, sería como comenzar casi de nuevo con lo mucho que me esta costando
Sí, ese es el inconveniente, especialmente si tienes la aplicación muy adelantada. En todo caso bien puedes probarlo en un formulario que aun no hayas hecho, o cuando termines puedes hacer un proyecto de prueba a ver si usar clientdatasets te resulta mas simple.

BlackDaemon
10-04-2007, 17:01:32
Sí, ese es el inconveniente, especialmente si tienes la aplicación muy adelantada. En todo caso bien puedes probarlo en un formulario que aun no hayas hecho, o cuando termines puedes hacer un proyecto de prueba a ver si usar clientdatasets te resulta mas simple.

Bueno esta bién, ya lo había tenido pensado eso, luego hacer otra app sacando las mejoras de esta y actualizando todo lo que se pueda, pero tengo una duda, cuando hablas de clientdatasets a que te refieres ?? Osea a que componente ::D
ahh tambien si me podría aclarar las dudas con el DATASET de los componentes ZOES lib, por que por lo que veo no las tienen y me han recomendado mucho :(

saludos

d-hugo
10-04-2007, 17:25:36
tengo una duda, cuando hablas de clientdatasets a que te refieres ?? Osea a que componente ::D
ahh tambien si me podría aclarar las dudas con el DATASET de los componentes ZOES lib, por que por lo que veo no las tienen y me han recomendado mucho :(
El ClientDataSet es un componente del Delphi (al menos del D7 enterprise), basicamente lo que hace es una base de datos virtual en memoria, con todas las propiedades normales de una base de datos. Pero también podrías usar el componente llamado KbmMemTable, que tiene buena reputación en cuanto a rapidez y funcionalidad, parece que es incluso mejor que el propio ClientDataSet. Haz una busqueda.

Con respecto al ZEOS, no puedo decirte la gran cosa, porque no lo he probado.

BlackDaemon
10-04-2007, 21:45:26
Bueno si, pero Lepe me ha hablado mucho de DataSet pero no los tengo en los ZEoS y si, si he visto el ClientDataSet, pero pensé que te referías a otro de los Zeos por ej, ahora como se usaría un ClientDataSet, y tu me dijiste que use en ClientDataSet en ves de un StringGrid pero la verdad es que yo no los veo nada de parecidos.. al princípio pensé que te referías al DBGrid pero veo que no, si me aclaras mis dudas te estaría muy agradecido.

saludos :)

BlackDaemon
12-04-2007, 07:29:43
Bueno despues de tanto luchar con este tema.. lo he logrado de una manera que aún no me convence pero que da resultados buenos, pero tambien tiene muuuuuchas contras, sin mas aquí les dejo mi código por si alguien lo quisiera usar, aunque estoy seguro que solo serviría para confundir aún mas :D

Bueno comenzemos.. como ya tengo las 2 tablas PRODUCTOS y la tabla TARIFAS en los anteriores post puse la estructura, así que no la repetiré
Asi que este es el código con el cual AGREGO tooooodos los campos que tengo en diferentes edits y DataBaseComboBoxsLoock y un meno.

AGREGAR PRODUCTOS

Tengo estas variables definidas


var
FrmAgregarProductos: TFrmAgregarProductos;
Editando : Boolean;
idTarifa, prec1Old, prec2Old, prec3Old, prec4Old, prec5Old, prec6Old : Integer;
codBarOld, codProOld : String;



Y el código del botón agregar :o si, ya se que esta largo y feo

procedure TFrmAgregarProductos.SBAgregarClick(Sender: TObject);
var
idProducto : Integer;
begin
if (ECodProducto.Text <> '') then
begin
if (ECodigoBarra.Text <> '') then
begin
if (MDescripcion.Text <> '') then
begin
if (DBLCBCategoria.Text <> '') then
begin
if (DBLCBSubCategoria.Text <> '') then
begin
if (ECantidad.Text <> '') then
begin
if (DBLCBUnidadPrecio.Text <> '') AND (DBLCBUnidad.Text <> '') then
begin
//Insertamos todos los registros de los campos Edits, DBComboBox, etc
with DM.ZQProductos do
begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO productos (Descripcion, Categoria, SubCategoria, Unidad, Cantidad, Proveedor, ');
SQL.Add('UnidadPrecio, PrecioCompraBs, PrecioCompraSus, Costo, FechaActualizacion)');
SQL.Add('VALUES (:Des, :Cat, :SubCat, :Uni, :Cant, :Prov, :UniPre, :PCB, :PCS, :Cos, :FechAct)');
//Asignamos los parámetros tomados de los edits.text
ParamByName('Des').AsString := MDescripcion.Text;
ParamByName('Cat').AsString := DBLCBCategoria.Text;
ParamByName('SubCat').AsString := DBLCBSubCategoria.Text;
ParamByName('Uni').AsString := DBLCBUnidad.Text;
ParamByName('Cant').AsString := ECantidad.Text;
ParamByName('Prov').AsString := DBLCBProveedor.Text;
ParamByName('UniPre').AsString := DBLCBUnidadPrecio.Text;
ParamByName('PCB').AsString := EPrecioCompraBs.Text;
ParamByName('PCS').AsString := EPrecioCompraSus.Text;
ParamByName('Cos').AsString := ECosto.Text;
ParamByName('FechAct').AsDateTime := DateTimePicker1.Date;
//Executamos todo e insertamo en la tabla Productos
ExecSQL;
end;
//Sacamos el último ID de la tabla productos.. sería el ID del producto insertado
with DM.ZQProductos do
begin
Close;
SQL.Clear;
SQL.Add('SELECT max(id_producto) as xxx FROM productos');
Open;
end;
idProducto := DM.ZQProductos.fieldByName('xxx').AsInteger;
//Insertamos ahora los campo "id_producto ( este es de la tabla productos )
//Código, Código Producto, precio1, precio2... precioN en la tabla Tarifas
with DM.ZQProductos do
begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO tarifas (Id_producto, CodigoBarra , CodProducto , ListaPrecio , Precio)');
SQL.Add('VALUES (:IDP, :CB, :CP, :LP1, :prec1), ');
SQL.Add('(:IDP, :CB, :CP, :LP2, :prec2), ');
SQL.Add('(:IDP, :CB, :CP, :LP3, :prec3), ');
SQL.Add('(:IDP, :CB, :CP, :LP4, :prec4), ');
SQL.Add('(:IDP, :CB, :CP, :LP5, :prec5), ');
SQL.Add('(:IDP, :CB, :CP, :LP6, :prec6)');
//Asignamos parámetros que se repiten en los 6 campos
ParamByName('IDP').AsInteger := idProducto;
ParamByName('CB').AsString := ECodigoBarra.Text;
ParamByName('CP').AsString := ECodProducto.Text;
//Asignamos parámetros a las lista de precios que son 6
ParamByName('LP1').AsString := 'precio1';
ParamByName('LP2').AsString := 'precio2';
ParamByName('LP3').AsString := 'precio3';
ParamByName('LP4').AsString := 'precio4';
ParamByName('LP5').AsString := 'precio5';
ParamByName('LP6').AsString := 'precio6';
//Asignamos parámetro a los precios que tambien son 6
ParamByName('prec1').AsInteger := StrToInt(EPrecio1.Text);
ParamByName('prec2').AsInteger := StrToInt(EPrecio2.Text);
ParamByName('prec3').AsInteger := StrToInt(EPrecio3.Text);
ParamByName('prec4').AsInteger := StrToInt(EPrecio4.Text);
ParamByName('prec5').AsInteger := StrToInt(EPrecio5.Text);
ParamByName('prec6').AsInteger := StrToInt(EPrecio6.Text);
ExecSQL;
end;
ModoEditar(False);
SBAgregar.Enabled := False;
SBCancelar.Enabled := False;
SBNuevo.Enabled := True;
SBEditar.Enabled := True;
SBEliminar.Enabled := True;
//Mostramos mensajes si los campos están vacíos
end
else
begin
ShowMessage('Los campos Unidad no pueden estar vacíos');
end;
end
else
begin
ShowMessage('El campo Cantidad no puede estar vacío');
end;
end
else
begin
ShowMessage('El campo proveedor no puede estar vacío');
end;
end
else
begin
ShowMessage('El campo Categoría no puede estar vacío');
end;
end
else
begin
ShowMessage('El campo Descripción no puede estar vacío');
end;
end
else
begin
ShowMessage('El campo Código Barra no puede estar vacío');
end;
end
else
begin
ShowMessage('El campo Código no puede estar vacío');
end;

end;



pfff Bueno ahora toca el código de edición, para lo cual realizo una búsqueda por CodigoBarra y llenos los edits, DataBaseComboBoxLook y el meno

BUSCAR Y LLENAR LOS COMPONTES

Todo esto en el evento OnClik del boton búsqueda

procedure TFrmAgregarProductos.SBBuscarClick(Sender: TObject);
begin
if (EPalabra.Text <> '') then
begin
//llenamos el edit Precio1 y los edits codigos
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM tarifas WHERE CodigoBarra = :CB AND ListaPrecio = :LP1');
//SQL.Add('SELECT * FROM tarifas WHERE codigo LIKE "%' +EPalabra.Text+ '%"');
ParamByName('CB').AsString := EPalabra.Text;
ParamByName('LP1').AsString := 'Precio1';
Open;
end;
EPrecio1.Text := IntToStr(DM.ZQBusqProducto.FieldByName('precio').AsInteger);
//tenemos el id_producto para usarlo en en query para la tabla productos
idTarifa := DM.ZQBusqProducto.FieldByName('id_producto').AsInteger;
codBarOld := DM.ZQBusqProducto.FieldByName('CodigoBarra').AsString;
codProOld := DM.ZQBusqProducto.FieldByName('CodProducto').AsString;
prec1Old := DM.ZQBusqProducto.FieldByName('precio').AsInteger;
//Lenamos el campo Edit CódigoBarra y CodProducto
ECodProducto.Text := DM.ZQBusqProducto.FieldByName('CodProducto').AsString;
ECodigoBarra.Text := DM.ZQBusqProducto.FieldByName('CodigoBarra').AsString;
//Llenamos el edit precio2
with DM.ZQBusqProducto do
begin
Close;
SQl.Clear;
SQL.Add('SELECT * FROM tarifas WHERE CodigoBarra = :CB AND ListaPrecio = :LP2');
ParambyName('CB').AsString := EPalabra.Text;
ParamByName('LP2').AsString := 'precio2';
Open;
end;
EPrecio2.Text := IntToStr(DM.ZQBusqProducto.FieldByName('precio').AsInteger);
prec2Old := DM.ZQBusqProducto.FieldByName('precio').AsInteger;
//Lenamos el edit cantidad3
with DM.ZQBusqProducto do
begin
Close;
SQl.Clear;
SQL.Add('SELECT * FROM tarifas WHERE CodigoBarra = :CB AND ListaPrecio = :LP3');
ParambyName('CB').AsString := EPalabra.Text;
ParamByName('LP3').AsString := 'precio3';
Open;
end;
EPrecio3.Text := IntToStr(DM.ZQBusqProducto.FieldByName('precio').AsInteger);
prec3Old := DM.ZQBusqProducto.FieldByName('precio').AsInteger;
//Lenamos el edit con Precio4
with DM.ZQBusqProducto do
begin
Close;
SQl.Clear;
SQL.Add('SELECT * FROM tarifas WHERE CodigoBarra = :CB AND ListaPrecio = :LP4');
ParambyName('CB').AsString := EPalabra.Text;
ParamByName('LP4').AsString := 'precio4';
Open;
end;
EPrecio4.Text := IntToStr(DM.ZQBusqProducto.FieldByName('precio').AsInteger);
prec4Old := DM.ZQBusqProducto.FieldByName('precio').AsInteger;
//llenamos el campo Precio5
with DM.ZQBusqProducto do
begin
Close;
SQl.Clear;
SQL.Add('SELECT * FROM tarifas WHERE CodigoBarra = :CB AND ListaPrecio = :LP5');
ParambyName('CB').AsString := EPalabra.Text;
ParamByName('LP5').AsString := 'precio5';
Open;
end;
EPrecio5.Text := IntToStr(DM.ZQBusqProducto.FieldByName('precio').AsInteger);
prec5Old := DM.ZQBusqProducto.FieldByName('precio').AsInteger;
//Llenamos el campo Precio6
with DM.ZQBusqProducto do
begin
Close;
SQl.Clear;
SQL.Add('SELECT * FROM tarifas WHERE CodigoBarra = :CB AND ListaPrecio = :LP6');
ParambyName('CB').AsString := EPalabra.Text;
ParamByName('LP6').AsString := 'precio6';
Open;
end;
EPrecio6.Text := IntToStr(DM.ZQBusqProducto.FieldByName('precio').AsInteger);
prec6Old := DM.ZQBusqProducto.FieldByName('precio').AsInteger;
//sacamos el id_tarifa de la otra tabla.
//Llenamos los campos Descripcion y Categoria
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM productos WHERE id_producto = :IDT');
ParamByName('IDT').AsInteger := idTarifa;
Open;
end;
//Lenamos toooodos los campos que faltan.. unidad, categoria , subCatetgoria..
MDescripcion.Text := DM.ZQBusqProducto.FieldByName('descripcion').AsString;
DBLCBCategoria.KeyValue := DM.ZQBusqProducto.FieldByName('Categoria').AsString;
DBLCBSubCategoria.KeyValue := DM.ZQBusqProducto.FieldByName('SubCategoria').AsString;
DBLCBProveedor.KeyValue := DM.ZQBusqProducto.FieldByName('Proveedor').AsString;
DBLCBUnidad.KeyValue := DM.ZQBusqProducto.FieldByName('Unidad').AsString;
DBLCBUnidadPrecio.KeyValue := DM.ZQBusqProducto.FieldByName('UnidadPrecio').AsString;
ECantidad.Text := DM.ZQBusqProducto.FieldByName('Cantidad').AsString;
ECosto.Text := DM.ZQBusqProducto.FieldByName('Costo').AsString;
EPrecioCompraBs.Text := DM.ZQBusqProducto.FieldByName('PrecioCompraBs').AsString;
EPrecioCompraSus.Text := DM.ZQBusqProducto.FieldByName('PrecioCompraSus').AsString;
DateTimePicker1.Date := DM.ZQBusqProducto.FieldByName('FechaActualizacion').AsDateTime;
//Abrimos los campos
modoEditar(True);
SBGuardar.Enabled := True;
SBCancelar.Enabled := True;
SBNuevo.Enabled := False;
SBAgregar.Enabled := False;
SBEditar.Enabled := False;
SBEliminar.Enabled := False;
SBDelete.Enabled := True;
end
else
begin
ShowMessage('Por Favor ingrese un código');
end;
end;

continuaaa...

BlackDaemon
12-04-2007, 07:38:32
Bueno y una ves llenados todos los componetes podemos editar a nustro gusto todo y luego tenemos que guardar los cambios con el boton GUARDAR que en su evento OnClick pongo esto.

procedure TFrmAgregarProductos.SBGuardarClick(Sender: TObject);
begin
if (MDescripcion.Text <> '') then
begin
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE productos SET Descripcion = : desc, Categoria = : cat, SubCategoria = : SubCat, ');
SQL.Add('Unidad = : Uni, Cantidad = : Cant, Proveedor = : Prov, UnidadPrecio = : UniPre, ');
SQL.Add('PrecioCompraBs = : PCBs, PrecioCompraSus = : PCSus, Costo = : Cos, FechaActualizacion = : FA');
SQL.Add('WHERE id_producto = : IDP');
//Asignamos parametros a la tabla Productos
ParamByName('desc').AsString := MDescripcion.Text;
ParamByName('cat').AsString := DBLCBCategoria.Text;
ParamByName('SubCat').AsString := DBLCBSubCategoria.Text;
ParamByName('Uni').AsString := DBLCBUnidad.Text;
ParamByName('Cant').AsString := ECantidad.Text;
ParamByName('Prov').AsString := DBLCBProveedor.Text;
ParamByName('UniPre').AsString := DBLCBUnidadPrecio.Text;
ParamByName('PCBs').AsString := EPrecioCompraBs.Text;
ParamByName('PCSus').AsString := EPrecioCompraSus.Text;
ParamByName('Cos').AsString := ECosto.Text;
ParamByName('FA').AsDateTime := DateTimePicker1.Date;

ParamByName('IDP').AsInteger := idTarifa;
ExecSQL;
end;
//Updateamos el código de la tabla Tarifas
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE tarifas SET CodigoBarra = : codBarNew, CodProducto = : CodProNew, Precio = :prec1New');
SQL.Add('WHERE id_producto = : IDP AND CodigoBarra = : codBarOld');
SQL.Add('AND CodProducto = : codProOld AND ListaPrecio = : P1 AND precio = : prec1Old');

ParamByName('codBarNew').AsString := ECodigoBarra.Text;
ParamByName('codProNew').AsString := ECodProducto.Text;
ParamByName('prec1New').AsInteger := StrToInt(EPrecio1.Text);
ParamByName('IDP').AsInteger := idTarifa;
ParamByName('codBarOld').AsString := codBarOld;
ParamByName('codProOld').AsString := codProOld;
ParamByName('P1').AsString := 'Precio1';
ParamByName('prec1Old').AsInteger := prec1Old;
ExecSQL;
end;
//Updateamos el precio1 de la tabla tarifas
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE tarifas SET CodigoBarra = : codBarNew, CodProducto = :CodProNew, Precio = : prec2New');
SQL.Add('WHERE id_producto = : IDP AND CodigoBarra = : codBarOld');
SQL.Add('AND CodProducto = : codProOld AND ListaPrecio = : P2 AND precio = : prec2Old');

ParamByName('codBarNew').AsString := ECodigoBarra.Text;
ParamByName('codProNew').AsString := ECodProducto.Text;
ParamByName('prec2New').AsInteger := StrToInt(EPrecio2.Text);
ParamByName('IDP').AsInteger := idTarifa;
ParamByName('codBarOld').AsString := codBarOld;
ParamByName('codProOld').AsString := codProOld;
ParamByName('P2').AsString := 'Precio2';
ParamByName('prec2Old').AsInteger := prec2Old;
ExecSQL;
end;
//vamos por el último precio3
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE tarifas SET CodigoBarra = : codBarNew, CodProducto = : CodProNew, Precio = : prec3New');
SQL.Add('WHERE id_producto = : IDP AND CodigoBarra = : codBarOld');
SQL.Add('AND CodProducto = : codProOld AND ListaPrecio = : P3 AND precio = : prec3Old');

ParamByName('codBarNew').AsString := ECodigoBarra.Text;
ParamByName('codProNew').AsString := ECodProducto.Text;
ParamByName('prec3New').AsInteger := StrToInt(EPrecio3.Text);
ParamByName('IDP').AsInteger := idTarifa;
ParamByName('codBarOld').AsString := codBarOld;
ParamByName('codProOld').AsString := codProOld;
ParamByName('P3').AsString := 'Precio3';
ParamByName('prec3Old').AsInteger := prec3Old;
ExecSQL;
end;
//Updateamos el precio4
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE tarifas SET CodigoBarra = : codBarNew, CodProducto = : CodProNew, Precio = : prec4New');
SQL.Add('WHERE id_producto = : IDP AND CodigoBarra = : codBarOld');
SQL.Add('AND CodProducto = : codProOld AND ListaPrecio = : P4 AND precio = : prec4Old');

ParamByName('codBarNew').AsString := ECodigoBarra.Text;
ParamByName('codProNew').AsString := ECodProducto.Text;
ParamByName('prec4New').AsInteger := StrToInt(EPrecio4.Text);
ParamByName('IDP').AsInteger := idTarifa;
ParamByName('codBarOld').AsString := codBarOld;
ParamByName('codProOld').AsString := codProOld;
ParamByName('P4').AsString := 'Precio4';
ParamByName('prec4Old').AsInteger := prec4Old;
ExecSQL;
end;
//Updatemos el precio5
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE tarifas SET CodigoBarra = : codBarNew, CodProducto = : CodProNew, Precio = :prec5New');
SQL.Add('WHERE id_producto = : IDP AND CodigoBarra = : codBarOld');
SQL.Add('AND CodProducto = : codProOld AND ListaPrecio = : P5 AND precio = : prec5Old');

ParamByName('codBarNew').AsString := ECodigoBarra.Text;
ParamByName('codProNew').AsString := ECodProducto.Text;
ParamByName('prec5New').AsInteger := StrToInt(EPrecio5.Text);
ParamByName('IDP').AsInteger := idTarifa;
ParamByName('codBarOld').AsString := codBarOld;
ParamByName('codProOld').AsString := codProOld;
ParamByName('P5').AsString := 'Precio5';
ParamByName('prec5Old').AsInteger := prec5Old;
ExecSQL;
end;
//Updateamos el precio6
with DM.ZQBusqProducto do
begin
Close;
SQL.Clear;
SQL.Add('UPDATE tarifas SET CodigoBarra = : codBarNew, CodProducto = : CodProNew, Precio = : prec6New');
SQL.Add('WHERE id_producto = : IDP AND CodigoBarra = : codBarOld');
SQL.Add('AND CodProducto = : codProOld AND ListaPrecio = : P6 AND precio = : prec6Old');

ParamByName('codBarNew').AsString := ECodigoBarra.Text;
ParamByName('codProNew').AsString := ECodProducto.Text;
ParamByName('prec6New').AsInteger := StrToInt(EPrecio6.Text);
ParamByName('IDP').AsInteger := idTarifa;
ParamByName('codBarOld').AsString := codBarOld;
ParamByName('codProOld').AsString := codProOld;
ParamByName('P6').AsString := 'Precio6';
ParamByName('prec6Old').AsInteger := prec6Old;
ExecSQL;
end;
modoEditar(False);
SBNuevo.Enabled := True;
SBEditar.Enabled := True;
SBEliminar.Enabled := True;
SBAgregar.Enabled := False;;
SBCancelar.Enabled := False;
GBBusqueda.Visible := False;
ShowMessage('Producto editado con éxito');

end
else
begin
ShowMessage('no hay datos que Editar');
end;

end;

Ahora ya estan editados nuentros datos en las 2 tablas.. :eek:

Y por último eliminar un producto con sus respectivos precios, como la estructura de las 2 tablas PRODUCTOS y TARIFAS son relacionales entonces solo bastará eliminar el producto para que así se eliminen TODOS sus precios de la tabla TARIFAS
Para que surta efecto tenemos que buscar primero el producto con el anterior código que puse de búsqueda.. e se llenan todos los componetes y esto va en el boton ELIIMINAR en el evento onclick

procedure TFrmAgregarProductos.SBDeleteClick(Sender: TObject);
var
resp : Integer;
begin
resp := Application.MessageBox(Pchar('¿Desea eliminar el código '+ECodigoBarra.Text+'?'),'Eliminar un registro',MB_YESNO+MB_ICONERROR);
if resp = ID_YES then begin
with DM.ZQProductos do
begin
Close;
SQL.Clear;
SQL.Add('DELETE FROM productos WHERE id_producto = : IDP');
ParamByName('IDP').AsString := DM.ZQBusqProducto.FieldByName('id_producto').AsString;
ExecSQL;
end;
modoEditar(False);
SBNuevo.Enabled := True;
SBEditar.Enabled := True;
SBEliminar.Enabled := True;
SBAgregar.Enabled := False;;
SBCancelar.Enabled := False;
GBBusqueda.Visible := False;
end;
end;


Los parámetros puse alejados de los 2 puntos por que me los pone como emoticons :_precioOld ahí quitan la barra baja que sería el espacio.
:eek:

bueno ya terminé el fin de pegar tanta basura de código, pero como digo lo pongo por 2 cosas.. una para que pueda servirle a alguien mas ( que lo dudo ) y la otra para que puedan dar una idea mejor de hacerla
O tambien de implementar cosas como por ej a la hora de agregar un producto que si ya esta repetido el código me diga que ese código ya existe y tambien me habría gustado _mucho_ que en la busqueda sep ued abuscar con un LIKE y los resultados mostrarmelos en un DBGrid y luego el hacerle doble click "Recién" me llene los Edits, pero como veran no soy experto en delphi y trato de hacer lo mejor que puedo mis cosas..

saludos y suerte

PD ahh para que esto no quede así he echo un pequeño ejemplo de su uso, pero con 3 pequeñas tablas y una interfáz, para que todo funcione lo único que tienen que tener las componentes ZEOSlib en su última versión, aunque tambien las otras les servirá ya que uso puros querys :D
PD2 si el mensaje esta muuuuy largo, perdón y lo siento mucho, puedo quitarlo :)

PD3 tienen solo que poner el user y pass de su base de datos en el componente ZConnection

joder el adjunto se me fue en un mensaje anterior :D