def test_define_base_dato_contacto(self):
        bd = BaseDatosContacto(id=1)
        bd.save()

        # -----

        creacion_base_de_datos_service = CreacionBaseDatosService()
        creacion_base_de_datos_service.define_base_dato_contacto(bd)

        self.assertEqual(bd.estado, BaseDatosContacto.ESTADO_DEFINIDA)
    def test_con_demas_planillas_de_ejemplo(self):

        PLANILLAS = (
            "planilla-ejemplo-1.csv",
            "planilla-ejemplo-2.csv",
            "planilla-ejemplo-7-celdas-vacias.csv",
            "planilla-ejemplo-8-ultima-celda-vacia.csv",
        )

        for planilla in PLANILLAS:
            logger.debug("Procesando planilla %s", planilla)
            bd_contacto = BaseDatosContacto.objects.create(
                nombre="base-datos-contactos-{0}".format(planilla),
                archivo_importacion=self.copy_test_resource_to_mediaroot(
                    planilla),
                nombre_archivo_importacion=planilla)

            parser = ParserCsv()
            estructura_archivo = parser.previsualiza_archivo(bd_contacto)
            predictor_metadata = PredictorMetadataService()
            metadata_inferida = predictor_metadata.inferir_metadata_desde_lineas(
                estructura_archivo)

            metadata = bd_contacto.get_metadata()
            metadata._metadata = metadata_inferida._metadata
            metadata.nombres_de_columnas = [
                "COL{0}".format(num)
                for num in range(metadata.cantidad_de_columnas)
            ]
            metadata.save()

            creacion_base_datos_service = CreacionBaseDatosService()
            creacion_base_datos_service.importa_contactos(
                bd_contacto, ["Telefono"], None)
            creacion_base_datos_service.define_base_dato_contacto(bd_contacto)

            # ----- checks

            self.assertEquals(
                BaseDatosContacto.objects.get(pk=bd_contacto.id).estado,
                BaseDatosContacto.ESTADO_DEFINIDA,
                "La BD generada desde '{0}' NO ha quedado en estado ESTADO_DEFINIDA"
                "".format(planilla))

            self.assertTrue(
                Contacto.objects.filter(bd_contacto=bd_contacto.id).count() >
                0, "La BD generada desde '{0}' NO posee contactos".format(
                    planilla))
    def test_con_planilla_ejemplo_3(self):
        bd_contacto = BaseDatosContacto.objects.create(
            nombre="base-datos-contactos",
            archivo_importacion=self.copy_test_resource_to_mediaroot(
                "planilla-ejemplo-3-headers-con-no-ascii-y-espacios.csv"),
            nombre_archivo_importacion=
            'planilla-ejemplo-3-headers-con-no-ascii-y-espacios.csv')

        parser = ParserCsv()
        estructura_archivo = parser.previsualiza_archivo(bd_contacto)
        predictor_metadata = PredictorMetadataService()
        metadata_inferida = predictor_metadata.inferir_metadata_desde_lineas(
            estructura_archivo)

        metadata = bd_contacto.get_metadata()
        metadata._metadata = metadata_inferida._metadata
        metadata.nombres_de_columnas = ["Telefono", "NOMBRE", "FECHA", "HORA"]
        metadata.columna_con_telefono = 0
        metadata.columnas_con_telefono = [0]
        metadata.save()

        creacion_base_datos_service = CreacionBaseDatosService()
        creacion_base_datos_service.importa_contactos(bd_contacto,
                                                      ["Telefono"], None)
        creacion_base_datos_service.define_base_dato_contacto(bd_contacto)

        # ----- checks

        self.assertEquals(
            BaseDatosContacto.objects.get(pk=bd_contacto.id).estado,
            BaseDatosContacto.ESTADO_DEFINIDA,
            "La BD no ha quedado en estado ESTADO_DEFINIDA")

        nros_telefono = [
            contacto.telefono
            for contacto in Contacto.objects.filter(bd_contacto=bd_contacto.id)
        ]

        self.assertEquals(len(nros_telefono), 3, "Deberia haber 3 contactos")

        self.assertEquals(
            set(nros_telefono),
            set(['354303459865', '111534509230', '283453013491']),
            "Deberia haber 3 contactos")
    def form_valid(self, estructura_archivo, form_primer_linea_encabezado):

        cantidad_columnas = len(estructura_archivo[0])

        lista_columnas_encabezado = estructura_archivo[0]

        error = None

        metadata = self.object.get_metadata()
        metadata.cantidad_de_columnas = cantidad_columnas

        for columna_base, columna_csv in zip(metadata.nombres_de_columnas,
                                             lista_columnas_encabezado):
            if columna_base != columna_csv:
                error = _("El nombre de la columna debe ser {0} en vez de {1}".
                          format(columna_base, columna_csv))

        if error:
            return self.form_invalid(estructura_archivo,
                                     form_primer_linea_encabezado,
                                     error=error)

        es_encabezado = False
        if self.request.POST.get('es_encabezado', False):
            es_encabezado = True
        metadata.primer_fila_es_encabezado = es_encabezado
        metadata.save()

        creacion_base_datos = CreacionBaseDatosService()

        try:
            # creacion_base_datos.valida_contactos(self.object)
            bd_metadata = self.object.get_metadata()
            columnas_con_telefono = bd_metadata.nombres_de_columnas_de_telefonos
            columna_id_externo = bd_metadata.columna_id_externo

            creacion_base_datos.importa_contactos(self.object,
                                                  columnas_con_telefono,
                                                  columna_id_externo)
        except CreacionBaseDatosServiceIdExternoError as e:
            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee contactos con identificadores externos '
                  'repetidos.<br> '
                  '<u>Línea Inválida:</u> {0}<br> <u>Contenido Línea:</u>'
                  ' {1}<br><u>ID repetido:</u> {2}').format(
                e.numero_fila, e.fila, e.valor_celda)

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )
            return self.render_to_response(
                self.get_context_data(
                    estructura_archivo=estructura_archivo,
                    form_primer_linea_encabezado=form_primer_linea_encabezado))

        except OmlParserCsvImportacionError as e:

            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee registros inválidos.<br> '
                  '<u>Línea Inválida:</u> {0}<br> <u>Contenido Línea:</u>'
                  '{1}<br><u>Contenido Inválido:</u> {2}').format(
                e.numero_fila, e.fila, e.valor_celda)

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )
            return self.render_to_response(
                self.get_context_data(
                    estructura_archivo=estructura_archivo,
                    form_primer_linea_encabezado=form_primer_linea_encabezado))

        except ContactoExistenteError as e:

            message = _('<strong>¡Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee registros inválidos.<br> '
                  'ERROR: {0}. Vuelva a cargar nuevamente la base de datos '
                  'sin el contacto existente ').format(e)

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )

            return self.render_to_response(
                self.get_context_data(
                    estructura_archivo=estructura_archivo,
                    form_primer_linea_encabezado=form_primer_linea_encabezado))

        except OmlParserMaxRowError:
            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee más registros de los '
                  'permitidos para ser importados.')

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )
            return redirect(reverse('lista_base_datos_contacto'))
        else:
            creacion_base_datos.define_base_dato_contacto(self.object)

            message = _('<strong>Operación Exitosa!</strong> ') +\
                _('Se llevó a cabo con éxito la creación de la Base de Datos de Contactos.')

            messages.add_message(
                self.request,
                messages.SUCCESS,
                message,
            )
            return redirect(self.get_success_url())
    def form_valid(self, estructura_archivo, form_primer_linea_encabezado,
                   form_campos_telefonicos):
        # columna_con_telefono = int(form_columna_telefono.cleaned_data.get(
        #                            'telefono', None))
        # cantidad_columnas = len(form_nombre_columnas.fields)
        cantidad_columnas = len(estructura_archivo[0])

        # for numero_columna in range(cantidad_columnas):
        #     dato_extra = form_datos_extras.cleaned_data.get(
        #         'datos-extras-{0}'.format(numero_columna), None)
        #     if dato_extra == BaseDatosContacto.DATO_EXTRA_FECHA:
        #         lista_columnas_fechas.append(numero_columna)
        #     elif dato_extra == BaseDatosContacto.DATO_EXTRA_HORA:
        #         lista_columnas_horas.append(numero_columna)
        #
        #     nombre_columna = form_nombre_columnas.cleaned_data.get(
        #         'nombre-columna-{0}'.format(numero_columna), None)
        #
        #     validador_nombre = ValidadorDeNombreDeCampoExtra()
        #     if not validador_nombre.validar_nombre_de_columna(nombre_columna):
        #         error = 'El nombre de la Columna{0} no es válido. Debe estar \
        #                  en mayúscula y sin espacios. Por ejemplo: \
        #                  TELEFONO_FIJO'.format(numero_columna)
        #
        #         return self.form_invalid(estructura_archivo,
        #                                  #form_columna_telefono,
        #                                  #form_datos_extras,
        #                                  #form_nombre_columnas,
        #                                  form_primer_linea_encabezado,
        #                                  error=error)
        #
        #     lista_nombre_columnas.append(nombre_columna)

        # error = None
        # lista_columnas_encabezado = estructura_archivo[0]
        # if lista_columnas_encabezado[0] != 'telefono':
        #     error = _("El nombre de la primera columna debe ser telefono")
        # if error:
        #     return self.form_invalid(estructura_archivo,
        #                             form_primer_linea_encabezado,
        #                             form_campos_telefonicos, error=error)

        parser = ParserCsv()
        # Detecto el encondig de la base de datoss recientemente subida
        encoding = parser.detectar_encoding_csv(estructura_archivo)
        metadata = self.object.get_metadata()
        metadata.cantidad_de_columnas = cantidad_columnas

        # predictor_metadata = PredictorMetadataService()
        # columnas_con_telefonos = predictor_metadata.inferir_columnas_telefono(
        #     estructura_archivo[1:], encoding)
        campos_telefonicos = form_campos_telefonicos.cleaned_data.get(
            'campos_telefonicos')
        columnas_con_telefono = form_campos_telefonicos.columnas_de_telefonos
        metadata.columnas_con_telefono = columnas_con_telefono
        columna_id_externo = form_campos_telefonicos.columna_id_externo
        if columna_id_externo is not None:
            metadata.columna_id_externo = columna_id_externo

        metadata.nombres_de_columnas = [
            value.decode(encoding) for value in estructura_archivo[0]
        ]
        es_encabezado = False
        if self.request.POST.get('es_encabezado', False):
            es_encabezado = True
        metadata.primer_fila_es_encabezado = es_encabezado
        metadata.save()

        creacion_base_datos = CreacionBaseDatosService()

        try:
            # creacion_base_datos.valida_contactos(self.object)
            creacion_base_datos.importa_contactos(self.object,
                                                  campos_telefonicos,
                                                  columna_id_externo)
        except CreacionBaseDatosServiceIdExternoError as e:
            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee contactos con identificadores externos '
                  'repetidos.<br> '
                  '<u>Línea Inválida:</u> {0}<br> <u>Contenido Línea:</u>'
                  ' {1}<br><u>ID repetido:</u> {2}').format(
                e.numero_fila, e.fila, e.valor_celda)

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )
            return self.render_to_response(
                self.get_context_data(
                    estructura_archivo=estructura_archivo,
                    form_primer_linea_encabezado=form_primer_linea_encabezado))

        except OmlParserCsvImportacionError as e:

            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee registros inválidos.<br> '
                  '<u>Línea Inválida:</u> {0}<br> <u>Contenido Línea:</u>'
                  '{1}<br><u>Contenido Inválido:</u> {2}').format(
                e.numero_fila, e.fila, e.valor_celda)

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )
            # FIXME: Ver bien que hacer acá.

        except ContactoExistenteError as e:

            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee registros inválidos.<br> '
                  'ERROR: {0}. Vuelva a cargar nuevamente la base de datos '
                  'sin el contacto existente ').format(e)

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )

            return self.render_to_response(
                self.get_context_data(
                    estructura_archivo=estructura_archivo,
                    form_primer_linea_encabezado=form_primer_linea_encabezado,
                    form_campos_telefonicos=form_campos_telefonicos))

        except OmlParserMaxRowError:
            message = _('<strong>Operación Errónea!</strong> ') +\
                _('El archivo que seleccionó posee más registros de los '
                  'permitidos para ser importados.')

            messages.add_message(
                self.request,
                messages.ERROR,
                message,
            )
            return redirect(reverse('lista_base_datos_contacto'))
        else:
            creacion_base_datos.define_base_dato_contacto(self.object)

            message = _('<strong>Operación Exitosa!</strong> ') +\
                _('Se llevó a cabo con éxito la creación de '
                  'la Base de Datos de Contactos.')

            messages.add_message(
                self.request,
                messages.SUCCESS,
                message,
            )
            return redirect(self.get_success_url())