La Wiki Preciosa: estado del proyecto, modo de trabajo, modelos empleados, consensos encontrados, etc. - mgaitan/preciosa GitHub Wiki
En este espacio apuntaremos ideas y recursos útiles para el desarrollo de Preciosa.
OBJETIVOS A CORTO PLAZO FIJADOS PARA PRECIOSA
Teniendo en cuenta la gran repercusión mediática que ha tenido la aplicación en distintos medios nacionales y provinciales, se hace urgente apurar el desarrollo con el objetivo de contar con una primera versión funcional de todo el sistema para fines de febrero, principios de marzo.
Las preguntas a realizarse para fijar estos objetivos pasan por:
- A DONDE HAY QUE LLEGAR
- CUANDO
- y COMO (que tareas concretas hay que hacer)
Teniendo en cuenta las limitaciones temporales y la disponibilidad de colaboradores se propone tratar de alcanzar un "MVP" de Preciosa: las funciones mínimas que prueben que "la idea funciona/puede funcionar". Esto está bosquejado en la maqueta de la app mobile, que podés ver en el siguiente link.
Resumiendo la idea: "El usuario indica en qué supermercado está, busca productos por código, categorías o palabras y recibe como información el último (o más confiable) precio en esa sucursal (si existe) y el mejor de la ciudad. A su vez se le pide al usuario que confirme o corrija con el precio que está viendo en la góndola"
A ese flow básico de uso se le pueden sumar muchísimas cosas: a) que "autodetecte" la sucursal donde está el usuario. b) que te ofrezca más información sobre el producto. c) que te deje dar de alta desde el propio teléfono una sucursal/producto, incluso ciudad, que no está en nuestra base de datos. y muchísimas otras cosas que se nos ocurrieron y se nos van a ir ocurriendo.
Para poder alcanzar el objetivo básico planteado hay muchos inconvenientes a solucionar y tareas a realizar:
+ API REST:
- Toda la API rest (el ticket #2, pilar de todo el sistema), el cual deberá poder:
- dar listas de ciudades / categorías / cadenas de supermercados / sucursales de supermercados que sean filtrables por nombre.
- dar listas de productos filtrables por ID de categoría, descripción y código de barras.
- dar toda la data de detalle de un producto para una determinada sucursal.
- recibir (POST) de un usuario autenticado la data de un precio nuevo (será el mismo, en el caso de una confirmación) para un producto-sucursal.
+ APP MOBILE:
- El cliente web HTML5/js debe saber como usar esa API Rest.
- El Interface de Usuario debe verse mínimamente bonito y sobre todo debe ser simple de usar.
- La App debería funcionar "lo mejor posible" en android, Iphone y blackberry.
- Para filtrar por "código de barra" se debería poder tanto ingresar los 13 números por teclado como usar el "scanner" de código de barra.
+ APLICACIÓN WEB:
- En la aplicacion web, la cosa debería ser mínimamente igual, sólo que a priori no pondría un formulario para "enviar precios" desde la web. (aunque quizás haya gente que se toma el trabajo de desgrabar un ticket más cómodo en su casa).
Datos Iniciales de Preciosa
Por el momento lo único que hay son aproximadamente 9000 productos con código de barra conocidos con los precios de las plataformas e-commerce de Walmart, Coto y Jumbo (no todos los productos tiene los tres precios) y también, claro, los productos dentro del acuerdo de precios del gobierno. Algo importante a resolver es que por el momento no tenemos ningún precio, de ningún producto, de ninguna sucursal.
Entonces la cuestión a resolver es ¿como mostrar lo que tenemos? Por ejemplo, si desde un super de Córdoba se realiza una consulta sobre cuanto sale la Yerba Taragûí de 1Kg, ¿que debería responder el sistema? "no hay datos para Córdoba pero el precio que conocemos online es $XX. ¿qué precio estás viendo en góndola?. La segunda vez que consulten desde Córdoba, ya podremos dar dos referencias y así, vamos mejorando la precisión de la aplicación.<
Implementación de Herramientas para Aprovechar la Ayuda de Colaboradores sin Conocimientos Técnicos
Para intentar aprovechar la "buena voluntad" de gente que se ha interesado por la idea pero no tiene conocimientos técnicos se ha implementado un conjunto básico de formularios en la web. Es decir, infraestructura básica para que humanos aumenten o corrijan nuestro datos.
Cualquiera persona puede colaborar en el proyecto simplemente ingresando a: http://preciosdeargentina.com.ar/voluntarios/
Modelos de Datos Utilizado:
-
Código del Modelo (con algunos agregados): https://github.com/mgaitan/preciosa/blob/feature/modelado-base/preciosa/precios/models.py La categoría es una árbol (subcategoria) y los precios bajo acuerdo se moldearon aparte.
-
Gráfico del Modelo: http://yuml.me/edit/44e615f4
Mecanismo de Recopilación de Información sobre productos/sucursales:
Se está realizando un proceso de scrapping para extraer la información de productos y sucursales de sitios web de las distintas cadenas de supermercados.
La tarea de scrapping, para aquellos interesados en colaborar con el tema, se podría resumir así: Sin importar de donde provengan los datos, van a terminar en la base de datos de Preciosa. Eso significa que van a tener un ID y todos los demas atributos que definen nuestros modelos. Como los datos están interrelacionados (ejemplo, un producto está asociado a (un ID de) una categoria) no podemos poner un ID arbitrario, tenemos que dejar que Django los asigne autoincrementalmente
Ahora, por ejemplo para establecer que la categoria "Almacen -> Yerba" es el ID 18 en la base online, y para que dos colaborares distintos puedan trabajar de forma paralela, hay que "copiar" esos datos que son comunes.
Para llevar a cabo dicha tarea vamos a realizar "dumps" de esas tablas que necesitamos compartir, que son concretamente los archivos json que estan en la carpeta fixtures del repositorio. Por suerte los genera y los carga django solo con los comandos dumpdata y loaddata (se puede buscar ayuda de estos comandos). Entonces, por ejemeplo si de alguna manera obtenemos un CSV con todos los datos concretos que necesitamos de sucursales de super, tendremos que:
-
- Avisamos que vamos a laburar en ese "Ticket" (es cuasi imposible hacer merge de "fixtures" en este caso).
-
- Tener ya en nuestra base de datos local todas las sucursales que ya conocemos es decir, tener cargado el fixture /sucursales.json
-
- Cargar la nueva info (via un script ingresado a través del shell de django) como instancias del modelo Sucursal (Sucursal.objects.create... () y previamente, si hiciera falta, el de la Cadena en cuestion.
-
- Una vez cargadas todas las sucursales, regeneramos el fixture sucursales.json (que incluye tanto el modelo Cadena como Sucursal)
$ python manage.py dumpdata precios.Cadena precios.Sucursal > fixtures/sucursales.json
-
- "Pusheamos" el cambio en el json y proponemos el pull request, que deberá ser mergeado rápido para desbloquear así nuevas sucursales pueden ser agregadas.
Sólo un detalle complica y es que el campo "ciudad" del modelo Sucursal no es una cadena sino un FK al modelo City, es decir un ID, y previo a crear las instancias de Sucursales tenemos que convertir el dato crudo al ID correspondiente. ¿Como sabemos cual es el ID de ciudad? De dos formas: a) Desde el mismo shell de django se puede buscar a ver si encontramos la instancia . Es decir, arrancamos el shell con
$ python manage.py shell_plus
y luego supongamos que queres buscar el ID correspondiente a "Calamuchita"
In [1]: City.objects.filter(name__icontains='Calamuchita') Out[1]: [<City: Santa Rosa de Calamuchita, Córdoba, Argentina>]
encontré un sólo objeto que es el que buscaba
In [2]: calamuchita = Out[1]
y entonces en la creacion de Sucursal, en vez de la palabra "Calamuchita" voy a darle la instancia de City Calamuchita (que, en el fixture, simplemente terminará siendo un numero, pero no nos importa)
_De todo esto que se describe hay ejemplos de "chupadores de sucursales" (ver ejemplos) En relación a este ejemplo verán que el codigo no es muy prolijo e inconexo: no programemos así. Pero en "esta parte" el objetivo es conseguir los datos, puede decirse que es código descartable y está allí sólo a modo de ejemplo.
Sirve perfectamente cualquier código, no necesariamente uno acoplado a Django, en cualquier lenguaje, que permita generar un fixture (por ejemplo en Json) de sucursales de una (o varias) cadenas de super. Los datos importantes son "nombre, ciudad, direccion" (si fuese posible, provincia, telefonos y otros datos). Hay otro ejemplo más prolijo pero más laborioso que generar jsons intermedios (agnosticos de django) a traves de screapper.py que tambien está en "/tools". En definitiva si la data está bien, lo pueden realizar con el método más comodo.
¿En que hace falta ayuda entonces?
Gente que quiera encarar tickets de scrapping de datos puede consultar la lista correspondiente.
Identificación, carga y descarga de datos de los usuarios.
Si bien aún no se ha tomado una definición concreta en relación a estos aspectos, se ha comenzado la discusión de la temática a través del grupo de desarrollo de googlegroups, en el cual han surgido varias propuestas:
+ Identificación de los usuarios: En general la única propuesta que ha surgido hasta el momento es que a la hora de registrarse como usuarios, lo más útil sería poder hacerlo con la cuenta de Facebook, Google, Twitter, etc. La estima que gente ya no quiere crearse más cuentas, y mucho menos para probar una app que no sabe si van a seguir usando a futuro. Registrándose con alguna de las cuentas existentes, ya pueden cargar automáticamente su nombre, su foto y si quieren su ciudad, para que la app arranque de manera más personalizada sin necesidad de que el usuario tenga que ponerse a definir esas cosas manualmente.
+ Carga y descarga de datos de los usuarios de la base de datos de Preciosa.
PROPUESTA 1: Se propone que para consultar precios (comparar, ver donde está más barato, etc) sea anónimo pero para suministrar información se solicite registrarse. Después se podría verificar con algún script cierta coherencia en los precios y detectar precios falsos: por ejemplo si en un día 3 usuarios pusieron que el Yogurt está $1.99 y un usuario pone que está a $5, rompiendo así con cierto humbral el promedio, se podría impugnar ese precio y anotar el antecedente en la reputación del usuario. Si un usuario llegara a 10 precios falsos, se le podría suspender la cuenta o algo por el estilo.
PROPUESTA 2: Una alternativa podría ser "premiar" o incentivar de alguna forma a los que cargan precios fiables, hasta se podria permitir dar de alta ofertas limitadas e informar a usuarios confiables unicamente cercanos al negocio como para incentivarlos. A mi me gustaria que me informe de esas cosas y por ahi tambien motiva a los negocios a cargar datos reales y usarlo como un canal de atraccion de clientes.
- La app podría venir con un "crédito" de 10 cargas de precios sin necesitar registrarse. Una vez agotado el crédito inicial, no se podrían cargar nuevos precios, sino sólamente votar los que suban usuarios registrados, por ejemplo.
- Los precios registrados por usuarios registrados, tendrían más peso que los registrados por usuarios anónimos. Los de usuarios registrados podrían tener "un color" distintivo y los de usuarios anónimos otro distinto.
- Si un producto tuviese un precio que ha sido subido y votado sólamente por usuarios "anónimos", el precio se podría publicar, pero con un cartelito que diga "sin validar" o algo por el estilo.
Los usuarios registrados estaría habilitados para subir un precio nuevo, y los otros usuarios podrían votarlo/verificarlo. El peso de los votos depende de si los que votan son usuarios registrados o usuarios anónimos, etc. Por ejemplo para verificar un precio podría hacer falta 1 voto de otro usuario registrado o 3 de usuarios anónimos. Otra forma de incentivar a participar es la típica gilada de las medallitas y los premios. Si la app tiene una web propia, se puede publicar un ranking de los mejores colaboradores, etc.
Ubicación del Cliente.
La idea de base es que cuando un usuario ingresa al sitio web debería consultarsele sobre su ubicación actual.
Una parte importante del trabajo es conseguir data de las direcciones de sucursales de supermercados en las distintas ciudades. Esa info se ha completado cruzandola con una BBDD de ciudades (dump de geonames.org) que tienen coordenadas lat/long. Por otro lado se ha logrado implementar un sistema para "geolocalizar" las sucursales que ya se encuentran cargadas en la base de datos y las que sean cargadas en el futuro mediante la API Pública de Google Maps.
La idea es que a traves de geolocalización automáticamente se pueda detectar desde el móvil en qué sucursal se encuentra el usaurio. De ser necesario, por razones temporales, en un principio bastará con la ciudad y un buscador de supermercados de esa ciudad.
En la web será analogo a esto último. Se podría detectar, con geoip por ejemplo, desde donde está el usuario consultando y de esta forma se podrían filtrar los resultados para esa ciudad.
Herramientas y Plataforma de Desarrollo de Preciosa
**Aplicación WEB y API Rest: ** El desarrollo será llevado adelante utilizando el framework de desarrollo de sitios web Django, de código abierto y basado en el lenguaje Python. Actualmente se está utilizando la versión 1.5.1 del framework.
¿Más info de Django? http://es.wikipedia.org/wiki/Django_(framework).
APP Celular: Las aplicación móbil de Preciosa será desarrolladas inicialmente con PhoneGap, un entorno de desarrollo multiplataforma que permite realizar un único desarrollo basado en lenguajes comunes como CCS3, Java Script y HTML5, siendo fácilmente exportable a todas las plataformas más populares de celualares de la actualidad (Android, Windows Mobile, Blackberry ,Symbian, IOS).
¿Más info de PhoneGap? http://es.wikipedia.org/wiki/PhoneGap
Licencia
Preciosa es un proyecto comunitario basado en software libre que será distribuido bajo licencia AGPL. ¿Qué es AGPL?: http://es.wikipedia.org/wiki/GNU_Affero_General_Public_License
Glosario
-
EAN/UPC/PLU: distintos tipos de códigos de barras. Véase Referencia
-
Scrapping: Web Scraping es una técnica utilizada mediante programas de software para extraer información de sitios web. Usualmente, estos programas simulan la navegación de un humano en la World Wide Web ya sea utilizando el protocolo HTTP manualmente, o incrustando un navegador en una aplicación como puede ser Internet Explorer o Mozilla Firefox. Véase Referencia
-
JSON: acrónimo de JavaScript Object Notation, es un formato ligero para el intercambio de datos. JSON es un subconjunto de la notación literal de objetos de JavaScript que no requiere el uso de XML. Véase Referencia..