Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Director:
Msc. Andrés Mauricio Martínez Hincapié
2
DECLARACIÓN DE DERECHOS DE AUTOR
Esta obra está licenciada bajo la Licencia Creative Commons Atribución 3.0 No
portada. Para ver una copia de esta licencia, visite
http://creativecommons.org/licenses/by/3.0/ o envíe una carta a Creative
Commons, PO Box 1866, Mountain View, CA 94042, USA.
3
AGRADECIMIENTOS
4
DEDICATORIA
Dedico este proyecto a mis padres, mi hermano y todos quienes creen estar en
capacidad de cambiar el mundo.
5
TABLA DE CONTENIDO
INTRODUCCIÓN ................................................................................................... 15
1. 2 JUSTIFICACIÓN ......................................................................................... 18
5. RESULTADOS................................................................................................... 49
6
6. CONCLUSIONES ............................................................................................. 61
7. RECOMENDACIONES ..................................................................................... 63
8. BIBLIOGRAFÍA ................................................................................................. 64
9. ANEXOS ........................................................................................................... 71
7
LISTA DE ILUSTACIONES
8
ILUSTRACIÓN 29. CLASE JPRINCIPALAPP................................................................................... 114
ILUSTRACIÓN 30. CLASE JROOTFRAME ...................................................................................... 116
ILUSTRACIÓN 31. CLASE OSVALIDATOR ..................................................................................... 118
ILUSTRACIÓN 32. CLASE BASESENTENCE .................................................................................. 120
ILUSTRACIÓN 33. CLASE SESSION ................................................................................................ 122
ILUSTRACIÓN 34. CLASE BASICEXCEPTION ............................................................................... 124
ILUSTRACIÓN 35. CLASE LOCALERESOURCES .......................................................................... 125
ILUSTRACIÓN 36. CLASE SAVEPROVIDER................................................................................... 127
ILUSTRACIÓN 37. CLASE PRODUCTSPANEL ............................................................................... 128
ILUSTRACIÓN 38. CLASE PRODUCTSEDITOR ............................................................................. 131
ILUSTRACIÓN 39. CLASE DIRTYMANAGER .................................................................................. 133
ILUSTRACIÓN 40. CLASE PRODUCTFILTER ................................................................................. 135
ILUSTRACIÓN 41. CLASE DATALOGICRECEIPTS ........................................................................ 137
ILUSTRACIÓN 42. DIAGRAMA DE CASOS DE USO – NIVEL 0: DISGREGACIÓN DE PRODUCTO
......................................................................................................................148
ILUSTRACIÓN 43. DIAGRAMA DE CASOS DE USO - NIVEL 1: DISGREGACIÓN DE PRODUCTO
......................................................................................................................148
ILUSTRACIÓN 44. DIAGRAMA DE ACTIVIDADES: DISGREGACIÓN DE PRODUCTO ................. 150
ILUSTRACIÓN 45. MODELO RELACIONAL: DISGREGACIÓN DE PRODUCTO ........................... 151
ILUSTRACIÓN 46. MOCKUP DE DISGREGACIÓN DE PRODUCTO .............................................. 151
ILUSTRACIÓN 47. MOCKUP DE BÚSQUEDA DE PRODUCTO....................................................... 152
ILUSTRACIÓN 48. CLASE PRODUCTSBUNDLEINFO ................................................................... 153
ILUSTRACIÓN 49. INTERFAZ PARA AGREGAR UN PRODUCTO A DISGREGAR ......................... 156
ILUSTRACIÓN 50. INTERFAZ DE BÚSQUEDA DE PRODUCTO ..................................................... 156
ILUSTRACIÓN 51. DIAGRAMA DE CASOS DE USO - NIVEL 0: SINCRONIZACIÓN CON
WOOCOMMERCE ...................................................................................................................... 162
ILUSTRACIÓN 52. DIAGRAMA DE CASOS DE USO - NIVEL 1: SINCRONIZACIÓN CON
WOOCOMMERCE ...................................................................................................................... 163
ILUSTRACIÓN 53. DIAGRAMA DE ACTIVIDADES: SINCRONIZACIÓN CON W OOCOMMERCE 164
ILUSTRACIÓN 54. MODELO RELACIONAL: SINCRONIZACIÓN CON W OOCOMMERCE .......... 165
9
ILUSTRACIÓN 55. DIAGRAMA DE DESPLIEGUE ............................................................................ 166
ILUSTRACIÓN 56. MOCKUP DE ATRIBUTOS PARA E-COMMERCE ............................................ 167
ILUSTRACIÓN 57. MOCKUP PARA MARCAR UN PRODUCTO COMO EN VENTA VIRTUAL ....... 167
ILUSTRACIÓN 58. CLASE APICOLLECTION ................................................................................. 168
ILUSTRACIÓN 59. CLASE PRODUCTAPI .................................................................... 170
ILUSTRACIÓN 60. INTERFAZ PARA MARCAR UN PRODUCTO COMO EN VENTA VIRTUAL...... 178
ILUSTRACIÓN 61. INTERFAZ DE ATRIBUTOS PARA E-COMMERCE ........................................... 179
ILUSTRACIÓN 62. DIAGRAMA DE CASO DE USO – NIVEL 0: OCTOPOS APP .......................... 185
ILUSTRACIÓN 63. DIAGRAMA DE CASO DE USO – NIVEL 1 : OCTOPOS APP ......................... 185
ILUSTRACIÓN 64. MOCKUP LISTADO DE MESAS: OCTOPOS APP .......................................... 186
ILUSTRACIÓN 65. MOCKUP LISTADO DE CATEGORÍAS: OCTOPOS APP ............................... 187
ILUSTRACIÓN 66. MOCKUP LISTADO DE PRODUCTOS: OCTOPOS APP ................................. 188
ILUSTRACIÓN 67. MOCKUP FINALIZACIÓN DE PEDIDO: OCTOPOS APP ................................. 189
ILUSTRACIÓN 68. USUARIOS DE LA APLICACIÓN ........................................................................ 203
ILUSTRACIÓN 69. LUGARES DEL RESTAURANTE ........................................................................ 204
ILUSTRACIÓN 70. PEDIDO ............................................................................................................... 205
ILUSTRACIÓN 71. CATEGORÍAS DE PRODUCTOS........................................................................ 206
ILUSTRACIÓN 72. SUB CATEGORÍAS DE PRODUCTOS ............................................................... 207
ILUSTRACIÓN 73. PRODUCTOS ...................................................................................................... 208
ILUSTRACIÓN 74. COMENZAR UN NUEVO PROYECTO EN NETBEANS ..................................... 216
ILUSTRACIÓN 75. NOMBRE Y LOCALIZACIÓN (NETBEANS) .......................................... 217
ILUSTRACIÓN 76. AÑADIR EL CÓDIGO DE UNICENTA OPOS..................................................... 218
ILUSTRACIÓN 77. INCLUIR/EXCLUIR ARCHIVOS .......................................................................... 219
ILUSTRACIÓN 78. INCLUIR/EXCLUIR ARCHIVOS .......................................................................... 220
ILUSTRACIÓN 79. AÑADIENDO LIBRERÍAS ................................................................................... 221
ILUSTRACIÓN 80. SELECCIONE 'AÑADIR JAR/CARPETAS' ........................................... 222
ILUSTRACIÓN 81. CONFIGURE LA CLASE PRINCIPAL ................................................................. 223
ILUSTRACIÓN 82. MODELO RELACIONAL PARTE 1 ...................................................... 224
ILUSTRACIÓN 83. MODELO RELACIONAL PARTE 2 ...................................................... 225
ILUSTRACIÓN 84. MODELO RELACIONAL PARTE 3 ...................................................... 226
10
ILUSTRACIÓN 85. MODELO RELACIONAL PARTE 4 ...................................................... 227
ILUSTRACIÓN 86. MODELO RELACIONAL PARTE 5 ...................................................... 228
ILUSTRACIÓN 87. MODELO RELACIONAL PARTE 6 ...................................................... 229
ILUSTRACIÓN 88. MODELO RELACIONAL PARTE 7 ...................................................... 230
ILUSTRACIÓN 89. MODELO RELACIONAL PARTE 9 ...................................................... 231
ILUSTRACIÓN 90. ACTA DE REUNION NRO. 1 ............................................................. 232
ILUSTRACIÓN 91. ACTA DE REUNION NRO. 2 ............................................................. 233
ILUSTRACIÓN 92. CARTA DE SATISFACCIÓN ............................................................................... 234
ILUSTRACIÓN 93. RUT ALMACEN TIENDA LOS CHIKOS ............................................................ 235
LISTA DE TABLAS
11
TABLA 20. PONDERACIÓN DE REQUISITOS: OCTOPOS APP ...................................... 181
TABLA 21. DEFINICIÓN DE REQUISITO 1: OCTOPOS APP ......................................................... 182
TABLA 22. DEFINICIÓN DE REQUISITO 2: OCTOPOS APP ......................................................... 182
TABLA 23. DEFINICIÓN DE REQUISITO 3: OCTOPOS APP ......................................................... 182
TABLA 24. DEFINICIÓN DE REQUISITO 4: OCTOPOS APP ......................................................... 182
TABLA 25. DEFINICIÓN DE REQUISITO 5: OCTOPOS APP ......................................................... 183
TABLA 26. DEFINICIÓN DE REQUISITO 6: OCTOPOS APP ......................................................... 183
TABLA 27. DEFINICIÓN DE REQUISITO 7: OCTOPOS APP ......................................................... 183
TABLA 28. DEFINICIÓN DE REQUISITO 8: OCTOPOS APP ......................................................... 184
TABLA 29. DEFINICIÓN DE REQUISITO 9: OCTOPOS APP ......................................................... 184
TABLA 30. CASOS DE PRUEBA: OCTOPOS APP ....................................................... 201
TABLA 31. REGISTRO DE ERRORES: OCTOPOS APP ................................................ 201
12
RESUMEN
13
ABSTRACT
Unicenta is a software dedicated to solve the needs found in the points of sale, it
focuses on retail markets such as restaurants, hotels, stores, supermarkets; Based
on explorations carried out in the different websites specialized in this software, the
need to have a new branch was demonstrated, which offers the possibility of
interacting with e-commerce platforms and mobile applications.
The project includes the development of three functionalities made for this
software, which creates a new project, forked from Unicenta called OctoPos. This
new project is based on the free software philosophy , and was developed with the
intention of divulge it, in order to create a community around it.
14
INTRODUCCIÓN
Las comunidades de software libre se vienen dando desde la década de los 80's,
gracias a Richard Stallman, creador del movimiento de software libre, a partir de
ese momento, surgen infinidad de proyectos de esta índole alrededor del mundo,
uno de estos es Unicenta.
Para lograr este objetivo es preciso crear una nueva rama de Unicenta alrededor
de la cual se cree una comunidad de desarrolladores, los cuales están interesados
en contribuir al proyecto de manera voluntaria.
15
posición libre al proyecto y en gitlab la cual facilitará el flujo de trabajo necesario
para poder contribuir a la comunidad.
16
1. PRIMERA PARTE: FORMULACIÓN DEL PROYECTO
17
1. 2 JUSTIFICACIÓN
18
1.3 OBJETIVOS
19
2. SEGUNDA PARTE: MARCO CONTEXTUAL
20
3. TERCERA PARTE: MARCO TEÓRICO
3.1 ANTECEDENTES
Descripción: Openbravo POS fue creado en 2008 por Adrián Romero, es un punto
de venta diseñado para pantallas táctiles, soporta impresoras de tickets, pantalla
de cliente y lector de códigos de barras. Es multiusuario a la hora de proveer los
permisos para agregar productos, mostrar reportes y graficos [2]. Además, este es
el proyecto base de Unicenta y de muchos otros puntos de venta. En la ilustración
1 se puede apreciar una captura de pantalla del inicio de OpenBravo.
21
Ilustración 1. OpenBravo Pos
Fuente: https://sourceforge.net/projects/openbravopos/
Maia POS:
22
tickets, lectores de código de barras, básculas, etc. También se rediseñó la
interfaz gráfica, se mejoró la usabilidad, se añadieron validaciones para evitar
vender productos que no están en existencia, entre otras [3].En la ilustración 2 se
puede apreciar una captura de pantalla del inicio de Maia POS.
Fuente: https://sourceforge.net/projects/maiapos/
Nord POS:
23
POS y brinda mayor funcionalidad a los usuarios. En la ilustración 3 se puede
apreciar una captura de pantalla de la toma de pedidos de Nord POS .
Licencia: Apache License V2.0, GNU General Public License version 3.0 (GPLv3)
Fuente: https://sourceforge.net/projects/nordpos/
MinPOS:
24
modificaciones y nuevas características, una de estas es el desarrollo de una
aplicación móvil para la toma de pedidos, aunque pretenden seguir desarrollando
funcionalidades para esta aplicación. En la ilustración 4 se puede apreciar una
captura de pantalla del inicio de MinPOS.
Ilustración 4. MinPOS
Fuente: https://sourceforge.net/projects/minpos/
RealComputer Pos:
25
atajos de teclado, e hizo modificaciones en los permisos del rol empleado. En la
ilustración 5 se puede apreciar una captura de pantalla del inicio de RealComputer
POS.
Fuente: https://sourceforge.net/projects/realcomputer-pos/
Streamline POS:
26
Licencia: GNU General Public License version 3.0 (GPLv3)
Fuente: https://sourceforge.net/projects/streamline-pos/
Chromis POS:
Descripción: Este proyecto se basa en Unicenta, fue creado por John Lewis en el
año 2012, y es de origen Inglés. Este proyecto fue creado básicamente porque
John Lewis realizaba nuevas funcionalidades al código fuente de Unicenta las
cuales no eran incluidas en las nuevas versiones, así que Lewis decidió comenzar
su propio proyecto y agregó las nuevas funcionalidades desarrolladas por el, cabe
resaltar que la funcionalidad más importante en este proyecto y por la cual surgió,
es el módulo para la pantalla de la cocina. En la ilustración 7 se puede apreciar
una captura de pantalla del inicio de Chromis POS.
27
Licencia: GNU General Public License version 3.0 (GPLv3)
Fuente: http://chromis.co.uk/chromispos/
28
3.2 CONCEPTOS TEÓRICOS
Es aquel software que no vulnera las libertades básicas de un usuario, las cuales
son [4] :
29
proyecto, las cuales fueron delegadas con anterioridad por el líder [6].
3.2.1.3 REST:
30
comunicación de la red, al mismo tiempo que maximiza la independencia y la
escalabilidad de las implementaciones de componentes. Esto se logra al colocar
restricciones en la semántica del conector, donde otros estilos se han centrado en
la semántica de los componentes [7].
3.2.1.6 Express:
3.2.1.7 Gson:
Es una librería de java usada para convertir los objetos java en su representación
JSON y viceversa. Una de las ventajas de Gson, sobre otros proyectos abiertos,
es que no usa anotaciones en las clases Java, sobre las cuales desea realizar las
31
conversiones, lo cual permite realizar las conversiones sin necesidad de tener
acceso al código fuente de la clase, además la mayoría no tiene un soporte
completo para las clases genéricas de java [11].
3.2.1.8 MySQL:
3.2.1.9 NPM:
3.2.1.11 UML:
32
El lenguaje unificado para construcción de modelos según el “Object Modeling
Group” (OMG) es: “Un lenguaje que permite especificar, visualizar y construir los
artefactos de los sistemas de software. así como para el modelado de negocios y
otros sistemas no software”. Este lenguaje de modelado fue desarrollado a
petición del OMG por Booch, Rumbaugh y Jacobson en 1997 [16].
3.2.2.1 UUID:
Los UUID (Universally unique identifier) son una cadena de 16 octetos, la cual es
un identificador único en el espacio tiempo, con respecto al espacio de todos los
UUID. Los UUID tiene múltiples usos desde identificar objetos persistentes en una
red, hasta identificar objetos de corta vida. La representación interna de un UUID
es una secuencia de bits descrita en la sección 4 del rfc 4122 [17][18].
3.2.2.2 BASE64:
3.2.2.3 URI:
33
de identificación, permite identificar cualquier tipo de recursos sin ninguna
limitación, las reglas de sintaxis pueden ser encontradas en la sección 3 del RFC
3986 [21].
3.2.2.4 Identificador:
3.2.2.5 HTTP:
3.2.2.6 Conexión:
3.2.2.7 Cliente:
34
3.2.2.8 Servidor:
3.2.3.1 JSON:
Como es descrito por Dayley, los backend services son todos aquellos servicios
que funcionan detrás del servidor, los cuales proporcionan los datos necesarios
para construir la respuesta que se enviará de vuelta a los clientes. Un ejemplo de
35
un backend service, es una base de datos, la cual almacena la información del
sistema; cuando el servidor recibe una petición de un cliente, en donde pide
ciertos datos, un proceso del backend trae la información de la base de datos le da
formato y devuelve la respuesta al cliente [9].
3.2.3.4 ECMAScript:
3.2.3.5 Hipertexto:
La palabra hipertexto fue acuñada por primera vez en el año de 1965 en el artículo
titulado “A File Structure for the Complex, the Changing, and the
Indeterminate” escrito por T. H. Nelson en donde definió teóricamente hipertexto
como: El cuerpo de un material escrito o pictórico interconectado de tal forma que
sus contenidos e interrelaciones puedan contener anotaciones, adiciones y notas
de pie de página de las personas que hayan estudiado dicho material. Además
resaltaba que si este tipo de estructura de archivo era bien diseñada y
administrada tendría un gran potencial para la educación, gracias a que
aumentaba el rango de opciones para los estudiantes [27][28].
36
3.2.4.1 Source forge:
3.2.4.2 JAVA:
3.2.4.3 Node.js:
3.2.4.4 POSTMAN:
37
una colección de peticiones o pruebas, entre otras. Lo que hace de postman una
herramienta esencial a la hora de desarrollo APIs [33].
3.2.4.5 TypeScript:
3.2.4.6 PhoneGap:
38
capacidades del dispositivo como lo son: cámara, gps, información del dispositivo,
entre otras [36].
3.2.4.8 JavaScript:
39
3.2.4.10 Android:
Una base de datos puede ser definida como todo conjunto de datos ordenados y
relacionados entre sí. Sin embargo un base datos debe cumplir con las siguientes
propiedades como lo expresa Elmasri y Navathe:
- Una base de datos debe representar algún aspecto del mundo real.
- Una base de datos es un conjunto de datos lógicamente coherente y con
significado, es decir si tengo una colección de datos aleatorios no lo puedo
llamar base de datos.
- Una base de datos es diseñada y desarrollada con un propósito específico.
En pocas palabras una base de datos debe tener un grupo de usuarios destinados
a aprovechar los recursos que esta puede proporcionar [44].
3.2.4.12 DBMS:
40
mantenimiento de una base de datos. Los DBMS facilitan el proceso de definir,
construir, manipular y compartir bases de datos entre varios usuarios [44].
3.2.4.13 Query:
El término query o consulta es una jerga usada para referirse a todo tipo de
interacción con una base de datos incluyendo la modificación de datos [44][45].
3.2.4.14 SQL:
41
4. CUARTA PARTE: MODELO TEÓRICO
42
Además, se debe considerar que un prototipo puede ser usado de distintas
maneras en un proceso de desarrollo de software, como lo expresa Sommerville, y
estas son [46] :
43
Ilustración 8. Paradigma de prototipos
Fuente: [47]
Ventajas:
Desventajas:
44
● El uso del paradigma de prototipos, puede ser difícil de manejar para
proyectos grandes.
● Tanto los usuarios como los analistas, puede adoptar un prototipo como si
fuera el desarrollo final, cuando el prototipo es deficiente y su propósito
nunca fue ser el sistema terminado.
Este modelo presenta varias fases de ciclo de vida (véase la ilustración 9), las
cuales son:
45
○ Programación: Se define el cronograma y los encargados de las
tareas.
○ Análisis de riesgos: Es una subfase muy importante dentro del
modelo, ya que permite identificar los riesgos por iteración, lo que
proporciona mayor control sobre los mismos y disminuye sus
probabilidades de ocurrencia.
46
Ilustración 9. Modelo de espiral
Fuente: [47]
47
● Modelado: Se modela el prototipo en forma de diseño rápido
48
5. RESULTADOS
En el desarrollo del estado del arte del proyecto Unicenta, se plasman sus
antecedentes, su historia y las oportunidades de trabajo que ha generado este
proyecto. Además, la importancia en el sector de ventas al por menor y los
proyectos que han surgido en base a Unicenta. Para profundizar en éste aspecto
es necesario consultar el ANEXO A: ESTADO DEL ARTE DE UNICENTA del
presente documento.
Class SaveProvider:
Esta clase se encarga de almacenar las acciones de los botones guardar, agregar
y eliminar de cada una de las interfaces de gestión del sistema, su constructor es
polimorfo pero el constructor que se usa con más frecuencia es public
SaveProvider(SentenceExec sentupdate, SentenceExec sentinsert,
SentenceExec sentdelete), el cual recibe tres parámetros , de tipo
SentenceExec, cada uno de los cuales representa la acción que tomará uno de
los tres botones anteriormente mencionados. El diagrama de esta clase se puede
observar en la ilustración 10.
49
Ilustración 10. Clase SaveProvider
50
Además el documento también posee el modelo relacional de la base de datos,
una tabla donde se describe cada una de las tablas y por último los scripts sql, con
una descripción de su función, que posee el proyecto. Para una mejor ilustración
de lo anteriormente mencionado, a continuación se puede apreciar un fragmento
del documento donde se observa el desarrollo de lo antes mencionado.
Script MySQL-create.sql
Este script es el encargado de crear las tablas de la base de datos por primera
vez, es decir, que si se desea adicionar otra tabla al proyecto, el query debería de
ir dentro de este archivo.
51
/* Header line. Object: attributeinstance. Script date:
27/08/2015 08:42:37. */
CREATE TABLE `attributeinstance` (
`id` varchar(255) NOT NULL,
`attributesetinstance_id` varchar(255) NOT NULL,
`attribute_id` varchar(255) NOT NULL,
`value` varchar(255) default NULL,
KEY `attinst_att` ( `attribute_id` ),
KEY `attinst_set` ( `attributesetinstance_id` ),
PRIMARY KEY ( `id` )
) ENGINE = InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT = Compact;
52
Tabla 1. Definición de requisito 3: Disgregación de producto
53
Ilustración 12. Diagrama de casos de uso: Disgregación de producto
54
Ilustración 13. Interfaz para agregar un producto a disgregar
55
Después de realizar la elicitación, se continuó con el diseño de este módulo, para
lograr este propósito se realizó un modelo relacional, con el fin de diseñar las
tablas de la base de datos necesarias, para el funcionamiento del módulo, este
diagrama es ilustrado en la ilustración 14.
También cabe resaltar que para el desarrollo de este módulo, se tomaron dos
decisiones importantes: la primera, apunta a la elección de la plataforma de
comercio electrónico para llevar a cabo la sincronización y la segunda, la elección
de la herramienta para realizar la conexión de Unicenta con el ecommerce. Luego
de un proceso de inspección se llegó a la decisión que se usaría el plugin de
Wordpress, Woocommerce, como plataforma de comercio electrónico y que se
desarrollaría una API en NodeJS que sirviera como intermediaria. En la ilustración
15 se puede apreciar el diagrama de despliegue.
56
Ilustración 15. Diagrama de arquitectura : Sincronización con Woocommerce
57
Fuente: elaboración propia
58
Después de haber realizado todo el análisis y el diseño, se realizó la codificación
de la aplicación en angular. En esta fase, se describieron fragmentos del código
desarrollado para la aplicación, a continuación se aprecia en la ilustración 17 un
pantallazo de la aplicación funcional.
Si se desea tener más conocimiento sobre este desarrollo por favor consulte el
ANEXO E: OCTOPOS APP de este documento.
59
Como ruta final en la consecución del presente proyecto, se construyó un artículo
con el fin de divulgar el proceso; en dicho documento se habla sobre los procesos
realizados y las lecciones aprendidas durante el desarrollo. Si desea leer el
artículo por favor diríjase al ANEXO F: ARTÍCULO PUBLICABLE del presente
documento.
60
6. CONCLUSIONES
61
mercado, sigue siendo un sector con potencial, el cual requiere de
proyectos diferentes e innovadores que tomen en cuenta los nuevos
factores que la sociedad requiere.
62
7. RECOMENDACIONES
● La seguridad que posee la API en este momento es baja, así que este es
un punto a mejorar, por tanto, en este momento es recomendable usar una
conexión HTTPS para evitar ataques informáticos tales como el phishing.
63
8. BIBLIOGRAFÍA
http://centralrepository.openbravo.com/openbravo/org.openbravo.forge.ui/ForgePr
[3] Sistemas del golfo, "Maia POS", SourceForge, 2013. [Online]. Available:
[4]R. Stallman, Software libre para una sociedad libre, 1st ed. Madrid: Traficantes
[6]S. Peters and N. Ruff, "Participating in Open Source Communities - The Linux
Foundation", The Linux Foundation, 2017. [Online]. Disponible:
https://www.linuxfoundation.org/participating-open-source-communities/.
[Accedido: 15- Oct- 2017].
64
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm. [Accedido:
[9]B. Dayley, Node.js, MongoDB and AngularJS web development. Upper Saddle
River, NJ [etc.]: Addison-Wesley, 2014.
manager architecture", Information and Software Technology, vol. 55, no. 2, pp.
459-474, 2013.
65
[15]J. Cappos, J. Samuel, S. Baker and J. Hartman, "A look in the mirror: Attacks
and communications security - CCS '08, pp. 565-574, Alexandria, VA, USA, 2008.
https://www.itu.int/en/ITU-T/asn1/Pages/UUID/uuids.aspx.
[18]P. Leach, M. Mealling and R. Salz, "A Universally Unique IDentifier (UUID)
[19]S. Josefsson, "The Base16, Base32, and Base64 Data Encodings", RFC 4648,
2006. [Online]. Disponible: https://www.rfc-editor.org/rfc/pdfrfc/rfc4648.txt.pdf.
[Accedido: 17- Abr- 2018].
[20]C. Xu, Y. Chen and K. Chiew, "An Approach to Image Spam Filtering Based on
Base64 Encoding and N-Gram Feature Extraction", 2010 22nd IEEE International
Conference on Tools with Artificial Intelligence,Arras, France, 2010.
66
[23]T. Bray, "The JavaScript Object Notation (JSON) Data Interchange Format",
[24]ECMA International, The JSON Data Interchange Syntax, 2nd ed. ECMA
International, 2017.
[25]D. Gourley and B. Totty, HTTP: the definitive guide. Beijing: O'Reilly, 2002.
[27]T. Nelson, "A file structure for the complex, the changing, and the
1965.
2018, p. 2
67
[31]N. Foundation, "About | Node.js", Node.js, 2018. [Online]. Disponible:
https://nodejs.org/en/about/. [Accedido: 21- Jun 2018].
https://docs.api.getpostman.com/?_ga=2.62019052.1355013722.1538345190-
2012.
[37]A. Group, "About the Apache HTTP Server Project - The Apache HTTP Server
2006.
68
[40]Google, "V8 JavaScript engine", V8.dev, 2018. [Online]. Disponible:
2012.
Complete Book, 2nd ed. Upper Saddle River, New Jersey: Pearson Education,
2009.
[46]I. Sommerville and M. Alfonso Galipienso, Ingeniería del software, 7th ed.
[47]R. Pressman, Ingeniería del software. México: MacGraw-Hill, 2010, pp. 37-40.
69
[49] Á. Manjavacas, ADAPTACIÓN E IMPLEMENTACIÓN DE MEJORAS EN UN
PROYECTO DE SOFTWARE LIBRE A UN SISTEMA CASH -FLOW MUY
EFICIENTE Y SEGURO. Madrid, España: Universidad Complutense de Madrid,
2016.
[50] Capterra, "Best Point of Sale Software | 2018 Reviews of the Most Popular
Systems", Capterra.com, 2018. [Online]. Disponible:
https://www.capterra.com/point-of-sale-
software/?utf8=%E2%9C%93&v=3#infographic. [Accedido: 22- May- 2018].
[51]J. Gerrad, "uniCenta oPOS Point Of Sale for SME Retailer and Hospitality
businesses", uniCenta, 2018. [Online]. Disponible: https://unicenta.com/about-
unicenta-opos-point-of-sale/. [Accedido: 25- May 2018].
70
9. ANEXOS
El proyecto fue iniciado en el año 2010 por su fundador Jack Gerrard como un
proyecto hobista, pero su crecimiento llevó a que se crearan unas metas las
cuales desde su inicio hasta este momento han sido el horizonte del mismo, estas
metas a cumplir son:
71
● Desarrollar un punto de venta de código abierto de calidad comercial
● Hacerlo lo más accesible posible para todas las PYMEs.
● Ayudar a las empresas en ahorro de tiempo y dinero
● Construir una marca global en el nicho de POS.
Para alcanzar las metas anteriormente planteadas, se decidió que sería software
libre y se encontraría bajo la licencia GNU GPL V3, además, empezó a ser
distribuido a través de canales casuales como lo son su sitio web, la página por
excelencia de software libre sourceforge, entre otros métodos, en ninguno de los
cuales se forza al usuario a registrarse, características que según Jack Gerrard su
fundador, han sido la clave fundamental para el éxito del proyecto.
72
Adicionalmente y apoyando la idea de que Unicenta sigue creciendo, en el 2016
se introdujo el soporte por suscripción, gracias a las peticiones de algunos
usuarios que solicitaron este servicio [51]. Este servicio tiene dos planes
diferentes, el base y el plus.
El plan base tiene un costo anual de $US 77.32, este plan es recomendado para
los negocios usuarios o simplemente vendedores del proyecto, y presta los
siguientes beneficios:
● Descargas
● Código Fuente
● Notificaciones de actualización
● Reporte Web
● Soporte estándar en el foro
● Guías de usuario
El plan plus tiene un costo anual de $US 175, este plan es recomendado para
desarrolladores o empresas interesadas en mejorar las características y
funcionalidades del proyecto, y presta los siguientes beneficios:
● Downloads
● Source code
● Update Notifications
● Web Reporting
● Remote Order Display
● Priority Forum support
● User Guides
● Rate discount 15%
● Developer Guides
73
● Access to Beta’s
● Limited Developer support
De igual forma es un reflejo del impacto que Unicenta ha tenido alrededor mundo,
la cantidad de solicitudes de trabajo como freelancer para desarrollar alguna
nueva funcionalidad para el proyecto, y esto se puede observar en la ilustración
19, la cual fue tomada de la página web freelancer.com.
74
Sabiendo entonces, que Unicenta oPos es un proyecto derivado de OpenBravo
Pos, a continuación se hará un listado de algunas de las modificaciones que
Unicenta realizó a OpenBravo en sus primeras versiones.
● Gestión de empleados
● Modificación de los reportes
● Modificación de los iconos
● Mostrar el cambio a la hora de realizar una venta
● Capacidad de modificar las conexiones a la base de datos desde la GUI.
● Gestión de clientes
● Posibilidad de importar productos especificando sus atributos en archivos
.csv.
● Entre otras
Del mismo modo, así como Unicenta oPos surgió como un proyecto derivado de
OpenBravo Pos, han surgido diferentes proyectos que se derivan de Unicenta.
Estos proyectos han surgido por diferentes circunstancias tales como el interés
privado de explotar el proyecto de forma comercial, u otros por razones un poco
más complejas, como lo son la falta de aceptación de nuevos aportes de personas
que pertenecían a la comunidad y querían aportar al proyecto, como es el caso del
proyecto Chromis el cual fue creado por John Lewis debido a que desde el año
2012 comenzó a dar soporte a sistemas pos de código abierto, en ese momento
se dio cuenta que existía la necesidad de una nueva funcionalidad, un módulo,
que funcionara con las pantallas de cocina, así que Lewis comenzó el desarrollo,
lo publicó y al pasar el tiempo sus cambios no eran adicionados a las nuevas
versiones de Unicenta, así que él, se ponía nuevamente en el trabajo de adicionar
su funcionalidad lo que conllevaba mucho esfuerzo y tiempo, y, al ver que los
usuarios se volvían dependientes de su módulo y no era adicionado al proyecto
decidió crear su nuevo proyecto derivado y lo llamó Chromis. Asi como este
75
proyecto surgieron algunos otros, a continuación se presenta una lista de
proyectos derivados de Unicenta:
● Grandpos (http://www.grandpos.com/)
● Mipos (https://www.mipos.com.au/)
● Chromis ( http://chromis.co.uk/)
● Streamline-pos (https://sourceforge.net/projects/streamline-pos/)
76
ANEXO B: INGENIERÍA INVERSA DE UNICENTA
LISTA DE ILUSTRACIONES
LISTA DE TABLAS
77
En este anexo, se muestra el trabajo realizado para lograr alcanzar la ingeniería
inversa del software unicenta. Cabe resaltar, que este apartado es de vital
importancia para el entendimiento del proyecto y por ende es base fundamental
para lograr el desarrollo de las nuevas funcionalidades que hacen parte de este
proyecto de grado.
A. Base de datos
78
la necesidad de identificación que se genera con el uso de los tickets de venta, los
cuales tienen un tiempo de vida de corta duración.
79
attributeuse Vinculación del Atributo al producto S
customers Clientes S
moorers Restos N
80
orders Lista dinámica de pedidos incompletos N
enviados a la impresora remota
people Usuarios S
products Productos S
reservations Reservaciones S
81
stockcurrent Valor unitario físico del producto N
suppliers Proveedores S
tickets Tickets N
82
uom Unidad de medida S
B. Código fuente
83
Adicionalmente, se documentaron también los scripts SQL de la base de datos, la
documentación de estos se realizó dando una descripción de lo que hace el script
y un fragmento de código.
Clase DataLogicSales:
84
Ilustración 20. Clase DataLogicSales
protected Session s;
85
protected Datas[] stockAdjustDatas;
86
paymenttabledatas = new Datas[] {
Datas.STRING, Datas.STRING, Datas.TIMESTAMP,
Datas.STRING, Datas.STRING, Datas.DOUBLE,
Datas.STRING};
- getProductCatInsert() :
87
+ "NAME, "
+ "PRICEBUY, "
+ "PRICESELL, "
+ "CATEGORY, "
+ "PRINTTO, "
+ "SUPPLIER, "
+ "UOM,"
+ "FLAG, "
+ "DESCRIPTION, "
+ "SHORT_DESCRIPTION, "
+ "WEIGTH, "
+ "WIDTH, "
+ "LENGTH, "
+ "HEIGHT ) "
+ "VALUES ("
+ "?, ?, ?, ?, ?, ?, "
+ "?, ?, ?, ?, ?, ?, "
+ "?, ?, ?, ?, ?, ?, "
+ "?, ?, ?, ?, ?, ?, "
+ "?, ?, ?, ?, ?, ?,"
+ "?, ?, ?, ?, ?, ?)"
, new SerializerWriteBasicExt(productsRow.getDatas(),
new int[]{0,
1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35}))
88
.exec(params);
if((boolean) values[29]){
m_apiConnection.createProduct(params);
}
- getProductCatUpdate():
89
+ "NAME = ?, "
+ "PRICEBUY = ?, "
+ "PRICESELL = ?, "
+ "CATEGORY = ?, "
+ "TAXCAT = ?, "
+ "ATTRIBUTESET_ID = ?, "
+ "STOCKCOST = ?, "
+ "STOCKVOLUME = ?, "
+ "IMAGE = ?, "
, new SerializerWriteBasicExt(productsRow.getDatas(),
new int[]{0,
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25,
26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 0}))
.exec(params);
if (i > 0) {
if (((Boolean)values[36])) {
if (new PreparedSentence(s
, "UPDATE products_cat SET
CATORDER = ? WHERE PRODUCT = ?"
, new
SerializerWriteBasicExt(productsRow.getDatas()
, new int[] {35,
0})).exec(params) == 0) {
new PreparedSentence(s
90
, "INSERT INTO products_cat (PRODUCT, CATORDER)
VALUES (?, ?)"
, new
SerializerWriteBasicExt(productsRow.getDatas(), new int[] {0,
37})).exec(params);
}
} else {
new PreparedSentence(s
, "DELETE FROM products_cat WHERE PRODUCT = ?"
, new
SerializerWriteBasicExt(productsRow.getDatas(), new int[]
{0})).exec(params);
}
- getProductCatDelete():
91
Object[] values = (Object[]) params;
new PreparedSentence(s
, "DELETE FROM products_cat WHERE PRODUCT = ?"
, new
SerializerWriteBasicExt(productsRow.getDatas(), new int[]
{0})).exec(params);
if((boolean) values[29]){
m_apiConnection.deleteProduct(params);
new PreparedSentence(s
, "DELETE FROM extern_product WHERE local_id = ?"
, new
SerializerWriteBasicExt(productsRow.getDatas(), new int[]
{0})).exec(params);
}
- getStockDiaryInsert1():
92
SentenceExecTransaction(s) y a la hora de ser llamada esta instancia se
ejecuta el método sobrescrito execInTransaction() , el cual retorna una
instancia de la clase PreparedSentence la cual será usada más adelante para
determinar si la transacción fue exitosa.
if (updateresult == 0) {
new PreparedSentence(s
, "INSERT INTO stockcurrent (LOCATION, PRODUCT, "
+ "ATTRIBUTESETINSTANCE_ID, UNITS) "
+ "VALUES (?, ?, ?, ?)"
93
, new SerializerWriteBasicExt(stockdiaryDatas,
new int[] {3, 4, 5, 6})).exec(params);
}
m_apiConnection.updateStockProduct(params);
return new PreparedSentence(s
, "INSERT INTO stockdiary (ID, DATENEW, REASON,
LOCATION, PRODUCT, "
+ "ATTRIBUTESETINSTANCE_ID, UNITS,
PRICE, AppUser, "
+ "SUPPLIER, SUPPLIERDOC) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?)"
, new SerializerWriteBasicExt(stockdiaryDatas,
new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10})).exec(params);
- saveTicket():
Transaction t;
94
t = new Transaction(s) {
@Override
public Object transact() throws BasicException {
// Set Receipt Id
if (ticket.getTicketId() == 0) {
switch (ticket.getTicketType()) {
case TicketInfo.RECEIPT_NORMAL:
ticket.setTicketId(getNextTicketIndex());
break;
case TicketInfo.RECEIPT_REFUND:
ticket.setTicketId(getNextTicketRefundIndex());
break;
case TicketInfo.RECEIPT_PAYMENT:
ticket.setTicketId(getNextTicketPaymentIndex());
break;
case TicketInfo.RECEIPT_NOSALE:
ticket.setTicketId(getNextTicketPaymentIndex());
break;
default:
throw new BasicException();
}
}
new PreparedSentence(s
, "INSERT INTO receipts (ID, MONEY, DATENEW,
ATTRIBUTES, PERSON) VALUES (?, ?, ?, ?, ?)"
, SerializerWriteParams.INSTANCE )
.exec(new DataParams() {
95
@Override
public void writeValues() throws BasicException {
setString(1, ticket.getId());
setString(2, ticket.getActiveCash());
setTimestamp(3, ticket.getDate());
try {
ByteArrayOutputStream o = new
ByteArrayOutputStream();
ticket.getProperties().storeToXML(o,
AppLocal.APP_NAME, "UTF-8");
setBytes(4, o.toByteArray());
} catch (IOException e) {
setBytes(4, null);
}
setString(5, ticket.getProperty("person"));
}
});
// new ticket
new PreparedSentence(s
, "INSERT INTO tickets (ID, TICKETTYPE, TICKETID,
PERSON, CUSTOMER, STATUS) "
+ "VALUES (?, ?, ?, ?, ?, ?)"
Class OctoPos:
96
función de esta clase, es cargar todos los datos necesarios para la sesión desde la
base de datos. Ya que las vistas del proyecto se construyen ,en su mayoría, de
forma recursiva, es decir se recicla demasiado código en cada una de las vistas,
esta clase se encarga de realizar la conexión a la base de datos, carga el estilo de
la vista, entre otras cosas. Además, desde esta clase se hace un llamado a la
clase JRootApp la cual es la vista principal del proyecto. El diagrama de esta clase
se puede observar en la ilustración 21.
private StartPOS() {
}
InstanceQuery i = null;
try {
i = new InstanceQuery();
97
i.getAppMessage().restoreWindow();
return false;
} catch (RemoteException | NotBoundException e) {
return true;
}
}
@Override
public void run() {
if (!registerApp()) {
System.exit(1);
}
config.load();
String slang =
config.getProperty("user.language");
String scountry =
config.getProperty("user.country");
String svariant =
config.getProperty("user.variant");
if (slang != null
98
&& !slang.equals("")
&& scountry != null
&& svariant != null) {
Formats.setIntegerPattern(config.getProperty("format.integer
"));
Formats.setDoublePattern(config.getProperty("format.double")
);
Formats.setCurrencyPattern(config.getProperty("format.curren
cy"))
Class JRootApp:
99
Ilustración 22. Clase JRootApp
100
public class JRootApp extends JPanel implements AppView,
DeviceMonitorEventListener {
initComponents ();
jScrollPane1.getVerticalScrollBar().setPreferredSize(new
Dimension(30, 30));
serverMonitor.setVisible(false);
101
}
private DSPortAdapter m_oneWireAdapter;
private DeviceMonitor m_oneWireMonitor;
m_oneWireAdapter.setSpeed(DSPortAdapter.SPEED_REGULAR);
m_oneWireMonitor = new
DeviceMonitor(m_oneWireAdapter);
// Normal state
m_oneWireMonitor.setMaxStateCount(5);
// Use for testing
// m_oneWireMonitor.setMaxStateCount(100);
m_oneWireMonitor.addDeviceMonitorEventListener(this);
new Thread(m_oneWireMonitor).start();
Class AppConfig:
Esta clase es la encargada de gestionar la configuración de la base de datos, las
impresoras y el mensaje que saldrá impreso en los tickets después de realizar una
venta.
102
Esta clase lee y modifica un archivo de configuración, el cual contiene toda la
información anteriormente mencionada. El diagrama de esta clase se puede
observar en la ilustración 23.
103
private static AppConfig m_instance = null;
private Properties m_propsconfig;
private File configfile;
/**
* Set configuration array
* @param args array strings
*/
public AppConfig(String[] args) {
if (args.length == 0) {
init(getDefaultConfig());
} else {
init(new File(args[0]));
}
}
Class AppLocal:
104
Ilustración 24. Clase AppLocal
static {
m_resources = new LocaleResources();
m_resources.addBundleName("pos_messages");
m_resources.addBundleName("erp_messages");
}
Class AppUser:
105
Esta clase, se encarga de cargar todos los atributos de un usuario, añadir los
permisos a cada uno de los roles y además es la encargada de realizar la
autentificación del sistema. El diagrama de esta clase se puede observar en la
ilustración 25.
106
private static final Logger logger =
Logger.getLogger("com.openbravo.pos.forms.AppUser");
static {
initOldClasses();
}
107
String card, String role, Icon icon) {
m_sId = id;
m_sName = name;
m_sPassword = password;
m_sCard = card;
m_sRole = role;
m_Icon = icon;
m_apermissions = null;
}
Class AppViewConnection:
108
/** Creates a new instance of AppViewConnection */
private AppViewConnection() {
}
/**
*
* @param props
* @return
* @throws BasicException
*/
public static Session createSession(AppProperties props)
throws BasicException {
try {
String dbURL=null;
String sDBUser=null;
String sDBPassword=null;
if (isJavaWebStart()) {
Class.forName(props.getProperty("db.driver"),
true, Thread.currentThread().getContextClassLoader());
} else {
ClassLoader cloader = new URLClassLoader(new
URL[] {
new
Class DataLogicSystem:
109
Esta clase es la encargada de generar todas las consultas, a la base de datos,
relacionadas con los datos necesarios para que el sistema funcione, tales como
los roles del sistema, los permisos que estos poseen, los clientes, lo proveedores,
entre otros.
110
protected String m_sInitScript;
private SentenceFind m_version;
private SentenceExec m_dummy;
private String m_dbVersion;
protected SentenceList m_peoplevisible;
protected SentenceFind m_peoplebycard;
/**
*
* @param s
*/
@Override
public void init(Session s){
m_sInitScript = "/com/openbravo/pos/scripts/" +
s.DB.getName();
m_dbVersion = s.DB.getName();
111
, SerializerWriteString.INSTANCE,
SerializerReadString.INSTANCE);
Class JPanelMenu:
Esta clase Es una interfaz gráfica, la cual se reutiliza cada vez que se va a
mostrar un menú, como por ejemplo en menú de configuración. Sobre esta interfaz
gráfica se construyen los menús. Esta clase recibe como parámetro un objeto tipo
“MenuDefinition”, su constructor no retorna ningún dato, pero a través del
método getComponet se retorna el objeto creado, para que sea manipulado en
otras clases. El diagrama de esta clase se puede observar en la ilustración 28.
112
Ilustración 28. Clase JPanelMenu
m_menu = menu;
created = false;
initComponents();
Class JPrincipalApp:
Esta es la clase grafica más importante, debido a que sobre esta interfaz se
construye todo el proyecto, esta clase se instancia una única vez durante toda la
ejecución y es reutilizada en todas las vistas del proyecto exceptuando la vista del
login. El constructor de esta clase recibe como parámetros un objeto tipo
JRootApp, el cual proviene de la primera vista, y además recibe otro objeto tipo
AppUser en el cual se encuentra encapsulado todos los permisos del usuario. El
diagrama de esta clase se puede observar en la ilustración 29.
113
Ilustración 29. Clase JPrincipalApp
114
Fuente: elaboración propia
//HS Updates
private CustomerInfo customerInfo;
115
* @param appview
* @param appuser */
public JPrincipalApp(JRootApp appview, AppUser appuser) {
Class JRootFrame:
Esta clase es llamada antes que la clase JRootApp, la clase JRootFrame invoca la
clase OSValidator para validar el sistema operativo en el que se está ejecutando el
programa, también hace un llamado a la clase AppProps la cual trae las
propiedades del sistema, y además invoca la clase JRootApp y le envía las
propiedades del sistema como parámetro, adicionalmente, define el título del
programa añadiendo el nombre del programa y su versión. El diagrama de esta
clase se puede observar en la ilustración 30.
116
public class JRootFrame extends javax.swing.JFrame implements
AppMessage {
initComponents();
}
/**
*
* @param props
* @throws java.io.IOException
*/
public void initFrame(AppProperties props) throws
IOException {
Class OSValidator:
117
Esta clase es invocada una única vez en la ejecución del programa y es la
encargada de identificar sobre qué sistema operativo se está ejecutando el
proceso. El diagrama de esta clase se puede observar en la ilustración 31.
private String OS =
System.getProperty("os.name").toLowerCase();
/**
*
*/
public OSValidator() {
/**
*
* @return
118
*/
public String getOS(){
if (isWindows()) {
return("w");
} else if (isMac()) {
return("m");
} else if (isUnix()) {
return("l");
} else if (isSolaris()) {
return("s");
} else {
return("x");
}
}
Class BaseSentence:
Esta clase es invocada cada vez que el sistema necesita realizar una consulta a la
base de datos, debido a que la clase es abstracta no posee método constructor y
cada clase que hace uso de esta clase le da sentido a cada uno de sus métodos,
el uso de esta clase siempre se realiza a través de interfaces. El diagrama de esta
clase se puede observar en la ilustración 32.
119
Ilustración 32. Clase BaseSentence
/**
*
* @throws BasicException
*/
public abstract void closeExec() throws BasicException;
// Funciones
120
/**
*
* @return
* @throws BasicException
*/
@Override
public final int exec() throws BasicException {
return exec((Object) null);
}
Class Session:
121
Ilustración 33. Clase Session
/**
*
*/
122
public final SessionDB DB;
m_c = null;
m_bInTransaction = false;
DB = getDiff();
}
Class BasicException:
123
Ilustración 34. Clase BasicException
/**
* Creates a new instance of <code>DataException</code>
without detail message.
*/
public BasicException() {
}
/**
*
* @param msg
*/
public BasicException(String msg) {
super(msg);
}
/**
*
* @param msg
124
* @param cause
*/
public BasicException(String msg, Throwable cause) {
super(msg, cause);
}
Class LocaleResources:
125
public LocaleResources() {
// m_resources = new LinkedList<ResourceBundle>();
m_resources = new LinkedList<>();
Class SaveProvider:
Esta clase se encarga de almacenar las acciones de los botones guardar, agregar
y eliminar de cada una de las interfaces de gestión del sistema, su constructor es
polimorfo pero el constructor que se usa con mas frecuencia es public
SaveProvider(SentenceExec sentupdate, SentenceExec sentinsert,
SentenceExec sentdelete), el cual recibe tres parámetros , de tipo
SentenceExec, cada uno de los cuales representa la acción que tomará uno de
126
los tres botones anteriormente mencionados. El diagrama de esta clase se puede
observar en la ilustración 36.
127
m_sentupdate = sentupdate;
m_sentinsert = sentinsert;
m_sentdelete = sentdelete;
}
Class ProductsPanel:
128
public class ProductsPanel extends JPanelTable2 implements
EditorListener {
public ProductsPanel() {
}
/**
*
*/
@Override
protected void init() {
m_dlSales = (DataLogicSales)
app.getBean("com.openbravo.pos.forms.DataLogicSales");
row = m_dlSales.getProductsRow();
129
m_dlSales.getProductCatUpdate(),
m_dlSales.getProductCatInsert(),
m_dlSales.getProductCatDelete()//,
//m_ai.createProduct(TOOL_TIP_TEXT_KEY)
);
Class ProductsEditor:
130
Ilustración 38. Clase ProductsEditor
131
private final SentenceList m_sentcat;
private ComboBoxValModel m_CategoryModel;
setAppView(app);
dlSales = (DataLogicSales)
app.getBean("com.openbravo.pos.forms.DataLogicSales");
m_dlSuppliers = (DataLogicSuppliers)
app.getBean("com.openbravo.pos.suppliers.DataLogicSuppliers");
initComponents();
taxsent = dlSales.getTaxList();
132
m_sentcat = dlSales.getCategoriesList();
m_CategoryModel = new ComboBoxValModel();
taxcatsent = dlSales.getTaxCategoriesList();
taxcatmodel = new ComboBoxValModel();
Class DirtyManager:
133
ChangeListener, ActionListener, PropertyChangeListener {
Class ProductFilter:
134
sobre los productos. El diagrama de esta clase se puede observar en la ilustración
40.
135
/** Creates new form JQBFProduct */
public ProductFilter() {
initComponents();
}
/**
*
* @param app
*/
@Override
public void init(AppView app) {
m_sentcat = dlSales.getCategoriesList();
m_CategoryModel = new ComboBoxValModel();
m_jCboName.setModel(ListQBFModelNumber.getMandatoryString())
;
m_jCboPriceBuy.setModel(ListQBFModelNumber.getMandatoryNumbe
r());
m_jCboPriceSell.setModel(ListQBFModelNumber.getMandatoryNumb
er());
}
136
Class DataLogicReceipts:
Esta clase se encarga de gestionar los permisos de los tickets que son
compartidos entre usuarios, es decir, esta clase puede bloquear la acción de
modificar un ticket a cualquier usuario. El diagrama de esta clase se puede
observar en la ilustración 41.
137
}
/**
*
* @param s
*/
@Override
public void init(Session s){
this.s = s;
}
/**
*
* @param Id
* @return
* @throws BasicException
*/
public final TicketInfo getSharedTicket(String Id) throws
BasicException {
if (Id == null) {
return null;
} else {
Object[]record = (Object[]) new StaticSentence(s
, "SELECT CONTENT, LOCKED FROM sharedtickets
WHERE ID = ?"
, SerializerWriteString.INSTANCE
, new SerializerReadBasic(new Datas[] {
Datas.SERIALIZABLE})).find(Id);
return record == null ? null : (TicketInfo) record[0];
}
}
138
Script MySQL-create.sql
Este script, es el encargado de crear las tablas de la base de datos por primera
vez, es decir, que si se desea adicionar otra tabla al proyecto, el query debería de
ir dentro de este archivo.
139
Script MySQL-check-tables.sql
Este script se encarga de verificar durante una actualización, si hay una tabla
dentro del proyecto que no exista y si es así la crea. Debido a esto acá también
debería ir el query si se llegase a crear una nueva tabla
*
* Script created by Jack, uniCenta 23/07/2016 08:00:00
*
* Check DB tables.
*/
/* Header line. Object: applications. Script date: 23/07/2016
08:00:00 */
CREATE TABLE IF NOT EXISTS `applications` (
`id` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`version` varchar(255) NOT NULL,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT = Compact;
140
KEY `attinst_att` ( `attribute_id` ),
KEY `attinst_set` ( `attributesetinstance_id` ),
PRIMARY KEY ( `id` )
) ENGINE = InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT = Compact;
Script MySQL-dropFKeys.sql
/*
* Script created by Jack, uniCenta 07/08/2016 08:00:00
*
*/
141
ALTER TABLE LEAVES DROP FOREIGN KEY lEAVES_PPLID;
142
ANEXO C: DISGREGACIÓN DE PRODUCTO
LISTA DE ILUSTRACIONES
ILUSTRACIÓN 42. DIAGRAMA DE CASOS DE USO – NIVEL 0: DISGREGACIÓN DE PRODUCTO ... 148
ILUSTRACIÓN 43. DIAGRAMA DE CASOS DE USO - NIVEL 1: DISGREGACIÓN DE PRODUCTO...... 148
ILUSTRACIÓN 44. DIAGRAMA DE ACTIVIDADES: DISGREGACIÓN DE PRODUCTO .......................... 150
ILUSTRACIÓN 45. MODELO RELACIONAL: DISGREGACIÓN DE PRODUCTO ..................................... 151
ILUSTRACIÓN 46. MOCKUP DE DISGREGACIÓN DE PRODUCTO ....................................................... 151
ILUSTRACIÓN 47. MOCKUP DE BÚSQUEDA DE PRODUCTO ................................................................ 152
ILUSTRACIÓN 48. CLASE PRODUCTSBUNDLEINFO ............................................................................. 153
ILUSTRACIÓN 49. INTERFAZ PARA AGREGAR UN PRODUCTO A DISGREGAR .................................. 156
ILUSTRACIÓN 50. INTERFAZ DE BÚSQUEDA DE PRODUCTO .............................................................. 156
LISTA DE TABLAS
143
Como se plantea en los objetivos, una de las intenciones del proyecto es llevar a
cabo una adaptación de la disgregación de productos; ésta consiste en lograr que
un producto esté conformado por sub-productos, los cuales podrán ser tenidos en
cuenta en la gestión de Inventarios, sean gestionados en el comercio electrónico.
Análisis:
En esta fase del módulo, lo que se realizó fue primero que todo la elicitación de los
requisitos, los cuales fueron adquiridos utilizando dos métodos diferentes, la lluvia
de ideas y a través del prototipado. Después de haber adquirido dichos requisitos,
se realizó un análisis de los mismos en donde se realizó una ponderación de cada
uno de ellos y se clasificaron.
Requisitos:
ID Nombre Ponderación
144
En las tablas 6,7,8,9,10 y 11 se definen los requisitos para la disgregación de
productos.
145
Tabla 8. Definición de requisito 3: Disgregación de producto
146
Tabla 11. Definición de requisito 6: Disgregación de producto
147
Diagramas de casos de uso:
148
Diagrama de actividades:
149
Ilustración 44. Diagrama de actividades: Disgregación de producto
150
Modelo relacional:
Mockups:
En las ilustraciones 46 y 47, se puede observar los mockups del módulo.
151
Ilustración 47. Mockup de búsqueda de producto
Codificación:
Clase ProductsBundleInfo:
152
Ilustración 48. Clase ProductsBundleInfo
/**
*
* @param id
* @param productId
* @param productBundleId
* @param quantity
*/
public ProductsBundleInfo(String id, String productId,
String productBundleId, Double quantity) {
153
this.id = id;
this.productId = productId;
this.productBundleId = productBundleId;
this.quantity = quantity;
}
Clase DataLogicSales:
/**
*
* @param productId The product id to look for bundle
* @return List of products part of the searched product
* @throws BasicException
*/
public final List<ProductsBundleInfo>
getProductsBundle(String productId) throws BasicException {
return new PreparedSentence(s
154
, "SELECT "
+ "ID, "
+ "PRODUCT, "
+ "PRODUCT_BUNDLE, "
+ "QUANTITY "
+ "FROM products_bundle WHERE PRODUCT = ?"
, SerializerWriteString.INSTANCE
,
ProductsBundleInfo.getSerializerRead()).list(productId);
}
if (bundle.size() > 0) {
for (ProductsBundleInfo component : bundle) {
Object[] adjustParams = new Object[4];
adjustParams[0] = component.getProductBundleId();
adjustParams[1] = ((Object[])params)[1];
adjustParams[2] = ((Object[])params)[2];
adjustParams[3] = ((Double)((Object[])params)[3])
* component.getQuantity();
adjustStock(adjustParams);
}
}
Resultados
155
Ilustración 49. Interfaz para agregar un producto a disgregar
156
ANEXO D: SINCRONIZACIÓN CON WOOCOMMERCE
LISTA DE ILUSTRACIONES
LISTA DE TABLAS
157
Uno de los objetivos específicos del proyecto, es la sincronización de unicenta con
una plataforma de comercio electrónico, en el presente anexo, se evidencia el
cumplimiento al objetivo anteriormente mencionado.
Requisitos:
ID NOMBRE PONDERACIÓN
158
REQ1 Definir productos en venta virtual 3.8
4.5
REQ6 Gestión de stock en woocommerce
En las tablas 13, 14, 15,16 y 17 se definen los requisitos para la disgregación de
productos.
159
Fuente: elaboración propia
Tabla 15. Definición de requisito 3: Sincronización con Woocommerce
160
Fuente: elaboración propia
Diagrama de casos de uso:
161
Ilustración 51. Diagrama de casos de uso - nivel 0: Sincronización con Woocommerce
162
Ilustración 52. Diagrama de casos de uso - nivel 1: Sincronización con Woocommerce
163
Diagrama de actividades:
164
Modelo relacional:
165
Diagrama de despliegue:
MockUps:
166
Ilustración 56. Mockup de atributos para e-commerce
167
Codificación:
168
Fuente: elaboración propia
/**
* Last modification: 08-08-2018 12:31 am
* @description This is the collection of
* api interfaces, if you want to consume the api
* you wanna see the method in this class
* @author ceul
*/
public class APICollection implements API_interface{
public APICollection() {
productAPI = new ProductAPI();
}
169
Esta clase es la encargada de realizar las peticiones a la API. Todos los métodos
de esta clase corresponden a un servicio de la API, los métodos de esta clase
reciben como parámetro un String en donde viene el JSON con el cual se va a
realizar la petición. El diagrama de esta clase se puede observar en la ilustración
58.
/**
* Last modification: 08-08-2018 12:31 am
* @description
* @author ceul
**/
public class ProductAPI implements ProductAPIInterface {
private Http con;
private String resource;
private String url;
170
} catch (Exception e) {
return resource;
}
}
@Override
public void writeValueInsert() {
m_jWebSell.setSelected(false);
m_jDescription.setText(null);
m_jShortDescription.setText(null);
m_jLength.setText("0");
m_jWeigth.setText("0");
171
m_jWidth.setText("0");
m_jHeight.setText("0");
}
@Override
public Object createValue() throws BasicException {
myprod[29] = Boolean.valueOf(m_jWebSell.isSelected());
myprod[30] = m_jDescription.getText();
myprod[31] = m_jShortDescription.getText();
myprod[32] =
Formats.DOUBLE.parseValue(m_jLength.getText());
myprod[33] =
Formats.DOUBLE.parseValue(m_jWeigth.getText());
myprod[34] =
Formats.DOUBLE.parseValue(m_jWidth.getText());
myprod[35] =
Formats.DOUBLE.parseValue(m_jHeight.getText());
myprod[36] = m_jInCatalog.isSelected();
myprod[37] =
Formats.INT.parseValue(m_jCatalogOrder.getText());
return myprod;
}
172
necesidad, además, ciertos métodos también realizan la acción de realizar
consultas directamente a la base de datos del proyecto.
/**
* Last modification: 09-07-2018 11:29 am
* @description This method consume the woocommerce api
* to get a list of products, return the response of
* woocomemerce's api
* @returns {json}
* @author Carlos Urrego
*/
public getProducts() {
try {
return this.WooCommerce.get('/products',
function(err, data, res){
if (err) {
return err;
} else {
return data;
}
});
} catch (error) {
console.log('An error occurred while the products
were obtained ' + error + ` ${WooProductDAO.name} ->
${this.getProducts.name}`);
return error;
}
}
/**
173
* Last modification: 06-07-2018 11:52 am
* @description This method consume the woocommerce api
* to get a product, return the response of
* woocomemerce's api
* @param id : string, is the product's id
* @returns {json}
* @author Carlos Urrego
*/
public getProductWithID(id: string) {
try {
return new Promise( ( resolve, reject ) => {
this.WooCommerce.get('products/' + id,
function(err, data, res){
if (err) {
resolve(err);
} else {
resolve(data);
}
});
} );
} catch (error) {
console.log('An error occurred while the product was
obtained ' + error + ` ${WooProductDAO.name} ->
${this.getProductWithID.name}`);
}
}
/**
* Last modification: 12-09-2018 17:40
* @description This method consume the woocommerce api
* to create a product, return the response of
* woocomemerce's api
* @param product : any, is the product object
* @returns {json}
* @author Carlos Urrego
*/
public async createProduct(product: OctoPosProduct) {
174
try {
let wooproduct =
this.OctoPosProducttoWoocommerce(product);
let imgUrl= await
this.uploadImage(product.image,product.id);
let cat = await
productDAO.getProductExternCategory(product.category);
if((<any> cat).length > 0){
wooproduct.categories = [{
id: cat[0].extern_id
}]
En esta clase se crean las rutas que va a aceptar la API, es decir, se exhiben los
servicios a los clientes, para cada uno de estos servicios se define el método por
el cual se va a acceder a él, el URL y cuál va a ser el proceso a realizar después
de recibida la petición.
app.route('/')
.get((req: Request, res: Response) => {
res.status(200).send({
message: 'GET request successfulll!!!!'
})
})
app.route('/product')
.post(this.productController.getProducts)
app.route('/product/read/:productId')
.post(this.productController.getProductWithID)
175
app.route('/product/create')
.post(this.productController.createProduct)
app.route('/product/update')
.post(this.productController.updateProduct)
app.route('/stock/update')
.post(this.productController.updateStockProduct)
Este es un fragmento del script utilizado para la creación de las tablas necesarias
para el funcionamiento del módulo de sincronización.
176
PRIMARY KEY ( `id` ),
KEY `platform_fk_extern_product` ( `platform_id` ),
KEY `product_fk_local_product` ( `local_id` )
) ENGINE = InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT = Compact;
Pruebas:
Como proceso final del desarrollo del módulo se llevaron a cabo, unas cuantas
pruebas las cuales quedaron registradas en las tablas 18 y 19.
Tabla 18. Casos de prueba: Sincronización
177
Tabla 19. Registro de bugs: Sincronización
Logros:
178
Ilustración 61. Interfaz de atributos para e-commerce
179
ANEXO E: OCTOPOS APP
LISTA DE ILUSTRACIONES
LISTA DE TABLAS
180
Dentro de los objetivos específicos del proyecto, se plantea el desarrollo de una
aplicación para realizar pedidos desde dispositivos móviles, con sistema operativo
android, esta aplicación tiene como propósito facilitar los procesos de toma de
pedidos en restaurantes, cafés y bares.
ID NOMBRE PONDERACIÓN
181
Fuente: elaboración propia
182
Fuente: elaboración propia
183
Fuente: elaboración propia
184
En la ilustración 61 y 62, se aprecia el diagrama de casos de uso del módulo
MockUps:
185
Ilustración 64. Mockup listado de mesas: Octopos App
186
Ilustración 65. Mockup listado de categorías: Octopos App
187
Ilustración 66. Mockup listado de productos: Octopos App
188
Ilustración 67. Mockup finalización de pedido: Octopos App
189
Código:
A. BackEnd (NodeJS):
Clase Routes:
Esta clase es la encargada de exponer los servicios de la API, para que puedan
ser consumidos, en el siguiente código se puede apreciar los servicios que
consume la aplicación para su funcionamiento.
190
.post(this.productController.insertSharedTicket)
app.route('/sharedticket/update')
.post(this.productController.updateSharedTicket)
app.route('/sharedticket/delete')
.post(this.productController.deleteSharedTicket)
app.route('/user/get')
.post(this.productController.getUser)
app.route('/place/get')
.post(this.productController.getPlaces)
app.route('/floor/get')
.post(this.productController.getFloors)
app.route('/tax/get')
.post(this.productController.getTaxes)
Clase ProductsController:
191
} catch (error) {
console.log('An error occurred while the categories were
obtained ' + error + ` ${ProductController.name}`);
}
}
Clase OctoPosDAO:
192
return con.query(`SELECT
ID,
NAME,
IMAGE,
TEXTTIP,
CATSHOWNAME,
CATORDER
FROM categories
WHERE PARENTID IS NULL AND CATSHOWNAME = TRUE
ORDER BY CATORDER, NAME;`, (err, rows) => {
if (err)
return reject(err);
resolve(rows);
});
});
} catch (error) {
console.log('An error occurred while getting Root Catergories
:' + error + `: ${OctoPosProductDAO.name} ->
${this.getRootCatergories.name}`);
}
}
193
CATORDER
FROM categories WHERE PARENTID = ${parentid}
ORDER BY CATORDER, NAME;`, (err, rows) => {
if (err)
return reject(err);
resolve(rows);
});
});
Clase DataBaseService:
private constructor() {
try {
this.connection.getConnection((err, connection) => {
if (err) {
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
console.error('Database connection was
closed.')
}
194
if (err.code === 'ER_CON_COUNT_ERROR') {
console.error('Database has too many
connections.')
}
if (err.code === 'ECONNREFUSED') {
console.error('Database connection was
refused.')
}
}
if (connection) connection.release()
return
})
} catch (error) {
console.log('An error occurred while the connection
was created ' + error + ` ${DataBaseService.name} ->
constructor`);
}
}
static getInstance() {
try {
if (!DataBaseService.instance) {
DataBaseService.instance = new DataBaseService();
}
return DataBaseService.instance;
} catch (error) {
console.log('An error occurred while the instance was
195
returned ' + error + ` ${DataBaseService.name} ->
${this.getInstance.name}`);
}
}
HomeRoutes:
Este archivo exporta las rutas del módulo de Home de la aplicación, con el
respectivo componente en caso de ser invocadas y además con el título de cada
una de las páginas
196
component: PlacesComponent,
data: {
pageTitle: 'Places'
}
},
];
export const homeRouting: ModuleWithProviders =
RouterModule.forChild(homeRoutes);
Clase UserComponet:
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styles: []
})
export class UsersComponent implements OnInit {
users: any[];
constructor(private userService: UserService,
private _router: Router,
private globalService: GlobalsService
) {
}
ngOnInit() {
197
try {
let servicio = this.userService.obtenerUsuarios().subscribe(
resp => {
this.users = resp;
console.log(this.users);
servicio.unsubscribe();
},
errResponse => {
servicio.unsubscribe();
throw new Error(errResponse);
}
);
}
catch (error) {
console.log(error);
}
}
Html UserComponet:
198
<div id="content">
<div class="row">
<div class="col-sm-12">
<div class="col-sm-6 col-md-6 col-lg-4 col-xs-6" *ngFor="let
user of users">
<div class="product-content product-wrap clearfix" >
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="product-deatil">
<h5 class="name">
<a (click)="goToPlaces(user.ID,
user.NAME)">
{{ user.NAME }}
</a>
</h5>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Clase PlacesService:
199
obligatorio, recibe los datos que sean necesarios para el consumo del servicio. Así
como esta clase existen más las cuales permiten la interacción con la API.
@Injectable()
export class PlacesService extends BaseService {
getPlaces(floor: string) {
try{
return this.consumeService('/place/get',{floor});
}
catch (error) {
console.log(error);
}
}
Pruebas:
200
Tabla 30. Casos de prueba: OctoPOS APP
201
Logros:
En las ilustraciones 66, 67, 68, 69, 70 y 71, se pueden apreciar los pantallazos de
la aplicación desarrollada, la cual cumple con el siguiente objetivo específico:
“Desarrollar un módulo para pedidos a través de dispositivos móviles android.”
202
Ilustración 68. Usuarios de la aplicación
203
Ilustración 69. Lugares del restaurante
204
Ilustración 70. Pedido
205
Ilustración 71. Categorías de productos
206
Ilustración 72. Sub categorías de productos
207
Ilustración 73. Productos
208
ANEXO F: ARTÍCULO PUBLICABLE
livre
Resumen — En el presente documento se verán comunidad, ya que al ser reconocido dentro de las
plasmados los aprendizajes obtenidos y los procesos comunidades, se va creando una reputación, la
realizados para llevar a cabo el desarrollo de tres cual servirá como apoyo a la hora de postularse a
módulos nuevos para el proyecto de software libre ofertas laborales o licitaciones en una empresa.
Unicenta.
Entre otros beneficios.
Palabras clave — Unicenta, NodeJS, Angular,
Software libre.
Las comunidades de software libre se
vienen dando desde la década de los 80's, gracias
Abstract - In this document, the lessons learned a Richard Stallman creador del movimiento de
and the processes carried out to carry out the software libre.
development of three new modules for the Unicenta A partir de este momento, han surgido
free software project will be captured. infinidad de proyectos de esta índole alrededor del
Keywords - Unicenta, NodeJS, Angular, Free mundo, uno de estos es Unicenta, un software
Software desarrollad para suplir las necesidades de los
pequeños negocios dedicados a la venta minorista.
Resumo - Neste documento, as lições aprendidas e
Este software es distribuido bajo la licencia GNU
os processos realizados para realizar o
desenvolvimento de três novos módulos para o General Public License version 3.0 (GPLv3), la
projeto de software livre da Unicenta serão cual convierte el proyecto en uno de software
capturados. libre.
Palavras chave- Unicenta, NodeJS, Angular, Unicenta en su versión 4.1 carece de algunas
Software Livre funcionalidades como la sincronización con un
Introducción comercio electrónico, aplicación para dispositivos
móviles, entre otras. Lo cual lleva a la necesidad
L A contribución a comunidades de software
libre es una actividad que, al menos las personas
o empresas involucradas en el sector de las
de desarrollar estos módulos, pero debido a que
los directores de Unicenta no agregan las nuevas
funcionalidades a su proyecto, se decidió crear un
tecnologías deberían realizar, ya que esta proyecto derivado de Unicenta denominado
actividad proporciona grandes beneficios OctoPOS.
devuelta, tales como conocimiento profundo sobre
un proyecto, lo cual beneficia demasiado a la hora II. MARCO TEORICO
de resolver posibles errores que surjan con el uso
del proyecto; reconocimiento dentro de la A. Antecedentes
209
Unicenta es un proyecto derivado del
software OpenBravo Pos el cual es propiedad de Chromis POS
la compañía OpenBravo, este proyecto comenzó
siendo software libre y como una comunidad, pero Descripción: Este proyecto se basa en
al pasar el tiempo fue privatizado y explotado de Unicenta, fue creado por John Lewis en el año
forma comercial por la compañía; debido a esto 2012, y es de origen Inglés. Este proyecto fue
surgieron derivados como lo es Unicenta. Así creado básicamente porque John Lewis realizaba
como Unicenta es un proyecto derivado, existen nuevas funcionalidades al código fuente de
otros mas que también son derivados de Unicenta las cuales no eran incluidas en las
OpenBravo, pero además, gracias a la gran nuevas versiones, así que Lewis decidió comenzar
acogida de Unicenta por parte de la comunidad y a su propio proyecto y agregó las nuevas
la falta de integración de las nuevas funcionalidades desarrolladas por el, cabe resaltar
funcionalidades aportadas por ésta al proyecto, que la funcionalidad más importante en este
han ido surgiendo otros proyectos derivados de proyecto y por la cual surgió, es el módulo para la
Unicenta. A continuación se mostrará un breve pantalla de la cocina. En la figura 2 se puede
lista de estos proyectos derivados, tanto de apreciar una captura de pantalla del inicio de
Unicenta como de OpenBravo, cada uno de los Chromis POS.
proyectos tendrá una breve descripción, la licencia Licencia: GNU General Public License
bajo la cual se distribuye el proyecto y una version 3.0 (GPLv3)
imagen del software
Nord POS
210
Licencia: Apache License V2.0, GNU en este software son:
General Public License version 3.0 (GPLv3)
Conectividad con impresoras fiscales de
1ra y 2da generación, comanderas,
scanners entre otras.
Manejo de sesiones de usuario, distinción
de roles.
Gestión de artículos.
Gestión de inventario.
Gestión de caja.
Gestión de proveedores.
Generación de informes.
211
del cliente en javascript, del lado del servidor se de estos módulos anteriormente mencionados, es
puede escribir desde un servidor web hasta los entender el funcionamiento del software base, en
scripts necesarios para soportar el servidor este caso Unicenta oPos , para esto se realizó un
[4][5][6]. proceso de ingeniería inversa el cual se dividió en
dos partes, el entendimiento de la base de datos a
REST: según Fielding, REST es una arquitectura través del análisis del modelo entidad relación de
de software desarrollada a partir de varias la base de datos de Unicenta y el entendimiento de
arquitecturas de red, que combinada con algunas su código fuente.
restricciones adicionales define una interface de Para poder entender la base de datos del
conexión uniforme. Esta arquitectura se enfatiza
proyecto el primer paso realizado fue saber sobre
en la escalabilidad de los componentes,
que motor de base datos estaba funcionando el
generalidad de las interfaces y un desarrollo
proyecto, debido a que al tener esta información
independiente de componentes. Además intenta
minimizar la latencia y la comunicación de la red, se creaba una idea de como serian los tipos de
al mismo tiempo que maximiza la independencia datos utilizados en esta base de datos, las
y la escalabilidad de las implementaciones de restricciones que tendría y la sintaxis SQL que se
componentes. Esto se logra al colocar utiliza para su gestión, además es un dato esencial
restricciones en la semántica del conector, donde para comenzar la búsqueda de una herramienta
otros estilos se han centrado en la semántica de los que facilite el proceso de obtener el modelo ER de
componentes [7]. la base de datos del proyecto.
Al realizar la búsqueda de una herramienta
III. PROBLEMA para el propósito anteriormente mencionado se
eligió el software dbeaver para lleva a cabo el
Los directores del proyecto Unicenta no cometido.
agregan las nuevas funcionalidades desarrolladas Es de resaltar que el proyecto contiene más de
por la comunidad, por tanto su crecimiento no es 40 tablas, las cuales se encuentran en su tercera
potenciado con la rapidez que la comunidad forma normal lo cual garantiza consistencia en los
requiere. Además, no existe ningún proyecto que datos almacenados, además se puede observar que
cuente con todas las funcionalidades planteadas, las llaves primarias de todas las tablas son de tipo
en los objetivos del presente documento. varchar, esto se debe a que los desarrolladores
Adicionalmente, debido a que los proyectos de
optaron por usar el metodo de identificacion
software libre no son patrocinados directamente
UUID, ya que este método se adapta muy bien a la
por una persona o empresa en particular, y en su
necesidad de identificación que se genera con el
mayoría se distribuyen de forma gratuita, sin
generar ganancia por el uso particular de este, uso de los tickets de venta, los cuales tienen un
necesitan de una comunidad de personas que tiempo de vida de corta duración.
tengan un ideario similar a las metas del proyecto, Ya entendiendo la base de datos del proyecto
las cuales sean capaz de sostenerlo, ya sea con su se inició con el entendimiento de su código el cual
conocimiento y/o tiempo. fue escrito en el lenguaje de programación Java
usando como entorno de desarrollo integrado
IV. RESULTADOS Netbeans, así que el primer paso para poder
entender el código del proyecto fue montar el
Aunque el Unicenta es un software maduro, código en dicha plataforma, después de esto se
con más de 7 años de trabajo, el mejoramiento del comenzó con un proceso de depuración del
mismo difícilmente acabará, gracias a que se van proyecto, el cual permitió seguir paso a paso los
creando nuevas necesidades en los usuarios. procesos realizados por el software, ver la
Gracias a esto se tomó la iniciativa del desarrollo interacción entre clases y los tipos de dato que
de dos nuevos módulos los cuales son: manejaba el programa y de esta manera se fue
construyendo un conocimiento frente a cómo
Sincronización con Woocommerce funcionaba el proyecto.
Una app móvil para la toma de pedidos Adicionalmente otro factor fundamental para
entender la estructura del proyecto y su
Pero una parte fundamental para el desarrollo funcionamiento, fue el diagrama de clases del
proyecto.
212
Ya conociendo el diagrama de clases, estas son: Es asíncrono y basado en eventos, es
entendiendo los procesos y algoritmos del muy rápido, posee un solo hilo pero es altamente
proyecto se generó la documentación de las clases escalable, su consumo de máquina es bajo, entre
más influyentes dentro del proyecto y que fueron otras. Lo que convierte a NodeJS la herramienta
necesarias para el desarrollo de los otros módulos. ideal para realizar el desarrollo.
Esta documentación, como fue mencionado Después de esto se procede al desarrollo de una
anteriormente, se generó por cada clase y consiste aplicación para realizar pedidos desde dispositivos
en: El diagrama de clases de la clase móviles con sistema operativo android, la cual
documentada, una descripción de la funcionalidad tiene como propósito facilitar los procesos de
de la clase con sus respectivos parámetros de toma de pedidos en restaurantes, cafés y bares.
entrada y salida, y por último un fragmento del La aplicación se limita a realizar pedidos y que
código de la clase. estos queden registrados en la base de datos.
Adicionalmente se documentaron también los Debido a que se tomó la decisión de desarrollar
scripts SQL de la base de datos, la documentación una aplicación híbrida ,con el fin que la aplicación
de estos se realizó dando una descripción de lo sea la base para un proyecto web, se optó por
que hace el script y un fragmento de código. desarrollar la aplicación en el framework de
Ya habiendo realizado el proceso de ingeniería desarrollo para JavaScript, Angular ya que este
se inició con el desarrollo del módulo de tiene cierta compatibilidad con los dispositivos
disgregación de productos el cual consiste en móviles a la hora de crear una aplicación basada
lograr que un producto esté conformado por sub- en el mismo. Para crear la apk en base al código
productos, los cuales podrán ser tenidos en cuenta Angular se hizo uso de Phonegap.
en la gestión de Inventarios. En este desarrollo se
puso a prueba el entendimiento adquirido después V. CONCLUSIÓN
de haber realizado la ingeniería inversa del
proyecto. El proceso de desarrollar nuevos
Seguidamente se procedió a desarrollar el módulos para un software libre, requiere de
módulo de sincronización con Woocommerce en tiempo y esfuerzo para entender su
el cual se realizó la selección de cuál sería la funcionamiento, el apoyo de la comunidad es
plataforma de comercio electrónico con la que se fundamental durante todo el proceso, ya que esta
realizará la sincronización, así que se eligió la se convierte en la fuente principal de información
y conocimiento del tema, lo que permite mejor
plataforma Woocommerce la cual brinda una muy
fluidez durante el desarrollo. Aunque el
buena documentación para los desarrolladores,
conocimiento de la comunidad es muy amplio , el
además, ya que es un plugin de wordpress cuenta
proceso de ingeniería inversa, permite ahondar
con el respaldo de la comunidad de wordpress, la mucho más en el funcionamiento del programa, lo
cual es bastante grande y activa en la red, lo que cual permite empoderarse más del proyecto para
brinda un canal de soporte adicional a la de esta forma se facilite el desarrollo de los
documentación proporcionada por el proyecto. módulos.
También cabe resaltar que Woocommerce es la En cuanto al desarrollo de los módulos se
plataforma más usada para soportar tiendas puede concluir que el uso de buenas prácticas de
virtuales, esta es usada por alrededor del 28% de programación tales como la documentación, el
todas las tiendas virtuales en internet, con lo cual manejo de versiones, entre otras; y adicionalmente
al hacer esta sincronización impactaría de manera la aplicación de la ingeniería del software y una
positiva un gran sector de las ventas electrónicas. buena planeación del proyecto, proporcionan unas
Por estas razones anteriormente expuestas se herramientas y una organización al mismo, lo cual
selecciono la plataforma Woocommerce como la asegura el buen término de cualquier desarrollo de
candidata ideal para llevar a cabo la software. Así también la elección correcta de las
sincronización. herramientas a usar en el desarrollo permiten
Adicionalmente se seleccionó también cual agilizar los procesos, e igualmente llevar a buen
seria la plataforma usada como intermediaria entre término el desarrollo
Unicenta oPos y Woocommerce, y se llegó a la
conclusión que se desarrollaría una API REST en Referencias
NodeJS gracias a sus características, algunas de
213
[1] Openbravo POS, "Openbravo POS - Openbravo Forge", [6] S. Tilkov and S. Vinoski, "Node.js: Using JavaScript to
Centralrepository.openbravo.com, 2008. [Online]. Build High-Performance Network Programs", IEEE
Disponible: Internet Computing, vol. 14, no. 6, 2010.
http://centralrepository.openbravo.com/openbravo/org.o [7] R. Fielding, "Fielding Dissertation: CHAPTER 5:
penbravo.forge.ui/ForgeProjectDetail/openbravopos. Representational State Transfer (REST)", Ics.uci.edu,
[Accedido: 13- Nov- 2018]. 2018. [Online]. Disponible:
[2] R. Stallman, Software libre para una sociedad libre, 1st https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_
ed. Madrid: Traficantes de Sueños, 2004, p. 45. arch_style.htm. [Accedido: 20- Abr- 2018].
[3] Á. Manjavacas, ADAPTACIÓN E
IMPLEMENTACIÓN DE MEJORAS EN UN
PROYECTO DE SOFTWARE LIBRE A UN SISTEMA
Carlos Enrique Urrego. Nació
CASH -FLOW MUY EFICIENTE Y SEGURO. Madrid,
en Pereira – Risaralda, Colombia, el 5
España: Universidad Complutense de Madrid, 2016.
de agosto de 1997. Estudiante de
[4] B. Dayley, Node.js, MongoDB and AngularJS web
Ingeniería de Sistemas y
development. Upper Saddle River, NJ [etc.]: Addison-
Telecomunicaciones de la Universidad
Wesley, 2014.
Católica de Pereira. Entre sus campos
[5] N. Foundation, "About | Node.js", Node.js, 2018.
de interés se encuentra el Software
[Online]. Disponible: https://nodejs.org/en/about/.
Libre, los algoritmos, y procesamiento
[Accedido: 21- Jun 2018].
de señales.
214
ANEXO G: CONFIGURACIÓN DEL PROYECTO EN NETBEANS
LISTA ILUSTRACIONES
Para poder entrar a realizar ingeniería inversa del proyecto y poder contribuir a él,
inicialmente se necesita descargar el código fuente de Unicenta desde su página
oficial en sourceForge, después de esto, se procede a descomprimir el archivo.
Posteriormente, se pasará a configurar el proyecto en el IDE Netbeans, cabe
resaltar que el proyecto a la hora de desarrollar es más compatible con la
plataforma de netbeans debido a algunos plugins que este IDE posee. Los pasos
para configurar el proyecto en netbeans son los siguientes:
215
Ilustración 74. Comenzar un nuevo proyecto en netbeans
216
Ilustración 75. Nombre y localización (NetBeans)
De click en el botón 'añadir carpeta' y añada las carpetas locales y los reportes,
una vez haya añadido esto, de click en siguiente - en este momento podrá dar
click en finalizar.
217
Ilustración 76. Añadir el código de uniCenta oPos
218
Ilustración 77. Incluir/Excluir archivos
Una vez realizado los pasos anteriores, verá que el asistente hará el resto del
trabajo, porque crea los archivos y las carpetas necesarias del proyecto. Cuando
el asistente termine verá el proyecto con algunos archivos que tendrán
advertencias en rojo, esto pasa debido a que el asistente no agrega las librerías
necesarias para el proyecto.
219
Ilustración 78. Incluir/Excluir archivos
220
Ilustración 79. Añadiendo Librerías
221
Ilustración 80. Seleccione 'Añadir JAR/carpetas'
Esta pantalla muestra todas las referencias a las librerías que han sido resueltas y
tu nuevo proyecto de unicenta está listo para comenzar.
Cuando corras el proyecto por primera vez netbeans te preguntará por la clase
principal del proyecto. Selecciona 'com.openbravo.pos.forms.StartPOS'.
222
Ilustración 81. Configure la clase principal
223
ANEXO H: MODELO RELACIONAL
224
Ilustración 83. Modelo relacional parte 2
225
Ilustración 84. Modelo relacional parte 3
226
Ilustración 85. Modelo relacional parte 4
227
Ilustración 86. Modelo relacional parte 5
228
Ilustración 87. Modelo relacional parte 6
229
Ilustración 88. Modelo relacional parte 7
230
Ilustración 89. Modelo relacional parte 9
231
ANEXO I: ACTAS DE REUNIÓN Y CARTA DE SATISFACCIÓN
232
Fuente: elaboración propia
233
Ilustración 92. Carta de satisfacción
234
Ilustración 93. RUT Almacen Tienda los chikos
235