def test_detalle_mesa_categoria(db, fiscal_client): opcs = OpcionFactory.create_batch(3) e1 = CategoriaFactory(opciones=opcs) e2 = CategoriaFactory(opciones=opcs) mesa = MesaFactory(categorias=[e1, e2]) c1 = CargaFactory(mesa_categoria__mesa=mesa, mesa_categoria__categoria=e1, tipo=Carga.TIPOS.parcial, origen=Carga.SOURCES.csv) mc = c1.mesa_categoria votos1 = VotoMesaReportadoFactory( opcion=opcs[0], votos=1, carga=c1, ) votos2 = VotoMesaReportadoFactory( opcion=opcs[1], votos=2, carga=c1, ) votos3 = VotoMesaReportadoFactory( opcion=opcs[2], votos=1, carga=c1, ) # a otra carga VotoMesaReportadoFactory(opcion=opcs[2], votos=1) c1.actualizar_firma() consumir_novedades_y_actualizar_objetos([mc]) assert mc.carga_testigo == c1 url = reverse('detalle-mesa-categoria', args=[e1.id, mesa.numero]) response = fiscal_client.get(url) assert list(response.context['reportados']) == [votos1, votos2, votos3]
def test_siguiente_happy_path_parcial_y_total_con_scheduler( db, fiscal_client, settings): settings.MIN_COINCIDENCIAS_CARGAS = 1 mesa = MesaFactory() a = AttachmentFactory(mesa=mesa, status='identificada') mc1 = MesaCategoriaFactory(categoria__requiere_cargas_parciales=True, coeficiente_para_orden_de_carga=1, mesa=mesa) scheduler() response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-parcial', args=[mc1.id]) carga = CargaFactory(mesa_categoria=mc1, tipo='parcial') consumir_novedades_carga() scheduler() mc1.refresh_from_db() assert mc1.status == MesaCategoria.STATUS.parcial_consolidada_dc assert mc1.carga_testigo == carga mc1.desasignar_a_fiscal() response = fiscal_client.get(reverse('siguiente-accion')) assert response.url == reverse('carga-total', args=[mc1.id]) carga = CargaFactory(mesa_categoria=mc1, tipo='total') consumir_novedades_carga() scheduler() mc1.refresh_from_db() assert mc1.status == MesaCategoria.STATUS.total_consolidada_dc assert mc1.carga_testigo == carga response = fiscal_client.get(reverse('siguiente-accion')) # No hay actas para cargar, vuelta a empezar. assert response.status_code == HTTPStatus.OK assert 'No hay actas para cargar' in str(response.content)
def test_mesa_de_circuito__url_mesa_con_resultados(carta_marina, fiscal_client): # resultados para mesa 1 mesa1, *otras_mesas = carta_marina categoria = mesa1.categorias.get() # sólo default # Esto no debería ser necesario si configuramos correctamente las opciones prioritarias en carta_marina CategoriaOpcion.objects.filter(categoria=categoria).update(prioritaria=True) # opciones a partido o1, o2, o3, o4 = categoria.opciones.filter(partido__isnull=False) # la opción 4 pasa a ser del mismo partido que la 1 o4.partido = o1.partido o4.save() blanco = Opcion.blancos() total = Opcion.total_votos() mc1 = MesaCategoria.objects.get(mesa=mesa1, categoria=categoria) carga = CargaFactory(mesa_categoria=mc1, tipo=Carga.TIPOS.parcial) consumir_novedades_y_actualizar_objetos([mesa1]) VotoMesaReportadoFactory(carga=carga, opcion=o1, votos=20) VotoMesaReportadoFactory(carga=carga, opcion=o2, votos=30) VotoMesaReportadoFactory(carga=carga, opcion=o3, votos=40) VotoMesaReportadoFactory(carga=carga, opcion=o4, votos=5) # votaron 95/100 personas VotoMesaReportadoFactory(carga=carga, opcion=blanco, votos=5) VotoMesaReportadoFactory(carga=carga, opcion=total, votos=100) carga.actualizar_firma() assert carga.es_testigo.exists() query_string_mesa_1 = ( f'?mesa={mesa1.id}&circuito={mesa1.circuito.id}' '&tipoDeAgregacion=todas_las_cargas' f'&opcionaConsiderar={OPCIONES_A_CONSIDERAR.prioritarias}' ) 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 content = response.content.decode('utf8') assert response.context['mensaje_no_hay_info'] not in content resultados = response.context['resultados'] assert len(resultados) == 6 # 4 opciones + blanco + total for voto_mesa_reportado in resultados: assert f'<th>{voto_mesa_reportado.opcion}</th>' in content assert f'<td>{voto_mesa_reportado.votos}</td>' in content
def test_formset_en_carga_total_reusa_parcial_confirmada( db, fiscal_client, admin_user, settings): # Solo una carga, para simplificar el setup settings.MIN_COINCIDENCIAS_CARGAS = 1 c = CategoriaFactory(id=25000, opciones=[]) # Notar que el orden no coincide con el id o1 = CategoriaOpcionFactory(categoria=c, orden=3, prioritaria=True).opcion o2 = CategoriaOpcionFactory(categoria=c, orden=1, prioritaria=False).opcion o3 = CategoriaOpcionFactory(categoria=c, orden=2, prioritaria=False).opcion o4 = CategoriaOpcionFactory(categoria=c, orden=4, prioritaria=True).opcion mc = MesaCategoriaFactory(categoria=c) mc.asignar_a_fiscal() admin_user.fiscal.asignar_mesa_categoria(mc) # Se carga parcialente, la opcion prioritaira "o" carga = CargaFactory(mesa_categoria=mc, tipo='parcial') VotoMesaReportadoFactory(carga=carga, opcion=o1, votos=10) VotoMesaReportadoFactory(carga=carga, opcion=o4, votos=3) # Consolidamos. consumir_novedades_carga() mc.refresh_from_db() assert mc.status == MesaCategoria.STATUS.parcial_consolidada_dc assert mc.carga_testigo == carga assert set(carga.opcion_votos()) == {(o1.id, 10), (o4.id, 3)} # Ahora pedimos la carga total totales = reverse('carga-total', args=[mc.id]) response = fiscal_client.get(totales) # Tenemos las tres opciones en orden assert len(response.context['formset']) == 4 + len( Opcion.opciones_no_partidarias_obligatorias()) assert response.context['formset'][0].initial['opcion'] == o2 assert response.context['formset'][1].initial['opcion'] == o3 assert response.context['formset'][2].initial['opcion'] == o1 assert response.context['formset'][3].initial['opcion'] == o4 # y los valores de los votos assert response.context['formset'][0].initial['votos'] is None assert response.context['formset'][1].initial['votos'] is None assert response.context['formset'][2].initial['votos'] == 10 assert response.context['formset'][3].initial['votos'] == 3 # el valor previo es readonly assert response.context['formset'][2].fields['votos'].widget.attrs[ 'readonly'] is True assert response.context['formset'][3].fields['votos'].widget.attrs[ 'readonly'] is True
def test_excluir_fiscal_que_ya_cargo(db, settings): """ Se verifica que no se propone una MesaCategoria para cargar, a un fiscal que ya hizo una carga sobre esa MesaCategoria. """ settings.MIN_COINCIDENCIAS_IDENTIFICACION = 1 settings.MIN_COINCIDENCIAS_CARGAS = 2 fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() fiscal_3 = nuevo_fiscal() pv = CategoriaFactory(nombre="PV") gv = CategoriaFactory(nombre="GV") # hago que la categoria pv sea prioritaria PrioridadSchedulingFactory(categoria=pv, desde_proporcion=0, hasta_proporcion=100, prioridad=30) mesa = MesaFactory(numero="51", categorias=[gv, pv]) identificar_mesa(mesa, fiscal_3) mesacat_pv = MesaCategoria.objects.filter(mesa=mesa, categoria=pv).first() mesacat_gv = MesaCategoria.objects.filter(mesa=mesa, categoria=gv).first() # antes de cargar, la siguiente mesacat para ambos fiscales es pv, que es más prioritaria mesacat_fiscal_2 = MesaCategoria.objects.con_carga_pendiente().sin_cargas_del_fiscal(fiscal_2).mas_prioritaria() mesacat_fiscal_3 = MesaCategoria.objects.con_carga_pendiente().sin_cargas_del_fiscal(fiscal_3).mas_prioritaria() assert mesacat_fiscal_2 == mesacat_pv assert mesacat_fiscal_3 == mesacat_pv # agrego una carga carga = CargaFactory(mesa_categoria=mesacat_pv, fiscal=fiscal_2, tipo=Carga.TIPOS.parcial) # la siguiente mesacat para el fiscal_2 es gv, porque de pv ya hizo una carga # la del fiscal 3 es pv, que es más prioritaria mesacat_fiscal_2 = MesaCategoria.objects.con_carga_pendiente().sin_cargas_del_fiscal(fiscal_2).mas_prioritaria() mesacat_fiscal_3 = MesaCategoria.objects.con_carga_pendiente().sin_cargas_del_fiscal(fiscal_3).mas_prioritaria() assert mesacat_fiscal_2 == mesacat_gv assert mesacat_fiscal_3 == mesacat_pv # el fiscal 2 carga la mesacat que le queda carga = CargaFactory(mesa_categoria=mesacat_gv, fiscal=fiscal_2, tipo=Carga.TIPOS.parcial) # ahora el fiscal 2 no tiene mesacat para cargar, el fiscal 3 sigue con pv como prioritaria mesacat_fiscal_2 = MesaCategoria.objects.con_carga_pendiente().sin_cargas_del_fiscal(fiscal_2).mas_prioritaria() mesacat_fiscal_3 = MesaCategoria.objects.con_carga_pendiente().sin_cargas_del_fiscal(fiscal_3).mas_prioritaria() assert mesacat_fiscal_2 == None assert mesacat_fiscal_3 == mesacat_pv
def test_chequear_resultado_categoria_desactivada(db, fiscal_client): opcs = OpcionFactory.create_batch(3, es_contable=True) e1 = CategoriaFactory(opciones=opcs) assert e1.activa is True mesa = MesaFactory(categoria=[e1]) # existe una carga para esa categoria / mesa CargaFactory(mesa=mesa, categoria=e1) url = reverse('chequear-resultado-mesa', args=[e1.id, mesa.numero]) response = fiscal_client.get(url) assert response.status_code == 200 e1.activa = False e1.save() response = fiscal_client.get(url) assert response.status_code == 404
def nueva_carga(mesa_categoria, fiscal, votos_opciones, tipo_carga=Carga.TIPOS.total): carga = CargaFactory(mesa_categoria=mesa_categoria, fiscal=fiscal, tipo=tipo_carga) for opcionVoto, cantidadVotos in zip( mesa_categoria.categoria.opciones.order_by('nombre'), votos_opciones): VotoMesaReportadoFactory(carga=carga, opcion=opcionVoto, votos=cantidadVotos) return carga
def test_datos_previos_parcial(db): o1 = OpcionFactory(tipo=Opcion.TIPOS.metadata) o2 = OpcionFactory() cat1 = CategoriaFactory(opciones=[o1, o2]) cat1o1 = CategoriaOpcionFactory(categoria=cat1, opcion=o1, orden=1) cat1o2 = CategoriaOpcionFactory(categoria=cat1, opcion=o2, orden=2) # tengo una consolidación parcial mc = MesaCategoriaFactory( categoria=cat1, status=MesaCategoria.STATUS.parcial_consolidada_dc) carga = CargaFactory(mesa_categoria=mc, tipo='total') VotoMesaReportadoFactory(carga=carga, opcion=o1, votos=10) VotoMesaReportadoFactory(carga=carga, opcion=o2, votos=12) mc.carga_testigo = carga mc.save() # si pedimos datos previos para realizar una carga total, los de consolidados parciales vienen assert mc.datos_previos('total') == {o1.id: 10, o2.id: 12}
def test_consumir_novedades_carga_tres_ok_tres_error(db, settings): # En esta variable se almacena el comportamiento que tendrá cada llamado a # la función consolidar_cargas para cada mesa_categoria a procesar. # Las mc1, mc3 y mc5 se procesarán con normalidad y sus cargas c1, c3 y c6 # quedarán marcadas como procesadas=True. # Para las mc2 y mc4 se lanzará una Exception y sus cargas c2, c4 y c5 # quedarán como procesada=False. side_effects = [ mock.DEFAULT, #comportamiento para mc1 Exception('error'), #comportamiento para mc2 mock.DEFAULT, #comportamiento para mc3 Exception('error'), #comportamiento para mc4 mock.DEFAULT #comportamiento para mc5 ] with mock.patch('adjuntos.consolidacion.consolidar_cargas', side_effect=side_effects): m1 = MesaFactory() m2 = MesaFactory() mc1 = MesaCategoriaFactory(mesa=m1) mc2 = MesaCategoriaFactory(mesa=m1) mc3 = MesaCategoriaFactory(mesa=m2) mc4 = MesaCategoriaFactory(mesa=m2) mc5 = MesaCategoriaFactory(mesa=m2) c1 = CargaFactory(mesa_categoria=mc1, tipo='parcial') c2 = CargaFactory(mesa_categoria=mc2, tipo='total') c3 = CargaFactory(mesa_categoria=mc3, tipo='total') c4 = CargaFactory(mesa_categoria=mc4, tipo='total') c5 = CargaFactory(mesa_categoria=mc4, tipo='parcial') c6 = CargaFactory(mesa_categoria=mc5, tipo='total') consumir_novedades_carga() # Chequeamos que las no procesadas son 3 no_procesadas = Carga.objects.filter(procesada=False) assert no_procesadas.count() == 3 # Chequeamos que las no procesadas son c2, c4 y c5 no_procesadas_ids = map(lambda x: x.id, no_procesadas) assert set([c2.id, c4.id, c5.id]) == set(no_procesadas_ids) # Chequeamos que las procesadas son 3 procesadas = Carga.objects.filter(procesada=True) assert procesadas.count() == 3 # # Chequeamos que las procesadas son c1, c3 y c6 procesadas_ids = map(lambda x: x.id, procesadas) assert set([c1.id, c3.id, c6.id]) == set(procesadas_ids)
def test_datos_previos_desde_metadata(db): o1 = OpcionFactory(tipo=Opcion.TIPOS.metadata) o2 = OpcionFactory() cat1 = CategoriaFactory(opciones=[o1, o2]) cat1o1 = CategoriaOpcionFactory(categoria=cat1, opcion=o1, orden=1) cat1o2 = CategoriaOpcionFactory(categoria=cat1, opcion=o2, orden=2) mc = MesaCategoriaFactory(categoria=cat1, status=MesaCategoria.STATUS.total_consolidada_dc) carga = CargaFactory(mesa_categoria=mc, tipo='total') VotoMesaReportadoFactory(carga=carga, opcion=o1, votos=10) VotoMesaReportadoFactory(carga=carga, opcion=o2, votos=12) # otra categoria incluye la misma metadata. o2 = OpcionFactory() cat2 = CategoriaFactory(opciones=[o1, o2]) cat1o1 = CategoriaOpcionFactory(categoria=cat2, opcion=o1, orden=1) cat2o2 = CategoriaOpcionFactory(categoria=cat2, opcion=o2, orden=2) mc2 = MesaCategoriaFactory(categoria=cat2, mesa=mc.mesa) # esa mesa categoria incluye la metadata ya cargada en mc1 assert mc2.datos_previos('parcial') == {o1.id: 10} assert mc2.datos_previos('total') == {o1.id: 10}
def test_formset_reusa_metadata(db, fiscal_client, admin_user): # Hay una categoria con una opcion metadata ya consolidada. o1 = OpcionFactory(tipo=Opcion.TIPOS.metadata) cat1 = CategoriaFactory(opciones=[o1]) from elecciones.models import CategoriaOpcion # Me aseguro de que no estuviese asociada con otro orden. CategoriaOpcion.objects.filter(categoria=cat1, opcion=o1).delete() cat1op1 = CategoriaOpcionFactory(categoria=cat1, opcion=o1, orden=1) mc = MesaCategoriaFactory(categoria=cat1, status=MesaCategoria.STATUS.total_consolidada_dc) carga = CargaFactory(mesa_categoria=mc, tipo='total') VotoMesaReportadoFactory(carga=carga, opcion=o1, votos=10) # Otra categoría incluye la misma metadata. o2 = OpcionFactory() cat2 = CategoriaFactory(opciones=[o1, o2]) # Me aseguro de que no estuviesen asociadas con otro orden. CategoriaOpcion.objects.filter(categoria=cat2, opcion=o1).delete() CategoriaOpcion.objects.filter(categoria=cat2, opcion=o2).delete() cat2op1 = CategoriaOpcionFactory(categoria=cat2, opcion=o1, orden=1) cat2op1 = CategoriaOpcionFactory(categoria=cat2, opcion=o2, orden=2) mc2 = MesaCategoriaFactory(categoria=cat2, mesa=mc.mesa) mc2.asignar_a_fiscal() admin_user.fiscal.asignar_mesa_categoria(mc2) response = fiscal_client.get(reverse('carga-total', args=[mc2.id])) assert len(response.context['formset']) == 2 + len( Opcion.opciones_no_partidarias_obligatorias()) assert response.context['formset'][0].initial['opcion'] == o1 assert response.context['formset'][1].initial['opcion'] == o2 # y los valores de los votos assert response.context['formset'][0].initial['votos'] == 10 assert response.context['formset'][0].fields['votos'].widget.attrs[ 'readonly'] is True assert response.context['formset'][1].initial['votos'] is None
def test_siguiente_happy_path_parcial_y_total_con_modo_ub( db, fiscal_client, admin_user, settings): # Este test no es del todo realista porque se lo ejecuta con la cantidad de cargas/identificaciones # necesarias para consolidar en 1, pero al menos prueba que se siga el circuito con modo_ub=True. settings.MIN_COINCIDENCIAS_CARGAS = 1 settings.MIN_COINCIDENCIAS_IDENTIFICACION = 1 modo_ub_querry_string = '?modo_ub=True' mesa = MesaFactory() from adjuntos.models import PreIdentificacion from scheduling.models import ColaCargasPendientes p = PreIdentificacion(fiscal=admin_user.fiscal, distrito=mesa.circuito.seccion.distrito) p.save() a = AttachmentFactory(status='sin_identificar', pre_identificacion=p) scheduler() assert ColaCargasPendientes.largo_cola() == 1 response = fiscal_client.get( reverse('siguiente-accion') + modo_ub_querry_string) assert response.status_code == HTTPStatus.FOUND # Me manda a idenficarlas con modo_ub assert response.url == reverse('asignar-mesa', args=[a.id]) + modo_ub_querry_string assert ColaCargasPendientes.largo_cola() == 0 # La identifico. a.mesa = mesa a.status = 'identificada' a.save() mc1 = MesaCategoriaFactory(categoria__requiere_cargas_parciales=True, coeficiente_para_orden_de_carga=1, mesa=mesa) scheduler() assert ColaCargasPendientes.largo_cola() == 1 response = fiscal_client.get( reverse('siguiente-accion') + modo_ub_querry_string) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-parcial', args=[mc1.id]) + modo_ub_querry_string carga = CargaFactory(mesa_categoria=mc1, tipo='parcial', origen='csv') consumir_novedades_carga() scheduler() mc1.refresh_from_db() assert mc1.status == MesaCategoria.STATUS.parcial_consolidada_dc # Porque la cant de cargas está en 1. assert mc1.carga_testigo == carga mc1.desasignar_a_fiscal() response = fiscal_client.get( reverse('siguiente-accion') + modo_ub_querry_string) assert response.url == reverse('carga-total', args=[mc1.id]) + modo_ub_querry_string carga = CargaFactory(mesa_categoria=mc1, tipo='total', origen='csv') consumir_novedades_carga() scheduler() mc1.refresh_from_db() assert mc1.status == MesaCategoria.STATUS.total_consolidada_dc # Porque la cant de cargas está en 1. assert mc1.carga_testigo == carga response = fiscal_client.get( reverse('siguiente-accion') + modo_ub_querry_string) # No hay actas para cargar, vuelta a empezar. assert response.status_code == HTTPStatus.OK assert 'No hay actas para cargar' in str(response.content)
def reportar_problema_mesa_categoria(mesa_categoria, fiscal): return CargaFactory(mesa_categoria=mesa_categoria, fiscal=fiscal, tipo=Carga.TIPOS.problema)