diff --git a/docs/rest/login.rest b/docs/rest/login.rest index 94dd73f..e6cec3c 100644 --- a/docs/rest/login.rest +++ b/docs/rest/login.rest @@ -8,8 +8,8 @@ POST {{server}}/auth/ Content-Type: application/json { - "username": "0", - "password": "0" + "username": "usuario1", + "password": "usuario1" } ### @@ -22,5 +22,24 @@ Authorization: Bearer {{token}} ### -GET {{server}}/paraderos-image/??id_paradero=42318 +GET {{server}}/paraderos-image/?id_paradero=42318 +Authorization: Bearer {{token}} + +### +# @name permisos_todos +POST {{server}}/usuarios/permisos/ +Authorization: Bearer {{token}} + +### +# @name permisos_path +POST {{server}}/usuarios/permisos/ +Authorization: Bearer {{token}} +Content-Type: application/json + +{ + "path": "/usuarios" +} + +### +GET {{server}}/lineas/?offset=0&limit=10 Authorization: Bearer {{token}} \ No newline at end of file diff --git a/docs/rest/upload.rest b/docs/rest/upload.rest new file mode 100644 index 0000000..7427288 --- /dev/null +++ b/docs/rest/upload.rest @@ -0,0 +1,31 @@ + +@server = http://localhost:4000/api +@token = {{login.response.body.$.token}} + +### +# @name login +POST {{server}}/auth/ +Content-Type: application/json + +{ + "username": "usuario1", + "password": "usuario1" +} + + +### +GET {{server}}/upload/zip +Authorization: Bearer {{token}} + +### +POST {{server}}/upload/zip/ +Authorization: Bearer {{token}} +Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="filezip"; filename="Gran Concepción20230727.zip" +Content-Type: application/zip + +< ./Gran Concepción20230727.zip +------WebKitFormBoundary7MA4YWxkTrZu0gW-- +### diff --git a/project/api/middlewares.py b/project/api/middlewares.py index d967fe4..ca7f6d5 100755 --- a/project/api/middlewares.py +++ b/project/api/middlewares.py @@ -24,11 +24,16 @@ class ApiMiddleware: match = resolve(request.path) logging.error(match) + # se omite esta regla al mostrar imagen de paradero if match.url_name == 'paradero_imagen-detail' and request.method == 'GET': response = self.get_response(request) return response + # se omite esta regla al mostrar informacion publica de paradero + if match.url_name == 'paradero-info-public' and request.method == 'GET': + response = self.get_response(request) + return response if not request.headers.get('Authorization'): return HttpResponse('Debe indicar el token de autorización', status = 400) diff --git a/project/api/models.py b/project/api/models.py index baa7c15..dcbbe10 100755 --- a/project/api/models.py +++ b/project/api/models.py @@ -11,11 +11,12 @@ from .validaciones import rut_valido class Aplicacion(models.Model): id_aplicacion = models.IntegerField(primary_key=True) - nombre_app = models.CharField(max_length=100, blank=True, null=True) + nombre_app = models.CharField(max_length=100, blank=False, null=False) + path_app = models.CharField(max_length=200, blank=False, null=False) vigente = models.BooleanField(blank=True, null=True) class Meta: - managed = False + managed = True db_table = 'aplicacion' @@ -293,13 +294,13 @@ class Rol(models.Model): class RolAplicacion(models.Model): - id_aplicacion = models.ForeignKey(Aplicacion, models.DO_NOTHING, db_column='id_aplicacion') - id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol') - solo_visualizar = models.BooleanField(blank=True, null=True) id_rol_app = models.AutoField(primary_key=True) + id_aplicacion = models.ForeignKey(Aplicacion, models.DO_NOTHING, db_column='id_aplicacion', blank=False, null=False) + id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=False, null=False) + solo_visualizar = models.BooleanField(blank=True, null=True) class Meta: - managed = False + managed = True db_table = 'rol_aplicacion' unique_together = (('id_aplicacion', 'id_rol'),) @@ -367,6 +368,7 @@ class Usuario(models.Model): rut = models.ForeignKey(Persona, models.DO_NOTHING, db_column='rut', blank=True, null=True) vigente = models.BooleanField(blank=True, null=True) superuser = models.BooleanField(blank=True, null=True) + id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=False, null=False) class Meta: managed = False @@ -385,16 +387,6 @@ class UsuarioClave(models.Model): db_table = 'usuario_clave' -class UsuarioRol(models.Model): - login = models.ForeignKey(Usuario, models.DO_NOTHING, db_column='login', blank=True, null=True) - id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=True, null=True) - vigente = models.BooleanField(blank=True, null=True) - - class Meta: - managed = False - db_table = 'usuario_rol' - - class Vehiculo(models.Model): ppu = models.CharField(primary_key=True, max_length=10) id_tipo_vehiculo = models.ForeignKey(TipoVehiculo, models.DO_NOTHING, db_column='id_tipo_vehiculo', blank=True, null=True) @@ -414,3 +406,13 @@ class VehiculoLinea(models.Model): managed = False db_table = 'vehiculo_linea' unique_together = (('patente', 'id_linea'),) + +class RolLinea(models.Model): + id_rol_linea = models.AutoField(primary_key=True) + id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol') + id_linea = models.ForeignKey(Linea, models.DO_NOTHING, db_column='id_linea') + + class Meta: + managed = True + db_table = 'rol_linea' + unique_together = (('id_rol', 'id_linea'),) diff --git a/project/api/serializers.py b/project/api/serializers.py index bc02731..edca5f2 100755 --- a/project/api/serializers.py +++ b/project/api/serializers.py @@ -94,6 +94,7 @@ class LineaParaderoSerializer(serializers.ModelSerializer): class UsuarioSerializer(serializers.ModelSerializer): # muestro informacion de persona en un objeto aparte persona = serializers.SerializerMethodField() + rol = serializers.SerializerMethodField() class Meta: model = models.Usuario @@ -102,6 +103,9 @@ class UsuarioSerializer(serializers.ModelSerializer): def get_persona(self, row): return model_to_dict(row.rut) + + def get_rol(self, row): + return model_to_dict(row.id_rol) def to_representation(self, instance): representation = super().to_representation(instance) @@ -126,6 +130,11 @@ class RolAplicacionSerializer(serializers.ModelSerializer): model = models.RolAplicacion fields = '__all__' +class RolLineaSerializer(serializers.ModelSerializer): + class Meta: + model = models.RolLinea + fields = '__all__' + class LetreroLUR_Serializer(serializers.ModelSerializer): class Meta: model = models.LetreroLUR diff --git a/project/api/urls.py b/project/api/urls.py index 9e2897a..a4d0aa1 100755 --- a/project/api/urls.py +++ b/project/api/urls.py @@ -1,11 +1,12 @@ from django.urls import path, include from rest_framework import routers # from api import views -from api.views import usuario, auth, aplicacion, tipo, persona, comuna, region, paradero, rol, rolaplicacion +from api.views import usuario, auth, aplicacion, tipo, persona, comuna, region, rol, rolaplicacion from api.views import mapa, linea, letrero_lur, operador -from api.views import paradero_imagen, linea_paradero +from api.views import paradero, paradero_imagen, linea_paradero from api.views import dispositivo -# from api.views import proto +from api.views import rol_linea +from api.views import upload router = routers.DefaultRouter() router.register('aplicaciones', aplicacion.AplicacionViewSet) @@ -27,12 +28,12 @@ router.register('letreros-lur', letrero_lur.LetreroLUR_ViewSet) router.register('operadores', operador.OperadorViewSet) router.register('roles', rol.RolViewSet) router.register('rolyaplicacion', rolaplicacion.RolAplicacionViewSet, basename='rol_aplicacion') +router.register('roles-lineas', rol_linea.RolLineaViewSet, basename='rol_linea') urlpatterns = [ path('', include(router.urls)), path('auth/', auth.jwt_login, name='auth'), path('mapas/paraderos/', mapa.paraderos, name='mapa-paraderos'), path('mapas/rutas/', mapa.rutas, name='mapa-rutas'), - path('paraderos/info-public//', paradero.info_public, name='paradero-infopublic'), - # path('proto/status/', proto.status, name='proto_status'), + path('upload/zip/', upload.upload_zip, name='upload_zip'), ] diff --git a/project/api/validaciones.py b/project/api/validaciones.py index 2906fd9..d134809 100755 --- a/project/api/validaciones.py +++ b/project/api/validaciones.py @@ -2,7 +2,7 @@ def rut_valido(rut): rut = rut.replace(".", "").replace("-", "") # Eliminar puntos y guiones if len(rut) < 2: return False - verificador = rut[-1] + verificador = rut[-1].upper() numero = rut[:-1] try: suma = 0 @@ -14,7 +14,7 @@ def rut_valido(rut): if digito_verificador == 11: digito_verificador = 0 if digito_verificador == 10: - digito_verificador = "k" - return str(digito_verificador) == verificador.lower() + digito_verificador = "K" + return str(digito_verificador) == verificador except ValueError: return False diff --git a/project/api/views/actualiza_GTFS.sql b/project/api/views/actualiza_GTFS.sql new file mode 100644 index 0000000..d902ea0 --- /dev/null +++ b/project/api/views/actualiza_GTFS.sql @@ -0,0 +1,203 @@ + +ALTER TABLE rol_linea drop CONSTRAINT IF EXISTS rol_linea_id_linea_fkey; + +----- + +ALTER TABLE linea_paradero drop CONSTRAINT IF EXISTS linea_paradero_id_linea_fkey; + +----- + +update operador +set vigente =false +where id_operador not in (select agency_id from z_agency za); + +----- + +update operador +set vigente =true +where id_operador in (select agency_id from z_agency za); + +----- + +insert into operador +select agency_id, null as id_region , true as vigente, +agency_name, agency_url , agency_timezone , agency_lang , agency_phone , agency_fare_url +from z_agency za +where agency_id not in (select id_operador from operador za); + +----- + +delete from gtfs_calendar ; + +----- + +insert into gtfs_calendar +select service_id, monday::bool , tuesday::bool , wednesday::bool , thursday::bool ,friday::bool ,saturday::bool ,sunday::bool +from z_calendar zc; + +----- + +update paradero p +set vigente = false +where id_paradero::text not in (select stop_id from z_stops ); + +----- + +update paradero +set vigente = true, +stop_name= (select stop_name from z_stops where stop_id=paradero.id_paradero::text limit 1 ), +stop_desc=(select stop_desc from z_stops where stop_id=paradero.id_paradero::text limit 1 ), +stop_lat =(select stop_lat from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8), +stop_lon =(select stop_lon from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8), +stop_code=(select stop_code from z_stops where stop_id=paradero.id_paradero::text limit 1) +where id_paradero::text in (select stop_id from z_stops ); + +----- + +insert into paradero +select +stop_id, null as id_comuna, null as id_tipo_paradero, true, +stop_code , stop_name , stop_desc , stop_lat::float(8) , stop_lon::float(8) , zone_id , +stop_url , location_type , +parent_station ,null as stop_time_zone , wheelchair_boarding::numeric +from z_stops zs +where stop_id not in (select id_paradero::text from paradero); + +----- + +delete from linea_paradero; + +----- + +delete from linea ; + +----- + +insert into linea +select distinct + trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id, + zr.agency_id , + substring(zt.trip_headsign FROM '(\S+) -') as route_short_name , + zr.route_desc , + zr.route_type::numeric , + zr.route_url, + zr.route_color , + zr.route_text_color , + zt.trip_headsign as route_long_name , true + from z_routes zr + inner join z_trips zt + on zr.route_id =zt.route_id + and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 1)||'-'||SPLIT_PART(route_long_name, '-', 2)),' ','') +where route_long_name not like '%'||route_short_name ||'%' +union +select distinct +trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id, + zr.agency_id , + substring(zt.trip_headsign FROM '(\S+) -') as route_short_name , + zr.route_desc , + zr.route_type::numeric , + zr.route_url, + zr.route_color , + zr.route_text_color , + zt.trip_headsign as route_long_name , true + from z_routes zr + inner join z_trips zt + on zr.route_id =zt.route_id + and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 3)||'-'||SPLIT_PART(route_long_name, '-', 4)),' ','') +where route_long_name not like '%'||route_short_name ||'%' + +union + +select distinct + trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id, + zr.agency_id , + route_short_name , + zr.route_desc , + zr.route_type::numeric , + zr.route_url, + zr.route_color , + zr.route_text_color , + zt.trip_headsign as route_long_name , true + from z_routes zr + inner join z_trips zt + on zr.route_id =zt.route_id + and + ( position('-' in zt.trip_headsign) = 0 + or + route_long_name like '%'||route_short_name ||'%' + ) +order by 1; + +----- + +delete from gtfs_shape; + +----- + +insert into gtfs_shape +select shape_id::numeric,shape_pt_lat::float8,shape_pt_lon::float8, +shape_pt_sequence::numeric,shape_dist_traveled::float8 +from z_shapes zs; + +----- + +delete from gtfs_stop_times; + +----- + +delete from gtfs_frequencie; + +----- + +delete from gtfs_trips; + +----- + +insert into gtfs_trips +select +trip_id, +trim(route_id)||'-'||trim(direction_id::varchar) as route_id, +shape_id::numeric ,null as regreso, trip_headsign,trip_short_name,direction_id::numeric,service_id::varchar,block_id +from z_trips zt ; + +----- + +insert into gtfs_stop_times +select stop_id,trip_id,arrival_time,stop_sequence::numeric,stop_headsign,departure_time,drop_off_type::numeric,null as shape_dist_traveled , +timepoint::numeric , pickup_type::numeric +from z_stop_times zst ; + +----- + +insert into linea_paradero (id_linea , id_paradero ) +SELECT DISTINCT +l.id_linea , p.id_paradero +FROM linea l +JOIN gtfs_trips t ON l.id_linea =t.id_linea +JOIN gtfs_stop_times st ON t.id_trip = st.id_trip +JOIN paradero p ON st.id_paradero = p.id_paradero; + +----- + +UPDATE paradero +SET stop_name = REGEXP_REPLACE( + REGEXP_REPLACE( + stop_name, + '\yentre\y', + '-entre', + 'gi' + ), + '\yesq\y', + '-esq', + 'gi' +); + +----- + +ALTER TABLE rol_linea ADD CONSTRAINT rol_linea_id_linea_fkey FOREIGN KEY (id_linea) REFERENCES linea(id_linea); + +----- + +ALTER TABLE linea_paradero ADD CONSTRAINT linea_paradero_id_linea_fkey FOREIGN KEY (id_linea) REFERENCES linea(id_linea); + +----- \ No newline at end of file diff --git a/project/api/views/aplicacion.py b/project/api/views/aplicacion.py index f07bd9d..3bca5e5 100755 --- a/project/api/views/aplicacion.py +++ b/project/api/views/aplicacion.py @@ -1,7 +1,17 @@ from rest_framework import viewsets from .. import models, serializers +from django.db import models as dj_models class AplicacionViewSet(viewsets.ModelViewSet): queryset = models.Aplicacion.objects.all() serializer_class = serializers.AplicacionSerializer - ordering_fields = '__all__' \ No newline at end of file + ordering_fields = '__all__' + + def create(self, request, *args, **kwargs): + # se indica que si no se indico el id, entonces sea el maximo + 1 + if not request.data.get('id_aplicacion', None): + max_id = models.Aplicacion.objects.aggregate(dj_models.Max('id_aplicacion'))['id_aplicacion__max'] + new_id = max_id + 1 if max_id is not None else 1 + request.data['id_aplicacion'] = new_id + + return super().create(request, *args, **kwargs) \ No newline at end of file diff --git a/project/api/views/linea.py b/project/api/views/linea.py index 0df137a..a58ec49 100755 --- a/project/api/views/linea.py +++ b/project/api/views/linea.py @@ -5,7 +5,8 @@ from rest_framework.decorators import action, api_view from django_filters.rest_framework import DjangoFilterBackend from django.db import connection from .. import models, serializers -from django.http import JsonResponse +from django.http import JsonResponse, HttpResponse +from django.forms.models import model_to_dict from os import getenv import redis import json @@ -16,8 +17,18 @@ class LineaViewSet(viewsets.ModelViewSet): queryset = models.Linea.objects.all() serializer_class = serializers.LineaSerializer filter_backends = [DjangoFilterBackend] - filterset_fields = ['id_operador', 'route_short_name', 'route_long_name', 'vigente'] + filterset_fields = ['id_operador', 'route_short_name', 'route_long_name', 'vigente', 'rollinea__id_rol'] + def list(self, request, pk=None, *args, **kwargs): + login = request.jwt_info['login'] + usuario = models.Usuario.objects.filter(login=login).first() + + if usuario.superuser != True: + self.request.GET.rollinea__id_rol = usuario.id_rol.id_rol + request.GET.rollinea__id_rol = usuario.id_rol.id_rol + # request.GET.setdefault('rollinea__id_rol',usuario.id_rol) + + return super().list(request, pk, *args, **kwargs) @action(detail=False, methods=['get']) def proto(self, request, pk=None): diff --git a/project/api/views/paradero.py b/project/api/views/paradero.py index 05a415a..bb16613 100755 --- a/project/api/views/paradero.py +++ b/project/api/views/paradero.py @@ -2,7 +2,7 @@ from django.http import JsonResponse from rest_framework import viewsets from rest_framework.decorators import action from api.serializers import ParaderoSerializer -from api.models import Paradero +from api.models import Paradero, Dispositivo import logging class ParaderoViewSet(viewsets.ModelViewSet): @@ -26,17 +26,24 @@ class ParaderoViewSet(viewsets.ModelViewSet): return JsonResponse({ 'count': queryset.count() }) + @action(detail=False, methods=['get'], url_path='info-public/(?P\S+)') + def info_public(self, request, pk=None): + if hasattr(request.META,'HTTP_REFERER'): + referer = request.META['HTTP_REFERER'] + else: + protocol = request.scheme + host = request.META['HTTP_HOST'] + port = request.META['SERVER_PORT'] + referer = f'{protocol}://{host}' -def info_public(request, pk): + record = Dispositivo.objects \ + .filter(id_tipo_dispositivo__descripcion='CODIGO QR', id_paradero=pk) \ + .first() - if hasattr(request.META,'HTTP_REFERER'): - referer = request.META['HTTP_REFERER'] - else: - protocol = request.scheme - host = request.META['HTTP_HOST'] - port = request.META['SERVER_PORT'] - referer = f'{protocol}://{host}:{port}' + url = None + if record != None: + url = f'https://transporte-paradero.hz.kursor.cl/rutaParadero/?id={record.id_dispositivo}' - return JsonResponse({ - 'url_public': f'{referer}/public/infoStop?codigoParadero={pk}' - }) \ No newline at end of file + + # url = f'{referer}/public/infoStop?codigoParadero={pk}' + return JsonResponse({ 'url_public': url }) \ No newline at end of file diff --git a/project/api/views/proto.py b/project/api/views/proto.py deleted file mode 100644 index c8985b9..0000000 --- a/project/api/views/proto.py +++ /dev/null @@ -1,46 +0,0 @@ - -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import action, api_view -from api.utils import gtfs_realtime_pb2 -from project.settings import BASE_DIR -from django.http import JsonResponse -import logging - -def status(request): - nombre_archivo_proto = f'{BASE_DIR}/api/utils/demo.proto' - with open(nombre_archivo_proto, 'rb') as proto_file: - feed = gtfs_realtime_pb2.FeedMessage() - feed.ParseFromString(proto_file.read()) - - data = {} #get_object(feed) - # logging.error(dir(feed)) - # logging.error(feed.header) - # logging.error(dir(feed.entity)) - logging.error(feed.entity[0]) - # logging.error(dir(feed.entity[0].trip_update)) - - return JsonResponse(data, safe=False) - - -def get_object(obj1, obj2 = {}, level = 1): - attributes = dir(obj1) - for attr in attributes: - if attr[0:1] != '_': - try: - for elem in obj1[attr]: - logging.error(elem) - except: - logging.error(attr) - pass - return obj2 - - -def is_subscriptable(obj): - return hasattr(obj, '__getitem__') - -def is_iterable(obj): - try: - iter(obj) - return True - except TypeError: - return False diff --git a/project/api/views/rol.py b/project/api/views/rol.py index 4a7bf52..2ca6e20 100755 --- a/project/api/views/rol.py +++ b/project/api/views/rol.py @@ -1,6 +1,16 @@ from rest_framework import viewsets from .. import models, serializers +from django.db import models as dj_models class RolViewSet(viewsets.ModelViewSet): queryset = models.Rol.objects.all() - serializer_class = serializers.RolSerializer \ No newline at end of file + serializer_class = serializers.RolSerializer + + def create(self, request, *args, **kwargs): + # se indica que si no se indico el id, entonces sea el maximo + 1 + if not request.data.get('id_rol', None): + max_id = models.Rol.objects.aggregate(dj_models.Max('id_rol'))['id_rol__max'] + new_id = max_id + 1 if max_id is not None else 1 + request.data['id_rol'] = new_id + + return super().create(request, *args, **kwargs) \ No newline at end of file diff --git a/project/api/views/rol_linea.py b/project/api/views/rol_linea.py new file mode 100644 index 0000000..af87624 --- /dev/null +++ b/project/api/views/rol_linea.py @@ -0,0 +1,14 @@ +from rest_framework import viewsets +from .. import models, serializers +import logging + +class RolLineaViewSet(viewsets.ModelViewSet): + serializer_class = serializers.RolLineaSerializer + + def get_queryset(self): + id_rol = self.request.query_params.get('id_rol') # Obtener el valor del parámetro id_rol desde la solicitud + + if id_rol is not None: + return models.RolLinea.objects.filter(id_rol=id_rol) + + return models.RolLinea.objects.all() \ No newline at end of file diff --git a/project/api/views/rolaplicacion.py b/project/api/views/rolaplicacion.py index be4225e..3f9adb4 100755 --- a/project/api/views/rolaplicacion.py +++ b/project/api/views/rolaplicacion.py @@ -4,8 +4,6 @@ import logging class RolAplicacionViewSet(viewsets.ModelViewSet): serializer_class = serializers.RolAplicacionSerializer - - def get_queryset(self): id_rol = self.request.query_params.get('id_rol') # Obtener el valor del parámetro id_rol desde la solicitud diff --git a/project/api/views/upload.py b/project/api/views/upload.py new file mode 100644 index 0000000..7b00d43 --- /dev/null +++ b/project/api/views/upload.py @@ -0,0 +1,153 @@ + +from django.views.decorators.csrf import csrf_exempt +from django.http import JsonResponse +from django.http import HttpResponse +from rest_framework.decorators import action +from django.db import connection +import tempfile +import threading +import logging +import zipfile +import os +import csv +import redis + + + +@csrf_exempt +@action(detail=False, methods=['get','post']) +def upload_zip(request): + + db_host = os.getenv('DB_REDIS_HOST') + db_port = os.getenv('DB_REDIS_PORT') + r = redis.Redis(host=db_host, port=db_port, decode_responses=True) + + if request.method == 'GET': + filezip = r.get('filezip') + return JsonResponse({ + 'process': filezip != None, + 'filename': filezip + }) + + if request.method == 'POST': + + status = r.get('filezip') + if status != None: + return HttpResponse('Ya existe un proceso en ejecución', status=400) + + filezip = request.FILES['filezip'] + if filezip.closed == False and hasattr(filezip,'temporary_file_path'): + # Notificar a Redis que proceso ha iniciado + r.set('filezip', filezip.name) + + hilo = threading.Thread(target=procesa_zip, args=(filezip,)) + hilo.start() + return JsonResponse({ + 'ok': True, + 'message': 'Procesando archivo zip' + }) + + return JsonResponse({ + 'ok': False, + 'message': 'Error en archivo zip enviado' + }) + + + + +def procesa_zip(file_upload): + carpeta_destino = tempfile.gettempdir() + + # descomprimir archivo zip + archivo_zip = zipfile.ZipFile(file_upload.temporary_file_path(), "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: + # notificar a Redis que proceso ha finalizado + db_host = os.getenv('DB_REDIS_HOST') + db_port = os.getenv('DB_REDIS_PORT') + r = redis.Redis(host=db_host, port=db_port, decode_responses=True) + r.delete('filezip') + + 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) diff --git a/project/api/views/usuario.py b/project/api/views/usuario.py index 84b5953..62438d6 100755 --- a/project/api/views/usuario.py +++ b/project/api/views/usuario.py @@ -1,9 +1,9 @@ from django.db import transaction -from django.http import HttpResponse - +from django.http import HttpResponse, JsonResponse from rest_framework import viewsets from rest_framework.response import Response +from rest_framework.decorators import action from .. import models, schemas, serializers import json @@ -24,8 +24,6 @@ class UsuarioViewSet(viewsets.ModelViewSet): with transaction.atomic(): input = json.loads(request.body) - # validaciones se realiza a nivel del model - persona = models.Persona.objects.filter(rut = input['rut']).first() id_tipo_tratamiento = input.get('id_tipo_tratamiento',None) if not id_tipo_tratamiento: @@ -50,68 +48,19 @@ class UsuarioViewSet(viewsets.ModelViewSet): persona.id_tipo_tratamiento = id_tipo_tratamiento persona.save() + rol = models.Rol.objects.filter(id_rol=input.get('id_rol',None)).first() + if rol == None: + raise ValueError('Rol no encontrado') + usuario = models.Usuario( rut = persona, login = input['login'], + id_rol = rol, vigente = input.get('vigente', False), ) usuario.save() - logging.error(f'clave = {input["clave"]}') - if input['clave']: - logging.error('Modificar clave de usuario') - clave = models.UsuarioClave.objects.filter(login = usuario.login).first() - if clave: - logging.error('Clave Usuario ya existe') - clave.clave_anterior = clave.clave - clave.clave = input['clave'] - clave.fecha_modificacion = datetime.datetime.now() - clave.save() - else: - logging.error('Clave Usuario se creará') - clave = models.UsuarioClave( - login = usuario.login, - clave = input['clave'], - fecha_modificacion = datetime.datetime.now() - ) - clave.save() - - return Response({ - 'rut': persona.rut, - 'dv': persona.dv, - 'nombres': persona.nombres, - 'apellido_a': persona.apellido_a, - 'apellido_b': persona.apellido_b, - 'email': persona.email, - 'login': usuario.login, - 'vigente': usuario.vigente, - }) - - except ValueError as e: - transaction.rollback() - return HttpResponse(str(e), status = 400) - - except Exception as e: - transaction.rollback() - print(e) - return HttpResponse(str(e), status = 500) - - def update(self, request, *args, **kwargs): - input = json.loads(request.body) - logging.error(input) - try: - pk = input['rut'] - with transaction.atomic(): - - # validaciones se realiza a nivel del model - - persona = models.Persona.objects.filter(rut = pk).first() - - usuario = models.Usuario.objects.filter(rut = pk).first() - usuario.vigente = input.get('vigente', False) - usuario.save() - - logging.error(f'clave = {input["clave"]}') + # logging.error(f'clave = {input["clave"]}') if input['clave']: logging.error('Modificar clave de usuario') clave = models.UsuarioClave.objects.filter(login = usuario.login).first() @@ -149,3 +98,98 @@ class UsuarioViewSet(viewsets.ModelViewSet): transaction.rollback() print(e) return HttpResponse(str(e), status = 500) + + def update(self, request, *args, **kwargs): + input = json.loads(request.body) + logging.error(input) + try: + pk = input['rut'] + with transaction.atomic(): + + # validaciones se realiza a nivel del model + + persona = models.Persona.objects.filter(rut = pk).first() + rol = models.Rol.objects.filter(id_rol = input.get('id_rol')).first() + + usuario = models.Usuario.objects.filter(rut = pk).first() + usuario.vigente = input.get('vigente', False) + usuario.superuser = input.get('superuser', False) + usuario.id_rol = rol + usuario.save() + + if 'clave' in input: + logging.error('Modificar clave de usuario') + logging.error(f'clave = {input["clave"]}') + + clave = models.UsuarioClave.objects.filter(login = usuario.login).first() + if clave: + logging.error('Clave Usuario ya existe') + clave.clave_anterior = clave.clave + clave.clave = input['clave'] + clave.fecha_modificacion = datetime.datetime.now() + clave.save() + else: + logging.error('Clave Usuario se creará') + clave = models.UsuarioClave( + login = usuario, + clave = input['clave'], + fecha_modificacion = datetime.datetime.now() + ) + clave.save() + + return Response({ + 'rut': persona.rut, + 'dv': persona.dv, + 'nombres': persona.nombres, + 'apellido_a': persona.apellido_a, + 'apellido_b': persona.apellido_b, + 'email': persona.email, + 'login': usuario.login, + 'vigente': usuario.vigente, + }) + + except ValueError as e: + transaction.rollback() + return HttpResponse(str(e), status = 400) + + except Exception as e: + transaction.rollback() + logging.error(e) + return HttpResponse(str(e), status = 500) + + @action(detail=False, methods=['post']) + def permisos(self, request): + input = {} + if request.body > b'': + input = json.loads(request.body) + + login = request.jwt_info['login'] + usuario = models.Usuario.objects.filter(login=login).first() + escritura = usuario.superuser == True + + if 'path' in input: + path = input.get('path') + aplicacion = models.Aplicacion.objects.filter(path_app=path).first() + + if escritura == False: + rol_aplicacion = models.RolAplicacion.objects.filter(id_rol=usuario.id_rol, id_aplicacion=aplicacion.id_aplicacion).first() + escritura = rol_aplicacion.solo_visualizar == False + + return JsonResponse({ + 'path_app': path, + 'nombre_app': aplicacion.nombre_app, + 'escritura': escritura + }) + else: + registros = models.RolAplicacion.objects.filter(id_rol=usuario.id_rol) + aplicaciones = [] + for registro in registros: + if registro.id_aplicacion.vigente: + rol_app = models.RolAplicacion.objects.filter(id_rol=registro.id_rol, id_aplicacion=registro.id_aplicacion).first() + + aplicaciones.append({ + 'path_app': registro.id_aplicacion.path_app, + 'nombre_app': registro.id_aplicacion.nombre_app, + }) + + return JsonResponse({ "aplicaciones": aplicaciones })