def get(self, request, *args, **kwargs): self.object = self.get_object() estructura_archivo = self.obtiene_previsualizacion_archivo(self.object) if estructura_archivo: parser = ParserCsv() encoding = parser.detectar_encoding_csv(estructura_archivo) estructura_archivo_transformada = parser.visualizar_estructura_template( estructura_archivo, encoding) try: error_predictor = False error_predictor_encabezado = False predictor_metadata = PredictorMetadataService() metadata = predictor_metadata.inferir_metadata_desde_lineas( estructura_archivo, encoding) except NoSePuedeInferirMetadataError: initial_predecido_datos_extras = {} initial_predecido_encabezado = {} error_predictor = True except NoSePuedeInferirMetadataErrorEncabezado: initial_predecido_datos_extras = {} initial_predecido_encabezado = {} error_predictor_encabezado = True else: initial_predecido_datos_extras = dict([ ('datos-extras-{0}'.format(col), BaseDatosContacto.DATO_EXTRA_FECHA) for col in metadata.columnas_con_fecha ]) initial_predecido_datos_extras.update( dict([('datos-extras-{0}'.format(col), BaseDatosContacto.DATO_EXTRA_HORA) for col in metadata.columnas_con_hora])) initial_predecido_encabezado = { 'es_encabezado': metadata.primer_fila_es_encabezado } form_primer_linea_encabezado = PrimerLineaEncabezadoForm( initial=initial_predecido_encabezado) form_campos_telefonicos = CamposDeBaseDeDatosForm( nombres_campos=estructura_archivo[0]) return self.render_to_response( self.get_context_data( error_predictor_encabezado=error_predictor_encabezado, error_predictor=error_predictor, estructura_archivo=estructura_archivo_transformada, form_primer_linea_encabezado=form_primer_linea_encabezado, form_campos_telefonicos=form_campos_telefonicos)) return redirect(reverse('nueva_base_datos_contacto'))
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())
def importa_contactos(self, base_datos_contacto, campos_telefonicos, columna_id_externo): """ Tercer paso de la creación de una BaseDatosContacto. Este método se encarga de generar los objectos Contacto por cada linea del archivo de importación especificado para la base de datos de contactos. """ assert (base_datos_contacto.estado in (BaseDatosContacto.ESTADO_EN_DEFINICION, BaseDatosContacto.ESTADO_DEFINIDA_ACTUALIZADA)) # FIXME: este metodo valida la consistencia de los metadatos, y # lanza una excepcion ante cualquier problema. OJO! Esto no implica # que los metadatos sean correctos y consistentes con los datos, # pero al menos validan la consistencia "interna" de los metadatos # metadata = base_datos_contacto.get_metadata() # metadata.validar_metadatos() # Antes que nada, borramos los contactos preexistentes # base_datos_contacto.elimina_contactos() parser = ParserCsv() ids_externos = base_datos_contacto.contactos.values_list('id_externo', flat=True) ids_externos = set(ids_externos) ids_nuevos_contactos = [] try: estructura_archivo = parser.get_estructura_archivo( base_datos_contacto) posicion_primer_telefono = estructura_archivo[0].index( campos_telefonicos[0]) encoding = parser.detectar_encoding_csv(estructura_archivo) cantidad_contactos = 0 if base_datos_contacto.cantidad_contactos: cantidad_contactos = base_datos_contacto.cantidad_contactos numero_fila = 0 for lista_dato in estructura_archivo[1:]: numero_fila += 1 telefono, datos, id_externo = self.obtener_telefono_y_datos( encoding, lista_dato, posicion_primer_telefono, columna_id_externo) cantidad_contactos += 1 if id_externo is not None and id_externo != '': # El id_externo no puede estar repetido if id_externo in ids_externos: base_datos_contacto.contactos.filter( id__in=ids_nuevos_contactos).delete() raise (CreacionBaseDatosServiceIdExternoError( numero_fila, columna_id_externo, lista_dato, id_externo)) else: ids_externos.add(id_externo) contacto = Contacto.objects.create( telefono=telefono, datos=datos, bd_contacto=base_datos_contacto, id_externo=id_externo) ids_nuevos_contactos.append(contacto.id) except OmlParserMaxRowError: base_datos_contacto.contactos.filter( id__in=ids_nuevos_contactos).delete() raise except OmlParserCsvImportacionError: base_datos_contacto.contactos.filter( id__in=ids_nuevos_contactos).delete() raise base_datos_contacto.cantidad_contactos = cantidad_contactos base_datos_contacto.save()