from django.core.management.base import BaseCommand from django.utils import timezone 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: self.stdout.write(self.style.SUCCESS(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: gtfs_archivo.status = 'PROCESANDO' gtfs_archivo.save() 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).first() if registro_anterior: registro_anterior.vigente = False registro_anterior.save() gtfs_archivo.status = 'GTFS CARGADO' 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)