0% encontró este documento útil (0 votos)
25 vistas80 páginas

Log Taller

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
25 vistas80 páginas

Log Taller

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Facultade de Informática

TRABAJO FIN DE GRADO


GRADO EN INGENIERÍA INFORMÁTICA
MENCIÓN EN INGENIERÍA SOFTWARE

Aplicación web para la gestión de citas


previas

Estudiante: Alexandre Maneiro Jueguen

Dirección: Fernando Bellas Permuy

A Coruña, Octubre de 2022.


Dedicado a mi familia, amigos y profesores
Agradecimientos

Gracias a mis padres por brindarme su apoyo emocional y económico, a mis amigos por
estar siempre ahí, a mis profesores por enseñarme gran parte de lo que sé y a la educación
pública por permitir que se me haya enseñado todo el conocimiento que me hacer ser quien
soy hoy.
Resumen

El objetivo de este proyecto es diseñar e implementar una aplicación web que facilita una
tarea presente en muchos tipos de negocios, la gestión de citas.
La gestión de citas es un proceso que históricamente siempre ha consistido en un flujo de
información a través del teléfono, mediante el cual el cliente pregunta la disponibilidad de una
hora concreta, el empleado comprueba esa hora en un libro de citas y le responde acorde al
libro. Con esta aplicación lo que se busca es substituir la llamada telefónica por una consulta
en nuestra página web, la cual contendrá directamente el libro de citas, liberando al empleado
de la gestión de la cita.
La aplicación está dividida en dos capas: el backend, que gestiona la lógica de negocio y
expone esta mediante una API REST implementada con Java, utilizando el framework Spring
Boot y persistiendo los datos en una base de datos MySql, y el frontend, que gestiona la in-
terfaz con la que interactúa el usuario y hace llamadas al backend en base a estas interaccio-
nes, implementado como una aplicación web SPA usando JavaScript, React, React-Redux y
Material-UI entre otros.

Abstract

The goal of this project is to design and implement a web application that facilitates a task
present in many kinds of businesses, the appointment management.
Appointment management is a process that historically has always consisted of a flow
of information through a telephone, in which the client asks the availability of a given hour,
the employee checks the hour on an appointment book and responds accordingly. With this
application what we want is to replace the phone call with a search on our web page, which
will contain the appointment book, releasing the employee from managing the appointment.
The application is divided into two layers, the backend, which manages the business logic
and exposes it through a REST API implemented with Java, using the Spring Boot framework
and persisting the data in a MySql database, and the frontend, which manages the interface
with which the user interacts and makes calls to the backend based on these interactions,
implemented as a SPA web application using JavaScript, React-Redux and Material-UI among
others.
Palabras clave: Keywords:

• Java • Java
• Javascript • Javascript
• Aplicación web SPA • SPA web application
• Spring Boot • Spring Boot
• React • React
• React-Redux • React-Redux
• Cita • Appointment

2
Índice general

1 Introducción 1
1.1 Contexto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Visión global del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 Estado del arte 5


2.1 Timify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Reservio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 SimplyBook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4 Otras aplicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3 Metodología 9
3.1 Metodología escogida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Razonamiento de la elección . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

4 Análisis de requisitos global 11


4.1 Actores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2 Casos de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

5 Planificación 17
5.1 Iteraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.1.1 Iteración 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.1.2 Iteración 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.1.3 Iteración 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.1.4 Iteración 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.1.5 Iteración 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.1.6 Iteración 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.1.7 Iteración 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

i
ÍNDICE GENERAL

5.1.8 Iteración 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.2 Planificación temporal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.3 Cálculo de costes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

6 Fundamentos tecnológicos 22
6.1 Tecnologías utilizadas en el backend . . . . . . . . . . . . . . . . . . . . . . . . 22
6.1.1 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.1.2 Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.3 Spring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.4 MySql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.5 Postman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.6 Jacoco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.7 Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.2 Tecnologías utilizadas en el frontend . . . . . . . . . . . . . . . . . . . . . . . 24
6.2.1 JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.2.2 React . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.2.3 React Redux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6.2.4 Material-UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6.2.5 Npm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.2.6 Redux DevTools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.2.7 Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.3 Tecnologías complementarias . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.3.1 Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.3.2 Docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

7 Desarrollo 27
7.1 Estructura de la aplicación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
7.1.1 Estructura del backend . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
7.1.2 Estructura del frontend . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.2 Modelo de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
7.3 Iteración 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.3.1 Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.3.2 Diseño e implementación . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.4 Iteración 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.4.1 Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.4.2 Diseño e implementación . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.5 Iteración 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.5.1 Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

ii
ÍNDICE GENERAL

7.5.2 Diseño e implementación . . . . . . . . . . . . . . . . . . . . . . . . . 46


7.6 Iteración 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
7.6.1 Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
7.6.2 Diseño e implementación . . . . . . . . . . . . . . . . . . . . . . . . . 50
7.7 Iteración 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.7.1 Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.7.2 Diseño e implementación . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.8 Iteración 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.8.1 Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.8.2 Diseño e implementación . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.9 Iteración 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

8 Conclusiones y trabajo futuro 63


8.1 Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.2 Trabajo futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

Lista de acrónimos 66

Glosario 67

Bibliografía 68

iii
Índice de figuras

1.1 Flujo de información canónico . . . . . . . . . . . . . . . . . . . . . . . . . . . 2


1.2 Flujo de información a través de nuestra web . . . . . . . . . . . . . . . . . . . 2
1.3 Arquitectura del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.1 Ejemplo de reserva online de Timify . . . . . . . . . . . . . . . . . . . . . . . . 7


2.2 Definición de horarios de atención en Reservio . . . . . . . . . . . . . . . . . . 7
2.3 Plantilla de SimplyBook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

4.1 Mockup de CU-06 Usuario busca negocios . . . . . . . . . . . . . . . . . . . . 13


4.2 Mockup de CU-09 Usuario consulta detalles de negocio . . . . . . . . . . . . . 13
4.3 Mockup de CU-11 Dueño gestiona bloqueos de empleados . . . . . . . . . . . 14
4.4 Mockup de CU-13 Cliente solicita cita . . . . . . . . . . . . . . . . . . . . . . . 16

6.1 Ilustración de la ejecución de un programa en una JVM . . . . . . . . . . . . . 22


6.2 Ilustración de una interfaz de usuario con componentes . . . . . . . . . . . . . 24

7.1 Modelo de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30


7.2 Formulario de registro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.3 Formulario de iniciar sesión . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.4 Parte del componente Header con el desplegable con operaciones para el usuario 36
7.5 Ventana modal con el formulario para añadir empleado . . . . . . . . . . . . . 40
7.6 Parte final del formulario de crear negocio . . . . . . . . . . . . . . . . . . . . 40
7.7 Desplegable de usuario con el componente BusinessSelector . . . . . . . . . . 41
7.8 Componentes involucrados en el CU-08 . . . . . . . . . . . . . . . . . . . . . . 44
7.9 Modal con formulario para añadir horario . . . . . . . . . . . . . . . . . . . . 48
7.10 Componentes diseñados para el CU-11 Dueño gestiona bloqueos de empleados 48
7.11 IU del CU-12 empleado consulta su horario . . . . . . . . . . . . . . . . . . . . 49
7.12 Diagrama de clases e interfaces involucradas en el CU-13 Cliente solicita cita . 51

iv
ÍNDICE DE FIGURAS

7.13 Componente ChooseAppointmentDate, que permite seleccionar fecha, hora y


empleado/recurso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.14 Componente ConfirmAppointment, que muestra datos confirmados y permite
añadir observaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.15 Componente CancelledAppointmentListModal, que avisa de las citas que van
a ser canceladas si la operación se confirma . . . . . . . . . . . . . . . . . . . . 54
7.16 Componente AppointmentList que muestra el historial de citas del usuario . . 55
7.17 Formulario para la reserva de cita por parte del empleado . . . . . . . . . . . . 57
7.18 Componente WarnedAppointmentListModal, que muestra los clientes que de-
ben ser atendidos telefónicamente . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.19 Componente ReviewDetails mostrando la reseña del usuario . . . . . . . . . . 60
7.20 Componente ReviewRoulette con las reseñas de usuarios . . . . . . . . . . . . 60
7.21 Ventana de Google pidiendo permisos al usuario . . . . . . . . . . . . . . . . . 61

v
Índice de tablas

5.1 Planificación del proyecto y duración estimada y real . . . . . . . . . . . . . . 20


5.2 Cálculo del coste real del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . 21

vi
Capítulo 1

Introducción

1.1 Contexto
Desde la existencia del teléfono este ha sido utilizado para llamar a establecimientos para
reservar cita previamente. Es un proceso que, en el negocio, requiere de una persona que esté
atenta al teléfono y, dependiendo del volumen de citas, esta tarea puede llegar a consumir
mucho tiempo a lo largo de una jornada. Por eso, muchos establecimientos de un tamaño ya
considerable, contratan directamente a un empleado para gestionar citas.
El problema es que muchos negocios de pequeño tamaño, debido a sus pequeños márgenes
de beneficio, no pueden permitirse el lujo de contratar a un empleado para ello. Por tanto,
cuando reciben una llamada pausan su trabajo para atenderla, produciendo perdidas de tiempo
y productividad.
Desarrollar una aplicación, lo más versátil posible, que ayude a gestionar citas de forma
telemática, podría ser de utilidad para muchas empresas de pequeño tamaño. Exponiendo el
libro de citas en una página web, el cliente puede ser él quien directamente apunte la cita.
La aplicación sería general y válida para pequeños negocios con tiempos de atención fi-
jos (e.g. una clínica de fisioterapia). Por una parte, los negocios gestionarían las citas con la
aplicación (la aplicación podría gestionar las citas de múltiple negocios) y pagarían una cuota
mensual por su uso, ahorrando costes de desarrollo y mantenimiento (hardware y software).
El pago de la cuota mensual por parte de las empresas queda fuera del alcance del TFG. Por
otra parte, los clientes podrían acceder gratuitamente a la aplicación para solicitar cita en un
negocio concreto.
Para los negocios con tiempos de atención variables en función del cliente (e.g. una pe-
luquería), la aplicación no sería tan útil. Este tipo de negocios queda fuera del alcance del
TFG.

1
CAPÍTULO 1. INTRODUCCIÓN

1.2 Objetivos
El objetivo de este proyecto es elaborar una aplicación web que mejore el flujo de infor-
mación de los negocios en la tarea de solicitar cita previa. Como se ilustra en la figura 1.1
(página 2), un flujo canónico requiere de un empleado para mediar entre el cliente y el libro
de citas.

Figura 1.1: Flujo de información canónico

Lo que se quiere obtener es un flujo de información sin necesidad del empleado, resultando
en una tarea más ágil y sencilla, como se ve ilustrado en la figura 1.2 (página 2), de forma que
se ahorre tiempo, dinero y recursos.

Figura 1.2: Flujo de información a través de nuestra web

La aplicación estará enfocada a atender 3 casuísticas: propietario de un negocio, empleado


de un negocio y cliente.
Para ello un usuario registrado, propietario de un negocio, podrá registrarlo, especifican-
do, entre otros, la duración de las citas, la lista de empleados/recursos utilizados en las citas
y un conjunto de horarios de atención. Estos horarios son el horario por defecto de todos los
empleados pero como es entendible pueden surgir imprevistos en determinados días, tener
trabajadores a media jornada o incluso tener horas reservadas para atención inmediata, por
lo tanto se ha implementado un sistema de bloqueos estáticos y recurrentes para establecer
los horarios de cada uno de los empleados adecuadamente.
Los clientes que quieran solicitar una cita pueden buscar negocios por nombre, tipo y/o
localización. De querer reservar cita, si están registrados, en el proceso eligen su empleado/-
recurso de preferencia y se les muestra su lista de horas disponibles. Una vez pedida la cita se
le envía un correo electrónico al cliente con los detalles. Además, si lo desea, puede añadir la
cita a su calendario de Google y también dispone de un histórico de citas.
En el caso de los clientes que no tengan acceso a internet, como personas mayores o en
situaciones desfavorecidas, se sigue pudiendo llamar al negocio y que el empleado realice la
reserva de la cita, con un proceso en el que se le pedirán un mínimo de datos para identificarlo.

2
CAPÍTULO 1. INTRODUCCIÓN

Las citas también se podrán cancelar. Existen tres situaciones en las que se puede dar una
cancelación: un cliente con cuenta cancela una cita; un empleado cancela una cita; un cliente
sin cuenta cancela la cita. El cliente o empleado con cuenta cancela la cita fácilmente, a través
de nuestra aplicación. Si el empleado cancela la cita debe justificar su cancelación, tras lo
cual, se le envía un correo electrónico al cliente. De no estar registrado el cliente, se avisa al
empleado de que tiene que llamar al cliente para notificar la cancelación. En el caso de que un
cliente sin cuenta quiera cancelar la cita, tiene que llamar al negocio, para que sea el empleado
quien la cancele.
Cuando se quieran efectuar cambios que afecten a citas, como añadir bloqueos o modi-
ficaciones del horario, se informará de aquellas citas que se verán afectadas si se efectúa el
cambio. Se pedirá una justificación y se notificará a los clientes vía correo electrónico. Por
otra parte, cuando se realicen estas modificaciones, también se pueden ver afectadas citas de
clientes que no tienen correo electrónico, porque la han solicitado de manera telefónica. Por
tanto también se le avisa al dueño de la necesidad de informar telefónicamente a estos clientes.

1.3 Visión global del sistema


El sistema está dividido en dos capas: backend y frontend. Cuando un usuario accede a la
aplicación web el navegador envía una petición HyperText Transfer Protocol (HTTP) GET al
servidor. Este responde con el código del frontend (compuesto fundamentalmente por JavaS-
cript y unos pocos ficheros Cascading Style Sheets (CSS)), que se ejecuta en su navegador.
El frontend internamente tiene dos capas: la de interfaz de usuario, encargada de presen-
tar los datos al usuario, y la de acceso a servicios, que se comunica con el backend. Cuando
el usuario interacciona con la capa de IU la capa de Acceso a Servicios hace una llamada
REpresentational State Transfer (REST) al backend.
El backend a su vez también está compuesto de dos capas: la de servicios y la modelo,
implementadas las dos usando el ecosistema Spring. La capa de servicios es la que se encar-
ga de las comunicaciones recibiendo peticiones HTTP y contestando con JavaScript Object
Notation (JSON); la capa modelo es la que gestiona la lógica de negocio, haciendo uso de una
base de datos MySql, con la que se comunica usando Spring e Hibernate, una implementación
de Java Persitance API (JPA) que nos permite tener un mapeador objeto-relacional. Cuando
el backend le responde al frontend este último manipula el árbol Document Object Model
(DOM) para presentar los datos. Este proceso se ve ilustrado en la figura 1.3 (página 4).

3
CAPÍTULO 1. INTRODUCCIÓN

Figura 1.3: Arquitectura del sistema

4
Capítulo 2

Estado del arte

L a gestión de citas es un proceso vital para muchos tipos de negocios, como resultado
existen muchas opciones en el mercado, con servicios base como historial de clientes,
estadísticas o recordatorios.
A continuación se muestran algunas de las soluciones más utilizadas y sus funcionalidades
más destacadas.

2.1 Timify
Timify [1], servicio enfocado a la gestión de citas, ofrecen además reuniones virtuales para
consultas, clases o reuniones en remoto; gestión de salas y recursos, para reducir los tiempos
de inactividad en tareas dependientes de estos o colas virtuales, para tareas del estilo vacuna-
ción, donde se vacuna primero al que antes llega. Opcionalmente también dispone de gestión
de sucursales y acceso a su Application Programming Interface (API) REST para desarrolla-
dores. Por último, la empresa que desarrolla Timify, también ofrece soluciones personalizadas
para aquellas empresas que necesiten un software de gestión de citas hecho a medida.
Timify es usado por más de 45000 empresas y gestionan un volumen de más de 3.2 millones
de citas mensualmente. Entre sus clientes destacan grandes empresas como Telefónica, Marc
O’Polo o Intersport.
En la figura 2.1 (página 7) podemos ver parte del proceso de reserva online que expone de
ejemplo Timify en su página web.

2.2 Reservio
Reservio [2] es un proyecto software que diseña sistemas de gestión de citas adaptán-
dose al sector del cliente. No aporta funcionalidades más allá de las comunes, como gestión
de calendarios, recordatorios, administración de clientes, integración con Google calendar o

5
CAPÍTULO 2. ESTADO DEL ARTE

estadísticas. Pero, teniendo en cuenta que ofrecen soluciones personalizadas, determinadas


funcionalidades más allá de estas, pueden no ser explotables dependiendo del sector.
Reservio trabaja para más de 150.000 negocios, entre las que se encuentran empresas del
calibre de Skoda, Allianz y Oracle. En la figura 2.2 (página 7) podemos ver la definición de
horarios de atención.

2.3 SimplyBook
SimplyBook [3] es la opción más interesante en cuestión de servicios. Ofrece integración
con Maps, Facebook e Instagram para poder solicitar citas a través de sus apps, plantillas para
páginas web en función del sector de negocio, gestión de ventas con TPV, sistema de puntos
para los clientes, pagos online, etc… También ofrecen acceso a su API.
Entre sus clientes figuran Paypal, Facebook y WordPress. En la figura 2.3 (página 8) se
visualiza un proceso de reservar mesa en una cafetería, en una de las plantillas que ofrece
SimplyBook.

2.4 Otras aplicaciones


Las aplicaciones anteriormente mencionadas son polivalentes, teóricamente se podrían
aplicar a cualquier tipo de negocio que quiera implementar un sistema de citas. Pero, existen
otras opciones especializadas en casuísticas de determinados sectores, ofreciendo una funcio-
nalidad de gestión de citas más afinada en esos sectores. Algunos ejemplos son:

• Virtuagym [4], dedicado al sector fitness.

• Combo [5], dedicado al sector de la restauración.

• Regiondo [6], especializado en el sector de actividades turísticas.

Incluso existen aplicaciones enfocadas a un determinado tipo de citas concretas, como es


el caso de Calendly [7], enfocado a las citas que se dan entre empleados dentro de la propia
empresa para meetings, entrevistas, llamadas, etc…

6
CAPÍTULO 2. ESTADO DEL ARTE

Figura 2.1: Ejemplo de reserva online de Timify

Figura 2.2: Definición de horarios de atención en Reservio

7
CAPÍTULO 2. ESTADO DEL ARTE

Figura 2.3: Plantilla de SimplyBook

8
Capítulo 3

Metodología

A continuación comentaremos cual es la metodología escogida para llevar a cabo este pro-
yecto, sus características, como la hemos usado y alternativas que han sido consideradas
con la justificación de su descarte.

3.1 Metodología escogida


Para el desarrollo de esta aplicación se ha elegido una metodología software iterativa. Se
planifica la implementación de la aplicación en bloques temporales, llamados iteraciones. Las
iteraciones son etapas de desarrollo, en las cuales se implementa un subconjunto de todos los
requisitos necesarios para alcanzar la completitud de la aplicación. Cuando una iteración se
termina, se obtiene un producto parcialmente terminado, pero totalmente funcional respecto
a los casos de uso desarrollados.
En nuestro caso, hemos hecho una etapa de análisis inicial, con un nivel suficiente de deta-
lle para estimar la carga de trabajo, identificando actores y casos de uso, para poder planificar
correctamente las iteraciones. Cada una de las iteraciones agrupa el desarrollo de casos de uso
relacionados lógicamente. Al principio del desarrollo de cada iteración, se realiza otra etapa
de análisis más detallado. Permitiendo identificar más fácilmente todas las situaciones que se
pueden dar al disparar el caso de uso.

3.2 Razonamiento de la elección


Este tipo de metodología tiene muchas ventajas enfocadas a satisfacer las necesidades del
cliente. En el caso de desarrollar los casos de uso más esenciales para la aplicación en las pri-
meras iteraciones, el producto puede ser usado ya por el cliente, para servir de prototipo y
retroalimentación para especificar las siguientes funcionalidades. A continuación, comenta-
mos las ventajas de este tipo de desarrollo que han sido explotadas en nuestro proyecto.

9
CAPÍTULO 3. METODOLOGÍA

Permite su uso parcial. El hecho de tener una aplicación, aunque no completa, funcional,
es explotable. Por ejemplo, al terminar una iteración, se puede utilizar como si tuviese un uso
real, permitiendo darse cuenta de errores que de otra manera sería más complicado identificar.
Cuesta menos realizar cambios en los requisitos. Debido a que los requisitos pueden sufrir
modificaciones en la fase de desarrollo, se puede hacer uso de la fase de análisis de la siguiente
iteración para modificar los requisitos.
Separación de intereses. La división en bloques facilita la detección de fallos al solo en-
capsularse en un determinado rango de código que estamos creando. El código anteriormente
implementado ya ha sido testado en su fase por lo tanto el origen del fallo no puede estar ahí.
Se podrían haber utilizado otros tipos de metodologías de desarrollo software, pero, por
desgracia, no se adecuaban correctamente a la concepción de nuestro producto.
El desarrollo en espiral está diseñado para ser usado en proyectos de grande tamaño, cuyos
requisitos son poco claros y complejos. Debido a que nuestro proyecto no es de complejidad
elevada, y tenemos los requisitos claramente definidos desde un primer momento, esta meto-
dología no es de gran utilidad.
La metodología SCRUM no es tan explotable, debido a que una de sus grandes ventajas es
el trabajo colaborativo, pero en el proyecto solo participamos mi tutor y yo. Además existen
roles como Product Owner que no se dan en nuestra situación.
Por último, no se ha utilizado el desarrollo en cascada, porque solo hay una fase de tes-
teo. Esto implica que todos los fallos que se pueden dar se van acumulando a lo largo de
la implementación, solo para ser detectados todos a la vez. Esto provoca volver a la fase de
implementación y, por lo tanto, romper el esquema del modelo en cascada.

10
Capítulo 4

Análisis de requisitos global

A continuación analizaremos cuales son los roles (actores) que pueden jugar nuestros usua-

su rol.
rios y cuales son las funcionalidades (casos de uso) que pueden utilizar en función de

4.1 Actores
El mayor factor limitante en cuanto a funcionalidades disponibles es estar registrado. Los
usuarios no registrado solo podrán buscar negocios y consultar sus detalles y reseñas. Los
usuarios registrados pueden tener tres categorías de permisos:

• Cliente: Todo usuario registrado como mínimo podrá disparar casos de uso asociados
a cliente, como consultar su historial de citas, solicitar cita, actualizar sus datos, etc…

• Empleado: Un empleado puede invocar las funcionalidades propias del cliente. Ade-
más, puede consultar el horario de citas que los clientes han solicitado con él y solicitar
cita para una persona que no pueda acceder a la aplicación.

• Dueño: El dueño de un negocio será el único que puede realizar modificaciones sobre
este, como sus datos,horarios, empleados, etc… Si el dueño lo desea también puede ser
empleado en su propio negocio.

4.2 Casos de uso


• CU-01 Usuario se registra: Un usuario puede crear una cuenta para poder identificar-
le, y por tanto reservar citas, registrar su negocio,etc… Para ello debe dar datos básicos
como nombre, apellidos, DNI, datos de contacto como correo electrónico y teléfono y
contraseña.

11
CAPÍTULO 4. ANÁLISIS DE REQUISITOS GLOBAL

• CU-02 Usuario inicia sesión: El usuario especifica su correo electrónico y su contra-


seña y, si sus credenciales son correctas, se autentica en la aplicación.

• CU-03 Usuario actualiza contraseña: El usuario puede cambiar su contraseña. Espe-


cifica la anterior y la nueva y se realiza el cambio. Cualquier usuario registrado puede
ejecutar este caso de uso.

• CU-04 Usuario actualiza perfil: El usuario puede cambiar alguno o todos sus datos,
se le presentan los ya existentes y cambia el que desee. Cualquier usuario registrado
puede ejecutar este caso de uso.

• CU-05 Usuario cierra sesión: Un usuario autenticado puede cerrar la sesión cuando
lo desee.

• CU-06 Usuario crea negocio: Cualquier usuario, dueño de un negocio, puede regis-
trarlo, para ello especifica datos básicos: nombre, descripción, teléfono, duración de ci-
tas,etc… Especifica también si en su negocio se reserva una cita con un empleado(e.g. un
psicólogo) o se reserva un material o recurso(e.g. un restaurante). Se le permite añadir
o eliminar estos recursos o empleados y en el caso de utilizar empleados puede añadirse
también él como empleado. Al añadir empleado este puede tener una cuenta previamen-
te creada o no. Por último también define los horarios de atención: hora de comienzo y
fin, fecha de comienzo de validez y fin y el día de la semana al que corresponde.

• CU-07 Dueño actualiza negocio: Cualquier usuario, dueño de un negocio e identifi-


cado, puede actualizar la información de su negocio. Puede cambiar datos básicos y/o
introducir/eliminar empleados/recursos.

• CU-08 Usuario busca negocios: Cualquier usuario, registrado o no, puede buscar ne-
gocios. Para ello puede utilizar su nombre, dirección, provincia o sector del negocio,
todos de manera opcional. Este proceso se ve ilustrado en la figura 4.1 (página 13).

• CU-09 Usuario consulta detalles de negocio: Cualquier usuario, registrado o no,


puede consultar los detalles de un negocio, pudiendo ver sus formas de contacto, hora-
rios de atención, lista de empleados, etc… Este proceso se ve ilustrado en la figura 4.2
(página 13).

• CU-10 Dueño modifica horario de atención: Cualquier usuario registrado, que dis-
ponga de un negocio, puede cambiar el horario de atención de este. Puede introducir
o eliminar horarios existentes. En el caso de eliminar un horario con citas pendientes
en él, se avisará de que serán eliminadas y se pedirá una justificación para avisar a los
clientes vía correo electrónico.

12
CAPÍTULO 4. ANÁLISIS DE REQUISITOS GLOBAL

Figura 4.1: Mockup de CU-06 Usuario busca negocios

Figura 4.2: Mockup de CU-09 Usuario consulta detalles de negocio

13
CAPÍTULO 4. ANÁLISIS DE REQUISITOS GLOBAL

• CU-11 Dueño gestiona bloqueos de empleados: Cualquier usuario registrado, que


disponga de un negocio que use empleados en sus citas, puede añadir/quitar bloqueos a
sus empleados. Estos bloqueos pueden ser estáticos o cíclicos. En el caso de ser cíclicos
se especifica día de la semana, fecha de inicio y fin de validez y horas de inicio y fin.
En el caso de ser estáticos se especifica fecha y hora de inicio y fecha y hora de fin. Si
hay citas pendiente, en un bloqueo que se vaya a introducir, se avisará de que esas citas
serán canceladas, y se pedirá una justificación para avisar a los clientes. Este proceso se
ve ilustrado en la figura 4.3 (página 14).

Figura 4.3: Mockup de CU-11 Dueño gestiona bloqueos de empleados

• CU-12 Empleado consulta su horario: Cualquier usuario, que esté trabajando para
un negocio, puede consultar las citas que sus clientes han reservado con él. En este
listado de citas se puede pinchar en una cita concreta para ir al detalle de esta.

• CU-13 Cliente solicita cita: Cualquier usuario registrado puede solicitar una cita des-
de el detalle de un negocio. Específica el empleado por el que quiere ser atendido o, sin
preferencia, y elige la fecha y hora disponible. Además, puede añadir observaciones so-
bre la cita para facilitar la preparación del empleado. Una vez solicitada la cita, se le
envía un correo electrónico, que confirma la reserva y contiene un enlace a los detalles
de la cita en la web. Este proceso se ve ilustrado en la figura 4.4 (página 16).

14
CAPÍTULO 4. ANÁLISIS DE REQUISITOS GLOBAL

• CU-14 Cliente consulta detalles de cita: Cualquier cliente puede consultar los deta-
lles de cualquier cita que haya reservado. En él se especifica el negocio, la fecha y hora,
el empleado, las observaciones,etc…

• CU-15 Cliente cancela cita: Cualquier cliente puede cancelar su cita desde el detalle
de esta, liberando la cita para que otro cliente pueda solicitarla.

• CU-16 Cliente consulta historial de citas: Cualquier cliente puede consultar un his-
torial de todas las citas que ha solicitado, hayan sido canceladas o no.

• CU-17 Empleado consulta detalles de una cita: Cualquier empleado puede consul-
tar los detalles de las citas solicitadas con él.

• CU-18 Empleado cancela cita: Cualquier empleado puede cancelar una cita que tenga
un cliente con él. Debe justificar la cancelación y se le enviará un correo electrónico
detallando la cancelación y el motivo.

• CU-19 Empleado solicita cita: Cualquier empleado puede solicitar una cita en su
negocio para un cliente que no puede usar la aplicación permanentemente o temporal-
mente. El cliente puede tener una cuenta creada o no. De tenerla creada solo se le pide el
DNI. De no tenerla creada se le piden nombre, apellidos, DNI y teléfono. Opcionalmen-
te, puede dar su correo electrónico, para crearle una cuenta en la aplicación. Finalmente,
indicar que un empleado puede pedir cita para sí mismo en su propio negocio.

• CU-20 Empleado constata que un cliente no se presentó: Cualquier empleado que


tenga una cita que ya haya ocurrido y cuyo cliente no haya acudido puede constatarlo.

• CU-21 Cliente añade una reseña de un negocio: Cualquier cliente, que haya tenido
una cita en un negocio, puede valorarlo. Para ello especifica una cualificación del 1 al
5, un título y una descripción.

• CU-22 Usuario consulta reseñas de un negocio: Cualquier usuario, no necesaria-


mente registrado, puede consultar las últimas reseñas del negocio.

• CU-23 Cliente añade cita a Google Calendar: La aplicación permite que cualquier
cliente pueda añadir una cita a Google Calendar, si tiene cuenta de Google. De esta
manera, el usuario, si lo desea, puede ver su cita reflejada en su calendario personal,
junto con el resto de eventos personales. La aplicación añade la cita a Google Calendar,
indicando el nombre y localización del negocio, así como un recordatorio.

15
CAPÍTULO 4. ANÁLISIS DE REQUISITOS GLOBAL

Figura 4.4: Mockup de CU-13 Cliente solicita cita

16
Capítulo 5

Planificación

E n este capítulo explicaremos como se han estructurado las iteraciones de la metodología


aplicada, exponiendo el trabajo que se tiene que hacer en cada una de ellas. Las itera-
ciones de desarrollo (1-6, ambas inclusive) agrupan casos de uso relacionados por su lógica.
Tenemos que tener en cuenta que determinados casos de uso dependen lógicamente de otros.
Un ejemplo simple es que un cliente no puede solicitar una cita sin que se puedan crear nego-
cios, pero también depende de que existan bloqueos, debido a que una cita no se puede efectuar
en donde haya un bloqueo. Estos factores se han tenido en cuenta a la hora de planificar las
iteraciones.

5.1 Iteraciones

5.1.1 Iteración 0
En esta iteración se ha definido cual es la meta del proyecto y determinado su alcance. Se
ha llevado a cabo la fase de análisis, describiendo historias de usuario y diseñando wireframes
que han ayudado a definir adecuadamente los actores y casos de uso finales.

5.1.2 Iteración 1
En esta iteración da comienzo a la fase de implementación. Se crea un proyecto Spring
Boot Maven para el desarrollo backend y un proyecto Npm React para el frontend. Se empieza
por los casos de uso relacionados con la gestión de la cuenta del usuario. Además se aborda
la formación en la librería Material-UI, aunque esta no se ve implementada hasta la iteración
2. Los casos de uso desarrollados son:

• CU-01 Usuario se registra

• CU-02 Usuario inicia sesión

17
CAPÍTULO 5. PLANIFICACIÓN

• CU-03 Usuario actualiza contraseña

• CU-04 Usuario actualiza perfil

• CU-05 Usuario cierra sesión

5.1.3 Iteración 2
En esta iteración se implementan los casos de uso relacionados a la gestión de negocios
por parte de los dueños y la búsqueda de información por parte de los clientes. Además, se
implanta Material-UI en todos los componentes anteriores.

• CU-06 Usuario crea negocio

• CU-07 Dueño actualiza negocio

• CU-08 Usuario busca negocios

• CU-09 Usuario consulta detalles de negocio

5.1.4 Iteración 3
En esta iteración se implementan los casos de uso relacionados a la gestión de los horarios
por parte del dueño y los empleados.

• CU-10 Dueño modifica horario de atención

• CU-11 Dueño gestiona bloqueos de empleados

• CU-12 Empleado consulta su horario

5.1.5 Iteración 4
En esta iteración se implementan los casos de uso relacionados a la gestión de citas por
parte de los clientes.

• CU-13 Cliente solicita cita

• CU-14 Cliente consulta detalles de cita

• CU-15 Cliente cancela cita

• CU-16 Cliente consulta historial de citas

18
CAPÍTULO 5. PLANIFICACIÓN

5.1.6 Iteración 5
En esta iteración se implementan los casos de uso relacionados a la gestión de citas por
parte de los empleados.

• CU-17 Empleado consulta detalles de una cita

• CU-18 Empleado cancela cita

• CU-19 Empleado solicita cita

• CU-20 Empleado constata que un cliente no se presentó

5.1.7 Iteración 6
En esta iteración se implementan los casos de uso relacionados con las reseñas y el calen-
dario de Google.

• CU-21 Cliente añade una reseña de un negocio

• CU-22 Usuario consulta reseñas de un negocio

• CU-23 Cliente añade cita a Google Calendar

5.1.8 Iteración 7
En esta iteración se redacta la memoria y se aprovecha para subsanar algunos defectos de
la aplicación.

19
CAPÍTULO 5. PLANIFICACIÓN

5.2 Planificación temporal


Al principio de cada una de las iteraciones se estimó cuantas horas llevaría completar la
iteración. Estas estimaciones se desvían, por lo general, de una manera subestimada, lo cual se
debe principalmente a la inexperiencia. Las fechas descritas son las que produjeron al llevar
a cabo las horas de trabajo reales, dedicando 3 horas diarias aproximadamente.

Iteración Fecha inicio Fecha fin Estimación (h) Tiempo real (h)
Iteración 0 08/06/2022 14/06/2022 10 12
Iteración 1 15/06/2022 21/06/2022 7 10
Iteración 2 22/06/2022 10/07/2022 45 54
Iteración 3 11/07/2022 28/07/2022 50 55
Iteración 4 29/07/2022 08/09/2022 90 118
Iteración 5 09/09/2022 24/09/2022 40 48
Iteración 6 25/09/2022 05/10/2022 20 25
Iteración 7 06/10/2022 27/10/2022 50 57
TOTAL 08/06/2022 10/10/2022 312 379

Tabla 5.1: Planificación del proyecto y duración estimada y real

Como se puede observar, la iteración 4 llevó una cantidad considerable de tiempo com-
parada al resto de iteraciones. El caso de uso cliente solicita cita, no solo llevó mucho tiempo
debido a la implementación de su lógica y la implementación de su interfaz de usuario, si no
que además también conllevó modificaciones en casos de uso anteriores.

5.3 Cálculo de costes


A continuación se realizan cálculos para determinar el coste que ha llevado finalizar este
proyecto. Para el coste de horas trabajadas se utiliza un importe de 30 euros/hora.

Coste de las horas trabajadas = 379 horas * 30 euros/hora = 11.370 euros

Además de las horas trabajadas hay costes asociados a servicios y recursos. Para calcular
los costes de los servicios y recursos se consideró cuanto tiempo habría llevado realizar el
proyecto trabajando a tiempo completo, es decir, 160 horas/mes.

Tiempo a jornada completa = 379 horas / 160 horas/mes = 2,37 meses

20
CAPÍTULO 5. PLANIFICACIÓN

Para simplificar las cifras se ha usado una aproximación de dos meses y medio. Se ha
asumido un trabajo telemático desde casa. Los recursos que han sido necesarios para llevar a
cabo este proyecto y sus costes asociados son los siguientes:

• Equipamiento informático: Equipamiento informático profesional para el desarrollo


de proyectos software. Consta de: un ordenador de sobremesa, dos pantallas, ratón y
teclado. Su coste es de 1.600 euros, considerando un tiempo de amortización de 3 años
el coste es de 1600 * (2,5/36) = 110 euros aproximadamente.

• Electricidad: Hacemos una aproximación de 50 euros/mes el coste de la electricidad


imputable al proyecto. 50 * 2,5 = 125 euros.

• Internet: Se asume un coste de internet imputable al proyecto de 20 euros/mes, resul-


tando en 50 euros.

Concepto Coste(euros)
Horas trabajadas 11.370
Equipamiento informático 110
Electricidad 125
Internet 50
Coste total del proyecto 11.655

Tabla 5.2: Cálculo del coste real del proyecto

21
Capítulo 6

Fundamentos tecnológicos

E n este capítulo se hará una descripción de cada una de las tecnologías utilizadas para
llevar a cabo este proyecto.

6.1 Tecnologías utilizadas en el backend

6.1.1 Java
Java es un lenguaje de programación orientado a objetos, imperativo y con tipado fuerte
y estático. Fue diseñado con el objetivo de obtener un lenguaje orienta a objetos, fácil de usar
y que se pudiese ejecutar en diferentes sistemas operativos. Esto último es posible gracias a
que, cuando se compila una aplicación, se generan archivos .class de código binario a partir
de los archivos de código fuente .java. Los archivos .class más tarde pueden ser interpretados
y ejecutados por una Java Virtual Machine (JVM) específica para el sistema operativo.

Figura 6.1: Ilustración de la ejecución de un programa en una JVM

22
CAPÍTULO 6. FUNDAMENTOS TECNOLÓGICOS

6.1.2 Maven
Maven [8] es una herramienta software utilizada para la gestión y construcción de proyec-
tos Java. Maven utiliza su Project Object Model (POM) en un archivo de formato eXtensible
Markup Language (XML) ([Link]) para definir la lógica de construcción del proyecto. Se
definen dependencias, plugins que se descargan de repositorios en línea y el ciclo de vida del
proyecto, entre otros. El ciclo de vida son una serie de fases que a su vez tienen goals o metas.
Las fases más importantes son: compile,test,package,install y deploy, aunque existen otras
opcionales que se pueden añadir y configurar mediante plugins.

6.1.3 Spring
Spring [9] es un framework de desarrollo de aplicaciones Java. Spring nos permite simpli-
ficar el acceso a datos mediante Spring Data, configurar autenticación y seguridad mediante
Spring Security o configuración automática y despliegue gracias a Spring Boot. Si entramos
en un grano más fino algunas de sus características más importantes son: inyección de de-
pendencias,configuración de Data Access Object (DAO), despliegue de aplicaciones web, in-
ternacionalización o validación, y gracias a Spring Boot todas estas utilidades no se necesitan
configurar.

6.1.4 MySql
MySql [10] es un sistema de gestión de base de datos relacional desarrollado por Oracle.
Tiene funcionalidades como indexación, transaccionalidad, claves foráneas, replicación,etc…
En este proyecto se ha utilizado MySql Workbench [11], herramienta gráfica que agiliza la
manipulación de base de datos.

6.1.5 Postman
Postman [12] es una herramienta que permite enviar peticiones HTTP a API REST pu-
diendo establecer cabeceras, cuerpo, parámetros, etc… Es de gran utilidad para testear la co-
municación con el backend.

6.1.6 Jacoco
Jacoco [13] es una herramienta que permite analizar la cobertura de código de los tests
realizados en Java. En determinados casos de uso se ha querido alcanzar una mayor cobertura
debido a la complejidad de la lógica de negocio.

23
CAPÍTULO 6. FUNDAMENTOS TECNOLÓGICOS

6.1.7 Eclipse
Eclipse [14] es un Integrated Development Environment (IDE). Un IDE a parte de permi-
tirnos editar código nos provee de funcionalidades a mayores para facilitar la programación,
como funciones de auto-completado, debugger, refactorización, compiladores, etc…

6.2 Tecnologías utilizadas en el frontend

6.2.1 JavaScript
JavaScript es un lenguaje de programación multi-paradigma, imperativo y con tipado débil
y dinámico. Su principal uso es el de escribir funciones embebidas en páginas HyperText
Markup Language (HTML) que interactúen con el DOM de estas. Como ya comentamos en
capítulos anteriores cuando los usuarios acceden a nuestra página web se traen archivos JS al
navegador. Estos archivos JavaScript son los que responden a las interacciones del usuario con
la página web, por ejemplo pulsando un botón, y son los archivos JavaScript los encargados
de realizar las llamadas al backend y modificar la interfaz de usuario acordemente.

6.2.2 React
React [15] es una librería de JavaScript que permite diseñar interfaces de usuario para
Single Page Application (SPA) utilizando componentes. Los componentes son piezas reusables
de la interfaz, que a su vez pueden tener otras piezas dentro, como se ilustra en la figura 6.2.

Figura 6.2: Ilustración de una interfaz de usuario con componentes

24
CAPÍTULO 6. FUNDAMENTOS TECNOLÓGICOS

Sus dos mayores características son el uso de un DOM virtual y JavaScript XML (JSX). Rea-
lizar modificaciones en el DOM real del navegador es una operación costosa, porque cuando
se rerenderiza uno de los elementos se rerenderizan en cascada todos sus hijos, hayan cambia-
do o no. Por esa razón, se utiliza un DOM virtual, una representación del DOM real guardado
en memoria, sobre el cual se realizan los cambios primero. Una vez actualizado el DOM vir-
tual se calcula la diferencia con el DOM real para calcular la forma más óptima de realizar los
cambios, produciendo una menor cantidad de renderizaciones.
JSX es una extensión del sintaxis de JavaScript, similar a HTML, que permite estructurar
la renderización de un componente. JSX nos permite, entre otras cosas, añadir expresiones
JavaScript mediante el uso de corchetes o hacer renderización condicional, mostrada en el
ejemplo siguiente.
1 const App = () => {
2 const i = 1;
3
4 return (
5 <div>
6 <h1>{ i === 1 ? 'true' : 'false' }</h1>
7 </div>
8 );
9 }

6.2.3 React Redux


React Redux [16] es una librería JavaScript utilizada para gestionar el estado de aplica-
ciones. Para ello Redux nos dispone de un store, un objeto en forma de árbol. El estado de
esta store es de sólo lectura y se manipula mediante el uso de actions, un objeto que describe
qué es lo que tiene que ocurrir. Para especificar como tiene que cambiar el estado de la store
cuando se produce una action se utilizan reducers. Los reducers son funciones que obtienen el
estado anterior y la action y devuelven un nuevo estado. Para que los componentes de React
puedan acceder al estado de Redux se nos provee de un hook llamado useSelector.

6.2.4 Material-UI
Material-UI [17] o MUI es una librería de JavaScript con herramientas utilizadas para di-
señar la interfaz de usuario. MUI fue diseñado implementando Material Design, un sistema
de diseño que busca mejorar la experiencia de usuario en todos los sentidos. MUI nos provee
de componentes React, con CSS y animaciones ya implementadas, que nos permite obtener
una interfaz más amigable y estéticamente agradable.

25
CAPÍTULO 6. FUNDAMENTOS TECNOLÓGICOS

6.2.5 Npm
Npm [18] es un sistema de gestión de paquetes para Javascript. Para ello se hace uso
del archivo [Link]. Este archivo especifica los paquetes que se quieren utilizar y sus
versiones. En nuestro caso se han utilizado paquetes de librerías anteriormente mencionadas:
React, React-Redux, Material-UI, etc…

6.2.6 Redux DevTools


Redux DevTools [19] es una extensión presente en varios navegadores web que nos per-
mite debuggear el estado de Redux. Nos permite ver el estado actual, las actions que se han
disparado y como ha ido cambiando el estado en función de estas.

6.2.7 Visual Studio Code


Visual Studio Code [20] o VS Code es un editor de código fuente desarrollado por Micro-
soft. Aunque no es un IDE, debido a que tiene un número mucho menor de funcionalidades,
tiene soporte para debugging, integración con git, refactorización de código, etc… En la en-
cuesta anual de Stack Overflow a desarrolladores fue la primera opción como editor de código
para un 71% de las personas.

6.3 Tecnologías complementarias

6.3.1 Git
Git [21] es un sistema de control de versiones. Su función principal es tener trazabilidad de
las versiones de un producto software, es decir, tener un historial de los cambios introducidos.
Aunque muchas de sus características no han sido explotadas en este proyecto, debido a que
solo hay una persona desarrollando, el hecho de tener una copia remota, y tener controlados
los cambios efectuados sobre el producto, brinda seguridad y facilita tareas de programación
como detección de fallos.

6.3.2 Docker
Docker [22] es una herramienta utilizada para automatizar el despliegue haciendo uso
de contenedores. Un contenedor es una virtualización de un sistema operativo aislado del
resto de procesos de una máquina. Esto nos permite desplegar nuestra aplicación de manera
eficiente, rápida y portable.

26
Capítulo 7

Desarrollo

A continuación se explicará, con detalle, el proceso que se ha seguido para desarrollar


los casos de uso a lo largo de las iteraciones. También comentaremos la estructura de
ficheros y el modelo de datos, necesario para entender el funcionamiento de la aplicación.

7.1 Estructura de la aplicación

7.1.1 Estructura del backend


El backend es un proyecto Maven que usa Spring Boot y su estructura es la siguiente:

• /src/main/java/es/udc/fic: Directorio que contiene todo el código fuente escrito en


Java

– model: Paquete que contiene todos los archivos necesarios para gestionar la ló-
gica de negocio, incluyendo entidades, DAOs, excepciones, todos dando soporte a
los servicios locales, que son los que definen la lógica, dando vida a la capa modelo.
∗ entities: En esta carpeta están definidas todas las entidades que son utiliza-
das por el mapeador objeto-relacional mediante el uso de anotaciones como
@Entity, dando vida a la capa de acceso a datos. Existen anotaciones @Many-
ToOne y @OneToMany para declarar las relaciones N:1 y 1:N existentes en
el modelo de datos. Por otra parte los archivos terminados en *[Link] son
los archivos Data Access Object, implementados con JPA e hibernate, que nos
permiten comunicarnos con la base de datos con operaciones como save, de-
lete, count, findAll, etc… También nos permite especificar nuestras propias
consultas sobre la base de datos.
∗ exceptions: Clases que especifican qué excepciones se pueden dar al imple-
mentar la lógica de negocio, por ejemplo, cuando se intenta reservar cita en

27
CAPÍTULO 7. DESARROLLO

una hora en la que hay un bloqueo se lanza la excepción DateIsBlockedEx-


ception.
∗ services: Contiene los archivos que definen e implementan la lógica de ne-
gocio.
– rest: En este paquete se define la capa de servicios mediante el uso de contro-
ladores REST, objetos Data Transfer Object (DTO) y definiendo parámetros de
seguridad.
∗ common: Se definen las respuestas a excepciones comunes que puede lanzar
la capa modelo y aspectos de seguridad como el JSON Web Token (JWT) [23]
y filtros de permisos.
∗ controllers: Se definen los controladores REST. Los controladores reciben
las peticiones HTTP procedentes del frontend, invocando una operación del
backend y devolviendo la respuesta al frontend. También se definen las res-
puestas que se dan cuando se producen excepciones.
∗ dtos: Se definen los objetos que Spring mapeará a JavaScript Object Notation
(JSON) para ser recibidos y devueltos por los controladores.
– [Link]: Clase raíz de un proyecto Spring.

• /src/main/resources: Ficheros properties que definen el texto internacionalizado de


las excepciones y fichero .yml que define parametros del proyecto Spring, como datos
necesarios para envíos de emails, datasources para el acceso a base de datos, etc…

• /src/sql: Ficheros .sql que definen el modelo de datos para su ejecución en MySql.

• /src/test: Ficheros que definen los tests automatizados con el uso de junit.

• /[Link]: Fichero de configuración Maven.

• /target: Contiene los artefactos generados por Maven (e.g. ficheros .class, ficheros .jar,
etc.).

7.1.2 Estructura del frontend


• /src: Carpeta donde se guardan todos los archivos JavaScript.

– /backend: Ficheros que establecen la comunicación con el mediante el uso de


fetch para enviar peticiones HTTP.
– /config: Ficheros de constantes.
– /i18n: Ficheros de internacionalización.

28
CAPÍTULO 7. DESARROLLO

– /modules: Carpeta con directorios que dividen los componentes agrupándolos


por lógica de negocio. Cada uno de estos directorios tiene una carpeta compo-
nents, con los componentes React; un fichero actions, que define las acciones que
se pueden llevar a cabo para comunicarse con el backend y la store de Redux; ac-
tionTypes, definiendo cuales son las acciones; reducer, definiendo como se com-
porta Redux en base al estado anterior y la action disparada; selectors exponiendo
a los componentes acceso al store de redux.
– /store: Ficheros de configuración de la store de Redux.

• /public: Carpeta con el [Link] e imágenes.

• /[Link]: Fichero de configuración de Npm que define las dependencias.

7.2 Modelo de datos


Como se puede visualizar en la figura 7.1 (página 30) en el centro tenemos el negocio. El
negocio puede tener varios empleados, pero estos empleados solo pueden trabajar para un
negocio. El negocio tiene un solo usuario dueño, el cual puede regentar varios negocios.
Mediante la entidad usuario modelamos 3 tipos de usuarios: cliente, propietario y emplea-
do. Un usuario puede tener varias citas sobre varios negocios pudiéndose repetir estos. La cita
involucra a otro usuario, un empleado, o a un recurso. La cita tiene 4 estados posibles, que no
están en la base de datos, pero se deducen a partir de sus atributos.
Un negocio tiene una sola provincia y una sola categoría, además tiene varios horarios.
Para adecuar los horarios a la realidad de los empleados estos disponen de bloqueos estáticos
y recurrentes.
Por último un usuario puede realizar un comentario o reseña sobre varios negocios, sin
poder repetirse, y el negocio puede tener varios comentarios de usuarios diferentes.

29
CAPÍTULO 7. DESARROLLO

Figura 7.1: Modelo de datos

30
CAPÍTULO 7. DESARROLLO

7.3 Iteración 1

7.3.1 Análisis
Empezamos creando los proyectos Maven para el backend y React para el frontend, aña-
diendo sus respectivas dependencias y configuraciones necesarias. Implementamos, primero,
todo el backend de los casos de uso, los testamos para asegurarnos de que no hay ningún fallo
y procedemos a implementar el frontend. Este modus operandi produce el menor cambios de
contexto entre Java y JavaScript reduciendo la cantidad de fallos posibles.
Los casos de uso desarrollados son los de gestión de la cuenta de usuario:

• CU-01 Usuario se registra

• CU-02 Usuario inicia sesión

• CU-03 Usuario actualiza contraseña

• CU-04 Usuario actualiza perfil

• CU-05 Usuario cierra sesión

7.3.2 Diseño e implementación


En esta iteración implementamos todos los casos de uso relacionados con la gestión de la
cuenta de usuario, tanto en el backend, como en el frontend. Empezamos creando los scripts
.sql a partir del modelo de datos y los ejecutamos en una base de datos en MySql. Creamos
un proyecto Maven Spring Boot, añadimos la configuración de los data sources para poder
acceder a la base de datos,las dependencias de Spring en el [Link] y la configuración del
plugin JaCoCo.
Creamos el esqueleto del frontend mediante el uso del comando npm create-react-app y
añadimos en el [Link] las dependencias necesarias.
CU-01 Usuario se registra
Este caso de uso tiene como entrada nombre, apellidos, contraseña, correo electrónico,
teléfono y DNI. Como resultado el usuario tiene una cuenta creada en nuestra aplicación a la
que puede acceder cuando lo desee.
El caso de uso comienza implementando la entidad usuario y el DAO correspondiente en
el backend. A continuación creamos la interfaz UserService, indicando cuales son las entradas
y salidas del caso de uso. Creamos las excepciones que se pueden dar al registrarse usuario,
como DuplicateInstanceException, que es una excepción genérica lanzada cuando se intentan
introducir entidades duplicadas. Creamos la clase UserServiceImpl que implementa la inter-
faz anteriormente mencionada. Inyectamos el DAO de la entidad usuario mediante el uso de

31
CAPÍTULO 7. DESARROLLO

@Autowired e implementamos la lógica de caso de uso, no pudiéndose repetir los campos


de correo electrónico y DNI y codificando la contraseña. Escribimos tests automatizados, los
ejecutamos y comprobamos que la lógica de negocio está correctamente implementada.
Por último, implementamos un DTO para usuario y el controlador REST, UserController,
que permite peticiones HTTP, y realizará llamadas a UserService. Testeamos su correcto fun-
cionamiento mediante el uso de Postman. También implementamos la gestión de JWT, que
nos permite realizar autenticación y autorización de manera segura. Cuando un usuario se
registra o autentica correctamente, es decir, es quien dice ser, le devolvemos este token, que
utilizará en las consecuentes llamadas al backend. Esto permitirá identificarle y saber si puede
o no ejecutar ciertos casos de uso en función de quién es.
Concluye así la implementación del backend del caso de uso, el cual ha seguido un proce-
dimiento que se repetirá en todos los casos de uso.
Para el diseño del frontend, empezamos implementado las llamadas al backend, mediante
peticiones asíncronas fetch y la llamada específica para el caso de uso en el archivo userSer-
vice. Cuando se registra correctamente, guardamos la información del perfil del usuario junto
con su token en el estado de Redux. Además guardamos el token en sessionStorage, de manera
que, si se recarga la página, se pueda identificar a partir de este.
Implementamos toda la configuración necesaria de la store de Redux y Redux Thunk [24],
un paquete Npm que nos permite hacer llamadas asíncronas a actions que requieran llamadas
al backend. Implementamos las actions signUp y signUpCompleted, que nos permiten llamar
al backend y guardar la respuesta en el estado de Redux respectivamente. Creamos el reducer
y selectors que nos permiten modificar y recuperar el estado de Redux respectivamente.
Creamos el componente SignUp, ilustrado en la figura 7.2 (página 35), que tendrá un
formulario con el cual interactúa el usuario para insertar las datos necesarios para registrarse.
Para almacenar estos datos hacemos uso del hook de React useState, que nos permite gestionar
el estado de un componente. El hook nos devuelve una dupla que nos permite acceder al valor
y cambiarlo mediante una función. Un ejemplo del hook usado en el componente:
1 const [firstName, setFirstName] = useState('');

Para implementar el formulario se hace uso de los componentes Typography,Box, Text-


Field y Button provistos por MUI. A lo largo del desarrollo se ha usado el TextField frecuen-
temente estructurado de la siguiente forma:
1 <TextField
2 margin="normal"
3 sx={{ width:'50%'
4 }}
5 required

32
CAPÍTULO 7. DESARROLLO

6 type="text"
7 id="firstName"
8 label={useFormatMessage('[Link]')}
9 autoFocus
10 value={firstName}
11 onChange={e => setFirstName([Link])}
12 error={firstName === "" && validation}
13 helperText={firstName === "" && validation ?
14 requiredMessage() : ' '}
15 />

Las propiedades definidas nos ayudan a establecer una mejor comunicación con el usuario
y una estética más agradable. La propiedad sx de MUI, de gran utilidad, nos permite modi-
ficar el CSS sin escribir un .css. La propiedad label nos ayuda a etiquetar el campo para que
lo identifique el usuario. Las propiedades value y onChange nos permiten identificar y cam-
biar su valor. Las propiedades error y helperText, dependientes de un estado del componente,
validation, nos permite cambiar su forma en caso de que no haya sido introducido un valor.
En el caso de que el formulario no responda true al metodo checkValidity ponemos a true
validation, de manera que si algún TextField está vacío y validation es true se enseñará el
helperText, que indica que es necesario rellenar ese campo y se pondrá a true la propiedad
error, que cambia el estilo del campo para ponerlo rojo, adquiriendo una interfaz más estética
y con mejor feedback.

Debido a que la contraseña es un dato sensible y que queremos estar seguros de que el
usuario la ha escrito correctamente, añadimos un campo extra, para asegurar que la contra-
seña introducida no tenga errores de escritura.
Por último, haciendo uso de la librería react-intl [25] y su hook useIntl y el componente
FormattedMessage, internacionalizamos la interfaz de usuario.

CU-02 Usuario inicia sesión


La entrada de este caso de uso es el correo electrónico y la contraseña con la que se ha
registrado el usuario. En caso de que los datos provistos coincidan con los de algún usuario
existente en la base de datos se le identifica como tal.
Empezamos implementando la lógica de negocio en el backend. Primero, debido a que el
usuario se identifica por correo electrónico debemos implementar la búsqueda por el campo
email en el DAO. También debemos implementar la excepción IncorrectLoginException, en
caso de que el correo electrónico no exista o la contraseña sea errónea. Codificamos el caso
de uso propiamente dicho, que busca en la base de datos un usuario con el correo electrónico
provisto, codifica la contraseña (haciendo uso de Spring Security) y la compara con la del

33
CAPÍTULO 7. DESARROLLO

usuario. Si alguna de estas dos operaciones falla devolvemos la excepción, si no, devolvemos el
usuario encontrado en base de datos. El controlador REST recibirá una petición POST, llamará
a este caso de uso y devolverá, además de la información del usuario, el token JWT.
En el frontend implementamos la llamada al backend, las actions login y loginCompleted
que llaman al backend y confirman la respuesta del backend respectivamente. Implementa-
mos el componente Login, ilustrado en la figura 7.3 (página 35), un simple formulario con
TextField correo electrónico y contraseña. Se ha desarrollado un componente Errors para
que cualquier otro componente que haga llamadas al backend pueda mostrar errores en caso
de que se produzcan.
También se hace uso del componente Link, provisto por el paquete npm react-router-
dom, que nos permite navegar la página y cambiar los componentes mostrados en función de
la ruta del navegador. En este caso, el Link cambiaría la ruta a /users/signup, que renderiza
el componente SignUp en caso de que el usuario aún no tenga una cuenta creada. Para poder
identificar al usuario a partir del token guardado en sessionStorage implementamos una action
que se dispara cada vez que se renderice la app.

34
CAPÍTULO 7. DESARROLLO

Figura 7.2: Formulario de registro

Figura 7.3: Formulario de iniciar sesión

35
CAPÍTULO 7. DESARROLLO

CU-03 Usuario actualiza contraseña


El usuario introduce la contraseña antigua (debido a que es una operación sensible) y la
contraseña nueva y se efectúa el cambio.
La lógica de negocio implementada en el backend es sencilla, se obtiene la contraseña
antigua y nueva, se comprueba que la contraseña antigua es la actual y se efectúa el cambio.
Se ha implementado también una clase PermissionChecker para hacer comprobaciones de
control de acceso, debido a que no tenemos roles de usuario estas comprobaciones se hacen
todas a través del id del usuario. Se testea, se añade un DTO con la contraseña nueva y antigua
y una operación POST en el controlador quedando finalizado el backend.
En el frontend se implementa la llamada al backend, la action correspondiente y un com-
ponente ChangePassword con un formulario para introducir los datos. Se vuelve a pedir
la contraseña nueva dos veces para evitar fallos de escritura. Este caso de uso junto con los
CU-04 Actualiza perfil y CU-05 son accesibles mediante un desplegable, situado en el extremo
derecho del componente Header, como se visualiza en la figura 7.4 (página 36).

Figura 7.4: Parte del componente Header con el desplegable con operaciones para el usuario

CU-04 Usuario actualiza perfil


Tiene como entrada el nombre, apellidos, correo electrónico, DNI y teléfono y de salida
el usuario actualizado. La lógica de negocio es simple, buscamos el usuario a través del id
provisto por el JWT. Comprobamos si el DNI o el correo electrónico, datos que le identifi-
can inequívocamente han cambiado, en caso de cambiar, estos no pueden coincidir con unos
ya existentes, si se da el caso lanzamos una excepción de duplicado. En caso contrario pro-
cedemos a la actualización de los datos. Lo testeamos y añadimos una petición PUT en el
controlador de usuario.
En el frontend se implementan la llamada al backend, la action correspondiente y el com-
ponente UpdateProfile con un formulario. Para renderizar el componente, es necesario obte-
ner los datos del perfil del usuario, pero no es necesario llamar al backend ya que disponemos
de estes datos en el estado de Redux. Accedemos a ellos mediante el hook de Redux useSelec-
tor. Cuando se ejecuta la action que llama al backend, en caso de que la respuesta sea correcta,
se actualiza el estado de Redux correspondiente al perfil del usuario.

36
CAPÍTULO 7. DESARROLLO

1 const user = useSelector([Link]);

CU-05 Usuario cierra sesión


Cerrar sesión es una operación que no necesita consultar ni efectuar cambios en la base
de datos, es una operación íntegra del frontend. Cuando se efectúa se borra el token de ses-
sionStorage, por tanto cuando se actualice la página no se va a poder identificar a través de él
y queda la sesión cerrada.

37
CAPÍTULO 7. DESARROLLO

7.4 Iteración 2

7.4.1 Análisis
En esta iteración se desarrollarán los casos de uso relacionados a la gestión del negocio
por parte del dueño y la búsqueda de información de negocios por parte del cliente. Los casos
de uso a desarrollar son:

• CU-06 Usuario crea negocio

• CU-07 Dueño actualiza negocio

• CU-08 Usuario busca negocios

• CU-09 Usuario consulta detalles de negocio

7.4.2 Diseño e implementación


Para la implementación de esta iteración se crea un nuevo servicio, BusinessService. Debi-
do a que la búsqueda de negocios va a ser paginada se crea una entidad Block que contiene los
negocios buscados y un booleano indicando si existen más negocios para la paginación. Tam-
bién se empiezan a hacer comprobaciones comparando atributos LocalDate y LocalDateTime
por tanto se ha creado una clase auxiliar DateAndTimeValidator que nos ayuda a realizar estas
comparaciones.
CU-06 Usuario crea negocio
Para crear un negocio el usuario especifica un nombre, descripción, dirección, teléfono,
correo electrónico, categoría, provincia, cual es la duración de las citas, un listado de horarios
y un listado de empleados o recursos. Como resultado el negocio queda creado y el usuario
pasa a ser dueño de ese negocio.
Antes de implementar la lógica de negocio se crean excepciones que se pueden dar: Exis-
tingScheduleException y EmployeeAlreadyWorkingException. En la lógica de negocio, nos
aseguramos de que no exista un negocio con ese nombre, que la categoría y provincia exis-
ten y creamos el negocio. Comprobamos que ninguno de los horarios se superponga, en caso
contrario lanzamos ExistingScheduleException. En caso de que use recursos los insertamos
en la base de datos. En caso contrario recorremos la lista de empleados provista atendiendo a
varias casuísticas. Puede haber tres tipos de empleados en la lista: el propio dueño, un usuario
con cuenta ya creada y un usuario sin cuenta. Si el empleado ya tiene cuenta creada hay que
comprobar que exista. Si el empleado aún no tiene cuenta, hay que comprobar que no existe
una cuenta con sus datos de identificación, crearle una cuenta con los datos provistos y en-
viarle un correo electrónico para que establezca él la contraseña. En caso de que cualquiera de

38
CAPÍTULO 7. DESARROLLO

los usuarios de la lista esté trabajando ya para otro negocio de la aplicación se lanza la excep-
ción EmployeeAlreadyWorkingException. Lo testeamos a fondo debido a que es un caso de
uso importante, creamos los DTO pertinente y una llamada POST en un nuevo controlador de
negocios. Terminamos implementando un caso de uso muy sencillo que no se ha mencionado,
consistente en buscar a un usuario por su DNI, que necesitaremos más adelante.
Para la implementación del frontend del caso de uso, se ha hecho uso de un formulario,
modales y listas para lograr una buena comunicación con el usuario. Para los modales se ha
usado el componente Modal de MUI, y para las listas el componente Table y sus componentes
asociado TableContainer, TableHead, TableRow y TableCell. En el diseño del formulario
se han usado TextField para nombre, descripción, teléfono, correo electrónico, dirección y
duración de citas. Para establecer la categoría y provincia se hace uso de componentes Cate-
gorySelector y ProvinceSelector, que serán reutilizados más tarde en el caso de uso buscar
negocios.
Después se usa un Switch para preguntar si el negocio utiliza recursos, de ser así, mos-
tramos un botón y una lista de recursos, o en el caso contrario, el cual es por defecto, se
muestra un Checkbox para saber si el dueño es empleado también, además del botón y lista
de empleados. Esta sección del formulario se ve ilustrada en la figura 7.6 (página 40).
Para añadir un empleado/recurso se hace uso de un modal, AddEmployeeDialog/Ad-
dResourceDialog, ilustrado en la figura 7.10 (página 48), con un formulario, AddEmplo-
yeeForm/AddResourceForm. En caso de que sean recursos, se pide un nombre y cantidad
y se comprueba que en el estado del componente no exista un duplicado. De ser empleados
hay que atender a dos casuísticas, empleado con cuenta o sin cuenta. De tener cuenta solo le
pedimos el DNI, hacemos una pequeña llamada al backend, para recuperar su nombre, ape-
llidos, DNI y correo electrónico para mostrarlos en el componente EmployeeList. En caso
contrario se le piden estos datos para que, cuando se finalice la creación del negocio, se le
envíe un correo, que le redireccionará a un formulario en el que establezca su contraseña y
quede así creada su cuenta.
Por último otra dupla de botón, AddScheduleDialog, y lista, ScheduleList, para añadir
y visualizas los horarios. Aunque la comprobación de que no se superpongan ya se hace en el
backend, también la hacemos en el momento de insertar los datos para no realizar llamadas
innecesarias.
CU-07 Dueño actualiza negocio
El dueño si lo desea puede cambiar la información de sus negocios y sus empleados/recur-
sos… No podrá cambiar la duración de las citas ni si su negocio utiliza empleados o recursos
en sus citas.
Empezamos implementando las operaciones de los DAO de recursos y empleados que nos
permita buscarlos por su negocio asociado. Diseñamos la lógica de negocio empezando por

39
CAPÍTULO 7. DESARROLLO

Figura 7.5: Ventana modal con el formulario para añadir empleado

Figura 7.6: Parte final del formulario de crear negocio

40
CAPÍTULO 7. DESARROLLO

la comprobación de que el usuario que quiera hacer la actualización sea el dueño del nego-
cio. Eliminamos los horarios antiguos e introducimos los nuevos, asegurándonos de que no se
superpongan mediante un método doSchedulesOverlap. Recuperamos los recursos antiguos,
en caso de que use recursos, y eliminamos los que no se encuentran en la lista nueva. Aña-
dimos todos los recursos de la lista que sean nuevos. De tener empleados, recuperamos los
empleados antiguos, si no se encuentran en la lista nueva, los eliminamos. En caso de que
haya empleados nuevos se comprueba si hay duplicidad de correo electrónico o DNI, si no
la hay le añadimos como empleado de este negocio. También comprobamos si el usuario no
tiene una cuenta existente, de darse el caso le enviamos un correo para que registre su con-
traseña. Actualizamos los datos básicos (nombre, descripción, etc…) y termina la lógica de
negocio. Se elaboran tests de unidad, una operación PUT en el controlador y se comprueba su
correcto funcionamiento con Postman. Además de este caso de uso es necesario implementar
ya el caso de uso CU-09 debido a que lo necesitaremos en el frontend, aunque su desarrollo
se comentará más adelante.
La interfaz de usuario es similar a la del caso anterior, pero es necesario que cuando se
renderice el componente esté poblado con la información del negocio. Además, el dueño puede
tener varios negocios, por lo tanto hay que darle una opción de seleccionar el que desee.
Para ello se hace uso de un componente BusinessSelector, presente en un desplegable en el
componente Header. La figura 7.7 (página 41) ilustra este componente.

Figura 7.7: Desplegable de usuario con el componente BusinessSelector

En el estado del usuario en Redux guardaremos una lista de los negocios de los que es
dueño nuestro usuario. Esta lista solo contiene el id y su nombre, por tanto cuando queremos
acceder al componente UpdateBusiness tenemos que llamar al backend para obtener la infor-
mación al completo del negocio seleccionado. Además también tenemos que tener guardado
en el estado de Redux cual es el negocio actualmente seleccionado en BusinessSelector.

41
CAPÍTULO 7. DESARROLLO

Para poder poblar el formulario con esta información, una vez se haya renderizado el
componente, hacemos uso del hook useEffect provisto por React. Este hook nos permite añadir
efectos cada vez que el componente se monte.

42
CAPÍTULO 7. DESARROLLO

1 useEffect(() => {
2
3 dispatch([Link]([Link],
updateBusiness));
4
5 return () => clearBusiness();
6
7 }, [selectedBusiness, dispatch]);

En este código podemos comprobar que, cuando se renderiza el componente, lanzamos


una action, que llama al backend para obtener los datos del negocio seleccionado. La función
return es una función de limpieza, que se ejecutará cuando se vuelva a renderizar el compo-
nente o se desmonte. Por último tenemos un array de dependencias opcional. Cuando el valor
de alguna de estas dependencias cambia se ejecutará la función de limpieza y el efecto.
De esta forma conseguimos que, de manera dinámica, estando en el componente Update-
Business, podamos cambiar desde BusinessSelector el negocio que estamos actualizando.
CU-08 Usuario busca negocios
El usuario podrá buscar negocios atendiendo a varios parámetros, todos opcionales. Podrá
buscar por nombre, dirección, provincia o categoría. La información provista de cada uno de
los negocios es un resumen que contiene su nombre, valoración media del 1 al 5 y descripción.
Empezamos implementando una consulta en businessDao que nos permita hacer esta bús-
queda paginada, haciendo uso de la anotación @Query, el objeto Slice y el objeto Pageable
que nos provee Spring Data. El servicio simplemente hace uso de esta consulta y construye
un objeto Block, con una lista de los negocios y un booleano para habilitar la paginación.
Hacemos tests, creamos un DTO BusinessSummary y una petición GET en el controlador de
negocio.
En el frontend crearemos tres componentes: un formulario para la búsqueda, FindBu-
sinessForm, una lista de negocios, Businesses, y un componente que englobe esta lista y
la paginación, FindBusinessesResult. Estos componentes se ven ilustrados en la figura 7.8
(página 44).
El formulario para la búsqueda se introduce en el componente Header que siempre está
disponible en la interfaz, debido a que va a ser el caso de uso más disparado. Se hace uso
de dos TextField para la búsqueda por nombre y dirección y se reutilizan los componentes
CategorySelector y ProvinceSelector implementados en el CU-06. El resultado de esta bús-
queda se guarda en el estado de Redux, al que accede el componente FindBusinessesResult
mediante el hook useSelector.
Para presentar la lista de negocios hacemos uso del componente Grid de MUI, además del

43
CAPÍTULO 7. DESARROLLO

componente Rating para la valoración media. Cada uno de los nombres de los negocios será
un componente Link que nos llevará a los detalles del negocio. Finalmente, la paginación se
implementa en un componente Pager, habilitando botones en función de un valor booleano,
que indica si hay más negocios acorde a los parámetros especificados.

Figura 7.8: Componentes involucrados en el CU-08

CU-09 Usuario consulta detalles de negocio


Cualquier usuario puede consultar los detalles de un negocio pudiendo ver sus empleado-
s/recursos, sus horarios, la duración de las citas, etc…
La lógica de negocio es muy sencilla, solo se hace una llamada a la operación findById,
provista por spring. findById devuelve un objeto tipo Optional. En caso de que no se haya
encontrado negocio con ese id se lanza una excepción InstanceNotFoundException, en ca-
so contrario se devuelve la información de ese negocio. Se realizan pruebas de unidad y se
implementa una petición GET en el controlador de negocio.
Cuando un cliente pincha en uno de los Links presentados en el CU anterior se le lleva a
una dirección web /business/details/:id . Mediante el uso de react-router-dom [26], en función
de la ruta, renderizamos el componente BusinessDetails. Este obtiene el id del negocio de la
dirección utilizando el hook useParams. Una vez obtenido el id hacemos uso del hook useEffect
para consultar al backend los detalles del negocio. Estos detalles se guardarán en el estado
de Redux, debido a que en el futuro los utilizaremos en otros componentes. Por último el
componente BusinessDetails consulta el estado de Redux para obtener los detalles mediante
el hook useParams.

44
CAPÍTULO 7. DESARROLLO

1 const { id } = useParams(); //Primer paso, obtenemos el id de la


dirección web
2 const business = useSelector([Link]); //
Tercer paso, accedemos al estado de Redux
3
4 useEffect(() => {
5
6 const businessId = Number(id);
7
8 if (![Link](businessId)) {
9 dispatch([Link](businessId)); //
Segundo paso, llamamos al backend y guardamos la respuesta en el
estado de Redux
10 }
11
12 return () => cleanComponent();
13
14 }, [id, dispatch]);

45
CAPÍTULO 7. DESARROLLO

7.5 Iteración 3

7.5.1 Análisis
En esta iteración se desarrollarán los casos de uso relacionados con la gestión de horarios.
Al terminar esta iteración los cimientos para poder solicitar una cita ya estarán terminados.
Los casos de uso a desarrollar son:

• CU-10 Dueño modifica horario de atención

• CU-11 Dueño gestiona bloqueos de empleados

• CU-12 Empleado consulta su horario

7.5.2 Diseño e implementación


CU-10 Dueño modifica horario de atención
Empezamos implementando la búsqueda de horarios y eliminación por el negocio al que
están asociados en ScheduleDao. Debido a que la actualización de los horarios es parte de la
actualización del negocio, esta operación la insertaremos en el CU-07 Dueño actualiza negocio.
Por lo tanto se añade una lista de horarios como parámetro en la operación updateBusiness
de BusinessService.
La lógica añadida consiste en eliminar los antiguos horarios e introducir los nuevos, ase-
gurándonos de que no se superpongan. Para ello hacemos uso de un método auxiliar doSche-
dulesOverlap, que a su vez hace uso de la clase DateAndTimeValidator. DateAndTimeValida-
tor es una clase con métodos de comparación de objetos Date y DateTime, que utilizaremos
con frecuencia en los casos de uso que gestionen tiempos. Añadimos pruebas de unidad y
modificamos el DTO utilizado en la operación PUT updateBusiness del controlador.
En el frontend añadimos el componente que muestre la lista de horarios, ScheduleList, y
el que nos permite añadir un horario, AddScheduleDialog, ilustrado en la figura 7.9 (pági-
na 48), en el componente UpdateBusiness. Afortunadamente estos componentes ya fueron
diseñados en el CU-06 Usuario crea negocio.
CU-11 Dueño gestiona bloqueos de empleados
Para este caso de uso necesitaremos implementar operaciones que nos permitan: buscar
los empleados de un negocio, buscar los bloqueos de un empleado y actualizar los bloqueos.
En estas operaciones debemos comprobar el id del usuario que solicita estos datos, para sa-
ber si es el dueño del negocio en el que trabaja el empleado. También necesitaremos crear
una excepción nueva, ExistingBlockException, que se lanzará cuando dos bloqueos se super-
pongan. Para comprobarlo haremos uso de los métodos auxiliares doStaticBlocksOverlap y
doRecurrentBlocksOverlap, que a su vez hacen uso de la clase DateAndTimeValidator.

46
CAPÍTULO 7. DESARROLLO

Para el diseño de la interfaz de usuario añadimos un apartado en el desplegable del perfil


del usuario para que nos lleve a un componente Blocks. Este componente tendrá un hook
useEffect, que solicitará la lista de empleados al backend además de los bloqueos del primer
empleado. Mostraremos la lista de empleados en un componente MUI Select, EmployeeSe-
lector. Mostraremos los bloqueos estáticos en una lista StaticBlockList y los recurrentes
en RecurrentBlockList. Por último creamos dos botones que nos muestren modales, AddS-
taticBlockDialog y AddRecurrentBlockDialog, para insertar bloqueos en sus respectivas
listas.
CU-12 Empleado consulta su horario
Como entrada de este caso de uso recibimos una fecha y el id del empleado. Como salida
obtenemos una lista de huecos, pudiendo estar disponibles o bloqueados.
Para esta operación debemos recuperar los horarios del negocio para el que trabaja el
empleado en un determinado día. Tendremos que recuperar los bloques introducidos por el
dueño y bloquear las horas correspondientes. Debido a que cada uno de los huecos de cita en el
futuro tendrán varios estados disponibles (cita pendiente, cita completada, huecos disponible
o hueco bloqueado) creamos un objeto LocalTimeAndState, que tenga la hora y el estado del
hueco. El servicio, implementado en UserService, comprobará que el usuario es un empleado
y construirá una lista de huecos a partir de los horarios de su negocio. Después, iteraremos
a través de la lista, comprobando si el hueco se encuentra dentro de un bloqueo estático o
recurrente, en cuyo caso cambiamos el estado del hueco a bloqueado. También cambiaremos
el hueco a bloqueado si está en el pasado. Por defecto todos los huecos estarán disponibles.
En el frontend tendremos un nuevo apartado, si somos empleados, en el desplegable de
perfil de usuario: mi horario. En el componente, Schedule, tendremos un TextField de tipo
date que nos permita elegir la fecha del horario que queremos ver. Cuando se modifique el va-
lor de este input, haremos una llamada al backend, para recuperar el horario de esa fecha. Para
terminar, mostraremos esa lista por pantalla, cambiando el color de los huecos dependiendo
de su estado, como se ve en la figura 7.11 (página 49).

47
CAPÍTULO 7. DESARROLLO

Figura 7.9: Modal con formulario para añadir horario

Figura 7.10: Componentes diseñados para el CU-11 Dueño gestiona bloqueos de empleados

48
CAPÍTULO 7. DESARROLLO

Figura 7.11: IU del CU-12 empleado consulta su horario

49
CAPÍTULO 7. DESARROLLO

7.6 Iteración 4

7.6.1 Análisis
En esta iteración se desarrollarán los casos de uso relacionados con la gestión de citas por
parte del cliente. Los casos de uso desarrollados son:

• CU-13 Cliente solicita cita

• CU-14 Cliente consulta detalles de cita

• CU-15 Cliente cancela cita

• CU-16 Cliente consulta historial de citas

7.6.2 Diseño e implementación


CU-13 Cliente solicita cita
El caso de uso, en el backend, recibirá como parámetros: el id del negocio, una fecha y hora,
el id del usuario, un id de empleado o recurso y, opcionalmente, observaciones del cliente sobre
la cita. Se devolverán los detalles de la cita: fecha y hora, negocio, cliente, empleado/recurso
y observaciones.
Para implementar este caso de uso empezamos por crear un nuevo servicio, Appointmen-
tService. Inyectamos los DAOs appointmentDao, scheduleDao, staticBlockDao, recurrentBlock-
Dao. Comprobamos que la fecha de la cita esté dentro de un horario válido y que la fecha sea
posterior a la hora actual. Comprobamos también, que la hora sea un múltiplo de la dura-
ción de citas del negocio desde la hora de comienzo del horario que la contiene. Por ejemplo,
con un horario que empiece a las 09:00 y duración de citas 30 minutos, solo se pueden dar
en 09:00,09:30,10:00,etc… Esto se debe a que, en caso contrario, se podrían producir tiem-
pos muertos. Si alguna de estas comprobaciones falla se lanza una excepción AppointmentO-
utOfScheduleException.
En el caso de que la cita sea con un empleado, comprobamos que este empleado no ten-
ga ningún bloqueo activo ni ninguna cita pendiente en ese instante. Si estas comprobaciones
fallan, se lanza una excepción DateIsBlockedException. En caso de ser con un recurso, com-
probamos que, dependiendo de la cantidad disponible de ese recursos, se pueda dar la cita.
De no ser así, se lanza una excepción ResourceIsExhaustedException. Finalmente, se le envía
un correo al cliente confirmando la cita. Para este caso de uso realizamos pruebas de unidad
exhaustivas, asegurándonos de tener un buen porcentaje de cobertura, debido a que es el caso
de uso más importante. También necesitaremos implementar una petición que nos permita
consultar el horario de un recurso, aunque no comentaremos su lógica. Implementamos los

50
CAPÍTULO 7. DESARROLLO

DTOs pertinentes, un controlador nuevo, AppointmentController, una petición GET, para la


consulta del horario de un recurso y una petición POST, para la reserva de la cita.
Como podemos observar en la figura 7.12 (página 51), la clase AppointmentController es la
que recibe las peticiones HTTP relacionadas con citas. Esta hace llamadas a AppointmentSer-
vice, interfaz que define los métodos de los casos de uso. AppointmentServiceImpl implementa
esta interfaz, creando la lógica de negocio. Para ello hace uso de la interfaz PermissionChec-
ker, que nos permite comprobar, por ejemplo, que un usuario que quiera actualizar el negocio
figure como su dueño. En nuestro caso comprueba que el negocio, el cliente y el empleado/-
recursos existan. Para ello hace uso de sus respectivos DAOs, businessDao, clientDao y re-
sourceDao. Por otra parte AppointmentServiceImpl hace uso de varios DAOs. ScheduleDAO
para comprobar que la cita está en un horario válido, recurrentBlockDao y staticBlockDao
para comprobar que la cita no se de en un bloqueo, y appointmentDao para comprobar que
no haya citas pendientes en esa hora con ese recurso/empleado y crear la propia cita.

Figura 7.12: Diagrama de clases e interfaces involucradas en el CU-13 Cliente solicita cita

Para diseñar la interfaz de usuario, haremos uso de dos pantallas, una en la que se elija el
empleado/recurso, la fecha y la hora, y otra en la que se presenten estos datos, además de dar
la opción de añadir observaciones antes de confirmar la reserva de la cita. Cuando se efectúe
la reserva se mostrará un mensaje, confirmando que se ha completado la reserva y también el
envío del correo.
Para la primera pantalla implementamos el componente ChooseAppointmentDate 7.13
(página 52). Este componente tiene un Select, que es alimentado con la lista de recursos/em-
pleados, y un TextField de tipo date. Cuando el cliente seleccione un recurso/empleado y

51
CAPÍTULO 7. DESARROLLO

una fecha se realizará una petición al backend, consultando el horario pertinente. Con este
horario se pinta la lista de huecos. Si están disponibles serán azules, en caso contrario, grises.
En caso de que no elija un empleado de preferencia, se le muestran huecos disponibles en
función de todos los horarios de los empleados. Una vez elegida la hora, el cliente pulsa un
botón continuar y se le muestra la segunda pantalla, con el componente ConfirmAppoint-
ment 7.14 (página 54). Este componente muestra el nombre del empleado/recurso elegido así
como la fecha y hora. Además también tiene un campo en el que puede añadir observaciones
sobre la cita. Estos dos componentes son navegables, es decir, se puede mover entre pantallas.
La coordinación de estas pantallas y la gestión de datos se hace por parte de un componente
matriz, BookAppointment. Una vez efectuada la reserva, se muestra un componente Ap-
pointmentBooked, con un mensaje confirmando la reserva y el envío del correo.

Figura 7.13: Componente ChooseAppointmentDate, que permite seleccionar fecha, hora y


empleado/recurso

Una vez finalizado este caso de uso se deben realizar modificaciones en los siguientes
casos de uso: CU-07 Dueño actualiza negocio, CU-10 Dueño modifica horario de atención,
CU-11 Dueño gestiona bloqueos de empleados y CU-12 Empleado consulta su horario. En
el CU-07 y CU-10 se consultará, previamente a efectuar la modificación, si hay citas en ho-
rarios eliminados o con clientes/recursos eliminados, mediante una consulta al backend. De
darse el caso se mostrará un componente modal CancelledAppointmentListModal 7.15
(página 54), informando de que se cancelarán ciertas citas. Contiene un componente Cance-
lledAppointmentList, con la lista de citas que serán canceladas, y un campo de texto que
solicita una justificación. En el caso de que el usuario quiera cancelarlas, se le enviará un
correo informando de la cancelación a los clientes afectados. En el CU-11 el procedimiento
es el mismo, pero consultando las citas canceladas al añadir los bloqueos. Por último, en el
CU-12, ahora el horario del empleado puede tener huecos disponibles, bloqueados, con citas

52
CAPÍTULO 7. DESARROLLO

pendientes o con citas completadas.


CU-14 Cliente consulta detalles de cita
El cliente podrá consultar los detalles de la cita, a través del enlace provisto en el correo
enviado al solicitar la cita o del historial de citas (CU-16). El backend solicita el id de la cita y
el id del usuario y devuelve los detalles de la cita.
Para ello buscamos la cita en función de su id y comprobamos que quien solicita esta
información es el cliente, mediante su id. Realizamos pruebas y creamos una petición GET en
el controlador appointmentController, además del correspondiente DTO.
En el frontend, diseñamos un componente AppointmentDetails, que simplemente mues-
tra el texto correspondiente a los detalles de la cita. Se muestran: fecha y hora, nombre del
cliente, nombre del empleado/recurso, nombre del negocio, dirección del negocio, observa-
ciones y su estado, que puede ser completada, pendiente o cancelada.
CU-15 Cliente cancela cita
El cliente podrá cancelar la cita mediante un botón en el detalle de esta. El caso de uso,
en el backend, recibe como parámetro el id de la cita y del usuario. Si el usuario es el cliente
de la cita, se establecerá una fecha de cancelación, la cual, en el método getState de la entidad
Appointment, confirma que la cita está cancelada. Se implementa una consulta PUT en el
controlador.
Para el frontend solo es necesario implementar un botón y, cuando se efectúe la cancela-
ción, se cambie el estado de la cita a cancelado y se muestre la hora de cancelación.
CU-16 Cliente consulta historial de citas
En el servicio del backend, se provee el id del cliente y la página que desea consultar. En
este caso las páginas son de tamaño seis, por lo tanto, la primera página muestra las 6 primeras
citas, en orden descendiente de fecha. Se ejecuta mediante una consulta GET.
En el frontend se añade una nueva opción en el desplegable del perfil de usuario que
sea ”Mis citas”. Lleva a una página que renderiza un componente AppointmentList 7.16
(página 55) y un componentePager para la paginación. En esta lista se muestra la fecha de la
cita, nombre del negocio, empleado/recurso involucrado y el estado de las citas.

53
CAPÍTULO 7. DESARROLLO

Figura 7.14: Componente ConfirmAppointment, que muestra datos confirmados y permite


añadir observaciones

Figura 7.15: Componente CancelledAppointmentListModal, que avisa de las citas que van a
ser canceladas si la operación se confirma

54
CAPÍTULO 7. DESARROLLO

Figura 7.16: Componente AppointmentList que muestra el historial de citas del usuario

55
CAPÍTULO 7. DESARROLLO

7.7 Iteración 5

7.7.1 Análisis
En esta iteración se desarrollarán los casos de uso relacionados con la gestión de citas por
parte del empleado.

• CU-17 Empleado consulta detalles de cita

• CU-18 Empleado cancela cita

• CU-19 Empleado solicita cita

• CU-20 Empleado constata que un cliente no se presentó

7.7.2 Diseño e implementación


CU-17 Empleado consulta detalles de cita
Para este caso de uso simplemente modificaremos el CU-14 Cliente consulta detalles de
cita y añadiremos al empleado entre los usuarios que pueden acceder al detalle de una cita.
Además, modificamos el CU-12 Empleado consulta su horario, para que los huecos con citas
sean enlaces al detalle de la cita.
CU-18 Empleado cancela cita
En este caso de uso también haremos modificaciones, en concreto en el CU-15, añadiendo
al empleado en el control de acceso. Además estableceremos la justificación provista por el
empleado en la cita y le enviaremos un correo al cliente mediante Spring Boot Mail.
Para la implementación del frontend, comprobaremos quién es el que quiere cancelar la
cita al presionar el botón de cancelar cita. Si es el empleado se le mostrará un modal, pidiendo
confirmación sobre la cancelación y una justificación. Para ello reutilizamos el modal Cance-
lledAppointmentListModal.
CU-19 Empleado solicita cita
Debido a que en este caso de uso, el empleado puede solicitar cita para alguien que no
usa nuestra aplicación, empezaremos implementando una llamada POST que cree un usuario
básico con solo su nombre, apellidos, DNI y teléfono. Una vez implementada esta llamada,
modificaremos el CU-13 Cliente solicita cita, para realizar la búsqueda del cliente en función
de su id o DNI. Además comprobaremos si el cliente tiene correo electrónico antes de enviarlo.
En el frontend, empezamos añadiendo un apartado reservar cita para cliente en el desple-
gable del perfil de usuario. Este nos llevará a la reserva de citas. Modificamos el componente
ConfirmAppointment, de manera que, si el usuario solicitando la cita trabaja el negocio,
se le enseña el formulario de la figura 7.17 (página 57). Dependiendo de las casuísticas co-
mentadas en el análisis se muestran diferentes TextField. Si la cita es para él mismo no se le

56
CAPÍTULO 7. DESARROLLO

muestra ninguno. Si la cita es para un cliente con cuenta se le pide su DNI. Si la cita es para
un cliente sin cuenta se le pide nombre, apellidos, teléfono y DNI.

Figura 7.17: Formulario para la reserva de cita por parte del empleado

Una vez finalizado este caso de uso, tendremos que implementar una nueva consulta al
backend, que se realizará siempre que un empleado/dueño cancele citas. Esto ocurre en los
siguientes casos: CU-07 Dueño actualiza negocio, CU-10 Dueño modifica horario de atención,
CU-11 Dueño gestiona bloqueos de empleados y CU-18 Empleado cancela cita. Cuando se
cancelen citas, es posible que los clientes afectados no tengan cuenta, y no se les pueda avi-
sar por correo electrónico. Por tanto han de ser avisados telefónicamente. Para ello hacemos
uso de un modal, WarnedAppointmentListModal 7.18 (página 58), que contiene una lis-
ta de citas, reutilizando el componente CancelledAppointmentList, con citas de clientes
sin cuenta. Este componente avisa de que, los clientes que figuran en esas citas, deben ser
avisados telefónicamente.
CU-20 Empleado constata que un cliente no se presentó
Como parámetros necesitamos el id del usuario que solicita la llamada y el id de la cita.
Comprobamos que quien realiza la llamada es el empleado. De no serlo lanzamos la excepción
PermissionException. Ponemos a falso el boolean clientPresent que indica que el cliente no
acudió a la cita.
En la interfaz de usuario simplemente añadimos un botón que se muestre en el detalle de
la cita, solo si el usuario que consulta el detalle es el empleado.

57
CAPÍTULO 7. DESARROLLO

Figura 7.18: Componente WarnedAppointmentListModal, que muestra los clientes que deben
ser atendidos telefónicamente

58
CAPÍTULO 7. DESARROLLO

7.8 Iteración 6

7.8.1 Análisis
En esta iteración se implementarán los casos de uso relacionados con las reseñas y el uso
de Google Calendar. Los casos de so a desarrollar son:

• CU-21 Cliente añade una reseña a un negocio

• CU-22 Usuario consulta reseñas de un negocio

• CU-23 Cliente añade cita a Google Calendar

7.8.2 Diseño e implementación


CU-21 Cliente añade una reseña a un negocio
Empezamos en el backend, creando un nuevo servicio local ReviewService. En él creamos
dos métodos, uno que nos permita añadir la reseña y otro para recuperar la reseña de un
usuario. Introducir una reseña implica actualizar la valoración media de un negocio, lo cual
llevamos a cabo mediante el método updateAvgScore de la entidad Business. Implementamos,
en el controlador, una operación POST, para la creación de la reseña, y una operación GET, que
además de recuperar la reseña, devolverá un booleano indicando si el cliente ha solicitado cita
alguna vez. Creamos también el DTO pertinente y testeamos las operaciones con Postman.
En el frontend creamos dos componentes: CreateReviewForm y ReviewDetails. Cuan-
do se cargue el componente BusinessDetails haremos una llamada al backend, para recupe-
rar la reseña del cliente en ese negocio y saber ha solicitado cita con anterioridad. En caso de
que tenga reseña se mostrará en el componente ReviewDetails, en caso contrario se mos-
trará el componente CreateReviewForm, para que introduzca su reseña. En la figura 7.19
(página 60) se muestra el componente ReviewDetails.
CU-22 Usuario consulta reseñas de un negocio
Creamos una consulta GET en el backend que nos permita obtener las 6 últimas reseñas
obtenidas de más reciente a más antigua.
En el frontend creamos un componente ReviewRoulette, que nos permite navegar y
mostrar estas reseñas. Para mostrar las reseñas se reutiliza el componente ReviewDetails.
En la figura 7.20 (página 60) se muestra el componente ReviewRoulette.
CU-23 Cliente añade cita a Google Calendar
Este caso de uso no requiere de cambios en el backend.
Para poder realizar consultas a la API de Google creamos un proyecto en Google Develo-
per Console. Una vez creado solicitamos una API key y un id de cliente OAuth, que nos permite
identificarnos ante Google. Especificamos además las URI que permitiremos que hagan uso

59
CAPÍTULO 7. DESARROLLO

Figura 7.19: Componente ReviewDetails mostrando la reseña del usuario

Figura 7.20: Componente ReviewRoulette con las reseñas de usuarios

60
CAPÍTULO 7. DESARROLLO

de nuestro id de cliente, en nuestro caso localhost. Creamos un componente AddToGoogle-


CalendarButton, haciendo uso del snippet provisto por Google [27]. Cuando el componente
se renderice nos autenticamos ante Google con la API key y el id de cliente OAuth. Una vez
autenticados mostramos el botón que solicitará permisos al usuario mediante una ventana
emergente, ilustrada en la figura 7.21 (página 61). Modificamos el snippet, cambiando la pe-
tición que se hace a la API y el scope. El scope son los permisos que el usuario nos da para
realizar cambios en sus servicios de Google. En nuestro caso, el scope que especificamos nos
permite añadir citas a su calendario de Google. Por último añadimos el componente AddTo-
GoogleCalendarButton al componente BusinessDetails.

Figura 7.21: Ventana de Google pidiendo permisos al usuario

61
CAPÍTULO 7. DESARROLLO

7.9 Iteración 7
En esta iteración redactamos la memoria y realizamos retoques y mejoras sobre algunos
casos de uso. Algunos de los cambios introducidos son:

• Modificamos el CU-21 Cliente añade una reseña de un negocio, para que el cliente solo
pueda realizar reseñas si ha solicitado cita en el negocio.

• Modificamos los CU-06 Usuario crea negocio y CU-07 Dueño actualiza negocio para
poder añadir empleados con cuenta a un negocio.

• Se mejora la interfaz de usuario del CU-13 Cliente solicita cita.

• Modificamos el CU-19 para que, cuando el empleado solicite cita a un cliente sin cuenta,
pueda especificar un coreo electrónico y se le envíe un correo para crearse una cuenta.

• Modificamos el CU-13 para añadir un enlace al detalle de la cita. Hacemos uso de ses-
sionStorage para guardar el id de la cita y le redirigimos a la pantalla de inicio de sesión.
Una vez autenticado le mostramos el detalle de la cita.

62
Capítulo 8

Conclusiones y trabajo futuro

8.1 Conclusiones
El objetivo de este trabajo era automatizar al máximo el proceso de solicitar cita previa.
Para ello se quería reducir al mínimo las interacciones de las personas involucradas en el
proceso. Por ejemplo, al reservar cita, el cliente llama al negocio y, en el caso de que pueda
contestar, dejará su trabajo para atenderle. Haciendo uso de nuestra aplicación solo se ve
involucrado el cliente en el proceso, por tanto se consiguen mejoras de productividad por
ambos lados. El empleado no necesita atender al teléfono y el cliente no depende de que le
cojan, ni siquiera depende de que el negocio esté abierto. E incluso, si posteriormente quiere
cancelarla, se da la misma situación, ya no necesita hacer una llamada, solo pulsar un botón
en nuestra aplicación. Conseguimos así un proceso más sencillo, eficiente y productivo.
Todo el trabajo planificado para conseguir este objetivo ha sido finalizado y por tanto se
considera que el objetivo ha sido conseguido.
Por otra parte se han adquirido y mejorado conocimientos sobre varias tecnologías. Se
ha utilizado React y React-Redux, consolidando conocimientos adquiridos en el grado sobre
estas populares librerías. Se ha aprendido a utilizar la librería MUI, que provee de compo-
nentes React para una interfaz de usuario más atractiva. Se ha aprendido a usar la API de
Google mediante OAuth. También se han afianzado conocimientos sobre JavaScript, Java y su
ecosistema Spring.
En el grado y, especialmente, en la mención de Ingeniería Software, los dos lenguajes de
programación más utilizados son Java y JavaScript. Esto viene sin sorpresa porque son dos de
los lenguajes más demandados en el mercado laboral. Por estas razones se quiso utilizar estas
tecnologías para el desarrollo de esta aplicación, mejorando aptitudes obtenidas en el grado
y adquiriendo nuevas. Por último se han enriquecido competencias propias de la ingeniería,
como son el análisis de requisitos, metodologías de desarrollo, arquitectura software, etc…

63
CAPÍTULO 8. CONCLUSIONES Y TRABAJO FUTURO

8.2 Trabajo futuro


La aplicación en su estado actual es totalmente funcional y brinda al usuario las funciona-
lidades planteadas en el análisis. Aún así, esto no implica que se puedan seguir desarrollando
nuevas funcionalidades, consiguiendo un producto más atractivo y de mayor utilidad.
Se podría implementar un sistema de imágenes. Por un lado, que el dueño pueda añadir
una serie de imágenes en la creación del negocio, para que el cliente pueda visualizar las
instalaciones del negocio. Por otra parte, que los empleados o incluso los clientes puedan
disponer de una imagen en su perfil de usuario, para poder identificarlos rápidamente. Se
podría implementar una gestión de recursos más sofisticada, como salas o material específico
del negocio. Esto permitiría a los empleados saber qué recursos están disponibles para una cita
y especificar los que van a usar en sus citas. También se podría implementar un sistema de
estadísticas, mostrando citas por empleados/recursos, por fechas, citas canceladas por fechas,
etc… Esto sería de gran utilidad, porque permitiría tomar decisiones de riesgo al dueño, como
contratar empleados o modificar los horarios de atención.
Por otra parte, aunque más ambicioso, sería interesante el desarrollo de una aplicación
móvil. Una aplicación móvil facilitaría al cliente el acceso a nuestro producto, pudiendo acce-
der a él desde un icono en la pantalla principal del móvil. Además nos permitiría implementar
nuevas funcionalidades, como el uso de notificaciones push, para poder notificar al usuario de
cancelaciones, por ejemplo. Esta aplicación móvil se podría hacer con un framework que nos
de acceso a desarrollo multiplataforma, como Ionic [28] o React Native [29], que permiten, a
partir de una sola fuente de código, desarrollar una aplicación web y móvil.

64
Apéndices

65
Lista de acrónimos

API Application Programming Interface. 5, 6, 23, 59, 63

CSS Cascading Style Sheets. 3, 25, 33

DAO Data Access Object. 23, 27, 31, 33, 39, 50, 51

DOM Document Object Model. 3, 24, 25

DTO Data Transfer Object. 28, 32, 36, 39, 43, 46, 51, 53, 59

HTML HyperText Markup Language. 24, 25

HTTP HyperText Transfer Protocol. 3, 23, 28, 32

IDE Integrated Development Environment. 24, 26

JPA Java Persitance API. 3, 27

JSON JavaScript Object Notation. 3, 28

JSX JavaScript XML. 25

JVM Java Virtual Machine. 22

JWT JSON Web Token. 28, 32, 34, 36

REST REpresentational State Transfer. 3, 5, 23, 28, 32

SPA Single Page Application. 24

XML eXtensible Markup Language. 23

66
Glosario

backend Parte del servidor de una aplicación, que gestiona la lógica de negocio y el acceso
a datos.. 3, 17, 23, 24, 27–29, 31–34, 36, 39, 41, 43, 44, 47, 50, 52, 53, 57, 59

framework Entorno de trabajo con artefactos software utilizado para el desarrollo software..
23, 64

frontend Parte del cliente de una aplicación que gestiona la interfaz gráfica con la que se
comunica el usuario.. 3, 17, 28, 31, 32, 34, 36, 37, 39, 41, 43, 46, 47, 53, 56, 59

hook Función utilizada para crear o acceder al estado y los ciclos de vida de React.. 25, 32,
36, 42–44, 47

67
Bibliografía

[1] “Página web de timify.” [En línea]. Disponible en: [Link]

[2] “Página web de reservio.” [En línea]. Disponible en: [Link]

[3] “Página web de simplybook.” [En línea]. Disponible en: [Link]

[4] “Página web de virtuagym.” [En línea]. Disponible en: [Link]


es/

[5] “Página web de combo.” [En línea]. Disponible en: [Link]

[6] “Página web de regiondo.” [En línea]. Disponible en: [Link]

[7] “Página web de calendly.” [En línea]. Disponible en: [Link]

[8] “Página web de maven.” [En línea]. Disponible en: [Link]

[9] “Página web de spring.” [En línea]. Disponible en: [Link]

[10] “Página web de mysql.” [En línea]. Disponible en: [Link]

[11] “Página web de mysql workbench.” [En línea]. Disponible en: [Link]
products/workbench/

[12] “Página web de postman.” [En línea]. Disponible en: [Link]

[13] “Página web de jacoco.” [En línea]. Disponible en: [Link]


[Link]

[14] “Página web de eclipse.” [En línea]. Disponible en: [Link]

[15] “Página web de react.” [En línea]. Disponible en: [Link]

[16] “Página web de redux.” [En línea]. Disponible en: [Link]

68
BIBLIOGRAFÍA

[17] “Página web de mui.” [En línea]. Disponible en: [Link]

[18] “Página web de npm.” [En línea]. Disponible en: [Link]

[19] “Git de redux devtools.” [En línea]. Disponible en: [Link]


redux-devtools

[20] “Página web de vs code.” [En línea]. Disponible en: [Link]

[21] “Página web de git.” [En línea]. Disponible en: [Link]

[22] “Página web de docker.” [En línea]. Disponible en: [Link]

[23] “Página web de json web token.” [En línea]. Disponible en: [Link]

[24] “Git de redux thunk.” [En línea]. Disponible en: [Link]

[25] “Tutorial de react-intl.” [En línea]. Disponible en: [Link]


getting-started/installation/

[26] “Página web de la librería react-router-dom.” [En línea]. Disponible en: https:
//[Link]/web/guides/quick-start

[27] “Tutorial de uso de la api de google en javascript.” [En línea]. Disponible en:
[Link]

[28] “Página web de ionic.” [En línea]. Disponible en: [Link]

[29] “Página web de react native.” [En línea]. Disponible en: [Link]

69

También podría gustarte