from django.core.management.base import BaseCommand from django.db import connection from api.models import GtfsArchivo, RedTransporte from decouple import config import os import csv import zipfile import tempfile import threading class Command(BaseCommand): help = 'Procesa los archivos gtfs en formato comprimido (zip)' def handle(self, *args, **options): # Lógica de tu comando aquí folder = config('GTFS_UPLOADS','/tmp') redes = RedTransporte.objects.filter(vigente=True) for red in redes: print(f'nombre red: {red.nombre_red}') gtfs_archivo = GtfsArchivo.objects \ .filter(vigente=False, id_red = red.id_red, status = 'PENDIENTE') \ .order_by('-created').first() if gtfs_archivo != None: filepath = os.path.join(folder, gtfs_archivo.ruta_archivo) print(f'procesa: {filepath}') procesa_zip(filepath) registro_anterior = GtfsArchivo.objects.filter(vigente=True, id_red = red.id_red) registro_anterior.vigente = False registro_anterior.save() gtfs_archivo.status = 'PROCESADO' gtfs_archivo.vigente = True gtfs_archivo.save() self.stdout.write(self.style.SUCCESS('¡Comando ejecutado con éxito!')) def procesa_zip(filepath): carpeta_destino = tempfile.gettempdir() # descomprimir archivo zip archivo_zip = zipfile.ZipFile(filepath, "r") password='' try: # Extraer todos los archivos del archivo ZIP archivo_zip.extractall(pwd=password, path=carpeta_destino) print("Archivos extraídos con éxito", flush=True) except Exception as e: print("Error al extraer archivos:", e, flush=True) finally: archivo_zip.close() # Lista de archivos GTFS para cargar en la base de datos gtfs_files = [ "agency.txt", "calendar.txt", "feed_info.txt", "routes.txt", "shapes.txt", "stops.txt", "stop_times.txt", "trips.txt" ] try: # Crear las tablas en el esquema y cargar los datos cur = connection.cursor() for file in gtfs_files: filepath = os.path.join(carpeta_destino, file) if os.path.exists(filepath): create_and_load_table(filepath, file, cur) os.remove(filepath) procesa_tablas_z(cur) cur.close() connection.commit() except Exception as e: print(f'ERROR: {e}', flush=True) finally: print('==============', flush=True) print(f'fin proceso archivo: {archivo_zip}', flush=True) # Función para crear la definición de la tabla como texto y cargar los datos def create_and_load_table(filepath, file_name, cursor): with open(filepath, 'r', encoding='utf-8-sig') as file: reader = csv.reader(file) columns = next(reader) table_name = "z_"+file_name.replace('.txt', '') column_definitions = ',\n'.join([f"{column_name} TEXT" for column_name in columns]) create_table = f"CREATE TABLE IF NOT EXISTS {table_name} (\n{column_definitions}\n);" print(f'SQL> {create_table}', flush=True) cursor.execute(create_table) print('', flush=True) truncate_table = f"truncate table {table_name}; commit;" print(f'SQL> {truncate_table}', flush=True) cursor.execute(truncate_table) print('', flush=True) file.seek(0) next(reader) insert_query = f"COPY {table_name} ({', '.join(columns)}) FROM STDIN WITH CSV" print(f'SQL> {insert_query}', flush=True) cursor.copy_expert(sql=insert_query, file=file) print('', flush=True) def procesa_tablas_z(cursor): current_folder = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(current_folder, 'actualiza_GTFS.sql'),'r') as file: content = ''.join(file.readlines()) arr_sql = content.split('-----') for sql in arr_sql: sql = sql.strip() if sql > ' ': print(f'SQL> {sql}', flush=True) cursor.execute(sql) print('', flush=True)