Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Tutorial vídeo club (https://www.clubdelphi.com/foros/showthread.php?t=87705)

José Luis Garcí 14-02-2015 10:17:22

Tutorial vídeo club
 
Visto que la encuesta va ganando por 15 a 1 los si, he decidido empezar este nuevo tutorial de como crear un vídeo club.

Lo haré introduciendo partes 1 ó 2 veces a la semana, cuando me sea posible incluso más. La herramientas que usare son:

La biblioteca de iconos: Cristal clear
Para crear las tablas y la base de datos: Ibexpert P.E. (Edición personal)
El motor de base de datos: Firebird 2.5
El Delphi 2010 y sus componentes estándar
Para los informes: El Report manager
Y para los diagramas que presento el Diagram desing

Salvo el delphi el resto o son gratuitos o son para uso personal

Intentaré que sea sencillo de entender, corregidme si no es así y para todos los niveles, pero no explicaré como hacer la base de datos, ya que hay un muy buen tutorial en el club que lo explica.

¿Por qué sobre un vídeo club? Sencillo, es un tipo de negocio en decadencia, además fue mi primer gran proyecto en clipper y tiene conceptos que podremos extrapolar a otros programas.

¿Qué no encontraremos? por ejemplo tablas maestro detalle como tales

¿Qué si encontraremos? El uso de varios sistemas y el aprovechamiento por lo menos en parte de nuevas tecnologías

Algo de historia

El vídeo club nació con las primeras películas en vídeo beta, sistema 2000 y Vhs, siendo el franco ganador este último sistema a pesar de no ser el más eficiente ni el de mejor calidad, ya que el beta tenía mejor revolución y el sistema 2000 era el más avanzado de todos ellos.
Los tiempos fueron avanzando y vino el dvd y el Blue-Ray, pero también los juegos de múltiples consolas que también se fueron añadiendo a productos alquilables y por lo tanto pertenecientes a los vídeo clubs.
En los últimos años estos han decaído como muchas otras cosas, en parte por los canales satélites y derivados y en parte por la crisis. Pero aun subsisten algunos teniendo que adaptarse a los tiempos, por lo que tienen salas para llamadas, fotocopiadoras, fax, golosinas, vaporizadores y un largo etc. de productos y servicios

Nosotros nos vamos a quedar en la parte media, no dedicándonos a otra cosa que el alquiler y la venta de nuestras películas y juegos, para este tutorial.

Programare como si se tratase de un sistema moderno tipo TPV, pero sin entrar en visores, impresoras de tickets y cajoneras, aunque dejándolo apunto para que os sea fácil añadírselo, si intentando implementar otros sistemas a nuestro programa.

Por último quiero pedir disculpas por algunas de mis faltas de ortografía que seguro las habrá, pero con 46 años me han detectado que tengo una epilepsia :p cada año descubro partes más jodidas de mi :eek:. Las he descubierto por que al escribir mis libros repetía una y mil veces los mismos fallos y tras hacerme un analisis y la doctora comprobar que sabía esas normas ortográficas y que también sabía como se escribían esas palabras casi el 90% de las veces lo hacía mal.

José Luis Garcí 14-02-2015 10:26:45

La tabla CONFIGURACION
 


Es la tabla que mantendrá los datos de nuestro Vídeo Club, como podéis ver llevara una serie de numeradores para nuestro sistema, usando en este caso numeradores simples, sin otro tipo de caracteres, por lo que he optado por tipo integer, ya que usaremos sistemas de búsqueda por SQL.

Además he añadido en esta tabla el poder poner un día en el que hagamos ofertas tipo integer también siendo mi idea que el 1 sea lunes al 7 que sea domingo.
También usaremos un sistema de colores para saber si la unidad esta disponible, alquilada o bloqueada por otro motivo.
Cómo el tema del impuesto es otro añadido que cambia según la zona o el país, no uso uno especifico pidiendo el nombre y el porcentaje a aplicar. Por cierto nuestros precios finales ya tienen el impuesto incluido, dato a tener en cuenta, ya que no aparecerá como tal.
Por último como trabajamos con datos tendremos nivel de acceso y por lo tanto la Ley de protección de datos, poniendo un campo memo con el texto que aparecerá en nuestros documento y emails.

José Luis Garcí 14-02-2015 10:42:30

Tabla UNIDADES
 


Como ya hemos comentado en los vídeo clubs ya no se se alquila sólo películas, por lo que nuestra base que contenga los datos se llamará UNIDADES, en esta tabla me extenderé en algunos campos explicándolos un poco más.

ALQUILADA_VECES: nos indicará el número de veces que la unidad ha sido alquilada, podríamos sacarlo mediante SQL, pero hay ciertos datos que prefiero tratar así directamente

VALOR_ALQUILER: Es el código de una tabla con el mismo titulo, en ella estableceremos varios datos que estimaran su precio y demás, ya lo veremos más adelante

FORMATO: Se refiere al formato físico, pero también al formato de soporte Ejemplos: DVD, BLue-Ray, JUEGO PS3, etc.

GENERO: al genero de película o juego del que trata esta unidad

FECHA_ALTA y FECHA_BAJA: Día en que damos de alta a la unidad y en la que le damos de baja, pero esta última se puede cambiar, ya veremos por qué un poco más abajo

COSTE y REDIMIENTO: El primero es cuanto nos ha costado la unidad, el segundo es un campo que incrementará cada vez que la unidad se alquile o cuando se venda

DISPONIBLE: La unidad esta disponible para su alquiler o venta haremos que admita S o N simplemente

VENDIDA: LA unidad ha sido vendida, por lo que no aparecerá en nuestras búsquedas para alquilar y cambiara el disponible a N y la fecha de la baja será la de la venta, no dejándola cambiar

PERDIDA: La unidad no se encuentra, este es nuestro campo, al igual que vendida nos rellena los campos disponible y fecha de baja, pero al recuperarla, podremos seguir usándola nuevamente, por esto la fecha de baja no es fija, salvo que este vendida

NOTAS: este es un campo de incidencia sobre la unidad, por si un cliente se queja de un problema y seguimos adelante con el alquiler y otros expresasen el mismo problema, poder tener un registro del mismo

José Luis Garcí 14-02-2015 10:44:35

Tabla CLIENTES
 


Bueno de esta tabla poco que decir salvo en los campos

A_CUENTA:Si el cliente ha entregado una cantidad por adelantado
PENDIENTE:Si el cliente debe dinero a nuestro vídeo club

José Luis Garcí 14-02-2015 10:50:07

Tabla USUARIO
 


Será la tabla que controle a nuestros empleados, como podéis ver la he reducido bastante, para que sea más manejable el tutorial, pudiendo añadir muchos más campos

NIVEL:Será el nivel de nuestro usuario, según este podrá obtener más datos en ciertas pantallas (Por ejemplo el coste y el rendimiento en la unidades) o acceder a ciertos apartados del programa estándole vetados el resto

CLAVE:Será la clave que elija nuestro usuario, apareciendo codificado en el programa, para lo que usaremos una función que se encargara de administrar el sistema

José Luis Garcí 14-02-2015 10:54:49

Tabla VALOR_ALQUILER
 


Esta es la tabla a la que hacíamos referencia en la tabla UNIDADES, comentaré algunos campos

DIAS: El número de días de alquiler, contando siempre desde la fecha del alquiler

PRECIO y PRECIO_OFERTA: es el precio del alquiler en días normales y los días de oferta según la tabla CONFIGURACION

PENALIZACION_DIA: Es la recarga que aplicaremos por cada día de retraso en devolver la unidad

José Luis Garcí 14-02-2015 10:58:18

Varias tablas
 


Son varias tablas auxiliares sin mucho que comentar sobre ellas, salvo de la última, ya que al tratarse de un sistema TPV podríamos pagar con tarjeta, por lo que lo lógico es que tengamos la imagen de estas para seleccionar, junto a otros muchos sistemas, desde efectivo, bonos, mixto, etc., haciéndolo más rápido de esta manera.

José Luis Garcí 14-02-2015 11:01:04

Tabla CAJA
 


Añadiremos un módulo de Caja y otro de movimientos (Pagos y cobros), el motivo de hacerlo por separado ya lo comentaré en la próxima entrada

José Luis Garcí 14-02-2015 11:04:46

Tabla MOVIMIENTOS
 


Como podéis ver esta es una tabla idéntica a la de caja o casi, pero la necesitamos independiente para el tema de recibos, facturas o tickets, teniendo en cuenta que el campo cantidad puede ir en positivo o negativo, según sea un cobro (la penalización de un cliente o el a cuenta del mismo, etc.) o pagos (Una remesa nueva de unidades, material auxiliar, etc.)

José Luis Garcí 14-02-2015 11:16:32

Tabla ALQUILER
 


La parte central del programa, es el alquiler y esta es nuestra tabla por lo que detallare sus campos principales

REGISTRO: es el registro de nuestro numerador, debemos tener en cuenta que si hay varios alquileres a la vez tendrán el mismo número de registro. Importante es especificar que digo a la vez y no al día ya que por una parte puede venir el marido y por el otro la mujer o hijos, dándole a cada uno un registro diferente

UNIDAD, CLIENTE, USUARIO: El el código de cada uno

DIA_ALQUILER:Es la fecha en que alquilamos

DIA_DEVOLUCION_PREVISTO: es para cuando estimamos la devolución, se que podríamos tomarlo del VALOR Alquiler usando SQL con esta tabla y la de unidades de la que ya conocemos el código, pero que pasa si hemos cambiado ese campo en VALOR_ALQUILER mientras la unidad estaba alquilada, no nos cuadraría por eso lo registramos

DIA_DEVOLUCION: El verdadero día en que se nos devuelve la unidad, fundamental para calcular la penalización

PAGADA: Nos dirá si este alquiler ya ha sido pagado

RECARGO: Si este alquiler ha generado recargo

VALOR_RECARGO_DIA: Lo registramos por el mismo motivo que DIA_DEVOLUCION_PREVISTO

Como podéis ver no hay un campo que ponga el valor del alquiler, se lo podríamos añadir, pero no lo veo imprescindible, ya que como veremos más adelante, el cliente tiene una serie de opciones y en caso de no pagarla se registra en su pendiente.

José Luis Garcí 14-02-2015 11:19:38

Con esto hemos terminado el apartado de Tablas, como veréis no he querido hacerlas muy liosas ni extensas, ya que se tratan de un tutorial, si veis que falta algo que consideréis imprescindible decidme lo o añadirlo vosotros mismos, aclarando el porque de su uso.

Por cierto la Base de datos había pensado en llamarla VIDEOCLUB.

Lo próximo es unos diagramas de algunos de los apartados del programa, para ir haciendo boca

José Luis Garcí 14-02-2015 11:28:28

Diagrama módulo unidades
 


Intento expresar según el siguiente diagrama el como veo que debería ir el funcionamiento del programa, como es lógico aunque esta puesto linealmente, esto no es real, ya que podemos saltar de un campo a otro.

Aspectos importantes son el genero y el formato, donde creo que no se deberían omitir el dato.

Al introducir la caratula podríamos optar por cargar una imagen, bajarla de internet o omitirla, alguien me dijo de escanearla, pero no se como hacerlo sin usar códigos de terceros, que es lo que quiero evitar en el tutorial, esquivando incluso los míos. Si se animan adelante :D.

Por último pedimos una cantidad de entrada, ya que podemos haber comprado varios DVD con el mismo título, al poner esta cantidad, el genera con los mismos datos el resto ahorrándonos el trabajo y asignándole a cada uno un código. Importante es que los grabará con los mismos datos a todos, por lo que si hemos comprado 3 Dvd y 3 Blue-Ray, tendremos que hacerlo por separado o más fácilmente editar 3 de las que se hayan generado.

José Luis Garcí 14-02-2015 11:34:31

Diagrama alquiler
 


Como veis aquí expreso mi idea de como sería el alquiler, no lo comentaré ya que lo haremos cuando estemos en dicho módulo. Si hay dudas sobre alguna de las partes comentarlo en este tema e intentaré responder a ello


Por último añado el esquema de entradas, lo mismo que en el anterior, no lo comentaré de momento.



Seguramente ya no publique más sobre el tutorial hasta la semana que viene, pero intentaré responder a vuestras dudas y atento a las sugerencias y aportes, por cierto por si alguien se lo pregunta, de momento todo es teoría, por lo que podría cambiar cuando comience a elaborar el programa.

ElKurgan 15-02-2015 12:39:13

Muchas gracias por tan gran aporte. Vaya trabajito te has impuesto, amigo

^\||/

José Luis Garcí 15-02-2015 18:20:00

Es lo que tiene el estar en el paro

Neftali [Germán.Estévez] 16-02-2015 11:05:51

^\||/^\||/^\||/^\||/

Ñuño Martínez 17-02-2015 11:51:34

Genialérrimo. ^\||/

Una preguntita: Al principio pones "Para crear las tablas y la base de datos: Ibexpert P.E. (Edición personal)". ¿La aplicación no va a crear la base de datos por sí misma si no existe? ¿O se creará en la instalación?

José Luis Garcí 17-02-2015 15:05:45

Cita:

Empezado por Ñuño Martínez (Mensaje 488889)
Genialérrimo. ^\||/

Una preguntita: Al principio pones "Para crear las tablas y la base de datos: Ibexpert P.E. (Edición personal)". ¿La aplicación no va a crear la base de datos por sí misma si no existe? ¿O se creará en la instalación?

Podría añadirse, pero creo que como tutorial deberíamos empezar con algo más sencillo, pero si alguien se anima, fabuloso, a mí personalmente no me gusta que se auto creen, por lo menos hasta haber dado por buena a la aplicación y la base de datos, ya que normalmente se te olvidan generar las modificaciones hechas después de la idea original.

hace años vi una aplicación free que creaba el código para generar la base de datos, todas sus tablas, con indices y demás, pero no recuerdo cual era, si alguien lo sabe que comparta :D o si alguién se atreve a desarrollarla :rolleyes:

José Luis Garcí 17-02-2015 15:06:52

Lo que si añadiré es al sistema que implanto a mis aplicaciones, para que la base de datos no se vincule a una ruta y si a donde este el ejecutable.

tuni 20-02-2015 21:00:40

Felicidades estas haciendo un gran trabajo y ayudando con él a muchos entre los que me incluyo.

Saludos

José Luis Garcí 21-02-2015 13:15:30

Cita:

Empezado por tuni (Mensaje 489067)
Felicidades estas haciendo un gran trabajo y ayudando con él a muchos entre los que me incluyo.

Saludos

Gracias Tuni ^\||/

José Luis Garcí 21-02-2015 13:30:37

Sigamos hoy con el tutorial, hoy montaremos nuestras tablas y explicare algunas cosas, luego veremos como será el diseño de nuestros forms

Primero especifico que la estoy montando en firebird 2.5, e usado el collate ES_ES_CI_AI y el Charset o juego de caracteres ISO8859_1 desde la creación de la base de datos para no tener problemas con el unicode luego.

En las tablas solo usaremos los indices primarios (Primary Keys) ya que el resto lo haremos por SQL y sólo he marcado como campos no nulos los que llevan estos indices.

Hay una tabla que no tiene indice, el motivo es que esta tabla sólo tendrá un registro y ni siquiera tendrá el botón para insertar nuevos registros, ni para navegar por ella, ya veremos como solucionamos esto más adelante, está es la tabla CONFIGURACION.

Solo he usado un dominio para los campos Char que aceptaran S o N únicamente

Código SQL [-]
CREATE DOMAIN DOMSN AS CHAR(1) CHARACTER SET ISO8859_1 CHECK (VALUE IN ('S','N')) COLLATE ES_ES_CI_AI;

El motivo es que quiero que manejemos las tablas lo más a pelo posible, esto no es útil para los que ya saben trabajar bien con ellas pero si para los que estan empezando.

Buscar en el club que hay tutoriales de como crear la base de datos y las tablas con Ibexpert, de todas maneras si alguno tiene aun dudas puedo explicar alguna cuestión a lo largo del tutorial al igual que otros muchos compañeros. :rolleyes:

Pondré los resultados de la DDL de cada tabla del Ibexpert, por lo que podéis copiar y pegar para crearlas en el editor SQL de la aplicación ya mencionada, pero recordar que si estáis iniciándoos es mejor hacer el trabajo campo por campo para que lo aprendáis bien.

En caso de usar el editor SQL recordar que tenéis que hacer por una parte la tabla, por otra el indice primario y luego aparte crear los campos de auto incremento para los campos ID.

Por último decir que he creado una nueva tabla llamada etiquetas, ya explicare como funciona más adelante y he añadido algún campo a las tablas USUARIO, CONFIGURACION y UNIDADES.

Comienzo a mostrar las diferentes tablas de manera separada.

José Luis Garcí 21-02-2015 13:34:07

Creamos la tabla unidades (hemos añadido el campo código de barras)

Código SQL [-]
CREATE TABLE UNIDADES (
    ID               INTEGER,
    ALQUILADA_VECES  INTEGER,
    CODIGO           VARCHAR(20) NOT NULL,
    TITULO           VARCHAR(100),
    GENERO           VARCHAR(20),
    VALOR_ALQUILER   VARCHAR(20),
    FORMATO          VARCHAR(20),
    LIBRE            VARCHAR(80),
    FECHA_ALTA       DATE,
    FECHA_BAJA       DATE,
    COSTE            NUMERIC(15,4),
    RENDIMIENTO      NUMERIC(15,4),
    DISPONIBLE       DOMSN /* DOMSN = CHAR(1) CHECK (VALUE IN ('S','N')) */,
    VENDIDA          DOMSN /* DOMSN = CHAR(1) CHECK (VALUE IN ('S','N')) */,
    PERDIDA          DOMSN /* DOMSN = CHAR(1) CHECK (VALUE IN ('S','N')) */,
    NOTAS            BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    PORTADA          BLOB SUB_TYPE 0 SEGMENT SIZE 80,
    CODIGO_BARRAS    VARCHAR(20)
);


Y su PK

Código SQL [-]
ALTER TABLE UNIDADES ADD CONSTRAINT PK_UNIDADES PRIMARY KEY (CODIGO);


Comentar que no usaremos códigos de barras comerciales como el Ean 8 o 13, usando para este caso una fuente con formato de códigos de barra probablemente al codebar39, me falta comprobar una cosa y lo confirmare

José Luis Garcí 21-02-2015 13:37:09

Creamos la tabla configuración a la que añadimos los campos SEGUNDOS_RETENIDOS y SALTO_REGISTROS)


Código SQL [-]
CREATE TABLE CONFIGURACION (
    ID                        INTEGER,
    NUMERADOR_CLIENTE         INTEGER,
    NUMERADOR_UNIDAD          INTEGER,
    NUMERADOR_VALOR_ALQUILER  INTEGER,
    NUMERADOR_ALQUILER        INTEGER,
    NUMERADOR_CAJA            INTEGER,
    NUMERADOR_MOVIMIENTOS     INTEGER,
    NUMERADOR_FORMATO         INTEGER,
    NUMERADOR_FORMA_PAGO      INTEGER,
    NUMERADOR_CARGOS          INTEGER,
    NUMERADOR_GENERO          INTEGER,
    DIA_OFERTA                INTEGER,
    SEGUNDOS_RETENIDOS        INTEGER,
    SALTO_REGISTROS           INTEGER,
    CODIGO_POSTAL             VARCHAR(6),
    NOMBRE                    VARCHAR(80),
    DIRECCION                 VARCHAR(100),
    POBLACION                 VARCHAR(60),
    PROVINCIA                 VARCHAR(60),
    DOCUMENTO                 VARCHAR(20),
    TELEFONO                  VARCHAR(20),
    MOVIL                     VARCHAR(20),
    FAX                       VARCHAR(20),
    WEB                       VARCHAR(120),
    EMAIL                     VARCHAR(120),
    COLOR_DISPONIBLE          VARCHAR(20),
    COLOR_NO_DISPONIBLE       VARCHAR(20),
    COLOR_BLOQUEADA           VARCHAR(20),
    NOMBRE_IMPUESTO           VARCHAR(10),
    LIBRE                     VARCHAR(80),
    PORCENTAJE_IMPUESTO       NUMERIC(15,4),
    LEY_PROTECCION_DATOS      BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    LOGO                      BLOB SUB_TYPE 0 SEGMENT SIZE 80
);

OJO no lleva indice primario ya que estará compuesta de un único registro


Los campos SEGUNDOS_RETENIDOS es para saber los tiempos de espera en un Splash, algunos mensajes y pre visualización de caratulas en el menú principal

y SALTO_REGISTROS nos servirá para ver la cantidad de registros que saltaremos de una vez

José Luis Garcí 21-02-2015 13:38:47

A partir de ahora no haré comentarios salvo que lo estime necesario

Código SQL [-]
CREATE TABLE CLIENTES (
    ID             INTEGER,
    CODIGO         VARCHAR(20) NOT NULL,
    NOMBRE         VARCHAR(80),
    DIRECCION      VARCHAR(100),
    POBLACION      VARCHAR(60),
    PROVINCIA      VARCHAR(60),
    DOCUMENTO      VARCHAR(20),
    TELEFONO       VARCHAR(20),
    MOVIL          VARCHAR(20),
    EMAIL          VARCHAR(120),
    CODIGO_POSTAL  VARCHAR(6),
    LIBRE          VARCHAR(80),
    A_CUENTA       NUMERIC(15,4),
    PENDIENTE      NUMERIC(15,4),
    NOTAS          BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    FOTO           BLOB SUB_TYPE 0 SEGMENT SIZE 80
);

Código SQL [-]
ALTER TABLE CLIENTES ADD CONSTRAINT PK_CLIENTES PRIMARY KEY (CODIGO);

José Luis Garcí 21-02-2015 13:42:41

Vamos a poner todas las tablas pequeñas

Código SQL [-]
CREATE TABLE GENEROS (
    ID      INTEGER,
    CODIGO  VARCHAR(20) NOT NULL,
    GENERO  VARCHAR(60)
);


Código SQL [-]
ALTER TABLE GENEROS ADD CONSTRAINT PK_GENEROS PRIMARY KEY (CODIGO);

----------------------------------------

Código SQL [-]
CREATE TABLE FORMATOS (
    ID       INTEGER,
    CODIGO   VARCHAR(20) NOT NULL,
    FORMATO  VARCHAR(60)
);


Código SQL [-]
ALTER TABLE FORMATOS ADD CONSTRAINT PK_FORMATOS PRIMARY KEY (CODIGO);

----------------------------------------

Código SQL [-]
CREATE TABLE CARGOS (
    ID      INTEGER,
    CODIGO  VARCHAR(20) NOT NULL,
    CARGO   VARCHAR(100)
);


Código SQL [-]
ALTER TABLE CARGOS ADD CONSTRAINT PK_CARGOS PRIMARY KEY (CODIGO);

----------------------------------------

Código SQL [-]
CREATE TABLE FORMA_PAGO (
    ID        INTEGER,
    CODIGO    VARCHAR(20) NOT NULL,
    CONCEPTO  VARCHAR(60),
    IMAGEN    BLOB SUB_TYPE 0 SEGMENT SIZE 80
);


Código SQL [-]
ALTER TABLE FORMA_PAGO ADD CONSTRAINT PK_FORMA_PAGO PRIMARY KEY (CODIGO);

José Luis Garcí 21-02-2015 13:44:17

Código SQL [-]
CREATE TABLE VALOR_ALQUILER (
    ID                INTEGER,
    DIAS              INTEGER,
    CODIGO            VARCHAR(20) NOT NULL,
    CONCEPTO          VARCHAR(60),
    LIBRE             VARCHAR(80),
    PRECIO            NUMERIC(15,4),
    PRECIO_OFERTA     NUMERIC(15,4),
    PENALIZACION_DIA  NUMERIC(15,4)
);


Código SQL [-]
ALTER TABLE VALOR_ALQUILER ADD CONSTRAINT PK_VALOR_ALQUILER PRIMARY KEY (CODIGO);

José Luis Garcí 21-02-2015 13:48:13

Tengamos en cuenta que el indice primario esta en el ID y no en otro campo, así lo encontraremos en varios, esto no quiere decir que no tenga el campo de auto incremento

Código SQL [-]
CREATE TABLE ALQUILER (
    ID                       INTEGER NOT NULL,
    REGISTRO                 VARCHAR(20),
    UNIDAD                   VARCHAR(20),
    CLIENTE                  VARCHAR(20),
    USUARIO                  VARCHAR(20),
    LIBRE                    VARCHAR(80),
    DIA_ALQUILER             DATE,
    DIA_DEVOLUCION_PREVISTO  DATE,
    DIA_DEVOLUCION           DATE,
    PAGADA                   DOMSN /* DOMSN = CHAR(1) CHECK (VALUE IN ('S','N')) */,
    RACARGO                  NUMERIC(15,4),
    VALOR_RECARGO_DIA        NUMERIC(15,4)
);


Código SQL [-]
ALTER TABLE ALQUILER ADD CONSTRAINT PK_ALQUILER PRIMARY KEY (ID);

José Luis Garcí 21-02-2015 13:49:36

Código SQL [-]
CREATE TABLE CAJA (
    ID        INTEGER NOT NULL,
    REGISTRO  VARCHAR(20),
    CONCEPTO  VARCHAR(100),
    CLIENTE   VARCHAR(20),
    USUARIO   VARCHAR(20),
    LIBRE     VARCHAR(80),
    CARGO     VARCHAR(100),
    FECHA     DATE,
    CANTIDAD  NUMERIC(15,4)
);

Código SQL [-]
ALTER TABLE CAJA ADD CONSTRAINT PK_CAJA PRIMARY KEY (ID);

José Luis Garcí 21-02-2015 13:52:01

Código SQL [-]
CREATE TABLE MOVIMIENTO (
    ID        INTEGER NOT NULL,
    REGISTRO  VARCHAR(20),
    CONCEPTO  VARCHAR(100),
    CLIENTE   VARCHAR(20),
    USUARIO   VARCHAR(20),
    LIBRE     VARCHAR(80),
    CARGO     VARCHAR(100),
    FECHA     DATE,
    CANTIDAD  NUMERIC(15,4)
);


Código SQL [-]
ALTER TABLE MOVIMIENTO ADD CONSTRAINT PK_MOVIMIENTO PRIMARY KEY (ID);

José Luis Garcí 21-02-2015 13:54:29

Esta es la tabla nueva


Código SQL [-]
CREATE TABLE ETIQUETAS (
    ID             INTEGER NOT NULL,
    FECHA          DATE,
    UNIDAD         VARCHAR(20),
    TITULO         VARCHAR(20),
    CODIGO_BARRAS  VARCHAR(20),
    USUARIO        VARCHAR(20),
    IMPRIMIDO      DOMSN /* DOMSN = CHAR(1) CHECK (VALUE IN ('S','N')) */
);

Código SQL [-]
ALTER TABLE ETIQUETAS ADD CONSTRAINT PK_ETIQUETAS PRIMARY KEY (ID);

José Luis Garcí 21-02-2015 13:58:20

Creamos la tabla USUARIO y añadimos los campos telefono y movil, con esta de momento y esperemos que siga así están nuestras tablas

Código SQL [-]
CREATE TABLE USUARIO (
    ID        INTEGER,
    NIVEL     INTEGER,
    CODIGO    VARCHAR(20) NOT NULL,
    NOMBRE    VARCHAR(80),
    CLAVE     VARCHAR(100),
    TELEFONO  VARCHAR(20),
    MOVIL     VARCHAR(20),
    EMAIL     VARCHAR(120),
    LIBRE     VARCHAR(80),
    NOTAS     BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    FOTO      BLOB SUB_TYPE 0 SEGMENT SIZE 80
);


Código SQL [-]
ALTER TABLE USUARIO ADD CONSTRAINT PK_USUARIO PRIMARY KEY (CODIGO);

José Luis Garcí 21-02-2015 14:29:57

Antes de proseguir con el tutorial nos toca algunas explicaciones para los más novatos ;), sobre todo algunos términos que suelo usar.

Los módulos de altas bajas y modificaciones o (ABM), son los módulos principales donde introduciremos los datos, pero algunos no tendrán muchas veces todas estas opciones aun así usare este termino muchas veces. Podréis encontrar otro tutorial mio sobre este tema y aplicare algunos de los conceptos en el en este.

Ahorraremos código usando un dbnavigator sólo para los movimientos entre registros, no teniendo que controlar así el Fist, Prior, Next y Last.

También usaremos un Dtasourse llamado Dsprincipal en cada formulario que mueva datos, añadiendo los restantes para otras tablas.

Por supuesto usaremos un Datamodule, que en mi caso llamare DM, donde tendremos nuestra base de datos y ibdataset principales, por cierto usaremos los componente IBX que vienen de forma nativa con delphi en este tutorial ya que como dije no quiero usar componentes de terceros ni míos propios.

Como vamos a trabajar con la idea de una pantalla táctil, usaremos botones grandes y por ello si es necesario, crearemos sistemas algo más complejos para ciertos campos debido a las limitaciones de ciertos componentes para usar en estos sistemas.

Para evitar ciertos errores comunes usaremos un sistema de paneles que nos evitaran ciertos quebraderos de cabeza, su distribución sera la siguiente:

Panel botornera: será el panel donde estarán todas las acciones posibles sobre movimiento, edición, creación y borrado de nuestra tabla/s, así como otras opciones como búsqueda, imprimir, etc.

Panel de datos: en este encontraremos los apartados los campos a rellenar y los grid con información, pero dentro de estos estarán dos paneles que haremos visibles en ciertas condiciones.

Panel ocultable: dentro de Panel de datos para información que será visible según elñ nivel del usuario.

Panel Confirmación: dentro de Panel de datos permite confirmar o cancelar los cambios o creación de datos

Panel de búsqueda: quedará fuera del panel de datos al igual que el de botonera y sólo se mostrará en el caso de querer hacer búsquedas, simples o más complejas.


¿Por que este lió de paneles y su control? por el simple motivo de que por un error podemos registrar los cambios en una tabla sin querer al pulsar sobre un botón deseado, o entrar en edición de un registro al pulsar sobre uno de sus campos, errores mucho más típico de lo que pensamos. Debo decir que para evitar estas cosas uso normalmente un componente mio que podéis buscar en los foros llamado panelDB, este nos ahorraría bastante código y trabajo, ya que esta conectado al datasource que queremos controlando de esta manera, que esta visible , editable, etc... automáticamente.


Creo que ya comente las colecciones de iconos usados, por lo que no usare ninguno que no este dentro de estas colecciones, si hace falta diré donde se encuentran.


Por su puesto explicaré las cosas una vez salvo que alguien no lo entienda, por lo que los primeros módulos serán algo más extensos que los siguientes.

Al estar diseñado para táctil, usaremos un menú basado en botones, pero también usare un menú normal, junto con un actionlist, para controlar las ejecuciones y no tener que estar repitiendo código. Para este motivo también usaremos muchas funciones.

Todas las funciones irán dentro de un módulo que llamaremos UFunciones.Pas, así no estarán desperdigadas por el programa y será más fácil controlarla.

En el modulo DM (Data module) también insertaremos varias variables , para ciertas operaciones que nos permitirán movernos de un form a otro sin tener que estar recordando donde estaba esa variable, llamándolas variables fijas.

Haré especial hincapié en ciertas partes de código sobre todo algunas funciones, ya que de estas dependerán partes del programa.

Por último usaremos ciertos diálogos estándar en operaciones, como crear, editar, borra y las transacciones de error al grabar, aparte de estos habrá otros más que ya iremos viendo.

Después de todo esto, comenzamos con la aplicación de nuestro sistema en el tutorial, como tengo que ir creándolo lo iré explicando según vaya terminan dolo. haciendo alguna anotación especial sobre ciertos procesos antes.

José Luis Garcí 21-02-2015 14:42:44

Bueno ya estoy con el menú trabajando y debo deciros algunas cosas comunes para todos nuestros forms.

En todos llevaremos un statusbar en la parte baja y haremnos algunas cosas con el ya las iremos viendo más delante.

Todos nuestros paneles deben aparecer inicialmente centrados por lo que usaremos la propiedad position a poScreenCenter

También activaremos a true la propiedad Keypreview, para que detecte las pulsaciones del teclado en nuestro form

Y por supuesto usaremos mucho la propiedad aling, para distribuir nuestros componentes

Y el fom tendra un height de 800 por un width de 1000 en estado normal

José Luis Garcí 21-02-2015 16:36:48

Se que dije que primero haría el menú, pero para explicar ciertas características primero debo explicar el data module (DM) y como lo vamos con formando.

Lo primero lo creamos gracias al repositorio de Delphi, en el delphi 10 es Flie>New>Otther y luego dentro de Delphi File

Una vez lo tengamos añadimos el componente IBDataBase de la pestaña interbase, cambiamos su propiedad name por DB y en vez de rellenar las propiedades aquí hacemos lo siguiente




Rellenamos este pequeño formulario teniendo en cuenta lo siguiente



Después de esto añadimos un componente IBTransaction de la misma pestaña cambiamos el name por IBT y pulsamos en la propiedad defaultDatabase seleccionando DB, luego pulsamos dos veces con el botón derecho sobre el y seleccionamos como en la siguiente imagen




Con esto ya tenemos configurado la base de datos y la transacciones (quienes se aseguran de grabar los datos en las tablas)

Ahora añadimos dos IBDataSet uno sera para la configuración y otra para el usuario llamándolos IBDConfiguracion y IBDUsuarios, los seleccionamos a ambos y rellenamos su propiedad Database seleccionando DB con lo que nos rellena automáticamente la propiedad transaction con IBT.

Seleccionamos IBDUsuarios y pulsamos sobre SelectSQL haciendo lo siguiente



Seguimos sobre la misma tabla y pulsamos en GeneratorFiled rellenando el siguiente formulario



Con esto activamos los campos auto incremento, por lo que debemos usar el generador adecuado a nuestra tabla, el campo de incremento, la cantidad a incrementar (Incrment By) y por último seleccionar el evento On Post para realizar este. Pulsamos Ok y esto también está configurado para esta tabla.

Seguimos en la misma tabla y pulsamos sobre el IBDUsuario con el ratón derecho saliendo el popmenu del el seguimos los siguientes pasos



En rojo y en más grande los números de los pasos a seguir, por lo que ahora explico el paso 3 y el 4, dentro del paso 3 tenemos las siguientes opciones:

[1] Elegimos el campo clave en este caso código
[2] Seleccionamos todos los campos sobre los que queremos actuar, normalmente todos
[3] Seleccionamos el Quoters Identifirs, para que nos registre adecuadamente los campos y sus valores
[4] Seleccionamos el generate SQl con lo que nos muestra la pantalla 4 con los códigos necesarios para modificar, insertar, borrar y refrescar los datos en sus diversos apartados
[5] realmente debería ir en la siguiente pantalla con esto confirmamos los cambios

Ya nos quedan dos pasos con esta tabla y terminamos, el siguiente aunque lioso nos permite mejorar la vista de nuestros datos y el siguiente es mucho más sencillo lo prometo.

Para el primero volvemos a pulsar sobre el IBDUsuario con el ratón derecho saliendo el popmenu, seleccionamos la primera opción y seguimos los siguientes pasos




[1] Es el formulario que nos sale tras elegir la opción, pulsamos con el botón derecho del ratón saliendo un nuevo popmenu
[2] Elegimos añadir todos los campos
[3] Así nos queda ahora con los campos de nuestra taba añadidos
[4] Ahora podemos usar el inspector de objeto y cambiar campos como los siguientes

DisplayLabel: la etiqueta con la que aparecerá nuestros campos
DisplayWidth: el número de caracteres a mostrar de nuestra etiqueta
EditFormat: el formato de entrada y mostrar nuestros datos usando máscaras para ellos como #,##0.00

Hay muchas más pero no es que nos interesen demasiado ahora salvo tal vez el Maxvalue y Minvalue para cierto campo que ya veremos

Bueno con esto sólo quedaría ahora activar nuestra tabla colocándonos nuevamente sobre el IBDUsuario y pulsando sobre la propiedad active a true, si no ha habido problemas así se quedará.

José Luis Garcí 21-02-2015 17:06:35

Con esto ya hemos aprendido a usar las tablas de nuestra base de datos con los componentes IBX de interbase, tienen ciertas limitaciones que ya comentaré en breve, ahora deberíais hacer lo mismo con la de configuración, pero teniendo en cuenta que es para la tabla configuración y no usuarios.

No se si podre poneros algo más hoy pero si os pondré para que sirve el editar los campos de la tabla

Tener en cuenta que esto no sirve salvo como demostración para ellos crear un nuevo formulario dentro de vuestra aplicación que luego vamos a eliminar.



Como ya digo esto no sirve de nada salvo como demostración de la utilidad de este sistema. Podéis ver que tenemos el listado de campos de la tabla usuarios (IBDUusario) al lado, seleccionaremos todos los campos menos notas (en poco os explico por qué).



Como veréis tampoco he cogido el campo ID ya que no sería de utilidad aquí. Pulsamos con el botón izquierdo de nuestro ratón y mantenemos pulsado el mismo mientras lo soltamos donde queremos dentro del formulario, saltándonos el siguiente aviso



Este nos dice básicamente que no hay conección entre el Datamodule (DM) y este form si queremos crearlo le damos al Ok y ved lo que pasa



Como veis nos ha creado las etiquetas de los campos con los valores como los hemos modificado, añadiendo un datasourse que esta conectado a IBDUsuarios dentro del data module.

Como ya he dicho este ejemplo es sólo eso ya que no tenemos control aun sobre los procesos, pero esto es lo que haremos con los campos una vez editados, viéndose así en los dbgrid y demás conexiones con los campos que hagamos. Por su puesto en vez de arrastrando todos podemos arrastrar uno por uno y colocandolos donde queremos, pero eso como veáis.

Advertiros que en tablas con muchos campos, estos datos desaparecen de la vista, por lo que debéis ser cautos al usar este sistema,seleccionando pocos campos a la vez.

Podéis seleccionar los campos manteniendo la tecla Shift después de seleccionar el primer campo y eligiendo el último antes de soltarla, así todos los que estén entra ambos quedarán seccionados.

Bueno por hoy es todo, intentare mañana proseguir con ejemplo de formularios, el menú, ciertos procesos y demás.

José Luis Garcí 22-02-2015 10:23:43

Buenos días, lo prometido es deuda, así que empecemos con algo sencillo, será convertir el punto del teclado numérico en una coma, para los decimales, respetando el del teclado normal, para ello debemos hacer lo siguiente.

Código Delphi [-]
//Uses  ShellAPI ///1

//-----------------------------------------------------

//Después del TYPE
procedure ApplicationEvents1Message(var Msg: tagMSG;var Handled: Boolean); //2
//-----------------------------------------------------

var
  FMenu: TFMenu;  //O como se llame nuestro primer formulario
  MapearPuntoAComa: Boolean;   //3
implementation

//-----------------------------------------------------

procedure TFMenu.ApplicationEvents1Message(var Msg: tagMSG;var Handled: Boolean); //4
//-------------------------------------------------------------------------------
//*******************************[DEcimal del teclado númerico el . por coma]****
//-------------------------------------------------------------------------------
begin

  if MapearPuntoAComa AND (Msg.message = WM_KEYDOWN) AND
     (Msg.wParam = VK_DECIMAL) AND (DecimalSeparator = ',') then
  begin
    Msg.message := WM_CHAR;   // cambiamos el tipo de mensaje
    Msg.wParam := 44;  // si omitimos la línea anterior, aquí sería Msg.wParam := 188;
    Handled := FALSE;
  end;
  //Se puede activar o desactivar a la entrada y sadila de componentes
end;

procedure TFMenu.FormCreate(Sender: TObject);  //5
begin
   MapearPuntoAComa:=True;
   Application.OnMessage:=ApplicationEvents1Message;
end;



Como veis lo he dividido en cinco partes y aunque creo que esta claro lo explicare un poco
1: en donde metemos las unit que usamos para nuestros componentes y funciones por defecto de delphi, llamamos al ShellApi
2:Declaramos un procedimiento estándar de delphi
3:Donde esta declarada nuestra variable del form de la unidad principal añadimos la variable MapearPuntoAComa
4:rellenamos el procedimiento descrito en el punto 2
5: añadimos al evento OnCreate de diño form la linea MapearPuntoAComa: Boolean; y la linea siguiente


Y con esto tenemos el resultado que buscabamos

José Luis Garcí 22-02-2015 13:08:02

Bueno estoy trabajando en las form, más adelante hoy pondré la de usuarios terminada y algo de código de la del menú.



Como veis el menú aun le falta mucho, pero ya podemos ver los paneles de la botonera, hay cosas que quitar y sobre todo corregir, pero indica parte del camino ya veremos como ir perfilandolo



Aunque la pantalla de usuario no esta terminada ni por asomo., podemos ver como ira quedando y voy a a explicar un poco el diseño y uso de paneles

1: Como podemos apreciar en este apartado tenemos 1 panel (Botonera1) 1 Dbnavigator, del que hemos seleccionado de su propiedad VisibleButtons, los cuatro primeros y hemos dejado el nombre por defecto (DbNavigator1) y 5 Spedbuttons que hemos llamado SBNuevo, SBEdit, SBBorrar, SBBuscar y SBSalir, tanto el dbnavigator como los 4 primeros speddbutton estan alineados a la izquierda, mientras que el último está alineado a la derecha

El panel tiene un height de 81, los speddbuttons tien un width de 80 y el del dbnavigator de 304.

El panel inicialmente esta enble y visible, pero su estado enable cambiara a false cuando entremos a insertar o modificar un registro.

//--------------------------

2: Panel de datos (PanelDatos) contendrá la información de nuestros campo para que los editemos, como podemos ver tanto los campos nivel como código tienen un color diferente, ya que se los he cambiado ya que los he puesto en enable=False, ya vereis por que.

Este panel es de tamaño fijo y dentro de el podemos ver lo puntos 3 y 4 que luego explicaremos.

El estado inicial de este panel es enable=false cambiando cuando entremos en edición o inserción de datos.

Los campos son la mayoría dbedits, cada uno se llamara inicialmente DBE y el campo que el, por ejemplo nivel sería DBENivel, mientras que código seria DBECódigo

También podemos ver un DBImagen, al que no le cambiare el nombre ya que es único en el formulario

Y por último tenemos un Memo al que he llamado MemoNotas, el motivo de no usar un DBMEMO es que los componentes IBX con Firebird dan problemas directamente con los componentes dbMemo estándar de Delphi, por lo que haremos el trabajo a pelo y usaremos un editor para el.

Realmente deberíamos usar un editor para los campos también, pero confiaremos en el sistema táctil de windows y dejaremos que el ponga su propio teclado, también podríamos hacerlo para el memo, pero quiero que veáis las dos opciones.

//----------------------------------

3: Para el DBnivel he añadido dos spedbuttons llamados SBmas y SBMenos, cada pulsación aumentara o disminuirá el nivel del usuario dentro de unos limites claro y estos están contenidos dentro del PanelDatos

//-----------------------------------

4: Otro Panel (PanelOculto) este contendrá los botones necesarios para ciertos campos, así como la confirmación o cancelación del registro. Su contenido en este caso es el siguiente SbCargarImagen, SbWebCam, SBEditMemo, SBConfirmar y SBCancelar, el primero carga una imagen, el segundo obtiene una imagen des de cámaras webcan (De muchos modelos), el tercero abre el editor del memo, el cuarto confirma los cambios y el último cancela el registro.

Este panel está oculto hasta que pulsemos nuevo o editar, volviéndose a ocultar en cuanto le demos a confirmar o cancelar

Podéis ver que hay varios Speedbuttons que están en enable=False, el motivo es que ahora los uso de separadores, ya que salvo los dos últimos estan alineados a la izquierda, mientras que los de confirmar y cancelar lo están a la derecha. Los botones no usados pueden estar enables por tener utilidad en otros momentos, ya lo veremos más adelante.

//----------------------------------

5: Es un dbgrid y he dejado el nombre que tenia, por supuesto queda organizar su aspecto. Lo he puesto en enable False

//---------------------------------

6: Panel mover (PanelMover) es una tontería de panel que podemos eliminar ya que sus opciones subir y bajar también las podemos usar con el DBNavigator, en este caso lo dejare a modo de que los que no tiene experiencia, puedan ver como movernos por los registros sin usar un dbnavigator, pero sólo aumenta el trabajo y no lo pondré en otras pantallas. Tendrá los mismo controles que el Botonera1

//-----------------------------------

7: Panel botonera 2 (Botonera2) este panel solo se pone visible cuando pulsemos búsqueda y en este caso será muy sencillo usando un simple locate, pero en otros casos será mucho más complejo su uso, ademas tiene los spedbuttons SBSalirBusqueda y SBEncontrar, supongo que se entiende su utilidad. Además tiene un edit que he dejado como tal
//-----------------------------------


Debo comentaros que los puntos 2,3,4,5,6 están dentro de otro panel que he llamado panelcontenedor y que para la distribución de los paneles y demás he usado mucho la propiedad Align

José Luis Garcí 22-02-2015 13:16:18

Primer campo que Faltaba, :p Hay que añadir a la tabla configuración el campo NUMERADOR_USUARIO tipo integer

José Luis Garcí 22-02-2015 14:00:28

Vamos con el editor, lo he hecho muy simple y aunque ahora no lo entendáis en cuanto ponga el modulo de usuarios lo entenderéis bien



Y este es su código, aunque normalmente pondré un enlace para poner los módulos completo, este lo hago al ser pequeño

Código Delphi [-]
unit UEditor;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, Keyboard, StdCtrls, ExtCtrls;

type
  TFeditor = class(TForm)
    Panel1: TPanel;
    Memo1: TMemo;
    TouchKeyboard1: TTouchKeyboard;
    SBRecarga: TSpeedButton;
    SBBlanco: TSpeedButton;
    SBCancelar: TSpeedButton;
    SBOk: TSpeedButton;
    procedure SBBlancoClick(Sender: TObject);
    procedure SBRecargaClick(Sender: TObject);
    procedure SBOkClick(Sender: TObject);
    procedure SBCancelarClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Feditor: TFeditor;

implementation

{$R *.dfm}

uses UDM;

procedure TFeditor.SBBlancoClick(Sender: TObject);
//------------------------------------------------------------------------------
//*************************************************************[ SBBlanco ]*****
// Pone el memo en blanco
//------------------------------------------------------------------------------
begin
  Memo1.Lines.Clear;
end;

procedure TFeditor.SBCancelarClick(Sender: TObject);
//------------------------------------------------------------------------------
//***********************************************************[ SBCancelar ]*****
// No graba los datos salimos
//------------------------------------------------------------------------------
begin
   Close;
end;

procedure TFeditor.SBOkClick(Sender: TObject);
//------------------------------------------------------------------------------
//*****************************************************************[ SBOk ]*****
// Graba los datos en la variable y salimos
//------------------------------------------------------------------------------
begin
   VarSMEMO:=Memo1.Lines.Text;
   Close;

end;

procedure TFeditor.SBRecargaClick(Sender: TObject);
//------------------------------------------------------------------------------
//************************************************************[ SBRecarga ]*****
// Recupera el texto de la variable fija VarSMemo
//------------------------------------------------------------------------------
begin
  Memo1.Lines.Text:=VarSMEMO;
end;

end.


La franja horaria es GMT +2. Ahora son las 21:24:47.

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