http://www.ajpdsoft.com/mod http://www.ajpdsoft.com/modules.php?name=N ules.php?name=News&file=art ews&file=article&sid=260 icle&sid=260 Este artículo explica cómo realizar un programa en Delphi (extensible para cualquier lenguaje de programación) programación) que gestione y calcule e ficientemente ficientemente el control de stock (control de e xistencias de artículos en almacén). Os explicaremos paso a paso los campos necesarios en la tabla de artículos, facturas a clientes y facturas de proveedores. También os explacamos en qué eventos de los formularios/ventanas formularios/ventanas de Delphi será preciso colocar el código fuente necesario para llevar esta gestión.
Cómo programar control de stock (existencias en almacén) de artículos paso a paso Este artículo explica cómo realizar un programa en Delphi (extensible para cualquier lenguaje de programación) programación) que gestione y calcule e ficientemente el control de stock (control de existencias de artículos en almacén). Os explicaremos paso a paso los campos necesarios en la tabla de artículos, facturas a clientes yfacturas de proveedores. También os explacamos en qué eventos de los formularios/ventanas formularios/ventanas de Delphi será preciso colocar el código fuente necesario para llevar esta gestión.
El control de existencias en almacén se hace imprescindible en organizaciones/empresas organizaciones/empresas de compra/venta compra/venta de artículos (para controlar los artículos disponibles en almacén), de montaje de maquinaria (para controlar la disponibilidad disponibilidad de las piezas necesarias para el montaje), agrícolas agrícolas (para controlar la disponibilidad disponibilidad de l os productos fitosanitarios fitosanitarios en almacén), informáticas informáticas (para controlar la disponibilidad del material para montaje y venta de equipos). En definitiva se hace necesario para cualquier empresa que realice compras de material/artículos/prod material/artículos/productos uctos y quiera saber en todo momento de cuantos elementos dispone. En este manual mencionaremos mencionaremos siempre "almacén" como el sitio físico donde se alojen los productos/material/art productos/material/artículos, ículos, no tiene por qué ser un almacén como tal, puede ser cualquier tipo de ubicación, incluso puede que no sea física. En primer lugar crearemos las tablas de la base de datos necesarias para esta gestión, por supuesto este artículo es un ejemplo simple, se puede complicar todo lo que se quiera. La primera tabla y la más importante importante es la de artículos, os mostramos el script sql para MySQL necesario para crear esta tabla (en negrita destacamos los campos para el stock): CREATE TABLE articulo ( codigo int(10) unsigned NOT NULL auto_increment, fecha datetime, codigoproveedor codigoproveedor int(10) unsigned, nombre varchar(150), varchar(150), preciocompra float, float, precioventa float, float, stock float, float, stockminimo stockminimo float, avisostockminimo char(1), observacion varchar(255), codigomarca int(10) unsigned, codigofamilia int(10) unsigned,
codigomodelo int(10) unsigned, codigobarras varchar(30), caracteristicas text, porcentajebeneficio float, porcentajeiva float, porcentajedto float, PRIMARY KEY (codigo) );
Otra de las tablas será la que almacene las facturas de proveedores (los que nos sirven el material), estará formada a su vez por dos tablas enlazadas por la clave foránea, por un lado la tabla de factura propiamente dicha, con la siguiente estructura: CREATE TABLE facturaproveedor ( codigo int(10) unsigned NOT NULL auto_increment, numero varchar(10), importetotal float, baseimponible float, porcentajeiva float, importeiva float, porcentajedescuento float, importedescuento float, codigoproveedor int(10) unsigned NOT NULL, fecha datetime, cobrado char(1), observacion varchar(255), importepagado float, PRIMARY KEY (codigo) );
y por otro lado la tabla detalle, donde se guardarán las líneas de la factura (en negrita indicamos el campo que afectará a la gestión del stock): CREATE TABLE facturaproveedordetalle ( codigo int(10) unsigned NOT NULL auto_increment, codigofactura int(10) unsigned, codigoarticulo int(10) unsigned, concepto varchar(150), cantidad float, importe float, precio float, porcentajedto float, PRIMARY KEY (codigo) );
Al igual que l as facturas de los proveedores, también guardaremos, necesariamente, las facturas de los clientes. Así podremos controlar las dos formas de entrada (proveedores) y salida (clientes) de stock. La estructura de la tabla de facturas de clientes sería: CREATE TABLE facturacliente ( codigo int(10) unsigned NOT NULL auto_increment, numero varchar(15), importetotal float, baseimponible float, porcentajeiva float, importeiva float, porcentajedescuento float, importedescuento float, codigocliente int(10) unsigned NOT NULL, fecha datetime, cobrado char(1), observacion varchar(255), importecobrado float, contabiliza char(1), imprimida char(1), enviada char(1), fechaenvio datetime, piefactura text, PRIMARY KEY (codigo) );
la tabla donde se guardarán las líneas de las facturas de los clientes será:
CREATE TABLE facturadetalle ( codigo int(10) unsigned NOT NULL auto_increment, codigofactura int(10) unsigned, codigoarticulo int(10) unsigned, concepto varchar(150), cantidad float, importe float, precio float, porcentajedto float, PRIMARY KEY (codigo) );
Por supuesto, las tablas anteriores y su estructura es un ejemplo sencillo, se puede enfocar como se desee, dependiendo de las características de la organización que vaya a utilizar la aplicación. Una vez creadas las tablas, desde Delphi o cualquier otro lenguaje de programación, tendremos en cuenta las siguientes acciones: * En el formulario de alta de artículo, una ventana como esta:
colocaremos los dos campos, el primero para saber y poder modificar (aunque se puede impedir la modificación manual) el stock actual del artículo, el segundo para indicar cual es el stock mínimo a partir del cual se avisará al usuario. En principio. * En el formulario de alta de línea de factura de proveedor (entrada de stock), una ventana como esta:
colocaremos el campo "cantidad" necesario para el control de stock, opcionalmente podremos colocar una etiqueta informativa con el stock actual de artículo, para mostrarlo, en el evento "onExit" del código de artículo o al seleccionar el artículo con el botón de selección o mediante el lector de códigos de barras, añadiremos el siguiente código fuente:
md.TC2.Close; md.TC2.SQL.Clear; md.TC2.SQL.Add('Select a.stock'); md.TC2.SQL.Add ('from articulo'); md.TC2.SQL.Add ('where a.codigo = :pCodigo'); md.TC2.ParamByName('pCodigo').Value := codigo; md.TC2.Open; if md.TC2.RecordCount > 0 then lstock.Caption := md.tc2.fieldbyname('stock').AsString; else lstock.Caption := ''; si se trata de una modificación de un artículo existente, deberemos guardar en una variable global la cantidad actual (antes de que el usuario la modifique) del artículo actual. Para ello declararemos esta variable en esta ventana:
private { Private declarations } codigoArticuloAnterior : integer; cantidadActual : Double; public { Public declarations } end; y en el evento "show" ó "create" del formulario añadiremos el siguiente código:
if tag = 2 then //Modificar begin BSeleccionarProducto.Enabled := true; md.tFacturaDetalleProveedor.edit; txtCodigoArticulo.SetFocus; caption := 'Modificación de ' + ventana + '...'; obtenerDatosArticulo(md.tFacturaDetalleProveedorcodigoarticulo.Value, ''); cantidadActual := md.tFacturaDetalleProveedorcantidad.AsFloat; end;
y, por supuesto, en el evento "onClick" del botón "Aceptar", colocaremos las siguientes líneas de código:
try md.tFacturaDetalleProveedor.Post; //validar actualizarStock (true, md.tFacturaDetalleProveedorcantidad.AsFloat cantidadActual, md.tFacturaDetalleProveedorcodigoarticulo.AsInteger);
except txtCodigoArticulo.setfocus; raise; end; close;
el código del procedimiento "actualizarStock" será el siguiente:
procedure actualizarStock (entrada : boolean; cantidad : double; codigo : Integer); begin with md.tcStock do begin close; SQL.Clear; SQL.Add('UPDATE articulo); if entrada then SQL.Add('SET stock = stock + :pCantidad') else SQL.Add('SET stock = stock - :pCantidad'); SQL.Add('WHERE Codigo = :pCodigo'); ParamByName('pCantidad').DataType := ftFloat; ParamByName('pCantidad').Value := cantidad; ParamByName('pCodigo').DataType := ftInteger; ParamByName('pCodigo').Value := codigo; execsql; close; end; end; en el caso de que sea una inserción de una nueva línea de factura de proveedor, no será necesario guardar la cantidad anterior pues no existe, con lo cual la variable global "cantidadActual" se i nicializará a cero. El resto de procedimientos será el mismo que para la modificación. * En el formulario de alta de línea de factura de cliente (salida de stock), una ventana como esta:
se tratará de forma similiar a las líneas de facturas de proveedores, con la única salvedad del procedimiento "onClick" del botón "Aceptar" que será el siguiente:
try md.tFacturaDetalle.Post; //validar actualizarStock (false, md.tFacturaDetallecantidad.AsFloat cantidadActual, md.tFacturaDetallecodigoarticulo.AsInteger); except txtCodigoArticulo.setfocus; raise; end; close; Si queremos avisar al usuario en el caso en que el stock actual del artículo sea inferior al stock mínimo, en el evento "onClick" del botón "Aceptar" podremos colocar el siguiente código, después de validar la línea:
md.TC2.Close; md.TC2.SQL.Clear; md.TC2.SQL.Add('Select a.stock, a.stockminimo'); md.TC2.SQL.Add ('from articulo'); md.TC2.SQL.Add ('where a.codigo= :pCodigo'); md.TC2.ParamByName('pCodigo').Value := codigo; md.TC2.Open; if md.TC2.RecordCount > 0 then if md.TC2.FieldByName('stock').AsFloat < md.TC2.FieldByName('stockminimo').AsFloat then showmessage ('Atención: el stock del artículo es inferior a ' + md.TC2.fieldbyname ('stockminimo').AsString; Otro evento que debemos tener en cuenta es la posibilidad de que el usuario elimine una línea de la factura de proveedor o de la factura de cliente o incluso una factura de cliente o proveedor completa. En estos casos se debe restablecer el stock de los artículos que se eliminarán, en cuyo caso colocaremos el siguiente código, en el evento "eliminarFacturaCliente":
md.tc2.Close; md.tc2.sql.clear; md.tc2.SQL.add('SELECT cantidad, codigoarticulo'); md.tc2.SQL.add('FROM facturadetalle'); md.tc2.SQL.add('WHERE CodigoFactura = :pCodigo'); md.tc2.ParamByName('pCodigo').DataType := ftString; md.tc2.ParamByName('pCodigo').AsInteger := codigoFacturaEliminar;
md.tc2.open; while not md.tc2.Eof do begin codigoMaterial := md.tc2.fieldbyname ('codigoarticulo').AsInteger; cantidad := md.tc2.fieldbyname ('cantidad').AsFloat; actualizarStock (true, cantidad, codigoMaterial); md.tc2.Next; end; try md.tc2.Close; md.tc2.sql.clear; md.tc2.SQL.add('DELETE FROM FacturaDetalle'); md.tc2.SQL.add('WHERE CodigoFactura = :pCodigo'); md.tc2.ParamByName('pCodigo').DataType := ftString; md.tc2.ParamByName('pCodigo').AsInteger := codigoFacturaEliminar; md.tc2.ExecSQL; ttabla.Delete; except raise; end; para "eliminarFacturaProveedor" haremos lo mismo cambiando "True" por "False" en el procedimiento "actualizarStock", obviamente cambiaremos también los nombres de los campos y tablas.
Por último, deberemos controlar el evento "Eliminar línea factura", que se producirá cuando un usuario decida eliminar sólo una línea de la factura, en cuyo caso colocaremos el siguiente código (para restablecer el stock):
if messagedlg ('¿Está seguro que desea eliminar el concepto [' + nombre + '] de la ' + ventana + '?', mtconfirmation, [mbyes, mbno], 0) = mryes then begin codigoMaterial := md.tFacturaDetallecodigoarticulo.AsInteger; cantidad := md.tFacturaDetallecantidad.AsFloat; actualizarStock (true, cantidad, codigoMaterial); try md.tFacturaDetalle.delete; except raise; end; end;
otro
Conceptos básicos en la programación con Delphi No es el objeto del presente proyecto hacer un repaso exhaustivo de la programación en Pascal, por eso vamos a ver de forma somera solo algunas de las características de que dispone Delphi, principalmente aquellas que le diferencian más del Pascal estándar. Para ello, vamos a introducir una serie de conceptos:
1.
Objetos
2.
Componentes
3.
Propiedades
4.
Eventos
5.
Métodos
Objetos
Como su propio nombre indica, el Object Pascal (usado por Delphi) es un lenguaje totalmente orientado a objetos. Prácticamente todos los elementos del entorno Delphi son o bjetos, que unas veces se encuentran definidos de antemano (los forms, los componentes de la paleta, objetos no visuales, etc), y otras se definen en nuestra propia aplicación (por ejemplo el componente TPostIt de ANALOGIA.EXE definido en la unit U_Misc). Todo el desarrollo de aplicaciones en Delphi está íntimamente ligado con la definición y uso de objetos, por lo que es fundamental conocer la mecánica que Object Pascal utiliza para describir un objeto, sus características y su funcionamiento, sobre todo a la hora de que el programador cree sus propios componentes. En muchos casos no es necesario conocer el funcionamiento de la programación orientada a objetos para programar con Delphi, puesto que en la m ayoría de los casos existen controles ya creados sin necesidad de tener que programarlos. Por ejemplo en ANALOGIA.EXE la m ayoría de los objetos forman parte de la VCL de Delphi y otros dos componentes han sido escritos por terceros (RChart y TFormulaParser), sin embargo ha sido útil desarrollar un componente propio (TPostIt) para mostrar la tabla de valores de los componentes en el programa. La propia programación visual de Delphi, que escribe parte del código automáticamente, h ace posible utilizar objetos de forma práctica sin tener por qué comprender al cien por cien su funcionamiento.
Componentes
Un componente es cualquiera de los elementos que podemos insertar en una ficha, tanto si su función es visual como si no lo es (por supuesto un componente es también un objeto). Un ejemplo de componente puede ser RChart, usado en ANALOGIA.EXE para dibujar las gráficas. Sin conocer exactamente el cómo realiza su función, el programador manipula una serie de propiedades, métodos y eventos que caracterizan al componente, a través de los cuales se "maneja" el componente en la forma deseada. Por supuesto el usuario puede crear sus propios componentes y usarlos en distintas aplicaciones, de forma que la reusabilidad del código es máxima. A los com ponentes que cuentan con una parte visual, como puede ser un botón, se les denomina controles.
Propiedades
Los componentes, y de hecho todos los objetos de Delphi son de uso general, por lo que a la hora de usarlos de alguna forma deberemos adecuarlos a nuestras necesidades. Para ello nos serviremos de las propiedades de cada objeto, mediante las cuales podremos establecer el título de una ventana, el tipo de letra de una etiqueta de texto o el color en el que aparecen los distintos controles. Se puede pensar en las propiedades como si fuesen variables pertenecientes a un objeto (veremos que no es así exactamente), de tal forma que para acceder a ellas generalmente habrá que indicar no sólo el nombre de la propiedad, sino también a qué objeto pertenece. La modificación o consulta del valor de una propiedad puede diferir según intentemos acceder a ella mientras estamos diseñando un form, en tiempo de diseño, o bien mediante el código del programa, en tiempo de ejecución. Ciertas propiedades están sólo accesibles en tiempo de ejecución, por lo que mientras estamos diseñando la ficha no aparecerán. Además hay algunas propiedades que s on de sólo lectura, por lo que su valor puede ser consultado, pero no modificado, y otras que son sólo de escritura. Aunque a primera vista si usamos un componente prefabricado, las propiedades pueden parecer simples variables, en la mayoría de las ocasiones una propiedad no es una variable, y la modificación o consulta de su valor puede conllevar que internamente el componente ejecute un cierto código. Si por ejemplo tuviésemos un componente para comunicaciones serie que se encargase de enviar mensajes a un ordenador remoto, podríamos tal vez asignar una cadena de caracteres a una hipotética propiedad "Envia". De esta forma, con una sim ple asignación (Envia:='Mensaje a mandar') se pondría en marcha todo el mecanismo implícito en el componente para enviar el mens aje al ordenador remoto. Esta propiedad podría ser un ejemplo de propiedad de sólo escritura, ya que sólo interesa mandar el mensaje al ordenador remoto, sin conservar información acerca del mensaje, por lo que sería inapropiada su lectura.
Eventos
Como dije anteriormente, la programación en el entorno Windows se caracteriza por estar dirigida por eventos, de tal forma que un programa no tiene por qué ejecutarse necesariamente de forma secuencial, sino que ciertas porciones de código se ejecutarán cuando ocurra un cierto evento. Los eventos son señales que el entorno recibe desde distintos elementos, como puedan ser el ratón, el teclado o un temporizador. Estos eventos son redirigidos a las aplicaciones, que en caso de aceptarlos deberán responder adecuadamente de ellos. Ciertos eventos pueden ser gestionados por el propio Windows, otros quedarán a cargo del propio lenguaje que estemos usando, y un tercer grupo serán los que lleguen hasta nuestro programa. En Delphi prácticamente todo el código que escribimos irá asociado a algún evento. Si retomamos el ejemplo del componente para comunicaciones serie, podría interesarnos que se ejecutara un evento cada vez que se recibiese un carácter por el puerto serie, de forma que podríamos escribir el código necesario para guardar el carácter en un archivo cada vez que se produjese el evento. Normalmente los eventos a los que reaccionarán los componentes serán las pulsaciones del teclado o el ratón, activaciones de los componentes, etc.
Métodos
Los componentes Delphi además de disponer de propiedades y poder responder a ciertos eventos, habitualmente también disponen de métodos. Un método es un procedimiento o función que nos permite realizar una determinada acción en el componente, pudiendo necesitar o no el paso de algún parámetro. Al igual que ocurre en las propiedades, a la hora de usar un cierto método normalmente tendremos que indicar primero el objeto o componente al que pertenece, de tal forma que la acción del método recaiga sobre él, y no sobre cualquier otro. El hecho de que cada objeto sea propietario de una serie de propiedades y métodos, variables y código, que no son accesibles a ningún otro objeto externo, recibe el nombre de encapsulación, aunque también es posible definirlos de tal modo que sean accesibles a otros objetos.
http://www.gratisprogramas.org/descargar/manual-de-programacion-delphi-6-y-7/ http://www.weblibrosgratis.com/search/label/Ofimatica