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_prioriza_categoria(db, settings): f = FiscalFactory() c = CategoriaFactory(prioridad=2) c2 = CategoriaFactory(prioridad=1) m1 = MesaFactory() AttachmentFactory(mesa=m1) mc1 = MesaCategoriaFactory( status=MesaCategoria.STATUS.parcial_sin_consolidar, categoria=c, mesa=m1, ) mc1.actualizar_coeficiente_para_orden_de_carga() m2 = MesaFactory() AttachmentFactory(mesa=m2) mc2 = MesaCategoriaFactory( categoria=c2, status=MesaCategoria.STATUS.parcial_sin_consolidar, mesa=m2, ) mc2.actualizar_coeficiente_para_orden_de_carga() # Se recibe la mc con categoria más prioritaria. assert MesaCategoria.objects.siguiente() == mc2 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): mc2.asignar_a_fiscal() # Luego la de la categoría menos prioritaria. assert MesaCategoria.objects.siguiente() == mc1
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 definir_prioridades_seccion_categoria(settings): asignar_prioridades_standard(settings) seccion_cuatro_prioridades = SeccionFactory(nombre="Cuatro prioridades") seccion_dos_cantidades = SeccionFactory(nombre="Dos cantidades") seccion_prioritaria = SeccionFactory(nombre="Prioritaria") seccion_standard = SeccionFactory(nombre="Standard") PrioridadSchedulingFactory(seccion=seccion_cuatro_prioridades, desde_proporcion=50, hasta_proporcion=100, prioridad=250) PrioridadSchedulingFactory(seccion=seccion_cuatro_prioridades, desde_proporcion=30, hasta_proporcion=50, prioridad=120) PrioridadSchedulingFactory(seccion=seccion_cuatro_prioridades, desde_proporcion=10, hasta_proporcion=30, prioridad=80) PrioridadSchedulingFactory(seccion=seccion_cuatro_prioridades, desde_proporcion=0, hasta_proporcion=10, hasta_cantidad=12, prioridad=20) PrioridadSchedulingFactory(seccion=seccion_dos_cantidades, desde_proporcion=0, hasta_proporcion=2, hasta_cantidad=7, prioridad=5) PrioridadSchedulingFactory(seccion=seccion_dos_cantidades, desde_proporcion=2, hasta_proporcion=10, hasta_cantidad=20, prioridad=25) PrioridadSchedulingFactory(seccion=seccion_dos_cantidades, desde_proporcion=10, hasta_proporcion=100, prioridad=110) PrioridadSchedulingFactory(seccion=seccion_prioritaria, desde_proporcion=0, hasta_proporcion=2, hasta_cantidad=7, prioridad=10) PrioridadSchedulingFactory(seccion=seccion_prioritaria, desde_proporcion=2, hasta_proporcion=10, prioridad=50) PrioridadSchedulingFactory(seccion=seccion_prioritaria, desde_proporcion=10, hasta_proporcion=100, prioridad=80) pv = CategoriaFactory(nombre="PV") gv = CategoriaFactory(nombre="GV") categoria_standard = CategoriaFactory(nombre="Standard") PrioridadSchedulingFactory(categoria=pv, desde_proporcion=0, hasta_proporcion=100, prioridad=5) PrioridadSchedulingFactory(categoria=gv, desde_proporcion=0, hasta_proporcion=100, prioridad=30) # tambien hay que definir una mesa en cada seccion, para lo cual tengo que definir # circuitos y lugares de votacion crear_mesa(seccion_cuatro_prioridades) crear_mesa(seccion_dos_cantidades) crear_mesa(seccion_prioritaria) crear_mesa(seccion_standard)
def test_secuencia_carga_escenario_complejo_2(db, settings): """ Se verifica la secuencia con la que se asignan mesas considerando - dos secciones, una standard y una muy prioritaria, de 50 mesas cada una - dos categorias, una standard y una moderadamente prioritaria """ asignar_prioridades_standard(settings) settings.MIN_COINCIDENCIAS_IDENTIFICACION = 1 fiscal = nuevo_fiscal() seccion_prioritaria, circuito_prioritario, lugar_votacion_prioritario = crear_seccion("Barrio marítimo") seccion_standard, circuito_standard, lugar_votacion_standard = crear_seccion("Bera centro") pv = CategoriaFactory(nombre="PV") dip = CategoriaFactory(nombre="Diputados") categorias = [pv, dip] PrioridadSchedulingFactory(seccion=seccion_prioritaria, desde_proporcion=0, hasta_proporcion=2, prioridad=2) PrioridadSchedulingFactory(seccion=seccion_prioritaria, desde_proporcion=2, hasta_proporcion=10, prioridad=5) PrioridadSchedulingFactory(seccion=seccion_prioritaria, desde_proporcion=10, hasta_proporcion=100, prioridad=25) PrioridadSchedulingFactory(categoria=pv, desde_proporcion=0, hasta_proporcion=100, prioridad=30) mesas_seccion_standard, mesas_seccion_prioritaria = \ crear_mesas([lugar_votacion_standard, lugar_votacion_prioritario], categorias, 50) # se identifican las mesas en orden for nro in range(50): identificar_mesa(mesas_seccion_standard[nro], fiscal) identificar_mesa(mesas_seccion_prioritaria[nro], fiscal) verificar_siguiente_mesacat(mesas_seccion_standard[0], pv) # mesacat 1 - orden de carga 60 verificar_siguiente_mesacat(mesas_seccion_prioritaria[0], pv) # mesacat 2 - orden de carga 24 verificar_siguiente_mesacat(mesas_seccion_standard[0], dip) # mesacat 3 - orden de carga 200 verificar_siguiente_mesacat(mesas_seccion_prioritaria[0], dip) # mesacat 4 - orden de carga 200 verificar_siguiente_mesacat(mesas_seccion_prioritaria[1], pv) # mesacat 5 - orden de carga 450 verificar_siguiente_mesacat(mesas_seccion_prioritaria[2], pv) # mesacat 6 - orden de carga 750 verificar_siguiente_mesacat(mesas_seccion_prioritaria[3], pv) # mesacat 7 - orden de carga 1050 verificar_siguiente_mesacat(mesas_seccion_prioritaria[4], pv) # mesacat 8 - orden de carga 1350 verificar_siguiente_mesacat(mesas_seccion_prioritaria[1], dip) # mesacat 9 - orden de carga 1500 verificar_siguiente_mesacat(mesas_seccion_standard[1], pv) # mesacat 10 - orden de carga 1800 verificar_siguiente_mesacat(mesas_seccion_prioritaria[2], dip) # mesacat 11 - orden de carga 2500 verificar_siguiente_mesacat(mesas_seccion_standard[2], pv) # mesacat 12 - orden de carga 3000 verificar_siguiente_mesacat(mesas_seccion_prioritaria[3], dip) # mesacat 13 - orden de carga 3500 verificar_siguiente_mesacat(mesas_seccion_standard[3], pv) # mesacat 14 - orden de carga 4200 verificar_siguiente_mesacat(mesas_seccion_prioritaria[4], dip) # mesacat 15 - orden de carga 4500 verificar_siguiente_mesacat(mesas_seccion_standard[4], pv) # mesacat 16 - orden de carga 5400 verificar_siguiente_mesacat(mesas_seccion_standard[1], dip) # mesacat 17 - orden de carga 6000 verificar_siguiente_mesacat(mesas_seccion_prioritaria[11], pv, 8) # mesacat 26 - orden de carga 17250 verificar_siguiente_mesacat(mesas_seccion_standard[4], dip) # mesacat 27 - orden de carga 18000 verificar_siguiente_mesacat(mesas_seccion_prioritaria[5], dip, 6) # mesacat 34 - orden de carga 27500 verificar_siguiente_mesacat(mesas_seccion_prioritaria[6], dip, 4) # mesacat 39 - orden de carga 32500 verificar_siguiente_mesacat(mesas_seccion_standard[5], pv) # mesacat 40 - orden de carga 33000 verificar_siguiente_mesacat(mesas_seccion_prioritaria[22], pv) # mesacat 41 - orden de carga 33750 verificar_siguiente_mesacat(mesas_seccion_prioritaria[14], dip, 38) # mesacat 80 - orden de carga 72500 verificar_siguiente_mesacat(mesas_seccion_prioritaria[48], pv) # mesacat 81 - orden de carga 72750 verificar_siguiente_mesacat(mesas_seccion_prioritaria[49], pv) # mesacat 82 - orden de carga 74250 verificar_siguiente_mesacat(mesas_seccion_standard[12], pv) # mesacat 83 - orden de carga 75000
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 nueva_categoria(slug, nombres_opciones_prioritarias, nombres_opciones_no_prioritarias, distrito=None): categoria = CategoriaFactory( opciones=[], slug=slug, distrito=distrito) if distrito else CategoriaFactory(opciones=[], slug=slug) # sin opciones para crearlas ad hoc for nombre in nombres_opciones_prioritarias: CategoriaOpcionFactory(categoria=categoria, opcion__nombre=nombre, prioritaria=True) for nombre in nombres_opciones_no_prioritarias: CategoriaOpcionFactory(categoria=categoria, opcion__nombre=nombre, prioritaria=False) return categoria
def test_carga_mesa_redirige_a_siguiente(db, fiscal_client): o = OpcionFactory(es_contable=True) o2 = OpcionFactory(es_contable=False) e1 = CategoriaFactory(opciones=[o, o2]) e2 = CategoriaFactory(opciones=[o]) m1 = AttachmentFactory(mesa__categoria=[e1, e2]).mesa response = fiscal_client.get(reverse('elegir-acta-a-cargar')) assert response.url == reverse('mesa-cargar-resultados', args=[e1.id, m1.numero]) # formset para categoria e1 arranca en blanco url = response.url response = fiscal_client.get(response.url) formset = response.context['formset'] assert len(formset) == 2 assert formset[0].initial == {'opcion': o} assert formset[1].initial == {'opcion': o2} # response = fiscal_client.get(url) response = fiscal_client.post(url, { 'form-0-opcion': str(o.id), 'form-0-votos': str(m1.electores // 2), 'form-1-opcion': str(o2.id), 'form-1-votos': str(m1.electores // 2), 'form-TOTAL_FORMS': '2', 'form-INITIAL_FORMS': '0', 'form-MIN_NUM_FORMS': '2', 'form-MAX_NUM_FORMS': '1000', }) assert response.status_code == 302 assert response.url == reverse('mesa-cargar-resultados', args=[e2.id, m1.numero]) # el form de la nueva categoria e2 está en blanco url = response.url response = fiscal_client.get(response.url) formset = response.context['formset'] assert len(formset) == 1 assert formset[0].initial == {'opcion': o} # si completamos y es valido, no quedan # categorias por cargar y pide otra acta response = fiscal_client.post(url, { 'form-0-opcion': str(o.id), 'form-0-votos': str(m1.electores), 'form-TOTAL_FORMS': '1', 'form-INITIAL_FORMS': '0', 'form-MIN_NUM_FORMS': '1', 'form-MAX_NUM_FORMS': '1000', }) assert response.status_code == 302 assert response.url == reverse('elegir-acta-a-cargar')
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 test_troll_total_consolidada_dc_a_parcial_sin_consolidar(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() 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]) 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]) nueva_carga(mesa_categoria_1, fiscal_2, [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_2) consumir_novedades_carga() refrescar_data([mesa_categoria_1, fiscal_2]) assert mesa_categoria_1.status == MesaCategoria.STATUS.parcial_sin_consolidar assert Carga.objects.filter(invalidada=True).count() == 3
def test_troll_parcial_dc_a_sin_consolidar(db, settings): with override_config( SCORING_MINIMO_PARA_CONSIDERAR_QUE_FISCAL_ES_TROLL=20): 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() 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 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 assert Carga.objects.filter(invalidada=True).count() == 0 aplicar_marca_troll(fiscal_2) consumir_novedades_carga() refrescar_data([mesa_categoria_1, fiscal_2]) assert mesa_categoria_1.status == MesaCategoria.STATUS.parcial_sin_consolidar assert Carga.objects.filter(invalidada=True).count() == 1
def nueva_categoria(nombres_opciones, prioritaria=False): categoria = CategoriaFactory( opciones=[]) # sin opciones para crearlas ad hoc for nombre in nombres_opciones: CategoriaOpcionFactory(categoria=categoria, opcion__nombre=nombre, prioritaria=prioritaria) return categoria
def test_elegir_acta_mesas_redirige(db, fiscal_client): assert Mesa.objects.count() == 0 assert VotoMesaReportado.objects.count() == 0 c = CircuitoFactory() e1 = CategoriaFactory() e2 = CategoriaFactory() m1 = AttachmentFactory(mesa__categoria=[e1], mesa__lugar_votacion__circuito=c).mesa e2 = CategoriaFactory() m2 = AttachmentFactory(mesa__categoria=[e1, e2], mesa__lugar_votacion__circuito=c).mesa assert m1.orden_de_carga == 1 assert m2.orden_de_carga == 2 response = fiscal_client.get(reverse('elegir-acta-a-cargar')) assert response.status_code == 302 assert response.url == reverse('mesa-cargar-resultados', args=[e1.id, m1.numero]) # como m1 queda en periodo de "taken" (aunque no se haya ocupado aun) # se pasa a la siguiente mesa response = fiscal_client.get(reverse('elegir-acta-a-cargar')) assert response.status_code == 302 assert response.url == reverse('mesa-cargar-resultados', args=[e1.id, m2.numero]) # se carga esa categoria VotoMesaReportadoFactory( carga__mesa=m2, carga__categoria=e1, opcion=e1.opciones.first(), votos=1 ) # FIX ME . El periodo de taken deberia ser *por categoria*. # en este escenario donde esta lockeado la mesa para la categoria 1, pero no se está # cargando la mesa 2, un dataentry queda idle response = fiscal_client.get(reverse('elegir-acta-a-cargar')) assert response.status_code == 200 # no hay actas m2.taken = None m2.save() response = fiscal_client.get(reverse('elegir-acta-a-cargar')) assert response.status_code == 302 assert response.url == reverse('mesa-cargar-resultados', args=[e2.id, m2.numero])
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_data_acciones_para_monitoreo_antitrolling(db): # 40 mesas con su mesacat # 30 cargas, 22 procesadas, de esas 1 inválidas # de las 8 no procesadas, 2 inválidas presi = CategoriaFactory() fiscal = nuevo_fiscal() for ix in range(40): nueva_mesa = MesaFactory(categorias=[presi]) mesacat = MesaCategoria.objects.filter(mesa=nueva_mesa, categoria=presi).first() if (ix < 30): carga = nueva_carga(mesacat, fiscal, [20, 15], Carga.TIPOS.parcial) if (ix < 1): carga.invalidada = True carga.procesada = True elif (ix < 22): carga.invalidada = False carga.procesada = True elif (ix < 24): carga.invalidada = True carga.procesada = False else: carga.invalidada = False carga.procesada = False carga.save(update_fields=['invalidada', 'procesada']) ParametrosAntitrolling.reset() rangos = GeneradorInfoAcciones(Carga.objects).rangos() rango_total = next(rango for rango in rangos if rango.texto == 'Total') assert rango_total.cantidad == 30 assert rango_total.porcentaje == 100 rango_validas = next(rango for rango in rangos if rango.texto == 'Válidas procesadas') assert rango_validas.cantidad == 21 assert rango_validas.porcentaje == 70 rango_pendientes = next(rango for rango in rangos if rango.texto == 'Pendientes de proceso') assert rango_pendientes.cantidad == 6 assert rango_pendientes.porcentaje == 20 rango_invalidas = next(rango for rango in rangos if rango.texto == 'Invalidadas') assert rango_invalidas.cantidad == 3 assert rango_invalidas.porcentaje == 10 assert rango_invalidas.indicador_peligro == IndicadorDePeligro.indicador_rojo # con otros valores de peligro, corresponde otro indicador para el mismo porcentaje rango_invalidas.set_umbrales_de_peligro(8, 15, 30) assert rango_invalidas.cantidad == 3 assert rango_invalidas.porcentaje == 10 assert rango_invalidas.indicador_peligro == IndicadorDePeligro.indicador_amarillo rango_invalidas.set_umbrales_de_peligro(28, 35, 50) assert rango_invalidas.cantidad == 3 assert rango_invalidas.porcentaje == 10 assert rango_invalidas.indicador_peligro == IndicadorDePeligro.indicador_verde
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_cargar_resultados_redirige_a_identificar(db, fiscal_client, status, parcial): mesa = MesaFactory() a = AttachmentFactory(mesa=mesa) c1 = CategoriaFactory(requiere_cargas_parciales=True) m1c1 = MesaCategoriaFactory(categoria=c1, coeficiente_para_orden_de_carga=0.1, status=status, mesa=mesa) response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url.startswith('/clasificar-actas/')
def test_setup_opciones(db): assert not Opcion.objects.exists() c = CategoriaFactory(opciones=[]) call_command('setup_opciones_basicas') assert Opcion.objects.get(**settings.OPCION_BLANCOS) assert Opcion.objects.get(**settings.OPCION_TOTAL_VOTOS) assert Opcion.objects.get(**settings.OPCION_TOTAL_SOBRES) assert Opcion.objects.get(**settings.OPCION_NULOS) assert Opcion.objects.get(**settings.OPCION_RECURRIDOS) assert Opcion.objects.get(**settings.OPCION_ID_IMPUGNADA) assert Opcion.objects.get(**settings.OPCION_COMANDO_ELECTORAL) assert c.opciones.count() == 7
def test_configuracion_categoria(db): categoria = CategoriaFactory(prioridad=15) prioridades = PrioridadScheduling.objects.filter(categoria=categoria) assert prioridades.count() == 1 assert prioridades.first().prioridad == 15 categoria.prioridad = 21 categoria.save(update_fields=['prioridad']) prioridades = PrioridadScheduling.objects.filter(categoria=categoria) assert prioridades.count() == 1 assert prioridades.first().prioridad == 21 categoria.prioridad = None categoria.save(update_fields=['prioridad']) prioridades = PrioridadScheduling.objects.filter(categoria=categoria) assert prioridades.count() == 0 categoria_2 = CategoriaFactory() prioridades = PrioridadScheduling.objects.filter(categoria=categoria) assert prioridades.count() == 0
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_cargar_resultados_redirige_a_parcial_si_es_necesario( db, fiscal_client, status, parcial): mesa = MesaFactory() a = AttachmentFactory(mesa=mesa) c1 = CategoriaFactory(requiere_cargas_parciales=True, sensible=True) m1c1 = MesaCategoriaFactory(categoria=c1, coeficiente_para_orden_de_carga=0.1, status=status, mesa=mesa) response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse( 'carga-parcial' if parcial else 'carga-total', args=[m1c1.id])
def carga_inicial(db): d1 = DistritoFactory(numero=1) s1 = SeccionFactory(numero=50, distrito=d1) circ = CircuitoFactory(numero='2', seccion=s1) # Creamos los partidos. fdt = OpcionFactory(codigo='FdT', nombre='FdT', partido__nombre='FpT') jpc = OpcionFactory(codigo='JpC', nombre='JpC', partido__nombre='JpC') c2019 = OpcionFactory(codigo='C2019', nombre='C2019', partido__nombre='C2019') categorias = [] for categoria, prioritaria in CATEGORIAS: categoria_general = CategoriaGeneralFactory(nombre=categoria) # La categoría en sí tiene un nombre arbitrario para testear que # el matching sea en base a la categoría general. categoria_bd = CategoriaFactory(nombre=f'Categoría {categoria}', categoria_general=categoria_general) # La factory las crea con unas opciones que hacen ruido en estos tests. for nombre in ['opc1', 'opc2', 'opc3', 'opc4']: opcion = Opcion.objects.get(nombre=nombre) opcion.delete() categorias.append(categoria_bd) CategoriaOpcionFactory(categoria=categoria_bd, prioritaria=prioritaria, opcion=fdt) CategoriaOpcionFactory(categoria=categoria_bd, prioritaria=prioritaria, opcion=jpc) if categoria == 'Presidente y vice': CategoriaOpcionFactory(categoria=categoria_bd, prioritaria=False, opcion=c2019) if prioritaria: # Adecuamos las opciones prioritarias. hacer_prioritaria_en_cat(categoria_bd, Opcion.total_votos()) hacer_prioritaria_en_cat(categoria_bd, Opcion.blancos()) hacer_prioritaria_en_cat(categoria_bd, Opcion.nulos()) hacer_prioritaria_en_cat(categoria_bd, Opcion.sobres()) hacer_prioritaria_en_cat(categoria_bd, Opcion.recurridos()) hacer_prioritaria_en_cat(categoria_bd, Opcion.id_impugnada()) hacer_prioritaria_en_cat(categoria_bd, Opcion.comando_electoral()) MesaFactory(numero='4012', lugar_votacion__circuito=circ, electores=100, circuito=circ, categorias=categorias)
def test_orden_de_carga_escenario_base(db, settings): """ Se verifica la asignacion de ordenes de carga para una seccion standard, con dos categorias standard con una categoria prioritaria y una standard """ asignar_prioridades_standard(settings) settings.MIN_COINCIDENCIAS_IDENTIFICACION = 1 fiscal = nuevo_fiscal() # una seccion standard, un circuito, 25 mesas en el mismo lugar de votacion, dos categorias standard la_seccion, circuito, lugar_votacion = crear_seccion("Bera centro") pv = CategoriaFactory(nombre="PV") gv = CategoriaFactory(nombre="GV") categorias = [pv, gv] [mesas] = crear_mesas([lugar_votacion], categorias, 25) # primera mesa identificar_mesa(mesas[0], fiscal) verificar_valores_scheduling_mesacat(mesas[0], pv, 1, 1, 200) verificar_valores_scheduling_mesacat(mesas[0], gv, 1, 1, 200) # segunda mesa identificar_mesa(mesas[1], fiscal) verificar_valores_scheduling_mesacat(mesas[1], pv, 5, 2, 10000) verificar_valores_scheduling_mesacat(mesas[1], gv, 5, 2, 10000) # quinta mesa for nro in range(2, 5): identificar_mesa(mesas[nro], fiscal) verificar_valores_scheduling_mesacat(mesas[4], pv, 17, 5, 170000) verificar_valores_scheduling_mesacat(mesas[4], gv, 17, 5, 170000) # mesa 25 for nro in range(5, 25): identificar_mesa(mesas[nro], fiscal) verificar_valores_scheduling_mesacat(mesas[24], pv, 97, 25, 970000) verificar_valores_scheduling_mesacat(mesas[24], gv, 97, 25, 970000)
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_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_mesa_de_circuito__navegacion_categorias(fiscal_client): categoria1 = CategoriaFactory(nombre='cat1') categoria2 = CategoriaFactory(nombre='cat2') mesa1 = MesaFactory(categorias=[categoria1, categoria2]) 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=[categoria1.id]) + query_string_mesa_1 response = fiscal_client.get(url_mesa_1) assert response.status_code == 200 content = html.unescape(response.content.decode('utf-8')) assert response.context['mensaje_no_hay_info'] in content link_categoria_1 = f" href=\"/elecciones/resultados/mesas_circuito/{categoria1.id}{query_string_mesa_1}\"" link_categoria_2 = f" href=\"/elecciones/resultados/mesas_circuito/{categoria2.id}{query_string_mesa_1}\"" assert link_categoria_1 in content assert link_categoria_2 in content
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_cargar_resultados_redirige_a_parcial_si_es_necesario_con_scheduler( db, fiscal_client, status, parcial): mesa = MesaFactory() a = AttachmentFactory(mesa=mesa) c1 = CategoriaFactory(requiere_cargas_parciales=True, sensible=True) with override_config(ASIGNAR_MESA_EN_EL_MOMENTO_SI_NO_HAY_COLA=False): m1c1 = MesaCategoriaFactory(categoria=c1, coeficiente_para_orden_de_carga=0.1, status=status, mesa=mesa) scheduler() response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse( 'carga-parcial' if parcial else 'carga-total', args=[m1c1.id])
def test_chequear_resultado_mesa(db, fiscal_client): opcs = OpcionFactory.create_batch(3, es_contable=True) e1 = CategoriaFactory(opciones=opcs) e2 = CategoriaFactory(opciones=opcs) mesa = MesaFactory(categoria=[e1, e2]) me = MesaCategoria.objects.get(categoria=e1, mesa=mesa) assert me.confirmada is False votos1 = VotoMesaReportadoFactory(opcion=opcs[0], carga__mesa=mesa, carga__categoria=e1, votos=1) votos2 = VotoMesaReportadoFactory(opcion=opcs[1], carga__mesa=mesa, carga__categoria=e1, votos=2) votos3 = VotoMesaReportadoFactory(opcion=opcs[2], carga__mesa=mesa, carga__categoria=e1, votos=1) # a otra categoria VotoMesaReportadoFactory(opcion=opcs[2], carga__mesa=mesa, carga__categoria=e2, votos=1) url = reverse('chequear-resultado-mesa', args=[e1.id, mesa.numero]) response = fiscal_client.get(url) assert list(response.context['reportados']) == [votos1, votos2, votos3] response = fiscal_client.post(url, {'confirmar': 'confirmar'}) assert response.status_code == 302 assert response.url == reverse('chequear-resultado') me.refresh_from_db() assert me.confirmada is True
def test_siguiente_prioriza_estado_y_luego_coeficiente(db, settings, setup_constance, django_assert_num_queries): f = FiscalFactory() c = CategoriaFactory(prioridad=1) m1 = MesaFactory() AttachmentFactory(mesa=m1) mc1 = MesaCategoriaFactory( status=MesaCategoria.STATUS.parcial_sin_consolidar, categoria=c, coeficiente_para_orden_de_carga=1.0, mesa=m1 ) m2 = MesaFactory() AttachmentFactory(mesa=m2) mc2 = MesaCategoriaFactory( categoria=c, status=MesaCategoria.STATUS.total_en_conflicto, coeficiente_para_orden_de_carga=99.0, mesa=m2 ) m3 = MesaFactory() AttachmentFactory(mesa=m3) mc3 = MesaCategoriaFactory( categoria=c, status=MesaCategoria.STATUS.total_en_conflicto, coeficiente_para_orden_de_carga=2.0, mesa=m3 ) with django_assert_num_queries(17): assert MesaCategoria.objects.siguiente() == mc1 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): mc1.asignar_a_fiscal() assert MesaCategoria.objects.siguiente() == mc3 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): mc3.asignar_a_fiscal() assert MesaCategoria.objects.siguiente() == mc2 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): mc2.asignar_a_fiscal() # A igualdad de asignaciones, se vuelven a repetir. assert MesaCategoria.objects.siguiente() == mc1 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): mc1.asignar_a_fiscal() assert MesaCategoria.objects.siguiente() == mc3 for i in range(settings.MIN_COINCIDENCIAS_CARGAS): mc3.asignar_a_fiscal() assert MesaCategoria.objects.siguiente() == mc2