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_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_problema_troll(db): fiscal_troll = nuevo_fiscal() fiscal_troll.troll = True fiscal_troll.save(update_fields=['troll']) fiscal_ok = nuevo_fiscal() attach = AttachmentFactory() ident_troll = reportar_problema_attachment(attach, fiscal_troll) Problema.reportar_problema(fiscal_troll, "foto fea", ReporteDeProblema.TIPOS_DE_PROBLEMA.ilegible, identificacion=ident_troll) ident_ok = reportar_problema_attachment(attach, fiscal_ok) Problema.reportar_problema(fiscal_ok, "no me gusta", ReporteDeProblema.TIPOS_DE_PROBLEMA.falta_lista, identificacion=ident_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_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 form_valid(self, form): # por algun motivo seguramente espantoso, pasa dos veces por acá # una vez desde el POST ajax, y otra luego de la primer redirección # meto este hack para que sólo cree el objeto cuando es ajax # y en la segunda vuelta sólo redireccion if self.request.is_ajax(): fiscal = self.request.user.fiscal # Lo falso grabo para quedarme con la data de sus campos. reporte_de_problema = form.save(commit=False) tipo_de_problema = reporte_de_problema.tipo_de_problema descripcion = reporte_de_problema.descripcion # Creo la identificación. identificacion = Identificacion.objects.create( status=Identificacion.STATUS.problema, fiscal=fiscal, mesa=None, attachment=self.attachment ) # Creo el problema asociado. Problema.reportar_problema(fiscal, descripcion, tipo_de_problema, identificacion=identificacion) return JsonResponse({'status': 'hack'}) # acá sólo va a llegar la segunda vez messages.info( self.request, f'Gracias por el reporte. Ahora pasamos a la siguiente acta.', extra_tags="problema" ) return redirect('siguiente-accion')
def form_valid(self, form): # mismo hack que en la misma vista adjuntos.views.ReporteDeProblemaCreateView # FIX ME: no tiene tests if self.request.is_ajax(): fiscal = self.request.user.fiscal carga = form.save(commit=False) carga.fiscal = fiscal carga.status = Carga.TIPOS.problema # Lo falso grabo para quedarme con la data de sus campos. reporte_de_problema = form.save(commit=False) tipo_de_problema = reporte_de_problema.tipo_de_problema descripcion = reporte_de_problema.descripcion # Creo la carga. carga = Carga.objects.create(tipo=Carga.TIPOS.problema, fiscal=fiscal, origen=Carga.SOURCES.web, mesa_categoria=self.mesa_categoria) # Creo el problema asociado. Problema.reportar_problema(fiscal, descripcion, tipo_de_problema, carga=carga) return JsonResponse({'status': 'hack'}) messages.info( self.request, f'Gracias por el reporte. Ahora pasamos a la siguiente acta.', extra_tags="problema") return redirect('siguiente-accion')
def consolidar_cargas_con_problemas(cargas_que_reportan_problemas): # Tomo como "muestra" alguna de las que tienen problemas. carga_con_problema = cargas_que_reportan_problemas.first() # Confirmo el problema porque varios reportaron problemas. Problema.confirmar_problema(carga=carga_con_problema) return MesaCategoria.STATUS.con_problemas, None
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 novo_problema(dados_problema): """ Cadastra um novo problema no sistema para ser utilizado em testes. """ numero_problemas = Problema.objects.count() indice = numero_problemas + 1 dados_problema.setdefault("titulo", "Título Problema Teste {0}".format(indice)) dados_problema.setdefault("publicado", True) problema = Problema(**dados_problema) problema.save() return problema
def novo_problema(dados_problema): """ Cadastra um novo problema no sistema para ser utilizado em testes. """ numero_problemas = Problema.objects.count() indice = numero_problemas + 1 dados_problema.setdefault('titulo', "Título Problema Teste {0}".format(indice)) dados_problema.setdefault('publicado', True) problema = Problema(**dados_problema) problema.save() return problema
def test_efecto_problema_descartado(db): fiscal_1 = nuevo_fiscal() a = AttachmentFactory() m1 = MesaFactory() i1 = IdentificacionFactory(attachment=a, status='problema', mesa=None) f = FiscalFactory() Problema.reportar_problema(fiscal_1, 'reporte 1', ReporteDeProblema.TIPOS_DE_PROBLEMA.spam, identificacion=i1) assert i1.problemas.first().problema.estado == Problema.ESTADOS.potencial problema = i1.problemas.first().problema problema.descartar(nuevo_fiscal().user) from constance import config assert EventoScoringTroll.objects.filter(fiscal_afectado=fiscal_1).get( ).variacion == config.SCORING_TROLL_PROBLEMA_DESCARTADO
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_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 consolidar_identificaciones(attachment): """ Consolida todas las identificaciones del Attachment parámetro. Deja una como testigo, si están dadas las condiciones. Si hay una identificación con origen csv, ésa es la testigo. En cualquier caso adecúa el estado de identificación del attach parámetro y lo asocia a la mesa identificada o a ninguna, si no quedó identificado. """ # Primero me quedo con todas las identificaciones para ese attachment # que correspondan con una identificación y no con un problema. status_count = attachment.status_count(Identificacion.STATUS.identificada) mesa_id_consolidada = None for mesa_id, cantidad, cuantos_csv in status_count: if (cantidad >= settings.MIN_COINCIDENCIAS_IDENTIFICACION or cuantos_csv > 0): mesa_id_consolidada = mesa_id break if mesa_id_consolidada: # Consolidamos una mesa, ya sea por CSV o por coincidencia múltiple. identificaciones_correctas = attachment.identificaciones.filter( mesa_id=mesa_id_consolidada, status=Identificacion.STATUS.identificada) identificacion_con_csv = identificaciones_correctas.filter( source=Identificacion.SOURCES.csv).first() # Si hay una de CSV, es la testigo. Si no, cualquiera del resto. testigo = identificacion_con_csv if identificacion_con_csv else identificaciones_correctas.first( ) # Identifico el attachment. status_attachment = testigo.status mesa_attachment = testigo.mesa # Si tenía asociado un problema de "falta hoja", se soluciona automáticamente # porque se agregó un attachment. Problema.resolver_problema_falta_hoja(mesa_attachment) # aumentar el scoring de los usuarios que identificaron el acta diferente efecto_scoring_troll_asociacion_attachment(attachment, mesa_attachment) else: status_attachment = Attachment.STATUS.sin_identificar mesa_attachment = None testigo = None # Si no logramos consolidar una identificación vemos si hay un reporte de problemas. status_count = attachment.status_count(Identificacion.STATUS.problema) for mesa_id, cantidad, cuantos_csv in status_count: if cantidad >= settings.MIN_COINCIDENCIAS_IDENTIFICACION_PROBLEMA: # Tomo como "muestra" alguna de las que tienen problemas. identificacion_con_problemas = attachment.identificaciones.filter( status=Identificacion.STATUS.problema).first() # Confirmo el problema porque varios reportaron problemas. Problema.confirmar_problema( identificacion=identificacion_con_problemas) status_attachment = Attachment.STATUS.problema # me acuerdo la mesa anterior por si se esta pasando a sin_identificar mesa_anterior = attachment.mesa # Identifico el attachment. # Notar que esta identificación podría estar sumando al attachment a una mesa que ya tenga. # Eso es correcto. # También podría estar haciendo pasar una attachment identificado al estado sin_identificar, # porque ya no está más vigente alguna identificación que antes sí. attachment.status = status_attachment attachment.mesa = mesa_attachment attachment.identificacion_testigo = testigo attachment.save(update_fields=['mesa', 'status', 'identificacion_testigo']) logger.info('Consolid. identificación', attachment=attachment.id, testigo=getattr(testigo, 'id', None), status=status_attachment) # Si el attachment pasa de tener una mesa a no tenerla, entonces hay que invalidar # todo lo que se haya cargado para las MesaCategoria de la mesa que perdió su attachment. if mesa_anterior and not mesa_attachment: mesa_anterior.invalidar_asignacion_attachment()