Ir al contenido



Foto

Programa de gestión desde 0 (Activo)


  • Por favor identifícate para responder
156 respuestas en este tema

#1 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 06 junio 2013 - 12:45

Debido aun problema que no se ha podido Subsanar en el tema Programa de Gestión desde 0 abro este nuevo hilo, y enlazo el mismo tema que llevo avanzado desde el Clubdelhi http://www.clubdelph...ad.php?t=83208, todo ello con ya el visto bueno por parte del maestro Egostar, pronto seguiré con el tema
  • 0

#2 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 06 junio 2013 - 03:33

Para que quede más claro el uso de la tabla clientes, con direcciones, contactos, personas de contacto y bancos os pongo un esquema, que acabo de hacer con un nuevo programa Free, que esta muy bien

Imagen Enviada

el programa se llama Ibeasy+ y lo podéis bajar de http://ibeasy.software.informer.com/.

Ahora que creo quede más claro mi idea de uso de las tablas modulares (no si sera correcto), paso a explicar un par de términos y su uso básico, para que luego al usarlos estén un pocos más claros.

Stock: Creo que es el más común y se refiere a la cantidad de mercancía que tenemos disponible

ADR: Se refiere al transporte de mercancía por carretera y una gran cantidad de países se han acogido al sistema, es obligatorio en los países de la comunidad europea y en todos los acogidos a este sistema. El llevar mercancías que necesitan ADR  y no llevarlo conlleva severas multas al conductor y a la empresa, e incluso in movilización del vehículo y la mercancías. para más información

http://es.wikipedia....s_por_carretera

Trazabilidad: Este es el punto más peliagudo, la mayor parte de la gente cree, que sólo es obligatorio a los productos comestibles, pero realmente hay que aplicarla a otros muchos sectores, como todos los derivados de los químicos, manufacturados, alimentación, agricultura, residuales, Nucleares y un largo etc.

Hay que tener en cuenta que la trazabilidad es desde la creación del producto (inclusive anterior de los proveedores) hasta el consumidor final (quedando exento en este punto supermercados, tiendas y pocos más al no tener un control exacto de a quién se le ha vendido la mercancía) la trazabilidad viene controlada por lo que se llaman seriales, lotes, etc e implica que toda una producción hecha o creada (Artificial o naturalmente) tenga un mismo número de registro, asignando el número de registro (lote) la cantidad/formato de producto sacado, aunque el (lote) no varia hay que especificar cantidad lote, pongo un ejemplo:

Hacemos 1000 Litros de lavavajillas lote 130001 y sacamos en los siguientes formatos
Lote................Cantidad.............Formato...............Total Litros
--------------------------------------------------------------
130001............20.....................Garrafas 25 L.........500 L.
130001............80.....................Garrafas 5 L...........400 L.
130001............100...................Botellas 1 L............100 L.

Esto obliga a tener controlado las ordenes de producción y al control de la trazabilidad de los 1000 Litros del lote 130001, mediante partes de rotura, utilización interna, en fabricación uso como materias primas o re conversión y por supuesto ventas (albaranes, facturas, etc.)

Hay que usar el sistema de recursividad,  con la trazabilidad, al igual que con el Stock, es decir si eliminamos una factura, cambiamos la cantidad a menos o nos devuelven una mercancía. eta debe ser controlada tanto en el stock como en su control de lotes.

La trazabilidad permite a los organismos públicos, en contacto con las empresas a tener controlado todo el proceso de una mercancía, aunque se hay trasformado en otra, desde su origen al consumidor final (hipotéticamente), el responsable del problema pagará una multa, pero si alguna de las partes no tiene la trazabilidad, la multa puede ser mucho mayor y si se produjesen muertes o lesiones graves, puede llevar incluso a prisión, en caso de tenerla controlada, esto  muy difícilmente ocurriría, salvo que seamos los responsables.

Y por último, es muy frecuente que tengamos que controlar junto con la trazabilidad la caducidad, ya que muchos productos, alimentarios, químicos, etc, tiene caducidad.

Para más información podéis dirigiros a http://es.wikipedia....ki/Trazabilidad

Ley de Protección de Datos (LPD): Esta ley obliga a todas las empresas que controlen cual quier tipo de datos de clientes, proveedores, etc. a tener contratado una empresa gestora de dicha ley, esto obliga al texto que deben aparecer, en emails, facturas y demás documentos y aplicarla a nuestro programa es bastante simple, se trata de tener 2 o 3 memos, que su texto se pueda editar y guardar, para posibles cambios futuros y que aparezcan en nuestros documentos físicos como digitales. aparte de esto, obliga a que el cliente si así lo pide, no sea puesto en listados de ningún tipo, e incluso sea borrada su información, pero tener cuidado, por que hacienda esta por encima de esta Ley y si borráis, datos antes del cierre con hacienda y no aparecen los datos del cliente podéis tener un grabe problema. Las multas por no tener este sistema aplicado van desde los 6.000 euros a los 600.000 o el cierre de la empresa con posibilidad de prisión.

Para más información ir a http://noticias.juri.../lo15-1999.html

Lotes: Así es como voy a denominar el control identificativo de nuestra trazabilidad. Los lotes pueden tener derivados, pudiendo ser padres e hijos, o maestros y esclavos. Quiero decir que de un producto con un lote se puede vender en varios productos diferentes, si haber alteración, cada producto tendrá un lote pero tenemos que tener controlado de que lo te viene. Ejemplo:

Hacemos un Desengrasante base lote 130002 de este embotellamos una parte como limpia suelos desengrasante u otro artículo y a este último le asignarnos el lote 130003, quedando de la siguiente manera
Lote Padre <>  Lote Hijo
130002...........130003 (este realmente es un derivado sin modificación del lote 130002 y cuando pidamos un informe del lote 130002 debe darnos la información del lote 130003, para tener la trazabilidad correcta e igualmente pero al revés si la solicitamos del 130003.

Ordenes de producción: Esto implica el proceso para la creación del lote con el producto fabricable (no confundir con el producto final), implica el operario, lote y formatos y cantidades.

Diferencias entre un producto fabricable y el producto final: El producto fabricable, es el producto que vamos a fabricar y el producto final  es el producto ya en su formato.  Ejemplo

Producto Fabricable: Lavavajillas producto finales , Lavavajillas 5L,  Lavavajillas 25L,  Lavavajillas 1L ,  Lavavajillas a granel, etc.

Estos conceptos deben quedar muy claros, ya que si no es fácil perderse más adelante, así que si tenéis dudas, preguntar ahora antes de seguir, y por supuesto, los que no sois de España, debéis informaros de las leyes en vuestro país. Pero la mayoría de programas no tiene estos conceptos que algunos de ellos son obligatorios hace más de una década.
  • 0

#3 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 07 junio 2013 - 03:17

Empezamos ahora con artículos

Estructura de la base de datos

CREATE TABLE ARTICULOS (
    ID                INTEGER NOT NULL,
    CODIGO            T20 /* T20 = VARCHAR(20) */,  //Código del artículo
    PRODUCTO          T80 /* T80 = VARCHAR(80) */,  //Nombre del producto
    COSTE              POR /* POR = NUMERIC(15,4) */,  //Coste del producto
    CODIGOPROVEEDOR    T20 /* T20 = VARCHAR(20) */,  //Código del proveedor
    PV1                POR /* POR = NUMERIC(15,4) */,  //Precio de venta tarifa 1
    PV2                POR /* POR = NUMERIC(15,4) */,  //Precio de venta tarifa 2
    PV3                POR /* POR = NUMERIC(15,4) */,  //Precio de venta tarifa 3
    PV4                POR /* POR = NUMERIC(15,4) */,  //Precio de venta tarifa 4
    PV5                POR /* POR = NUMERIC(15,4) */,  //Precio de venta tarifa 5
    DTO1              POR /* POR = NUMERIC(15,4) */,  //Descuento de venta tarifa 1
    DTO2              POR /* POR = NUMERIC(15,4) */,  //Descuento de venta tarifa 2
    DTO3              POR /* POR = NUMERIC(15,4) */,  //Descuento de venta tarifa 3
    DTO4              POR /* POR = NUMERIC(15,4) */,  //Descuento de venta tarifa 4
    DTO5              POR /* POR = NUMERIC(15,4) */,  //Descuento de venta tarifa 5
    FAMILIA            T20 /* T20 = VARCHAR(20) */,  //Familia del artículo 
    CODIGOBARRAS39    T20 /* T20 = VARCHAR(20) */,  //Código de barras libre
    CODIGOBARRASEAN13  T20 /* T20 = VARCHAR(20) */,  //Códigos de barra estándar Ean 13
    PESO              POR /* POR = NUMERIC(15,4) */,  //Peso del formato del producto
    PROPIO            LOG /* LOG = CHAR(1) */,  //Si es un artículo de fabricación propia
    TRAZABILIDAD      LOG /* LOG = CHAR(1) */,  //Si lleva trazabilidad
    SERVICIO          LOG /* LOG = CHAR(1) */,  //Si es un servicio
    CADUCO            LOG /* LOG = CHAR(1) */,  //Si el artículo es caduco (se lleva la caducidad con el lote
    TIPOIMPUESTO      INTEGER,  //Tipo de aimpuesto aplicable (va con el nombre del impuesto en configuración)
    COMISIONMAXIMA    POR /* POR = NUMERIC(15,4) */,  //Comisión máxima a pagar en este artículo, prevalece sobre la comisión en el agente
    DTOMAXIMO          POR /* POR = NUMERIC(15,4) */,  //Descuento máximo del artículo (prevalece sobre los descuentos en clientes o aplicados en DTO1...DTO5)
    RAPEL1            INTEGER,  //Rapel de ventas en tarifa 1
    RAPEL2            INTEGER,  //Rapel de ventas en tarifa 2
    RAPEL3            INTEGER,  //Rapel de ventas en tarifa 3
    RAPEL4            INTEGER,  //Rapel de ventas en tarifa 4
    RAPEL5            INTEGER,  //Rapel de ventas en tarifa 5
    ADR                VARCHAR(150) CHARACTER SET NONE,  //Descripción de la frase de adr
    ADREXEPCION        INTEGER,  // formatos que estan exentos del adr según el propio ADR
    ADRLIMITE          INTEGER  //Limite de mercancía a transportar por un conductor y vehículo sin el carnet y permiso de mercancías peligrosas
);


Rapel: Los clientes que se les hace descuento por rapel, deben hacerles albaranes, unificando a la hora de facturar, la mercancía por código, de manera que si el total de unidades vendidas es igual o superior al rapel de su tarifa se aplica el precio de esta tarifa, en caso contrario se aplica el PVP normal.

Escala de Rapel: Es cuando el cliente parte de un precio normal  y según sus ventas finales a la hora de facturar se aplica la tarifa según el rapel alcanzado (no lo he usado nunca y nunca me lo han pedido)


Ahora la tabla NOTAS

CREATE TABLE NOTAS (
    ID            INTEGER NOT NULL,
    NOMBREMODULO  T20 /* T20 = VARCHAR(20) */,  //Nombre del módulo
    CODIGO        T20 /* T20 = VARCHAR(20) */,  //Código del módulo al que pertenece
    DESCRIPCION  T20 /* T20 = VARCHAR(20) */,  //Descripción dentro del modulo, (Avisos, Notas, Alertas,etc.)
    NOTAS        MEMO /* MEMO = BLOB SUB_TYPE 1 SEGMENT SIZE 80 */  //Campo memo para notas
);


Y por último  La tabla imágenes

CREATE TABLE IMAGENES (
    ID            INTEGER NOT NULL,
    NOMBREMODULO  T20 /* T20 = VARCHAR(20) */,  //Nombre del módulo
    CODIGO        T20 /* T20 = VARCHAR(20) */,  //Código del módulo al que pertenece
    DESCRIPCION  T20 /* T20 = VARCHAR(20) */,  //Descripción dentro del modulo, (Foto, interior, exterior, detalle, etc.)
    IMAGENES      IMG /* IMG = BLOB SUB_TYPE 0 SEGMENT SIZE 80 */  //Imagen a  mostrar
);


  • 0

#4 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 07 junio 2013 - 09:46

Me gustaría saber si esta quedando claro lo que llevo explicado, o tengo que ser más claro.
  • 0

#5 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 07 junio 2013 - 04:06

Hola compañero antes de seguir considero oportuno poner algunas imágenes del programa de facturación que hice para mi antigua empresa.

Primero veréis que hay datos tachados, por que lo que os muestro son con información real y hay que respetar la protección de datos, así que pido disculpas, aun así creo que queda bastante claro

Para empezar una imagen del tema de los lotes

Imagen Enviada

Como podéis ver marco en rojo el lote del producto que buscamos, en verde sería el maestro (en este caso es el mismo que hemos introducido) y en naranja el lote derivado que vemos que es el 120402, se puede dar el caso que el lote 120401, tenga el derivado que tenga, pero también tenga un maestro que pueda ser por ejemplo el 120399.

Ya que hablo de mi antiguo programa, que por cierto este que empiezo nuevo es por hacerlo más sencillo y eficaz, os pongo una imagen de un proceso que más abajo os explico.

[img width=500 height=600]http://nsae01.casimages.net/img/2013/06/08/130608120642801849.jpg[/img]

como podéis ver se trata de la edición de Facturas, con datos reales, os pongo imagen del menú, del visor de documentos (presupuestos, pedidos, albaranes y facturas), del editor de documentos y por último el editor de artículos, que contiene aparte de la información habitual, contiene lotes disponible (La única condición será que 1º el stock disponibles sea igual o superior a  1 y 2º que la fecha de caducidad sea inferior a la actual), por supuesto esto lo veis en el apartado llamado lotes y vencimientos, después del Stringrid hay una última linea que nos permite introducir un lote de forma manual (Se da en más de una ocasión, de que aun no hemos dado la entrada de la mercancía y tengamos que facturarla))
Por otro lado en el apartado precios veréis  algo que es muy poco común, por un lado 5 tarifas de precios (esto es normal) y por otro precio especial del cliente, esto si os dais cuenta no esta en la estructura ni de clientes, ni en la de artículos, si no que esta en una tabla independiente y para que se muestre debe darse las siguientes condiciones el código del cliente y el del artículo, pero ya lo veremos mucho más adelante.

Por cierto algo que es muy posible que en breve sea obligatorio en la facturación y demás documentos de ventas, es que deben tener el peso por artículos, el total de la factura y una hoja de ruta detallando la factura, peso total de la misma y peso total de mercancía transportada. Pero aún no es obligatorio.
  • 0

#6 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 08 junio 2013 - 03:03

Cambios a realizar en la unidad UBAncos de Bancos

debe quedar de la siguiente manera:
[DELPHI]procedure TFBancos.DSPrincipalDataChange(Sender: TObject; Field: TField);
//------------------------------------------------------------------------------
//******************************************************[ Datasorce change ]****
//------------------------------------------------------------------------------
begin
  if (not (DsPrincipal.DataSet.State in [dsEdit,dsInsert])) and (FBancos.Active) then
  begin
    Label12.Caption :=ceros(DBEdit5.Text,4)+'/'+ ceros(DBEdit6.Text,4)+'/'+ceros(DBEdit7.Text,2)+'/'+ceros(DBEdit8.Text,10);
  end;
end;[/DELPHI]

y

[DELPHI]procedure TFBancos.DBEdit5Change(Sender: TObject);
//------------------------------------------------------------------------------
//********************************************************[ Change Dbedit5 ]****
// Comprueba el digíto de control
//------------------------------------------------------------------------------
begin
  TDBEdit(Sender).Text:=EditLogico(tedit(TDBEdit(Sender)), '0123456789');
  if (DBEdit5.Text<>'') and (DBEdit6.Text<>'') and (DBEdit8.Text<>'') and (FBancos.Active) then
  begin
    DBEdit7.Field.Value:=StrToInt( IntToStr(CalculaDC(ceros(DBEdit5.Text,4)+ ceros(DBEdit6.Text,4),ceros(DBEdit8.Text,10))));
  end;
  Label12.Caption :=ceros(DBEdit5.Text,4)+'/'+ ceros(DBEdit6.Text,4)+'/'+ceros(DBEdit7.Text,2)+'/'+ceros(DBEdit8.Text,10);
  if (Length(DBEdit5.Text)>=4) and (Sender=DBEdit5) then DBEdit6.SetFocus;
  if (Length(DBEdit6.Text)>=4) and (Sender=DBEdit6) then DBEdit8.SetFocus;
end;[/DELPHI]

Como podéis comprobar me faltaba en ambos casos  and (FBancos.Active) para evitar que cargue datos sin estar activo
  • 0

#7 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 09 junio 2013 - 07:16

Se que puede parecer un tostón este hilo, pero estamos hablando de miles de lineas y conceptos que no se pueden dejar de lados, aparte de eso, como creo que nos pasa a todos, vamos mejorando métodos y el código, o corrigiendo errores según vamos avanzando, así que no me queda otro remedio sino ir poniendo los diferentes cambios

Vamos ahora con artículos

Como siempre la imagen

Imagen Enviada

Como podéis ver no pongo la pestaña facturado, ya que aún no tenemos preparado la facturación y como en todos el código que llevo puesto, no pondré el código de impresión, por que al tener múltiples operadores a la hora de imprimir, que cada uno use y diseñe el que le gusta.

El código https://gist.github....onymous/5743472

Funciones usada de mi archivo fun_dbgrid.pas

[DELPHI]
function GridImagen(Grid:TDBGrid; Campo:TField; Rect:TRect; Column:TColumn; State:TGridDrawState):Boolean;
begin
  if Column.Field = Campo then
  begin
    if not (gdSelected in State) then // se não for a célula selecionada
      Grid.Canvas.FillRect(Rect); // limpa a célula
    with TPicture.Create do
    begin
      Assign(Campo);
      Grid.Canvas.StretchDraw(Rect,Bitmap); // desenha imagem
      Free;
    end;
    Result:=True;
  end else  Result:=False;
end;


function MemoGridB(Grid:TDBGrid; Campo:TField; Rect:TRect; Column:TColumn; State:TGridDrawState):Boolean;
var FixRect:TRect;
begin
  fixRect:=Rect; // declara uma variável local fixRect : TRect
  Dec(fixRect.Bottom,2);
  if Column.Field=Campo then
  begin
    if not (gdSelected in State) then
      Grid.Canvas.FillRect(Rect);
    DrawText(Grid.Canvas.Handle,pchar(Campo.AsString), length(campo.AsString),fixRect,DT_WORDBREAK);
    Result:=True;
  end else  Result:=False;
end;

[/DELPHI]
  • 0

#8 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 09 junio 2013 - 07:21

Ahora le toca al apartado de notas

Imagen Enviada

tengo un pequeño error en este módulo que aún no he encontrado, que es que no muestra las imágenes de los botones y no se si tendré que rehacerlo, pero la ida esta hay y los botones son los de siempre y el código no varia.

el código https://gist.github....onymous/5743504

y de este apartado nada más
  • 0

#9 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 09 junio 2013 - 07:33

Ahora a las imágenes

Imagen Enviada

el código https://gist.github....onymous/5743525

Aquí si hay un cambio importante en el botón de cargar imagen, yo ya he hecho el cambio en el resto de los módulos, el código queda de la siguiente manera

[DELPHI]procedure TFImagenes.SpeedButtonBC1Click(Sender: TObject);
//------------------------------------------------------------------------------
//*********************************************************[ Cargar imagen ]****
//------------------------------------------------------------------------------
begin
CargaIimagenADBImagen(OpenPictureDialog1,DBImage1);
end;[/DELPHI]

y la función es
[DELPHI]//------------------------------------------------------------------------------
//*************************************************[ CargaIimagenADBImagen ]****
//  Parte de la idea original de  ??? 09/06/2013
// bajada de http://www.planetade...a-um-campo-blob
//------------------------------------------------------------------------------
// Pequeñas modificaciones y convertido a unción por mi permitiendo cargar varios
// tipos de imágenes diferentes
//------------------------------------------------------------------------------
//  [Dialog]  TOpenPictureDialog  Dialogo de cargad de la imagen
//  [Dbimage] TDBImage   El nº de cuenta de 10 digitos usar la funcion ceros
//------------------------------------------------------------------------------
//---EJEMPLO--------------------------------------------------------------------
//  CargaIimagenADBImagen:(OpenPictureDialog1,Dbimage1);
//------------------------------------------------------------------------------

function CargaIimagenADBImagen(Dialog:TOpenPictureDialog;Dbimage:TDBImage):Boolean;
var imagem : TPicture;
begin
  if Dialog.Execute then
  begin
    try
      imagem:=TPicture.Create;
      imagem.LoadFromFile(Dialog.FileName);
      Clipboard.Assign(imagem);
      Dbimage.PasteFromClipboard;
      imagem.Free;
      Result:=True;
    except on E: Exception do
      Result:=False;
    end;
  end;
end;[/DELPHI]

También se realizaron cambios en mi módulo de datos (DM.pas) el código añadido es el siguiente

[DELPHI]

uses Fun;

....

procedure TDM.DataModuleDestroy(Sender: TObject);
//------------------------------------------------------------------------------
//*********************************************************[ Al destruirlo ]****
// Nos aseguramos de que no se nos queden Querys abiertos    //Añadir el archivo Fun.Pas
//------------------------------------------------------------------------------
begin
  QuerryOC(IBQIMAGENES);
  QuerryOC(IBQNOTAS);
end;[/DELPHI]

y una imagen de como va quedando

[img width=800 height=421]http://nsae01.casimages.net/img/2013/06/09/130609033219499667.jpg[/img]


Como ya comente, el código y uno va evolucionando, así que seguirá habiendo cambios.

De momento que tal os va pareciendo, es muy pesado, esta claro?, es que como hay tan pocos comentarios, no se si estoy aburriendo al personal.
  • 0

#10 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 09 junio 2013 - 08:33

Amigo Desart, primero que todo debo agradecer tu capacidad de compromiso y tu deseo de compartir tu trabajo, todos sabemos la enorme cantidad de tiempo y esfuerzo que un proyecto de este tipo demanda.
A pesar de que por cuestiones de tiempo no puedo mirar en detalle tu trabajo, por el poco código que veo en los post de este hilo, me permito hacerte una respetuosa sugerencia: Utiliza algún tipo de nomenclatura (cualquiera que sea un poco más legible)  para tus controles, métodos y clases, esto te lo digo porque después será casi imposible hacer mantenimiento a la aplicación. Por ejemplo si el DBEdit1 va a almacenar el valor del campo Apellidos entonces ponle el nombre  dbeApellidos, o si el procedimiento DBEdit5Change lo que hace es validar algo entonces llámalo "procedure ValidarAlgo" y le agregas un comentario que dicho procedimiento se dispara al cambiar tal o cual control; puedes usar el estilo de nomenclatura que más te guste y sin duda tu código se hará mucho mas legible.

Un cordial saludo, y una vez más, muchas gracias por compartir tu trabajo.
  • 0

#11 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 10 junio 2013 - 02:11

Gracias Wilson intentare tenerlo en cuenta en los siguientes Forms
  • 0

#12 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 10 junio 2013 - 02:12

Antes de seguir comentaros que el tema de la Ley de Protección de Datos obliga a que nuestro programa tenga acceso con claves y nuestra base de datos también, en este caso  estoy usando Firebird y para esta demo no lo haré, pero ademas uso unas funciones y encripto los nombres y documentos (NIF, DNI) dentro de la base de datos, desencriptandolas en los formas, ya que nos encargamos que al form sólo se accede si se tiene el nivel necesario.

Vamos con la estructura de las siguientes 6 tablas

Proveedores

CREATE TABLE PROVEEDORES (
    ID        INTEGER NOT NULL,
    CODIGO    T20 /* T20 = VARCHAR(20) */,  //Código del proveedor
    EMPRESA    T80 /* T80 = VARCHAR(80) */,  //Nombre de la empresa
    LIBRE      T80 /* T80 = VARCHAR(80) */,  //Campo libre sin uso inicialmente
    CIF        T20 /* T20 = VARCHAR(20) */,  //Número del CIF o documento identificativo
    FECHAALTA  DATE,  //Fecha de alta
    FORMAPAGO  T40 /* T40 = VARCHAR(40) */,  //Forma de pago
    DIASPAGO  T20 /* T20 = VARCHAR(20) */  //Los días de pago
);


Empleados incluye a los agentes

CREATE TABLE EMPLEADOS (
    ID                    INTEGER NOT NULL,
    CODIGO                T20 /* T20 = VARCHAR(20) */,  /Código del empleado
    AGENTE                LOG /* LOG = CHAR(1) */,  //Es un agente/comercial
    MEDIACOMISION          NUMERIC(15,2),  /Media de su comisión, se puede poner la más alta y el programa regulara sobre la comisión por producto
    FECHAALTA              DATE,  //Fecha de alta
    FECHABAJA              DATE,  //Fecha de su baja (Los datos de los empleados en ciertos sectores no se pueden borrar nunca, como en todas las empresas del sector químico
    NUMEROSEGURIDADSOCIAL  T40 /* T40 = VARCHAR(40) */,  //Número de la seguridad social
    NUMERODOCUMENTO        T40 /* T40 = VARCHAR(40) */,  //Número de documento identificativo, Nif, Dni, pasaporte, etc
    COMISIONDTO1          NUMERIC(15,2),  //Descuento a aplicar en la comisión si se aplica el Dto 1
    COMISIONDTORAPEL2      NUMERIC(15,2),  //Descuento a aplicar en la comisión si se aplica el Dto o rapel 2
    COMISIONDTORAPEL3      NUMERIC(15,2),  //Descuento a aplicar en la comisión si se aplica el Dto o rapel 2
    COMISIONDTORAPEL4      NUMERIC(15,2),  //Descuento a aplicar en la comisión si se aplica el Dto o rapel 3
    COMISIONDTORAPEL5      NUMERIC(15,2),  //Descuento a aplicar en la comisión si se aplica el Dto o rapel 5
    PUESTO                T20 /* T20 = VARCHAR(20) */,  //Puesto que ocupa dentro de la empresa
    NOMBRE                T80 /* T80 = VARCHAR(80) */,  //Nombre de la persona
    SALARIO                NUMERIC(15,2)//  //Sueldo de la persona (este campo sólo lo dejaremos ver a los empleados de mayor nivel
);


Como podéis ver se aplica un descuento en las comisiones según el rapel o descuento que aplicamos entre el 2 y el 5 (rapel), pero no en el 1 ya que es el precio base, este descuento de la comisión se aplica si el descuento dentro del producto es diferente de 0, ó si se ha aplicado el rapel.

Fabricables

CREATE TABLE FABRICABLES (
    ID        INTEGER NOT NULL,
    CODIGO    T20 /* T20 = VARCHAR(20) */,  //Código del fabricable
    PRODUCTO  T80 /* T80 = VARCHAR(80) */  //Nombre base del producto a fabricar
);


Formas de pago

CREATE TABLE FPAGOS (
    ID                INTEGER NOT NULL,
    CODIGO            T20 /* T20 = VARCHAR(20) */,  //Código de la forma de pago (este campo es único)
    FORMAPAGO        T40 /* T40 = VARCHAR(40) */,  //Formas de pago a establecer
    DIASPRESENTACION  T20 /* T20 = VARCHAR(20) */,  //Días de presentación
    DIASCOBRO        T20 /* T20 = VARCHAR(20) */,  //Dias de cobros
    NUMERODEPAGOS    INTEGER// Si tiene pago aplazado el numero de plazos
);


Pagos plazos

CREATE TABLE PAGOSPLAZOS (
    ID                INTEGER NOT NULL,
    CODIGOFORMADEPAGO  T20 /* T20 = VARCHAR(20) */,  //Código de forma de pago a la que esta unida
    NUMERODEDIAS      INTEGER, //Número de días desde la emisión de la factura, dejar en blanco si no se quiere especificar
    PORCENTAJEPAGO    NUMERIC(15,2)  //Porcentaje del total de la factura a  cobrar en este plazo
);


Bueno en primer lugar decir que estas son las primeras tabla que están enlazada ( FPAGOS es el maestro y PAGOSPLAZOS el detalle), después sobre la tabla PAGOSPLAZOS
deciros que mi modo de uso es el siguiente pongo dos ejemplos

1º) Cliente pago a 30(40%),60(30%),90(30%) días factura 1000, fecha 30/06/2013 y días de pago del 20 al 25, quedarían los pagos de  la siguiente manera

25/07/2013..Importe 400.00 euros  [Pago lógico 30/07/2013] (como podemos ver no llega a los 30 días, pero hemos cogido el dato de sus fechas de pago, en caso contrario se iría a casi dos meses)
25/08/2013..Importe 300.00 euros [Pago lógico 29/08/2013]
25/09/2013..Importe 300.00 euros [Pago lógico 28/09/2013]

2º) Cliente paga a 50% y 50%, factura de 1000 euros, fecha 30/06/2013 y días de pago del 20 al 25, lo pagos serían
25/ (mes a designar entre el cliente y la empresa)/2013..Importe 500.00 euros
25/ (mes a designar entre el cliente y la empresa)/2013..Importe 500.00 euros
Al no poner el número de días sólo tenemos en cuenta el día de pago y no el número de días a transcurrir para cada uno de los plazos.

La tabla Lotes

CREATE TABLE LOTES (
    ID                        INTEGER NOT NULL,
    CODIGOPRODUCTOFABRICABLE  T20 /* T20 = VARCHAR(20) */,  //Código del producto Fabricable
    CODIGOEMPLEADO            T20 /* T20 = VARCHAR(20) */,  //Código del empleado responsable
    FECHA                    DATE,  //Fecha en que se fabrico
    LOTE                      T20 /* T20 = VARCHAR(20) */,  //Lote asignado
    CADUCIDAD                DATE,  //Si es caduco su fecha de caducidad
    CANTIDAD                  NUMERIC(15,2),  //Cantidad total fabricada (litros, kilos unidades)
    ACTIVO                    LOG /* LOG = CHAR(1) */  //Si el producto esta activo
);


Sobre el campo ACTIVO, lo usamos para saber si es un lote que se puede vender (S) o no se puede vender (N), por que sea para trasformación, o sea un lote retirado del mercado.

Aunque nadie me ha preguntado, si os dais cuenta, en mi tabla artículos, no he puesto campos para tallas, colores, tamaños o si esta dividido en partes, si lo necesitáis sabéis que son campos que tienen que usarse con tablas auxiliares. yo en esta demo no las voy a poner, pero no esta demás comentarlo.
  • 0

#13 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 10 junio 2013 - 06:10

Módulo de productos fabricables

Imagen Enviada

Aquí el código  https://gist.github....onymous/5748411
  • 0

#14 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.940 mensajes
  • LocationMéxico

Escrito 10 junio 2013 - 08:00

Este tutorial va para Facebook, como no :p je.
  • 0

#15 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 19 junio 2013 - 01:22

Cambios importantes en los módulos auxiliares (Notas, Imágenes, Direcciones, Bancos, Contactos, Personas de contacto)

1º) se ha añadido un IBQuerry y su datasource el ModuleData (UDM en mi caso), para facilitar los datos a todos los modulos que lo llaman,, eliminando parte del código de control en cada uno de estos, el aspecto actual de mi UDM es el siguiente

Imagen Enviada

Los cambios en su código son los siguientes:

[DELPHI]
procedure TDM.conectar;
//------------------------------------------------------------------------------
//**************************************************************[ Conectar ]****
//Nos permite conectar las tablas, querrys + IBDatabase + IBTransaction
//------------------------------------------------------------------------------
begin
  IBDatabase1.Connected:=True;  //La base de datos
  IBTransaction1.Active:=True;  //Las Tansacciones
  IBDCLIEN.Active:=True;        //La tabla Clientes
  IBDirecciones.Active:=True;  //La tabla Direcciones
  IBDPC.Active:=True; //La tabla Personas de Contacto
  IBDContacto.Active:=True;    //La Tabla de datos de contacto
  IBDBcos.Active:=True; //La tabla de Bancos
  IBDCONFI.Active:=True;        //La tabla de Configuración
  IBDUSUA.Active:=True;        //La tabla de usuarios (permisos de acceso)
  IBDNOTAS.Active:=True;        //La tabla de notas
  IBDIMAGENES.Active:=True;    //La tabla de Imagenes
  IBDPROVEEDORES.Active:=True;  //La tabla de Proveedores
  IBDLOTES.Active:=True;        //La tabla de Lotes
  IBDARTICULOS.Active:=True;    //La tabla de Artículos
  IBDFAMILIAS.Active:=True;    //La tabla de Familias
  IBDFABRICABLES.Active:=True;  //La tabla de Fabricables
  IBDSTOCK.Active:=True;        //La tabla de Stock
end;


procedure TDM.DataModuleDestroy(Sender: TObject);
//------------------------------------------------------------------------------
//*********************************************************[ Al destruirlo ]****
// Nos aseguramos de que no se nos queden Querys abiertos    //Añadir el archivo Fun.Pas
//------------------------------------------------------------------------------
begin
  QuerryOC(IBQIMAGENES);
  QuerryOC(IBQNOTAS);
  QuerryOC(IBQDirecciones);
  QuerryOC(IBQPersonasContacto);
  QuerryOC(IBQContactos);
  QuerryOC(IBQBancos);
end;[/code]


2º) en el FormClose de cada módulo auxiliar ponemos el siguiente código





//////////He editado nuevamente este post cambiando lo que había puesto por lo siguiente y explico lo que he eliminado///////////

[DELPHI]

//Cambiar donde aparece XXX por lo que proceda (Nombre del MODULO, de la Tabla, de el IBDataSet, del IBQuerry, del módulo de llamada o del SpeedButtonBC)

procedure TFNotas.FXXXClose(Sender: TObject; var Action: TCloseAction);
//------------------------------------------------------------------------------
//*************************************************[ Al Cerrarse El Form ]******
// Cerramos todos los procesos para que no consuman memoria y posibles errores
//------------------------------------------------------------------------------
begin
  if Timer1.Enabled=true then  Timer1.Enabled:=False;
  ActIbdataset(DM.IBDXXX,'select * from XXX');
  //Retornos al modulo de llamada
  if VarSNomMod='XXX' then FArticulos.SpeedButtonBCXXXClick(sender);
end;[/code]

he eliminado el siguiente código

[DELPHI]
  if DM.IBQXXX.Active then  //Nos aseguramos de refrescar los datos del querry, con los nuevos introducidos si los ha habido
  begin  //No uso refresh, ya que muchas veces no funciona y de esta manera es más efectivo el refresco de datos
      DM.IBQXXX.Active:=False;
      DM.IBQXXX.Active:=True;
  end;
[/code]

, al ya esta controlado en la lineas

[DELPHI]
if VarSNomMod='XXX' then FArticulos.SpeedButtonBCXXXClick(sender);
[/code]

Que no había actualizado, con lo que el código anterior era redundante.
  • 0

#16 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 19 junio 2013 - 05:32

Saludos.

Una pequeña sugerencia, en vez de utilizar Active para los descendientes del TDataSet usa mejor los métodos Open y Close.  Que al final hacen la misma asignación que estas realizando, pero a mi modo de ver es más legible con los métodos.
  • 0

#17 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 19 junio 2013 - 12:07

Muchas Gracias  Rolphy Reyes, lo tendré muy en cuenta, ya es costumbre usar el active, pero espero recordar, como dices el Open/Close
  • 0

#18 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 19 junio 2013 - 12:21

Ahora le toca al modulo de proveedores

LA imagen

Imagen Enviada

he marcado algún olvido y lo que hacen algunos botones, ahora las pestañas

0º)  Es la de los datos, vemos que realmente en la tabla proveedores tenemos que introducir pocos datos, pero que el conjunto de datos con las auxiliares la completa bastante

1º) Contactos.  Recordar que esta tabla sera luego nuestra agenda, permitiendo, separarlo, por Clientes, proveedores, etc, ademas de todos, buscar por el nombre/empresa/etc y ponderemos un indice que nos permitirá ver clasificado por su inicio.

2º) Notas, como podemos ver en este caso tenemos dos notas y las hemos clasificado (campo descripción) como avisos y recordatorio, pero podríamos tener muchos más solo para este proveedor, aquí es donde se ve la potencia de este modo de programar, que aunque un poco más lioso nos da mucha más potencia.

3º) Las Imágenes, Como podemos ver también hemos puesto 2  la del logo y productos.

4º) Personas de contactos, , al tenerla en una tabla auxiliar, nos permite tener multitud de personas de contacto dentro del mismo registro

5º) Direcciones, al igual que la anterior tabla podríamos tener multitud de direcciones (Almacenes, oficinas, tiendas, etc).

6º) Bancos, sería más correcto decir cuentas, pero un cliente/proveedor/etc, puede trabajar con más de un banco o más de una cuenta corriente.

7º) Aquí ira nuestro modulo de compras a este proveedor, que aún no desarrollaremos.


No voy a entrar en algo que ya se ha hablado ampliamente en los foros, sobre las notas y las imágenes si guardarlas dentro de las tablas o sólo guardar su referencia  en la tabla y guardarla físicamente en archivos en el disco duro.

También quiero explicar que poner en las pestañas los campos nombre del módulo y código de las tablas auxiliares, es para que quede más claro en el tutorial, normalmente, serían campos no visibles.

y el código podéis bajarlo de  https://gist.github....onymous/5812746
  • 0

#19 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 19 junio 2013 - 12:25

El módulo de Formas de pago

Imagen Enviada

En este módulo hay cosas que cambian, al tratarse de usar una tabla maestro y otra detalle, como podemos ver tenemos 2 panales con botonera y debemos controlar ambas y  aunque en la imagen no se ve tenemos un sólo juego de botenes de confirmación y cancelación, para que quede más claro hay que estudiar el código

podemos ver que hemos hecho la relación maestro detalle en el módulo UDM

Imagen Enviada


Aquí el código  https://gist.github....onymous/5812904
  • 0

#20 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 19 junio 2013 - 12:30

Y por último en el día de hoy el modulo de búsqueda.

Imagen Enviada

como podemos ver un módulo sencillo de tan sólo 160 lineas actualmente, que ira creciendo según avancemos el proyecto, sólo tendremos que añadir el control de los módulos de llamada y su retorno, ya que este módulo sera llamado por varios módulos.

No usamos la función de coloración del grid, ya que al ser este variable, en número de campos nos daría un error, más adelante lo modificare y añadiré el código, para que se ajuste al resto del diseño.

El código aquí  https://gist.github....onymous/5812974
  • 0