[Diario] Control de gastos. Python & PostgreSQL

vago_21

Día 6. 8 Julio 2021

  • He refactorizado el código que importa los ficheros del banco:

  • Hoy quiero añadir algunos campos más a la base de datos para diferenciar los gastos fijos de los variables. También asignaré a los variables un periodo (Mensual, trimestral, etc)

vago_21

Día 7. 9 Julio 2021

  • He creado una entidad para poder categorizar los gastos fijos y su periodicidad, de esta forma, en el futuro podré hacerme un calendario de gastos fijos con alertas etc
  • Ya importo los movimientos controlando duplicados
  • Al importar un excel, se mueve a una carpeta de "Procesados"

Ahora tengo que ver la mejor forma de categorizar los movimientos según mis propias categorías y no las que manda el banco, que son imprecisas

1 1 respuesta
JuAn4k4

#32 Siempre puedes hacer mapping de las del Banco a las tuyas y ponerles flag de sin confirmar de forma que las vas confirmando manualmente y/o recategorizando.

1 respuesta
Phatality

No creo que sea necesario en este caso, pero una cosa que podrias hacer para practicar dependency injection es poner estas implementaciones tras interfaces (las interfaces en python se crean usando clases abstractas o bien protocolos).

Hace poco jugue con esta libreria de DI y ni tan mal, pero no esperes la sofisticacion q podrias encontrar en java o C# (por desgracia). El ecosistema python es muy flojo en este frente.

1 respuesta
desu

DI es un anti-pattern y esta mal usarlo.

http://gustavlundin.com/di-frameworks-are-dynamic-binding/

Como les explico a mis alumnos, siempre "constructor" y data flow unidireccional.

https://odrotbohm.de/2013/11/why-field-injection-is-evil/
https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x#general-core-revision

https://github.com/Dynam1co/Personal_budget/blob/main/Dockerfile
te falta la psql en el docker

2 respuestas
Phatality

#35

DI es un anti-pattern y esta mal usarlo.

Durisimas declaraciones con las q no puedo estar mas en desacuerdo. Puedes desarrollar esto?

1 1 respuesta
KazuluDev

#36 te ha contestado por telegram:

spoiler
2 respuestas
Ranthas

El ex-becario senior no deja a nadie indiferente con sus opiniones

2
JuAn4k4

#37 @desu Leete los enlaces que has puesto, ninguno habla de que DI sea un smell ni nada malo. Habla de field injection (la mayor aberración que creó Spring y que Java siguió. DI no es field injection.

vago_21

#33 Lo estoy haciendo por descripción, he estado revisando y solo con las categorías no me vale, por ejemplo, dependiendo de la gasolinera, me cataloga el banco como ocio jajajaj. Pero sí, voy a crearme una tabla con una marca para las que pueda hacer el sistema automáticamente, que son bastantes, las que queden, de momento las haré a mano.

#34 siempre me han llamado la atención las interfaces, pero nunca me ha dado por usarlas

#35 el postgre lo tengo en otro pc con un volumen compartido, que lo uso para varias cosillas

Gracias a todos!!!

1 3 respuestas
desu

#40 deberías tener un docker file de desarrollo y otro para prod.

1 1 respuesta
Soltrac

#40 y como vas a hacer los tests unitarios sin usar interfaces?

Phatality

#37 Buen energumeno el amigo. Luego en #41 propone duplicar imagenes de docker pudiendo usar docker-compose. La arrogancia es lo que tiene.

#40 Aunque siempre puedes usar la libreria que te viene built in para unit tests, te recomiendo esta que te hace la vida muuuucho mas facil. La feature que mas me gusta es que puedes parametrizar los tests con un decorator. Ademas, puedes configurar la libreria para correr tests de integracion y unittest por separado usando un fichero de configuracion (sin lios de variables de entorno, que son menos claros y explicitos).

1 respuesta
vago_21

Día 8. 12 Julio 2021

  • Ya he categorizado a manopla todos los movimientos existentes. Ahora que ya sé la casuística etc quiero implementar la categorización automática.

Aquí la duda:
Imaginemos que tengo la siguiente tabla para mapear descripciones de movimientos con la categoría y subcategoría que quiero asignar:

TEXTO BUSCARTEXTO EXCLUIRCAT DESTINOSUBCAT DESTINO
nominatraspaso periódico123
est. servicio157

¿Cómo lo implementaríais?
Yo como buen noob haría:

  • Script que me diese todos los movimientos pendientes de categorizar
  • Por cada uno, ir a la tabla a buscar qué categoría asignarle

Me gustaría saber cómo lo haríais los que tenéis más experiencia, si creando una clase etc

1 respuesta
desu
#43Phatality:

propone duplicar imagenes de docker pudiendo usar docker-compose. La arrogancia es lo que tiene.

base.yml
dev.yml
prod.yml

docker-compose -f base.yml -f dev.yml up -d
docker-compose -f base.yml -f prod.yml up -d

anda tira a hacer DI en python que te faltan unos cuantos petitsuis y colacaos.

1 respuesta
Phatality

#44 Asi a bote pronto suena como la clase de cosa que (quiza) es lo suficientemente simple como para hacerlo en la misma db. Por ej, si el unico criterio para categorizar algo es un texto a buscar y un texto a excluir, puedes tirar de regex en una query que updatee la tabla donde tengas los movimientos.

Ahora, si la logica de categorizar es algo que sql no te puede hacer (eg, si tuvieras que hacer una logica chunga para categorizar rollo busqueda fuzzy) y ademas el volumen de datos te cabe en memoria (que es el caso) pues puedes hacer alguna implementacion en python de esa categorizacion. Esta seria mi ultima opcion, eso si.

1 1 respuesta
Phatality

#45 Sisi, recoge cuerda listillo. En el post original le dijiste al chaval que montara 2 imagenes por separado.

1
vago_21

Día 9. 13 Julio 2021

  • He dockerizado una base de datos Postgre para desarrollo. Voy a tener que hacer muchas pruebas de categorización de movimientos automática y no quiero ensuciar la base de datos real.
  • También he actualizado el readme para que se sepa un poco de qué va el proyecto
  • He incluido un makefile que le copié a @desu ayer para agilizar un poco los pasos que hago antes de commitear, aunque ya tengo el black ejecutándose en el pre-commit e integración continua al hacer push a develop en github. Es increíble los que estoy aprendiendo gracias a este hilo

Hoy toca ya hacer la categorización automática de movimientos. Muchas gracias por los consejos #46 creo que lo implementaré en python, más que nada para que quede más visible en github, pero coincido que lo mejor sería disparar un stored en la base de datos.

3 1 respuesta
vago_21

Actualización día 9

Ya asigno las categorías y subcategorías automáticamente, funciona a la perfección, pero necesito codereview del código

Gracias hermanos y hermanas

1 respuesta
JuAn4k4

#48 Si no te quieres meter con IA, yo haría un motor de reglas. Y defines las reglas en un JSON/CSV que esté en otro sitio y ya está, lo cacheas en mem y lo recargas cada X minutos y listo.

JuAn4k4

#49 Y si dos reglas matchean? No hay score? Es decir, una regla matchea un movimiento con un score determinado, y eliges la "mejor categoría" Por score.

Para mi lo estás haciendo al revés, yo haría categorización de movimientos, ahí estas aplicando categorías de una regla.

Es decir, yo cojo un movimiento y le aplicó todas las reglas para ver qué categorías encajan, y ya elegiría la mejor categorías.

Con esa impl dependes del orden en el que se ejecuten, solo la primera que encaje se le pone.

Al final tendrías que tener reglas super específicas, y dejarás cosas sin categorizar, de la otra forma pueden ser reglas más genéricas. Ejemplo:
Si tiene la palabra Station, es Transporte score 0.2
Si tiene Tandori Station es Restaurante score 1
Gas station, sería Transporte, Gasolina, score 1

1 1 respuesta
vago_21

#51 ahora mismo tengo las reglas en bbdd, pero exacto, la primera que encuentra es la que se traga. Pero lo de asignar por IA lo quiero hacer sí o sí, es algo que me interesa mucho y así aprendo por el camino, en cuanto lo tenga funcionando me pondré con eso.

Y lo de los pesos es una idea de puta madre que ni había ni tenido en cuenta. Gracias!

Edit: que acabo de leer tu edit, exactamente, ahora es demasiado específico, se me quedan cosas pendientes, la mayoría son compras de Amazon que es imposible categorizar automáticamente, pero el problema de que vaya a un nuevo restaurante es que se va a quedar sin categorizar seguro. Si lo hiciese como tú dices podría abarcar mayor rango

1 respuesta
Unrack

#52 Puede que el core integrado en rasa te sirva para lo que quieras. Luego me extiendo.

Es un framework para construir chatbots. A priori no tiene mucho que ver pero el chatbot conversacional no es más que una clasificación sobre entradas de texto. Puedes tomar la literatura que ellos usan para tu caso: https://blog.rasa.com/introducing-dual-intent-and-entity-transformer-diet-state-of-the-art-performance-on-a-lightweight-architecture/

Algo más clásico sería hacer algo tipo embeddings y asignar al centroide de tus categorias más cercano

1 1 respuesta
vago_21

#53 gracias! tiene buena pinta. He estado mirando los word embeddings y he encontrado esto: https://machinelearningmastery.com/develop-word-embeddings-python-gensim/

Igual tiro por ahí

1 respuesta
desu

Se suele usar https://www.nltk.org/

1 1 respuesta
vago_21

#55 me mola, voy a acabar la versión 1 y me pongo con esto que me interesa mucho

Unrack

#54 Si, nltk es la librería principal para hacer todo esto. Yo creo que con algo basado en embeddings ya te debe funcionar bien. Más o menos lo que buscas es clasificar los conceptos semánticamente en las categorías.

vago_21

Día 10 y 11. 14-15 Julio 2019

  • He seguido testeando la importación de movimientos, poniendo 6 ficheros excel en la ruta y los procesa todos sin problemas
  • Ahora estoy haciendo un menú para cosas que tengo que ejecutar manualmente (clasificar movimientos raros, ver movimientos pendientes de categorizar, dividir movimientos en N etc)

Tengo dudas para estructurar el código que ejecuta cada opción de menú, de momento me ha salido meter todas esas funciones en un fichero a parte, pero se agradecen ideas.

vago_21

Ya tengo cosillas funcionando

Ranthas

¿Por qué no estás usando una interfaz gráfica? ¿O iba a ser una aplicación de consola?

1 respuesta

Usuarios habituales

  • vago_21
  • Ranthas
  • Unrack
  • desu
  • JuAn4k4
  • Phatality
  • PiPePiTo