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_siguiente_manda_a_parcial_si_es_requerido_sin_scheduler( db, client, setup_groups, settings): settings.MIN_COINCIDENCIAS_CARGAS = 1 m1 = MesaFactory() a1 = AttachmentFactory(mesa=m1, status=Identificacion.STATUS.identificada) m2 = MesaFactory() a2 = AttachmentFactory(mesa=m2, status=Identificacion.STATUS.identificada) mc1 = MesaCategoriaFactory(categoria__requiere_cargas_parciales=False, coeficiente_para_orden_de_carga=1, mesa=m1) mc2 = MesaCategoriaFactory(categoria__requiere_cargas_parciales=True, coeficiente_para_orden_de_carga=2, mesa=m2) fiscales = FiscalFactory.create_batch(2) # Da mc1 porque es más prioritaria. fiscal_client = fiscal_client_from_fiscal(client, fiscales[0]) response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-total', args=[mc1.id]) # Cerramos la sesión para que el client pueda reutilizarse sin que nos diga # que ya estamos logueados. fiscal_client.logout() # mc1 fue asignada, ahora da mc2 fiscal_client = fiscal_client_from_fiscal(client, fiscales[1]) response = fiscal_client.get(reverse('siguiente-accion')) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('carga-parcial', args=[mc2.id])
def test_identificacion_de_mesa_circuito_numero_case_insensitive(db): c1 = CircuitoFactory(numero='1A') # mesa asociada al circuito 1A con mayúscula m1 = MesaFactory(circuito=c1) # el usuario ingresa '1a' en minúscula form = IdentificacionForm({ 'mesa': m1.numero, 'circuito': '1a', 'seccion': c1.seccion.numero, 'distrito': c1.seccion.distrito.id, }) assert form.is_valid() assert form.cleaned_data['mesa'] == m1 c2 = CircuitoFactory(numero='23/B') # mesa asociada al circuito 23/B con mayúscula m2 = MesaFactory(circuito=c2) # el usuario ingresa '23/b' en minúscula form = IdentificacionForm({ 'mesa': m2.numero, 'circuito': '23/b', 'seccion': c2.seccion.numero, 'distrito': c2.seccion.distrito.id, }) assert form.is_valid() assert form.cleaned_data['mesa'] == m2
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_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_desmarca_masiva(db, settings): fiscal_1 = nuevo_fiscal() fiscal_2 = nuevo_fiscal() fiscal_3 = nuevo_fiscal() fiscal_4 = nuevo_fiscal() fiscal_5 = nuevo_fiscal() fiscal_6 = nuevo_fiscal() fiscal_7 = nuevo_fiscal() attach = AttachmentFactory() mesa_1 = MesaFactory() mesa_2 = MesaFactory() mesa_3 = MesaFactory() mesa_4 = MesaFactory() mesa_5 = MesaFactory() with override_config( SCORING_MINIMO_PARA_CONSIDERAR_QUE_FISCAL_ES_TROLL=200): identi_1 = reportar_problema_attachment(attach, fiscal_1) identi_2 = identificar(attach, mesa_1, fiscal_2) identi_3 = identificar(attach, mesa_2, fiscal_3) identi_4 = identificar(attach, mesa_3, fiscal_4) identi_5 = identificar(attach, mesa_4, fiscal_5) identi_6 = identificar(attach, mesa_5, fiscal_6) aumentar_scoring_troll_identificacion(300, identi_1) aumentar_scoring_troll_identificacion(400, identi_2) aumentar_scoring_troll_identificacion(500, identi_3) aumentar_scoring_troll_identificacion(100, identi_4) aumentar_scoring_troll_identificacion(50, identi_5) assert fiscal_1.troll assert fiscal_2.troll assert fiscal_3.troll assert not fiscal_4.troll assert not fiscal_5.troll assert not fiscal_6.troll Fiscal.destrolleo_masivo(fiscal_7, 450, 80) for fiscal in [ fiscal_1, fiscal_2, fiscal_3, fiscal_4, fiscal_5, fiscal_6 ]: fiscal.refresh_from_db() assert not fiscal_1.troll assert fiscal_1.scoring_troll() == 80 assert not fiscal_2.troll assert fiscal_2.scoring_troll() == 80 eventos = list( fiscal_2.eventos_scoring_troll.order_by('created').all()) assert len(eventos) == 2 assert eventos[1].variacion == -320 assert fiscal_3.troll assert not fiscal_4.troll assert fiscal_4.scoring_troll() == 100 assert not fiscal_5.troll assert fiscal_5.scoring_troll() == 50 assert not fiscal_6.troll
def test_identificacion_valida_jerarquia(db): m1 = MesaFactory() m2 = MesaFactory() form = IdentificacionForm({ 'mesa': m1.numero, 'circuito': m1.circuito.numero, 'seccion': m1.circuito.seccion.numero, 'distrito': m1.circuito.seccion.distrito.id, }) assert form.is_valid()
def test_identificadas_excluye_sin_orden(db): m1 = MesaFactory() AttachmentFactory(mesa=m1) mc1 = MesaCategoriaFactory(mesa=m1) m2 = MesaFactory() AttachmentFactory(mesa=m2) mc2 = MesaCategoriaFactory(coeficiente_para_orden_de_carga=0.1, mesa=m2) assert mc1.coeficiente_para_orden_de_carga is None assert mc1 not in MesaCategoria.objects.identificadas() assert mc2 in MesaCategoria.objects.identificadas()
def test_identificacion_valida_seccion_no_corresponde_a_distrito(db): m1 = MesaFactory() m2 = MesaFactory() form = IdentificacionForm({ 'mesa': m1.numero, 'circuito': m1.circuito.numero, 'seccion': m1.circuito.seccion.numero, 'distrito': DistritoFactory().id, }) assert not form.is_valid() assert form.errors['seccion'] == ['Esta sección no pertenece al distrito']
def test_preidentificacion_nok(db): m1 = MesaFactory() m2 = MesaFactory() form = PreIdentificacionForm({ 'circuito': m1.circuito.id, 'seccion': m2.circuito.seccion.id, 'distrito': m2.circuito.seccion.distrito.id, }) assert not form.is_valid() assert form.errors['circuito'] == [ 'Este circuito no pertenece a la sección' ]
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
def test_chequear_resultado_mesa(db, fiscal_client): opcs = OpcionFactory.create_batch(3, es_contable=True) e1 = EleccionFactory(opciones=opcs) e2 = EleccionFactory(opciones=opcs) mesa = MesaFactory(eleccion=[e1, e2]) me = MesaEleccion.objects.get(eleccion=e1, mesa=mesa) assert me.confirmada is False votos1 = VotoMesaReportadoFactory(opcion=opcs[0], mesa=mesa, eleccion=e1, votos=1) votos2 = VotoMesaReportadoFactory(opcion=opcs[1], mesa=mesa, eleccion=e1, votos=2) votos3 = VotoMesaReportadoFactory(opcion=opcs[2], mesa=mesa, eleccion=e1, votos=1) # a otra eleccion VotoMesaReportadoFactory(opcion=opcs[2], mesa=mesa, eleccion=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_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_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 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_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_aumentar_scrolling(db, settings): """ Se comprueba que al disparar eventos de aumento de scoring, el efecto sea el esperado """ with override_config( SCORING_MINIMO_PARA_CONSIDERAR_QUE_FISCAL_ES_TROLL=400): fiscal1 = nuevo_fiscal() fiscal2 = nuevo_fiscal() assert fiscal1.scoring_troll() == 0 assert fiscal2.scoring_troll() == 0 mesa1 = MesaFactory() attach1 = AttachmentFactory() attach2 = AttachmentFactory() identi1 = identificar(attach1, mesa1, fiscal1) identi2 = identificar(attach1, mesa1, fiscal2) identi3 = identificar(attach2, mesa1, fiscal1) aumentar_scoring_troll_identificacion(100, identi1) aumentar_scoring_troll_identificacion(150, identi2) aumentar_scoring_troll_identificacion(250, identi3) assert fiscal1.scoring_troll() == 350 assert fiscal2.scoring_troll() == 150 assert not fiscal1.troll assert not fiscal2.troll attach3 = AttachmentFactory() identi4 = reportar_problema_attachment(attach3, fiscal1) aumentar_scoring_troll_identificacion(80, identi4) assert fiscal1.scoring_troll() == 430 assert fiscal2.scoring_troll() == 150 assert fiscal1.troll assert not fiscal2.troll
def test_carga_problema_troll(db): fiscal_troll = nuevo_fiscal() fiscal_troll.troll = True fiscal_troll.save(update_fields=['troll']) fiscal_ok = nuevo_fiscal() categ = nueva_categoria(["a", "b"]) mesa = MesaFactory(categorias=[categ]) mesa_categoria = MesaCategoria.objects.filter(mesa=mesa).first() carga_troll = reportar_problema_mesa_categoria(mesa_categoria, fiscal_troll) Problema.reportar_problema(fiscal_troll, "foto fea", ReporteDeProblema.TIPOS_DE_PROBLEMA.ilegible, carga=carga_troll) carga_ok = reportar_problema_mesa_categoria(mesa_categoria, fiscal_ok) Problema.reportar_problema(fiscal_ok, "no me gusta", ReporteDeProblema.TIPOS_DE_PROBLEMA.falta_lista, carga=carga_ok) assert 2 == Problema.objects.count() assert 1 == ReporteDeProblema.objects.filter( reportado_por=fiscal_troll).count() assert 1 == ReporteDeProblema.objects.filter( reportado_por=fiscal_ok).count() problema_troll = ReporteDeProblema.objects.filter( reportado_por=fiscal_troll).first().problema assert Problema.ESTADOS.descartado == problema_troll.estado problema_ok = ReporteDeProblema.objects.filter( reportado_por=fiscal_ok).first().problema assert Problema.ESTADOS.potencial == problema_ok.estado
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_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_preidentificacion_create_view_post(fiscal_client): content = open('adjuntos/tests/acta.jpg', 'rb') file = SimpleUploadedFile('acta.jpg', content.read(), content_type="image/jpeg") mesa_1 = MesaFactory() data = { 'file_field': (file, ), 'circuito': mesa_1.circuito.id, 'seccion': mesa_1.circuito.seccion.id, 'distrito': mesa_1.circuito.seccion.distrito.id, } response = fiscal_client.post(reverse('agregar-adjuntos'), data) assert response.status_code == HTTPStatus.OK attachment = Attachment.objects.all().first() assert attachment.pre_identificacion is not None assert attachment.status == Attachment.STATUS.sin_identificar pre_identificacion = attachment.pre_identificacion assert pre_identificacion.circuito == mesa_1.circuito assert pre_identificacion.seccion == mesa_1.circuito.seccion assert pre_identificacion.distrito == mesa_1.circuito.seccion.distrito
def test_identificacion_create_view_post__desde_unidad_basica( fiscal_client, admin_user): mesa_1 = MesaFactory() attachment = AttachmentFactory() admin_user.fiscal.asignar_attachment(attachment) attachment.asignar_a_fiscal() data = { 'mesa': mesa_1.numero, 'circuito': mesa_1.circuito.numero, 'seccion': mesa_1.circuito.seccion.numero, 'distrito': mesa_1.circuito.seccion.distrito.id, } response = fiscal_client.post( reverse('asignar-mesa-ub', args=[attachment.id]), data) assert response.status_code == HTTPStatus.FOUND assert response.url == reverse('cargar-desde-ub', kwargs={'mesa_id': mesa_1.id}) # Refrescamos el attachment desde la base. attachment.refresh_from_db() assert attachment.identificaciones.count() == 1 assert attachment.status == Attachment.STATUS.identificada identificacion = attachment.identificaciones.first() assert attachment.identificacion_testigo == identificacion assert identificacion.status == Identificacion.STATUS.identificada assert identificacion.source == Identificacion.SOURCES.csv assert identificacion.mesa == mesa_1 # La identificación está consolidada, por lo tanto ya existe en la mesa assert mesa_1.attachments.exists()
def test_datos_fotos_nacional(db, settings): settings.MIN_COINCIDENCIAS_IDENTIFICACION = 2 fiscales = [nuevo_fiscal() for ix in range(10)] mesas = [MesaFactory() for ix in range(30)] # 25 fotos: # - 9 identificadas # - 1 con problemas # - 8 en proceso de identificación # - 7 sin acciones for ix in range(25): foto = AttachmentFactory() if (ix < 9): identificar(foto, mesas[ix], fiscales[0]) identificar(foto, mesas[ix], fiscales[1]) elif (ix < 10): reportar_problema_attachment(foto, fiscales[2]) reportar_problema_attachment(foto, fiscales[3]) elif (ix < 18): identificar(foto, mesas[ix], fiscales[4]) consumir_novedades() generador = GeneradorDatosFotosNacional() generador.calcular() assert generador.cantidad_mesas == 30 assert generador.mesas_con_foto_identificada == 9 assert generador.fotos_con_problema_confirmado == 1 assert generador.fotos_en_proceso == 8 assert generador.fotos_sin_acciones == 7 assert generador.mesas_sin_foto == 5
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_preidentificacion_ok(db): m1 = MesaFactory() form = PreIdentificacionForm({ 'circuito': m1.circuito.id, 'seccion': m1.circuito.seccion.id, 'distrito': m1.circuito.seccion.distrito.id, }) assert form.is_valid()
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_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