def test_consolidador_honra_timeout(db, settings): settings.MIN_COINCIDENCIAS_IDENTIFICACION = 1 a = AttachmentFactory() m1 = MesaFactory() i1 = IdentificacionFactory( attachment=a, status='identificada', mesa=m1, tomada_por_consolidador=timezone.now() - timedelta(minutes=settings.TIMEOUT_CONSOLIDACION - 1)) consumir_novedades_identificacion() a.refresh_from_db() i1.refresh_from_db() # No la tomó aún. assert i1.procesada is False assert a.status == Attachment.STATUS.sin_identificar i1.tomada_por_consolidador = timezone.now() - timedelta( minutes=settings.TIMEOUT_CONSOLIDACION + 1) i1.save() consumir_novedades_identificacion() a.refresh_from_db() i1.refresh_from_db() # Ahora sí assert i1.procesada is True assert a.identificacion_testigo == i1 assert a.mesa == m1 assert a.status == Attachment.STATUS.identificada
def test_identificacion_consolidada_ninguno(db): a = AttachmentFactory() m1 = MesaFactory() IdentificacionFactory(attachment=a, status='identificada', mesa=m1) i1 = IdentificacionFactory(attachment=a, status='problema', mesa=None) f = FiscalFactory() Problema.reportar_problema(f, 'reporte 1', ReporteDeProblema.TIPOS_DE_PROBLEMA.spam, identificacion=i1) assert i1.problemas.first().problema.estado == Problema.ESTADOS.potencial i2 = IdentificacionFactory(attachment=a, status='problema', mesa=None) Problema.reportar_problema(f, 'reporte 2', ReporteDeProblema.TIPOS_DE_PROBLEMA.ilegible, identificacion=i2) assert a.identificacion_testigo is None cant_novedades = Identificacion.objects.filter(procesada=False).count() assert cant_novedades == 3 consumir_novedades_identificacion() # Se consolidó un problema. assert i1.problemas.first().problema.estado == Problema.ESTADOS.pendiente cant_novedades = Identificacion.objects.filter(procesada=False).count() assert cant_novedades == 0 assert a.identificacion_testigo is None
def test_con_carga_pendiente_ignora_cats_inactivas(db): # Identifico una mesa. mesa = MesaFactory() a = AttachmentFactory() IdentificacionFactory(attachment=a, status='identificada', mesa=mesa) IdentificacionFactory(attachment=a, status='identificada', mesa=mesa) consumir_novedades_identificacion() cat = mesa.categorias.first() mc = MesaCategoriaFactory(mesa=mesa, categoria=cat) assert mc.status == MesaCategoria.STATUS.sin_cargar assert mc in MesaCategoria.objects.con_carga_pendiente() # Desactivo la categoría. cat.activa = False cat.save() assert mc not in MesaCategoria.objects.con_carga_pendiente() # La vuelvo a activar. cat.activa = True cat.save() assert mc in MesaCategoria.objects.con_carga_pendiente()
def test_fotos_de_mesa(db): m = MesaFactory() a1, a2, a3 = AttachmentFactory.create_batch(3) # a3 tiene una version editada. a3.foto_edited = a3.foto a3.save() IdentificacionFactory( status='identificada', source=Identificacion.SOURCES.csv, attachment=a1, mesa=m, ) # a2 está asociada a m pero se # ignora porque no está consolidada. IdentificacionFactory( status='identificada', attachment=a2, mesa=m ) IdentificacionFactory( status='identificada', source=Identificacion.SOURCES.csv, attachment=a3, mesa=m ) consumir_novedades_identificacion() assert m.fotos() == [ ('Foto 1 (original)', a1.foto), ('Foto 2 (editada)', a3.foto_edited), ('Foto 2 (original)', a3.foto), ]
def test_scheduler(db, settings): """ Ejecutar dos veces el scheduler sin nuevas cosas no cambia el estado. """ # Creamos 5 attachments sin identificar attachments = AttachmentFactory.create_batch( 5, status=Attachment.STATUS.sin_identificar) c1 = CategoriaFactory() c2 = CategoriaFactory() m1 = MesaFactory(categorias=[c1]) IdentificacionFactory( mesa=m1, status=Identificacion.STATUS.identificada, source=Identificacion.SOURCES.web, ) m2 = MesaFactory(categorias=[c1, c2]) IdentificacionFactory( mesa=m2, status=Identificacion.STATUS.identificada, source=Identificacion.SOURCES.csv, ) # Los cinco del principio y los dos de la identificación. assert Attachment.objects.count() == 7 assert MesaCategoria.objects.count() == 3 # Empezamos con la cola vacía. assert ColaCargasPendientes.largo_cola() == 0 # Ejecutar el scheduler antes de consolidar sólo encola identificaciones: # 2 por cada una de las fotos no identificadas y 1 para las creadas con # IdentificationFactory. scheduler() assert ColaCargasPendientes.largo_cola( ) == 5 * settings.MIN_COINCIDENCIAS_IDENTIFICACION + 2 * ( settings.MIN_COINCIDENCIAS_IDENTIFICACION - 1) # Al consumir las novedades de identificación, se consolidan las # categorías de la segunda mesa, así que agregamos 4 tareas. consumir_novedades_identificacion() scheduler() assert ColaCargasPendientes.largo_cola() == 16 cola_primera = list(ColaCargasPendientes.objects.all()) consumir_novedades_identificacion() scheduler() # Al volver ejecutar el scheduler sin que haya novedades se mantiene la # misma cantidad de tareas. assert ColaCargasPendientes.largo_cola() == 16 cola_segunda = list(ColaCargasPendientes.objects.all()) # Testeamos la igualdad de las colas con la inclusión mutua. for i in cola_primera: assert i in cola_segunda for i in cola_segunda: assert i in cola_primera
def test_identificacion_consolidada_alguna(db): a = AttachmentFactory() m1 = MesaFactory() i1 = IdentificacionFactory(attachment=a, status='identificada', mesa=m1) IdentificacionFactory(attachment=a, status='problema', mesa=None) i2 = IdentificacionFactory(attachment=a, status='problema', mesa=None) Problema.reportar_problema(FiscalFactory(), 'reporte 1', ReporteDeProblema.TIPOS_DE_PROBLEMA.ilegible, identificacion=i2) IdentificacionFactory(attachment=a, status='identificada', mesa=m1) assert a.identificacion_testigo is None cant_novedades = Identificacion.objects.filter(procesada=False).count() assert cant_novedades == 4 consumir_novedades_identificacion() # No se consolidó el problema. assert i2.problemas.first().problema.estado == Problema.ESTADOS.potencial cant_novedades = Identificacion.objects.filter(procesada=False).count() assert cant_novedades == 0 a.refresh_from_db() assert a.identificacion_testigo == i1 assert a.mesa == m1 assert a.status == Attachment.STATUS.identificada
def test_avance_de_carga_mesas_con_varias_fotos(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # una categoria con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # un circuito con 10 mesas de 100, 110, ..., 290 votantes. Total 1450 seccion_1, circuito_1, lugar_votacion_1 = crear_seccion("Luján oeste") [mesas_1] = crear_mesas([lugar_votacion_1], [pv], 10) for ix in range(len(mesas_1)): mesas_1[ix].electores = 100 + ix * 10 mesas_1[ix].save(update_fields=['electores']) # dos fiscales fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # identifico totalmente 5 mesas attachs = AttachmentFactory.create_batch(30) for ix in range(5): identificar(attachs[ix], mesas_1[ix], fiscal_1) identificar(attachs[ix], mesas_1[ix], fiscal_2) identificar(attachs[5], mesas_1[5], fiscal_1) identificar(attachs[6], mesas_1[6], fiscal_1) # agrego dos fotos más a la primer mesa identificar(attachs[7], mesas_1[0], fiscal_1) identificar(attachs[7], mesas_1[0], fiscal_2) identificar(attachs[8], mesas_1[0], fiscal_1) identificar(attachs[8], mesas_1[0], fiscal_2) # agrego otra foto parcial a la segunda mesa identificar(attachs[9], mesas_1[1], fiscal_1) # agrego una fotos más a la tercer mesa identificar(attachs[10], mesas_1[2], fiscal_1) identificar(attachs[10], mesas_1[2], fiscal_2) consumir_novedades_identificacion()
def test_scheduler_orden_distinto(db, settings): # Creamos 5 attachments sin identificar attachments = AttachmentFactory.create_batch( 5, status=Attachment.STATUS.sin_identificar) c1 = CategoriaFactory(sensible=True) c2 = CategoriaFactory(sensible=True) m1 = MesaFactory(categorias=[c1]) IdentificacionFactory( mesa=m1, status='identificada', source=Identificacion.SOURCES.csv, ) m2 = MesaFactory(categorias=[c1, c2]) assert MesaCategoria.objects.count() == 3 IdentificacionFactory( mesa=m2, status='identificada', source=Identificacion.SOURCES.csv, ) # Ambas consolidadas vía csv. consumir_novedades_identificacion() # Si hay más fotos que attachments primero se ponen las fotos, # hasta que haya la misma cantidad de cargas pendients. with override_config(COEFICIENTE_IDENTIFICACION_VS_CARGA=1): scheduler() assert ColaCargasPendientes.largo_cola() == 16 # items = ColaCargasPendientes.objects.all().order_by('orden') # for i in range(16): # it = items[i] # print(f'{i}: ({it.orden},{it.attachment},{it.mesa_categoria})') # Las primeras seis tareas son de identificaciones. for i in range(6): consumir() assert ColaCargasPendientes.largo_cola() == 10 # Luego vienen dos cargas... for i in range(2): consumir(False) assert ColaCargasPendientes.largo_cola() == 8 # luego dos identificaciones y dos cargas, dos veces: for j in range(2): for i in range(2): consumir() for i in range(2): consumir(False) # Ya no queda nada en la cola. assert ColaCargasPendientes.largo_cola() == 0 (mc, attachment) = ColaCargasPendientes.siguiente_tarea(fiscal=None) assert mc is None and attachment is None
def test_identificacion_consolidada_tres_ok_dos_error(db): # En esta variable se almacena el comportamiento que tendrá cada llamado a # la función consolidar_identificaciones para cada identicacion de un attachment # a procesar. # Los attachments a, c y e se procesarán con normalidad y su identificación # quedará maracada como procesadas=True. # Para los attachments b y d se lanzará una Exception y su identicación # quedará como procesada=False. side_effects = [ mock.DEFAULT, #comportamiento para a Exception('error'), #comportamiento para b mock.DEFAULT, #comportamiento para c Exception('error'), #comportamiento para d mock.DEFAULT #comportamiento para e ] with mock.patch('adjuntos.consolidacion.consolidar_identificaciones', side_effect=side_effects): m1 = MesaFactory() a = AttachmentFactory() b = AttachmentFactory() c = AttachmentFactory() d = AttachmentFactory() e = AttachmentFactory() i1 = IdentificacionFactory(attachment=a, status='identificada', mesa=m1) i2 = IdentificacionFactory(attachment=b, status='identificada', mesa=m1) i3 = IdentificacionFactory(attachment=c, status='identificada', mesa=m1) i4 = IdentificacionFactory(attachment=d, status='identificada', mesa=m1) i5 = IdentificacionFactory(attachment=e, status='identificada', mesa=m1) cant_novedades = Identificacion.objects.filter(procesada=False).count() assert cant_novedades == 5 consumir_novedades_identificacion() # Chequeamos que las no procesadas son 2 no_procesadas = Identificacion.objects.filter(procesada=False) assert no_procesadas.count() == 2 # Chequeamos que las no procesadas son i2 e i4 no_procesadas_ids = map(lambda x: x.id, no_procesadas) assert set([i2.id, i4.id]) == set(no_procesadas_ids) # Chequeamos que las procesadas son 3 procesadas = Identificacion.objects.filter(procesada=True) assert procesadas.count() == 3 # Chequeamos que las procesadas son i1, i3 e i5 procesadas_ids = map(lambda x: x.id, procesadas) assert set([i1.id, i3.id, i5.id]) == set(procesadas_ids)
def test_consolidador_desmarca_timeout(db, settings): a = AttachmentFactory() m1 = MesaFactory() i1 = IdentificacionFactory(attachment=a, status='identificada', mesa=m1) assert i1.tomada_por_consolidador is None consumir_novedades_identificacion() i1.refresh_from_db() assert i1.tomada_por_consolidador is None assert i1.procesada is True
def test_identificacion_consolidada_con_minimo_1(db, settings): settings.MIN_COINCIDENCIAS_IDENTIFICACION = 1 a = AttachmentFactory() m1 = MesaFactory() i1 = IdentificacionFactory(attachment=a, status='identificada', mesa=m1) consumir_novedades_identificacion() a.refresh_from_db() assert a.identificacion_testigo == i1 assert a.mesa == m1 assert a.status == Attachment.STATUS.identificada
def test_avance_de_carga_identificacion_parcial(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # una categoria con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # un circuito con 10 mesas de 100, 110, ..., 290 votantes. Total 1450 seccion_1, circuito_1, lugar_votacion_1 = crear_seccion("Luján oeste") [mesas_1] = crear_mesas([lugar_votacion_1], [pv], 10) for ix in range(len(mesas_1)): mesas_1[ix].electores = 100 + ix * 10 mesas_1[ix].save(update_fields=['electores']) # dos fiscales fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # identifico totalmente 5 mesas, parcialmente 2 más attachs = AttachmentFactory.create_batch(30) for ix in range(5): identificar(attachs[ix], mesas_1[ix], fiscal_1) identificar(attachs[ix], mesas_1[ix], fiscal_2) identificar(attachs[5], mesas_1[5], fiscal_1) identificar(attachs[6], mesas_1[6], fiscal_1) consumir_novedades_identificacion() # dos cargas parciales nueva_carga(mesacat(mesas_1[0], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_1[1], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) consumir_novedades_carga() # podemos mirar vorwaerts = AvanceDeCarga(NIVELES_DE_AGREGACION.circuito, [circuito_1.id]) resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 3, 540, 30, 37.24) verificar_resultado(resultados.sin_identificar_con_cargas(), 0, 0, 0, 0) verificar_resultado(resultados.en_identificacion_sin_cargas(), 2, 310, 20, 21.38) verificar_resultado(resultados.en_identificacion_con_cargas(), 0, 0, 0, 0) verificar_resultado(resultados.sin_cargar(), 3, 390, 30, 26.9) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 2, 210, 20, 14.48) verificar_resultado(resultados.carga_parcial_consolidada_csv(), 0, 0, 0, 0) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_sin_consolidar(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_consolidada_csv(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_consolidada_dc(), 0, 0, 0, 0)
def test_mesa_de_circuito__url_mesa_sin_resultados(fiscal_client): categoria = CategoriaFactory(nombre='default') mesa1 = IdentificacionFactory(status='identificada', source=Identificacion.SOURCES.csv).mesa consumir_novedades_identificacion() query_string_mesa_1 = ( f'?mesa={mesa1.id}&circuito={mesa1.circuito.id}' '&tipoDeAgregacion=todas_las_cargas&opcionaConsiderar=todas' ) url_mesa_1 = reverse('mesas-circuito', args=[categoria.id]) + query_string_mesa_1 response = fiscal_client.get(url_mesa_1) assert response.status_code == 200 assert response.context['mensaje_no_hay_info'] in response.content.decode('utf-8') assert not response.context['resultados'].exists()
def test_avance_de_carga_sencillo(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # categoria con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # 10 mesas de 100, 110, ..., 190 votantes. Total 1450 seccion, circuito, lugar_votacion = crear_seccion("Luján oeste") [mesas] = crear_mesas([lugar_votacion], [pv], 10) for ix in range(len(mesas)): mesas[ix].electores = 100 + ix * 10 mesas[ix].save(update_fields=['electores']) fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # a siete mesas les hago identificación total, a una identificación parcial attachs = AttachmentFactory.create_batch(10) for ix in range(7): identificar(attachs[ix], mesas[ix], fiscal_1) identificar(attachs[ix], mesas[ix], fiscal_2) identificar(attachs[7], mesas[7], fiscal_1) consumir_novedades_identificacion() # primer carga parcial en tres mesas for ix in range(3): nueva_carga(mesacat(mesas[ix], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) # a una de estas tres le mando una segunda carga coincidente nueva_carga(mesacat(mesas[0], pv), fiscal_2, [50, 30], Carga.TIPOS.parcial) consumir_novedades_carga() # estamos para probar vorwaerts = AvanceDeCarga() resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 2, 370, 20, 25.52) verificar_resultado(resultados.en_identificacion_sin_cargas(), 1, 170, 10, 11.72) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 2, 230, 20, 15.86) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 1, 100, 10, 6.9) verificar_resultado(resultados.carga_total_sin_consolidar(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_consolidada_dc(), 0, 0, 0, 0)
def test_troll_total_consolidada_dc_a_total_sin_consolidar(db, settings): fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() fiscal_3 = nuevo_fiscal() presi = CategoriaFactory() mesa_1 = MesaFactory(categorias=[presi]) mesa_categoria_1 = MesaCategoria.objects.filter(mesa=mesa_1, categoria=presi).first() attach_1 = AttachmentFactory() identificar(attach_1, mesa_1, fiscal_1) identificar(attach_1, mesa_1, fiscal_2) refrescar_data([ presi, fiscal_1, fiscal_2, fiscal_3, mesa_1, mesa_categoria_1, attach_1 ]) assert not fiscal_1.troll assert not fiscal_2.troll nueva_carga(mesa_categoria_1, fiscal_1, [20, 35], Carga.TIPOS.parcial) nueva_carga(mesa_categoria_1, fiscal_2, [20, 35], Carga.TIPOS.parcial) consumir_novedades_carga() refrescar_data([mesa_categoria_1]) assert mesa_categoria_1.status == MesaCategoria.STATUS.parcial_consolidada_dc nueva_carga(mesa_categoria_1, fiscal_3, [20, 35], Carga.TIPOS.total) nueva_carga(mesa_categoria_1, fiscal_1, [20, 35], Carga.TIPOS.total) consumir_novedades_carga() refrescar_data([mesa_categoria_1]) assert mesa_categoria_1.status == MesaCategoria.STATUS.total_consolidada_dc assert Carga.objects.filter(invalidada=True).count() == 0 aplicar_marca_troll(fiscal_3) consumir_novedades_identificacion() consumir_novedades_carga() refrescar_data([mesa_categoria_1, fiscal_3]) assert mesa_categoria_1.status == MesaCategoria.STATUS.total_sin_consolidar assert Carga.objects.filter(invalidada=True).count() == 1
def test_scheduler_orden_estandar(db, settings): # Creamos 5 attachments sin identificar attachments = AttachmentFactory.create_batch( 5, status=Attachment.STATUS.sin_identificar) c1 = CategoriaFactory(sensible=True) c2 = CategoriaFactory(sensible=True) m1 = MesaFactory(categorias=[c1]) IdentificacionFactory( mesa=m1, status='identificada', source=Identificacion.SOURCES.csv, ) m2 = MesaFactory(categorias=[c1, c2]) assert MesaCategoria.objects.count() == 3 IdentificacionFactory( mesa=m2, status='identificada', source=Identificacion.SOURCES.csv, ) # Ambas consolidadas vía csv. consumir_novedades_identificacion() with override_config(COEFICIENTE_IDENTIFICACION_VS_CARGA=10): scheduler() assert ColaCargasPendientes.largo_cola() == 16 # Las primeras seis tareas son de carga de votos. for i in range(6): consumir(False) assert ColaCargasPendientes.largo_cola() == 10 # las siguientes diez son identificaciones. for i in range(10): consumir() assert ColaCargasPendientes.largo_cola() == 0 # Ya no queda nada en la cola. (mc, attachment) = ColaCargasPendientes.siguiente_tarea(fiscal=None) assert mc is None and attachment is None
def test_carga_parcial_consolidada_dc(db, settings): fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() presi = CategoriaFactory() mesa_1 = MesaFactory(categorias=[presi]) mesa_categoria_1 = MesaCategoria.objects.filter(mesa=mesa_1, categoria=presi).first() attach_1 = AttachmentFactory() assert mesa_categoria_1.status == MesaCategoria.STATUS.sin_cargar identificar(attach_1, mesa_1, fiscal_1) identificar(attach_1, mesa_1, fiscal_2) refrescar_data( [presi, fiscal_1, fiscal_2, mesa_1, mesa_categoria_1, attach_1]) assert not fiscal_1.troll assert not fiscal_2.troll assert Identificacion.objects.filter(procesada=False).count() == 2 consumir_novedades_identificacion() refrescar_data([mesa_categoria_1, mesa_1, attach_1]) assert Identificacion.objects.filter(procesada=False).count() == 0 nueva_carga(mesa_categoria_1, fiscal_1, [20, 15], Carga.TIPOS.parcial) consumir_novedades_carga() refrescar_data([mesa_categoria_1]) assert mesa_categoria_1.status == MesaCategoria.STATUS.parcial_sin_consolidar nueva_carga(mesa_categoria_1, fiscal_2, [20, 15], Carga.TIPOS.parcial) refrescar_data([mesa_categoria_1]) assert Carga.objects.filter(procesada=False).count() == 1 consumir_novedades_carga() refrescar_data([mesa_categoria_1]) assert mesa_categoria_1.status == MesaCategoria.STATUS.parcial_consolidada_dc assert Carga.objects.filter(procesada=False).count() == 0
def test_resultados__generacion_url_ver_mesas_circuito(fiscal_client): categoria = CategoriaFactory(nombre='default') mesa1 = IdentificacionFactory(status='identificada', source=Identificacion.SOURCES.csv).mesa consumir_novedades_identificacion() url = reverse('resultados-categoria', args=[categoria.id]) response = fiscal_client.get(url) assert response.status_code == 200 texto_mesas_link = "Ver mesas del circuito" assert texto_mesas_link not in response.content.decode('utf8') response = fiscal_client.get(url, {"circuito": mesa1.circuito.id}) # como ahora en la URL hay especificado un circuito, debería aparecer el link de "Ver las mesas..." assert response.status_code == 200 assert texto_mesas_link in response.content.decode('utf8') url_mesa_distrito = reverse('mesas-circuito', args=[categoria.id]) assert url_mesa_distrito in response.content.decode('utf8')
def test_problema_falta_foto(db): mc = MesaCategoriaFactory() assert mc.status == MesaCategoria.STATUS.sin_cargar c1 = CargaFactory(mesa_categoria=mc, tipo='total', firma='1-10') consumir_novedades_y_actualizar_objetos([mc]) assert mc.status == MesaCategoria.STATUS.total_sin_consolidar assert mc.carga_testigo == c1 c2 = CargaFactory(mesa_categoria=mc, tipo='problema') Problema.reportar_problema(FiscalFactory(), 'falta foto!', ReporteDeProblema.TIPOS_DE_PROBLEMA.falta_foto, carga=c2) c3 = CargaFactory(mesa_categoria=mc, tipo='problema') Problema.reportar_problema(FiscalFactory(), 'spam!', ReporteDeProblema.TIPOS_DE_PROBLEMA.spam, carga=c2) consumir_novedades_y_actualizar_objetos([mc]) # Ahora sí hay un problema. assert mc.status == MesaCategoria.STATUS.con_problemas assert mc.carga_testigo is None problema = c2.problemas.first().problema assert problema.estado == Problema.ESTADOS.pendiente # Llega un nuevo attachment. a = AttachmentFactory() mesa = mc.mesa # Lo asocio a la misma mesa. IdentificacionFactory(attachment=a, status='identificada', mesa=mesa) IdentificacionFactory(attachment=a, status='identificada', mesa=mesa) consumir_novedades_identificacion() consumir_novedades_y_actualizar_objetos([mc]) # El problema se solucionó. problema.refresh_from_db() assert problema.estado == Problema.ESTADOS.resuelto # La mesa está vigente de nuevo. assert mc.status == MesaCategoria.STATUS.total_sin_consolidar assert mc.carga_testigo == c1
def test_ciclo_de_vida_problemas_resolver(db): a = AttachmentFactory() m1 = MesaFactory() IdentificacionFactory(attachment=a, status='identificada', mesa=m1) # Está pendiente. assert a in Attachment.objects.sin_identificar() i1 = IdentificacionFactory(attachment=a, status='problema', mesa=None) f = FiscalFactory() Problema.reportar_problema(f, 'reporte 1', ReporteDeProblema.TIPOS_DE_PROBLEMA.spam, identificacion=i1) assert i1.problemas.first().problema.estado == Problema.ESTADOS.potencial i2 = IdentificacionFactory(attachment=a, status='problema', mesa=None) Problema.reportar_problema(f, 'reporte 2', ReporteDeProblema.TIPOS_DE_PROBLEMA.ilegible, identificacion=i2) assert i1.invalidada == False assert i2.invalidada == False consumir_novedades_identificacion() # Se consolidó un problema. a.refresh_from_db() assert a.status == Attachment.STATUS.problema problema = i1.problemas.first().problema assert problema.estado == Problema.ESTADOS.pendiente # El attach no está entre los pendientes. assert a not in Attachment.objects.sin_identificar() problema.resolver(FiscalFactory().user) assert problema.estado == Problema.ESTADOS.resuelto i1.refresh_from_db() i2.refresh_from_db() # Las identificaciones están invalidadas. assert i1.invalidada == True assert i2.invalidada == True consumir_novedades_identificacion() # Se agrega una nueva identificación y se consolida. IdentificacionFactory(attachment=a, status='identificada', mesa=m1) consumir_novedades_identificacion() a.refresh_from_db() assert a.status == Attachment.STATUS.identificada assert a.mesa == m1
def test_siguiente_accion_redirige_a_cargar_resultados_sin_scheduler( db, settings, client, setup_groups): c1 = CategoriaFactory() c2 = CategoriaFactory() m1 = MesaFactory(categorias=[c1]) IdentificacionFactory( mesa=m1, status='identificada', source=Identificacion.SOURCES.csv, ) m2 = MesaFactory(categorias=[c1, c2]) assert MesaCategoria.objects.count() == 3 IdentificacionFactory( mesa=m2, status='identificada', source=Identificacion.SOURCES.csv, ) # Ambas consolidadas vía csv. consumir_novedades_identificacion() # Los fiscales que voy a usar. fiscales = FiscalFactory.create_batch(20) indice_fiscal = 0 m1c1 = MesaCategoria.objects.get(mesa=m1, categoria=c1) for i in range(settings.MIN_COINCIDENCIAS_CARGAS): fiscal_client = fiscal_client_from_fiscal(client, fiscales[indice_fiscal]) indice_fiscal += 1 response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m1c1.id]) # Cerramos la sesión para que el client pueda reutilizarse sin que nos diga # que ya estamos logueados. fiscal_client.logout() # Como m1c1 ya fue pedida por suficientes fiscales, # se pasa a la siguiente mesacategoría. m2c1 = MesaCategoria.objects.get(mesa=m2, categoria=c1) for i in range(settings.MIN_COINCIDENCIAS_CARGAS): fiscal_client = fiscal_client_from_fiscal(client, fiscales[indice_fiscal]) indice_fiscal += 1 response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m2c1.id]) fiscal_client.logout() # Ahora la tercera. m2c2 = MesaCategoria.objects.get(mesa=m2, categoria=c2) for i in range(settings.MIN_COINCIDENCIAS_CARGAS): fiscal_client = fiscal_client_from_fiscal(client, fiscales[indice_fiscal]) indice_fiscal += 1 response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m2c2.id]) fiscal_client.logout() # Ya no hay actas nuevas, vuelta a empezar. fiscal_client = fiscal_client_from_fiscal(client, fiscales[indice_fiscal]) indice_fiscal += 1 response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m1c1.id]) fiscal_client.logout() # Se libera una. m2c2.desasignar_a_fiscal() fiscal_client = fiscal_client_from_fiscal(client, fiscales[indice_fiscal]) indice_fiscal += 1 response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m2c2.id])
def test_cargar_resultados_mesa_desde_ub_con_id_de_mesa( db, fiscal_client, admin_user, django_assert_num_queries): """ Es un test desaconsejadamente largo, pero me sirvió para entender el escenario. Se hace un recorrido por la carga de dos categorías desde una UB. Cuando se llama a cargar-desde-ub, cuando va por GET, es para cargar el template carga-ub.html. Cuando se le pega con POST, va a cargar un resultado. Cuando ya no tiene más categorías para cargar, te devuelve a agregar-adjunto-ub """ categoria_1 = CategoriaFactory() categoria_2 = CategoriaFactory() mesa = MesaFactory(categorias=[categoria_1, categoria_2]) mesa_categoria_1 = MesaCategoriaFactory(mesa=mesa, categoria=categoria_1, coeficiente_para_orden_de_carga=1) mesa_categoria_2 = MesaCategoriaFactory(mesa=mesa, categoria=categoria_2, coeficiente_para_orden_de_carga=2) opcion_1 = OpcionFactory() opcion_2 = OpcionFactory() CategoriaOpcionFactory(categoria=categoria_1, opcion=opcion_1, prioritaria=True) CategoriaOpcionFactory(categoria=categoria_1, opcion=opcion_2, prioritaria=True) CategoriaOpcionFactory(categoria=categoria_2, opcion=opcion_1, prioritaria=True) CategoriaOpcionFactory(categoria=categoria_2, opcion=opcion_2, prioritaria=True) AttachmentFactory(mesa=mesa) IdentificacionFactory( mesa=mesa, status=Identificacion.STATUS.identificada, source=Identificacion.SOURCES.csv, ) consumir_novedades_identificacion() assert MesaCategoria.objects.count() == 2 for mc in MesaCategoria.objects.all(): mc.actualizar_coeficiente_para_orden_de_carga() nombre_categoria = "Un nombre en particular" # Sin tilde que si no falla el 'in' más abajo. categoria_1.nombre = nombre_categoria categoria_1.save(update_fields=['nombre']) categoria_2.nombre = 'Otro nombre' categoria_2.save(update_fields=['nombre']) url_carga = reverse('cargar-desde-ub', kwargs={'mesa_id': mesa.id}) response = fiscal_client.get(url_carga) # Nos aseguramos que haya cargado el template específico para UB. No es una redirección. assert response.status_code == HTTPStatus.OK assert url_carga in str(response.content) # categoria1 debería aparecer primero porque su mesa categoria tiene un coeficiente_para_orden_de_carga más grande assert nombre_categoria in str(response.content) tupla_opciones_electores = [ (opcion_1.id, mesa.electores // 2, mesa.electores // 2), (opcion_2.id, mesa.electores // 2, mesa.electores // 2) ] request_data = _construir_request_data_para_carga_de_resultados( tupla_opciones_electores) with django_assert_num_queries(47): response = fiscal_client.post(url_carga, request_data) # Tiene otra categoría, por lo que debería cargar y redirigirnos nuevamente a cargar-desde-ub carga = Carga.objects.get() assert carga.tipo == Carga.TIPOS.total assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('cargar-desde-ub', kwargs={'mesa_id': mesa.id}) # Hacemos el get hacia donde nos manda el redirect. Esto hace el take. response = fiscal_client.get(response.url) # Posteamos los nuevos datos. response = fiscal_client.post(url_carga, request_data) carga.refresh_from_db() cargas = Carga.objects.all() assert len(cargas) == 2 assert carga.tipo == Carga.TIPOS.total # Me lleva a continuar con el workflow. assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('cargar-desde-ub', kwargs={'mesa_id': mesa.id}) # La mesa no tiene más categorías, nos devuelve a la pantalla de carga de adjuntos. assert response.status_code == 302 # Hacemos el get hacia donde nos manda el redirect. response = fiscal_client.get(response.url) assert response.url == reverse('agregar-adjuntos-ub')
def test_siguiente_accion_considera_cant_asignaciones_realizadas_con_scheduler( db, fiscal_client, settings): c1 = CategoriaFactory() c2 = CategoriaFactory() m1 = MesaFactory(categorias=[c1]) IdentificacionFactory( mesa=m1, status='identificada', source=Identificacion.SOURCES.csv, ) m2 = MesaFactory(categorias=[c1, c2]) assert MesaCategoria.objects.count() == 3 IdentificacionFactory( mesa=m2, status='identificada', source=Identificacion.SOURCES.csv, ) # Ambas consolidadas vía csv. consumir_novedades_identificacion() scheduler() m1c1 = MesaCategoria.objects.get(mesa=m1, categoria=c1) for i in range(settings.MIN_COINCIDENCIAS_CARGAS): response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m1c1.id]) # Fiscal devuelve. m1c1.desasignar_a_fiscal() # Como m1c1 ya fue pedida por suficientes fiscales, # se pasa a la siguiente mesacategoría. m1c1.refresh_from_db() assert m1c1.cant_fiscales_asignados == 0 assert m1c1.cant_asignaciones_realizadas == settings.MIN_COINCIDENCIAS_CARGAS m2c1 = MesaCategoria.objects.get(mesa=m2, categoria=c1) assert m2c1.cant_fiscales_asignados == 0 assert m2c1.cant_asignaciones_realizadas == 0 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m2c1.id]) # Fiscal devuelve. m2c1.desasignar_a_fiscal() m2c1.refresh_from_db() assert m2c1.cant_fiscales_asignados == 0 assert m2c1.cant_asignaciones_realizadas == settings.MIN_COINCIDENCIAS_CARGAS # Ahora la tercera m2c2 = MesaCategoria.objects.get(mesa=m2, categoria=c2) for i in range(settings.MIN_COINCIDENCIAS_CARGAS): response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[m2c2.id]) # Fiscal devuelve. m2c2.desasignar_a_fiscal() m2c2.refresh_from_db() assert m2c2.cant_fiscales_asignados == 0 assert m2c2.cant_asignaciones_realizadas == settings.MIN_COINCIDENCIAS_CARGAS # Ya no hay actas nuevas, se terminó. response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.OK
def test_identificaciones_troll(db, settings): """ Se verifica que luego de que un fiscal es detectado como troll, el estado asociado a las identificaciones que hubiera hecho cambia tal cual se espera. """ settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() fiscal_3 = nuevo_fiscal() fiscal_4 = nuevo_fiscal() fiscal_5 = nuevo_fiscal() categoria_1 = nueva_categoria(["o1", "o2", "o3"]) mesa_1 = MesaFactory(categorias=[categoria_1]) mesa_2 = MesaFactory(categorias=[categoria_1]) mesa_3 = MesaFactory(categorias=[categoria_1]) mesa_4 = MesaFactory(categorias=[categoria_1]) mesa_categoria_1 = MesaCategoria.objects.filter( mesa=mesa_1, categoria=categoria_1).first() mesa_categoria_2 = MesaCategoria.objects.filter( mesa=mesa_2, categoria=categoria_1).first() attach_1 = AttachmentFactory() attach_2 = AttachmentFactory() attach_3 = AttachmentFactory() attach_4 = AttachmentFactory() def refrescar_data(): for db_object in [ mesa_categoria_1, mesa_categoria_2, attach_1, attach_2, attach_3, attach_4, fiscal_1, fiscal_2, fiscal_3, fiscal_4, fiscal_5 ]: db_object.refresh_from_db() with override_config( SCORING_MINIMO_PARA_CONSIDERAR_QUE_FISCAL_ES_TROLL=50, SCORING_TROLL_IDENTIFICACION_DISTINTA_A_CONFIRMADA=180): identificar(attach_1, mesa_1, fiscal_1) identificar(attach_1, mesa_1, fiscal_2) identificar(attach_2, mesa_2, fiscal_2) identificar(attach_2, mesa_2, fiscal_3) identificar(attach_3, mesa_1, fiscal_1) identificar(attach_3, mesa_4, fiscal_3) identificar(attach_4, mesa_1, fiscal_1) identificar(attach_4, mesa_4, fiscal_2) nueva_carga(mesa_categoria_1, fiscal_3, [20, 25, 15]) nueva_carga(mesa_categoria_1, fiscal_4, [20, 25, 15]) nueva_carga(mesa_categoria_2, fiscal_4, [60, 25, 20]) nueva_carga(mesa_categoria_2, fiscal_5, [60, 25, 20]) assert Identificacion.objects.filter(procesada=False).count() == 8 assert Identificacion.objects.filter(invalidada=True).count() == 0 assert Carga.objects.filter(procesada=False).count() == 4 assert Carga.objects.filter(invalidada=True).count() == 0 # hasta aca: a1, a2 identificada; a3, a4 sin identificar. consumir_novedades_identificacion() consumir_novedades_carga() refrescar_data() assert attach_1.status == Attachment.STATUS.identificada assert attach_2.status == Attachment.STATUS.identificada assert attach_3.status == Attachment.STATUS.sin_identificar assert attach_4.status == Attachment.STATUS.sin_identificar assert mesa_categoria_1.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_1.carga_testigo is not None assert mesa_categoria_1.coeficiente_para_orden_de_carga is not None assert mesa_categoria_2.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_2.carga_testigo is not None assert mesa_categoria_2.coeficiente_para_orden_de_carga is not None assert not fiscal_1.troll assert Identificacion.objects.filter(procesada=False).count() == 0 assert Identificacion.objects.filter(invalidada=True).count() == 0 assert Carga.objects.filter(procesada=False).count() == 0 assert Carga.objects.filter(invalidada=True).count() == 0 identificar(attach_4, mesa_4, fiscal_4) # al consolidar esta identificacion, el fiscal 1 pasa a ser troll # las identificaciones del fiscal 1 se invalidan consumir_novedades_identificacion() refrescar_data() assert attach_1.status == Attachment.STATUS.identificada assert attach_2.status == Attachment.STATUS.identificada assert attach_3.status == Attachment.STATUS.sin_identificar assert attach_4.status == Attachment.STATUS.identificada assert mesa_categoria_1.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_1.carga_testigo is not None assert mesa_categoria_1.coeficiente_para_orden_de_carga is not None assert mesa_categoria_2.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_2.carga_testigo is not None assert mesa_categoria_2.coeficiente_para_orden_de_carga is not None assert fiscal_1.troll assert Identificacion.objects.filter(procesada=False).count() == 3 assert Identificacion.objects.filter(invalidada=True).count() == 3 for ident in Identificacion.objects.filter(fiscal=fiscal_1): assert ident.invalidada assert Carga.objects.filter(procesada=False).count() == 0 assert Carga.objects.filter(invalidada=True).count() == 0 # se corre otra consolidacion de identificaciones # a1 pasa a sin_identificar, se invalidan las cargas de m1 y se le borra el orden de carga consumir_novedades_identificacion() refrescar_data() assert attach_1.status == Attachment.STATUS.sin_identificar assert attach_2.status == Attachment.STATUS.identificada assert attach_3.status == Attachment.STATUS.sin_identificar assert attach_4.status == Attachment.STATUS.identificada assert mesa_categoria_1.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_1.carga_testigo is not None assert mesa_categoria_1.coeficiente_para_orden_de_carga is None assert mesa_categoria_2.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_2.carga_testigo is not None assert mesa_categoria_2.coeficiente_para_orden_de_carga is not None assert fiscal_1.troll assert Identificacion.objects.filter(procesada=False).count() == 0 assert Identificacion.objects.filter(invalidada=True).count() == 3 assert Carga.objects.filter(procesada=False).count() == 2 assert Carga.objects.filter(invalidada=True).count() == 2 for carga in Carga.objects.filter(mesa_categoria=mesa_categoria_1): assert carga.invalidada # finalmente, se ejecuta una consolidacion de cargas # la MesaCategoria de m1 pasa a sin_cargas, y se le borra la carga testigo consumir_novedades_carga() refrescar_data() assert mesa_categoria_1.status == MesaCategoria.STATUS.sin_cargar assert mesa_categoria_1.carga_testigo is None assert mesa_categoria_1.coeficiente_para_orden_de_carga is None assert mesa_categoria_2.status == MesaCategoria.STATUS.total_consolidada_dc assert mesa_categoria_2.carga_testigo is not None assert mesa_categoria_2.coeficiente_para_orden_de_carga is not None assert fiscal_1.troll assert Identificacion.objects.filter(procesada=False).count() == 0 assert Identificacion.objects.filter(invalidada=True).count() == 3 assert Carga.objects.filter(procesada=False).count() == 0 assert Carga.objects.filter(invalidada=True).count() == 2 for carga in Carga.objects.filter(mesa_categoria=mesa_categoria_1): assert carga.invalidada
def test_carga_con_problemas(db): # Identifico una mesa. mesa = MesaFactory() a = AttachmentFactory() IdentificacionFactory(attachment=a, status='identificada', mesa=mesa) IdentificacionFactory(attachment=a, status='identificada', mesa=mesa) consumir_novedades_identificacion() mc = MesaCategoriaFactory(mesa=mesa, categoria=mesa.categorias.first()) assert mc.status == MesaCategoria.STATUS.sin_cargar c1 = CargaFactory(mesa_categoria=mc, tipo='total', firma='1-10') consumir_novedades_y_actualizar_objetos([mc]) assert mc.status == MesaCategoria.STATUS.total_sin_consolidar assert mc.carga_testigo == c1 c2 = CargaFactory(mesa_categoria=mc, tipo='problema') Problema.reportar_problema(FiscalFactory(), 'reporte 1', ReporteDeProblema.TIPOS_DE_PROBLEMA.spam, carga=c2) consumir_novedades_y_actualizar_objetos([mc]) # Sigue sin ser un problema. assert mc.status == MesaCategoria.STATUS.total_sin_consolidar assert mc.carga_testigo == c1 assert c2.problemas.first().problema.estado == Problema.ESTADOS.potencial # Está entre las pendientes. assert mc in MesaCategoria.objects.con_carga_pendiente() c3 = CargaFactory(mesa_categoria=mc, tipo='problema') Problema.reportar_problema(FiscalFactory(), 'reporte 2', ReporteDeProblema.TIPOS_DE_PROBLEMA.ilegible, carga=c3) consumir_novedades_y_actualizar_objetos([mc]) c2.refresh_from_db() c3.refresh_from_db() assert c2.invalidada == False assert c3.invalidada == False # Ahora sí hay un problema. assert mc.status == MesaCategoria.STATUS.con_problemas assert mc.carga_testigo is None problema = c2.problemas.first().problema assert problema.estado == Problema.ESTADOS.pendiente # No está entre las pendientes. assert mc not in MesaCategoria.objects.con_carga_pendiente() # Lo resolvemos. problema.resolver(FiscalFactory().user) assert problema.estado == Problema.ESTADOS.resuelto c1.refresh_from_db() c2.refresh_from_db() c3.refresh_from_db() assert c1.invalidada == False assert c2.invalidada == True assert c3.invalidada == True consumir_novedades_y_actualizar_objetos([mc]) # El problema se solucionó también en la MesaCategoria. assert mc.status == MesaCategoria.STATUS.total_sin_consolidar assert mc.carga_testigo == c1 # Está entre las pendientes. assert mc in MesaCategoria.objects.con_carga_pendiente() # Se mete otra carga y se consolida. c4 = CargaFactory(mesa_categoria=mc, tipo='total', firma='1-10') consumir_novedades_y_actualizar_objetos([mc]) assert mc.status == MesaCategoria.STATUS.total_consolidada_dc assert mc.carga_testigo == c4 or mc.carga_testigo == c1
def test_avance_de_carga_dos_categorias(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # dos categoríasas con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) gv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # 10 mesas de 100, 110, ..., 190 votantes. Total 1450 seccion, circuito, lugar_votacion = crear_seccion("Luján oeste") [mesas] = crear_mesas([lugar_votacion], [pv, gv], 10) for ix in range(len(mesas)): mesas[ix].electores = 100 + ix * 10 mesas[ix].save(update_fields=['electores']) fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # identifico 9 mesas attachs = AttachmentFactory.create_batch(10) for ix in range(9): identificar(attachs[ix], mesas[ix], fiscal_1) identificar(attachs[ix], mesas[ix], fiscal_2) consumir_novedades_identificacion() # doble carga parcial coincidente de 6 mesas pv y 2 mesas gv for ix in range(6): nueva_carga(mesacat(mesas[ix], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas[ix], pv), fiscal_2, [50, 30], Carga.TIPOS.parcial) for ix in range(2): nueva_carga(mesacat(mesas[ix], gv), fiscal_1, [55, 25], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas[ix], gv), fiscal_2, [55, 25], Carga.TIPOS.parcial) # una carga parcial de una mesa pv y tres gv nueva_carga(mesacat(mesas[6], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) for ix in range(3): nueva_carga(mesacat(mesas[ix + 2], gv), fiscal_1, [55, 25], Carga.TIPOS.parcial) consumir_novedades_carga() # resultados vorwaerts = AvanceDeCarga() # categoría pv resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 1, 190, 10, 13.1) verificar_resultado(resultados.en_identificacion_sin_cargas(), 0, 0, 0, 0) verificar_resultado(resultados.sin_cargar(), 2, 350, 20, 24.14) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 1, 160, 10, 11.03) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 6, 750, 60, 51.72) # categoría gv resultados = vorwaerts.get_resultados(gv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 1, 190, 10, 13.1) verificar_resultado(resultados.en_identificacion_sin_cargas(), 0, 0, 0, 0) verificar_resultado(resultados.sin_cargar(), 4, 660, 40, 45.52) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 3, 390, 30, 26.9) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 2, 210, 20, 14.48)
def test_avance_de_carga_mesas_con_carga_csv_sin_fotos(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # una categoria con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # un circuito con 10 mesas de 100, 110, ..., 290 votantes. Total 1450 seccion_1, circuito_1, lugar_votacion_1 = crear_seccion("Luján oeste") [mesas_1] = crear_mesas([lugar_votacion_1], [pv], 10) for ix in range(len(mesas_1)): mesas_1[ix].electores = 100 + ix * 10 mesas_1[ix].save(update_fields=['electores']) # dos fiscales fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # identifico totalmente 6 mesas, parcialmente dos mesas attachs = AttachmentFactory.create_batch(30) for ix in range(6): identificar(attachs[ix], mesas_1[ix], fiscal_1) identificar(attachs[ix], mesas_1[ix], fiscal_2) identificar(attachs[6], mesas_1[6], fiscal_1) identificar(attachs[7], mesas_1[7], fiscal_1) consumir_novedades_identificacion() # dos cargas parciales nueva_carga(mesacat(mesas_1[0], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_1[1], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) # tres cargas totales desde CSV de una mesa sin identificar (la última), una parcialmente identificada, una identificada nueva_carga(mesacat(mesas_1[9], pv), fiscal_1, [50, 30, 20, 10], Carga.TIPOS.total, Carga.SOURCES.csv) nueva_carga(mesacat(mesas_1[6], pv), fiscal_1, [50, 30, 20, 10], Carga.TIPOS.total, Carga.SOURCES.csv) nueva_carga(mesacat(mesas_1[2], pv), fiscal_1, [50, 30, 20, 10], Carga.TIPOS.total, Carga.SOURCES.csv) consumir_novedades_carga() # podemos mirar vorwaerts = AvanceDeCarga(NIVELES_DE_AGREGACION.circuito, [circuito_1.id]) resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 1, 180, 10, 12.41) verificar_resultado(resultados.sin_identificar_con_cargas(), 1, 190, 10, 13.1) verificar_resultado(resultados.en_identificacion_sin_cargas(), 1, 170, 10, 11.72) verificar_resultado(resultados.en_identificacion_con_cargas(), 1, 160, 10, 11.03) verificar_resultado(resultados.sin_cargar(), 3, 420, 30, 28.97) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 2, 210, 20, 14.48) verificar_resultado(resultados.carga_parcial_consolidada_csv(), 0, 0, 0, 0) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_sin_consolidar(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_consolidada_csv(), 3, 470, 30, 32.41) verificar_resultado(resultados.carga_total_consolidada_dc(), 0, 0, 0, 0)
def test_avance_de_carga_dos_circuitos(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # dos categorías con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) gv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # un circuito con 10 mesas de 100, 110, ..., 190 votantes. Total 1450 seccion_1, circuito_1, lugar_votacion_1 = crear_seccion("Luján oeste") [mesas_1] = crear_mesas([lugar_votacion_1], [pv, gv], 10) for ix in range(len(mesas_1)): mesas_1[ix].electores = 100 + ix * 10 mesas_1[ix].save(update_fields=['electores']) # otro circuito con 20 mesas de 200 votantes. Total 4000 seccion_2, circuito_2, lugar_votacion_2 = crear_seccion("Mercedes") [mesas_2] = crear_mesas([lugar_votacion_2], [pv, gv], 20) for ix in range(len(mesas_2)): mesas_2[ix].electores = 200 mesas_2[ix].save(update_fields=['electores']) fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # identifico todas las mesas salvo dos de la sección 2 attachs = AttachmentFactory.create_batch(30) for ix in range(10): identificar(attachs[ix], mesas_1[ix], fiscal_1) identificar(attachs[ix], mesas_1[ix], fiscal_2) for ix in range(18): identificar(attachs[ix + 10], mesas_2[ix], fiscal_1) identificar(attachs[ix + 10], mesas_2[ix], fiscal_2) consumir_novedades_identificacion() # sección 1 # doble carga parcial coincidente de 6 mesas pv y 2 mesas gv for ix in range(6): nueva_carga(mesacat(mesas_1[ix], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_1[ix], pv), fiscal_2, [50, 30], Carga.TIPOS.parcial) for ix in range(2): nueva_carga(mesacat(mesas_1[ix], gv), fiscal_1, [55, 25], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_1[ix], gv), fiscal_2, [55, 25], Carga.TIPOS.parcial) # una carga parcial de una mesa pv y tres gv nueva_carga(mesacat(mesas_1[6], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) for ix in range(3): nueva_carga(mesacat(mesas_1[ix + 2], gv), fiscal_1, [55, 25], Carga.TIPOS.parcial) consumir_novedades_carga() # sección 2 # doble carga parcial coincidente de 15 mesas pv y 12 gv for ix in range(15): nueva_carga(mesacat(mesas_2[ix], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_2[ix], pv), fiscal_2, [50, 30], Carga.TIPOS.parcial) for ix in range(12): nueva_carga(mesacat(mesas_2[ix], gv), fiscal_1, [55, 25], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_2[ix], gv), fiscal_2, [55, 25], Carga.TIPOS.parcial) # una carga parcial 6 mesas gv for ix in range(6): nueva_carga(mesacat(mesas_2[ix + 12], gv), fiscal_1, [55, 25], Carga.TIPOS.parcial) consumir_novedades_carga() # resultados circuito 1 vorwaerts = AvanceDeCarga(NIVELES_DE_AGREGACION.circuito, [circuito_1.id]) # categoría pv resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 0, 0, 0, 0) verificar_resultado(resultados.sin_cargar(), 3, 540, 30, 37.24) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 1, 160, 10, 11.03) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 6, 750, 60, 51.72) # categoría gv resultados = vorwaerts.get_resultados(gv) verificar_resultado(resultados.total(), 10, 1450, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 0, 0, 0, 0) verificar_resultado(resultados.sin_cargar(), 5, 850, 50, 58.62) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 3, 390, 30, 26.9) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 2, 210, 20, 14.48) # resultados circuito 2 vorwaerts = AvanceDeCarga(NIVELES_DE_AGREGACION.circuito, [circuito_2.id]) # categoría pv resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 20, 4000, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 2, 400, 10, 10) verificar_resultado(resultados.sin_cargar(), 3, 600, 15, 15) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 0, 0, 0, 0) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 15, 3000, 75, 75) # categoría gv resultados = vorwaerts.get_resultados(gv) verificar_resultado(resultados.total(), 20, 4000, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 2, 400, 10, 10) verificar_resultado(resultados.sin_cargar(), 0, 0, 0, 0) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 6, 1200, 30, 30) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 12, 2400, 60, 60)
def test_avance_de_carga_combinando_dc_y_csv(db, settings): # settings settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 settings.MIN_COINCIDENCIAS_CARGA = 2 # una categoria con cuatro opciones, dos prioritarias, dos no prioritarias pv = nueva_categoria(["a1", "a2"], ["b1", "b2"]) # un circuito con 20 mesas de 100, 110, ..., 290 votantes. Total 3900 seccion_1, circuito_1, lugar_votacion_1 = crear_seccion("Luján oeste") [mesas_1] = crear_mesas([lugar_votacion_1], [pv], 20) for ix in range(len(mesas_1)): mesas_1[ix].electores = 100 + ix * 10 mesas_1[ix].save(update_fields=['electores']) # dos fiscales fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() # identifico 18 mesas attachs = AttachmentFactory.create_batch(30) for ix in range(18): identificar(attachs[ix], mesas_1[ix], fiscal_1) identificar(attachs[ix], mesas_1[ix], fiscal_2) consumir_novedades_identificacion() # doble carga total coincidente de 4 mesas for ix in range(4): nueva_carga(mesacat(mesas_1[ix], pv), fiscal_1, [50, 30, 20, 10], Carga.TIPOS.total) nueva_carga(mesacat(mesas_1[ix], pv), fiscal_2, [50, 30, 20, 10], Carga.TIPOS.total) # cinco cargas totales desde CSV for ix in range(5): nueva_carga(mesacat(mesas_1[4 + ix], pv), fiscal_1, [50, 30, 20, 10], Carga.TIPOS.total, Carga.SOURCES.csv) # doble carga parcial coincidente de 3 mesas for ix in range(3): nueva_carga(mesacat(mesas_1[9 + ix], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) nueva_carga(mesacat(mesas_1[9 + ix], pv), fiscal_2, [50, 30], Carga.TIPOS.parcial) # dos cargas parciales desde CSV nueva_carga(mesacat(mesas_1[12], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial, Carga.SOURCES.csv) nueva_carga(mesacat(mesas_1[13], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial, Carga.SOURCES.csv) # una carga parcial nueva_carga(mesacat(mesas_1[14], pv), fiscal_1, [50, 30], Carga.TIPOS.parcial) consumir_novedades_carga() # podemos mirar vorwaerts = AvanceDeCarga(NIVELES_DE_AGREGACION.circuito, [circuito_1.id]) resultados = vorwaerts.get_resultados(pv) verificar_resultado(resultados.total(), 20, 3900, 100, 100) verificar_resultado(resultados.sin_identificar_sin_cargas(), 2, 570, 10, 14.62) verificar_resultado(resultados.sin_cargar(), 3, 780, 15, 20) verificar_resultado(resultados.carga_parcial_sin_consolidar(), 1, 240, 5, 6.15) verificar_resultado(resultados.carga_parcial_consolidada_csv(), 2, 450, 10, 11.54) verificar_resultado(resultados.carga_parcial_consolidada_dc(), 3, 600, 15, 15.38) verificar_resultado(resultados.carga_total_sin_consolidar(), 0, 0, 0, 0) verificar_resultado(resultados.carga_total_consolidada_csv(), 5, 800, 25, 20.51) verificar_resultado(resultados.carga_total_consolidada_dc(), 4, 460, 20, 11.79)