From 3331a4df7f1213f69ff7590772d8a44013d25c39 Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sat, 6 Jan 2024 12:25:12 -0300 Subject: [PATCH 1/9] avance manejo de roles --- project/api/models.py | 34 +++++++++++----------- project/api/serializers.py | 4 +++ project/api/urls.py | 1 - project/api/views/aplicacion.py | 12 +++++++- project/api/views/proto.py | 46 ------------------------------ project/api/views/rolaplicacion.py | 2 -- project/api/views/usuario.py | 32 ++++++++++++++++----- 7 files changed, 58 insertions(+), 73 deletions(-) delete mode 100644 project/api/views/proto.py 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..e913924 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) diff --git a/project/api/urls.py b/project/api/urls.py index 9e2897a..51709f9 100755 --- a/project/api/urls.py +++ b/project/api/urls.py @@ -34,5 +34,4 @@ urlpatterns = [ 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'), ] 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/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/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/usuario.py b/project/api/views/usuario.py index 84b5953..1f75894 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: @@ -106,14 +104,18 @@ class UsuarioViewSet(viewsets.ModelViewSet): # 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() - logging.error(f'clave = {input["clave"]}') - if input['clave']: + 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') @@ -147,5 +149,21 @@ class UsuarioViewSet(viewsets.ModelViewSet): except Exception as e: transaction.rollback() - print(e) + logging.error(e) return HttpResponse(str(e), status = 500) + + @action(detail=False, methods=['post']) + def permiso(self, request): + input = json.loads(request.body) + + logging.error(request.jwt_info) + usuario = models.Usuario.objects.filter(login=input['login']) + + + return JsonResponse({ + "path": input['path'], + "permisos": { + "": 1, + "MensajeParadero": "No considerar, uso futuro" + } + }) \ No newline at end of file From d42149192fa53725d0317a4830ffa42c1fd6d0fb Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sun, 7 Jan 2024 13:16:13 -0300 Subject: [PATCH 2/9] avance mantenedor roles --- docs/rest/login.rest | 13 +++++++++---- project/api/serializers.py | 5 +++++ project/api/urls.py | 2 ++ project/api/views/rol.py | 12 +++++++++++- project/api/views/rol_linea.py | 14 ++++++++++++++ project/api/views/usuario.py | 30 +++++++++++++++++++----------- 6 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 project/api/views/rol_linea.py diff --git a/docs/rest/login.rest b/docs/rest/login.rest index 94dd73f..05c375e 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,10 @@ Authorization: Bearer {{token}} ### -GET {{server}}/paraderos-image/??id_paradero=42318 -Authorization: Bearer {{token}} \ No newline at end of file +GET {{server}}/paraderos-image/?id_paradero=42318 +Authorization: Bearer {{token}} + +### +# @name permisos +POST {{server}}/usuarios/permisos/ +Authorization: Bearer {{token}} diff --git a/project/api/serializers.py b/project/api/serializers.py index e913924..edca5f2 100755 --- a/project/api/serializers.py +++ b/project/api/serializers.py @@ -130,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 51709f9..700b560 100755 --- a/project/api/urls.py +++ b/project/api/urls.py @@ -5,6 +5,7 @@ from api.views import usuario, auth, aplicacion, tipo, persona, comuna, region, from api.views import mapa, linea, letrero_lur, operador from api.views import paradero_imagen, linea_paradero from api.views import dispositivo +from api.views import rol_linea # from api.views import proto router = routers.DefaultRouter() @@ -27,6 +28,7 @@ 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)), 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/usuario.py b/project/api/views/usuario.py index 1f75894..893d868 100755 --- a/project/api/views/usuario.py +++ b/project/api/views/usuario.py @@ -153,17 +153,25 @@ class UsuarioViewSet(viewsets.ModelViewSet): return HttpResponse(str(e), status = 500) @action(detail=False, methods=['post']) - def permiso(self, request): - input = json.loads(request.body) + def permisos(self, request): + login = request.jwt_info['login'] - logging.error(request.jwt_info) - usuario = models.Usuario.objects.filter(login=input['login']) + usuario = models.Usuario.objects.filter(login=login).first() + 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() + escritura = True + if rol_app != None: + escritura = rol_app.solo_visualizar != True + + aplicaciones.append({ + 'id_aplicacion': registro.id_aplicacion.id_aplicacion, + 'path_app': registro.id_aplicacion.path_app, + 'nombre_app': registro.id_aplicacion.nombre_app, + 'escritura': escritura + }) - return JsonResponse({ - "path": input['path'], - "permisos": { - "": 1, - "MensajeParadero": "No considerar, uso futuro" - } - }) \ No newline at end of file + return JsonResponse({ "aplicaciones": aplicaciones }) \ No newline at end of file From 840f0449d65b6e4323dc60bc92a653d78e1dd7f6 Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sun, 7 Jan 2024 21:26:29 -0300 Subject: [PATCH 3/9] se modifica funcion que entrega permiso --- docs/rest/login.rest | 12 ++++++++- project/api/views/usuario.py | 47 ++++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/docs/rest/login.rest b/docs/rest/login.rest index 05c375e..121ba80 100644 --- a/docs/rest/login.rest +++ b/docs/rest/login.rest @@ -26,6 +26,16 @@ GET {{server}}/paraderos-image/?id_paradero=42318 Authorization: Bearer {{token}} ### -# @name permisos +# @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" +} diff --git a/project/api/views/usuario.py b/project/api/views/usuario.py index 893d868..989ca77 100755 --- a/project/api/views/usuario.py +++ b/project/api/views/usuario.py @@ -153,25 +153,36 @@ class UsuarioViewSet(viewsets.ModelViewSet): return HttpResponse(str(e), status = 500) @action(detail=False, methods=['post']) - def permisos(self, request): + 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() - 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() - escritura = True - if rol_app != None: - escritura = rol_app.solo_visualizar != True - - aplicaciones.append({ - 'id_aplicacion': registro.id_aplicacion.id_aplicacion, - 'path_app': registro.id_aplicacion.path_app, - 'nombre_app': registro.id_aplicacion.nombre_app, - 'escritura': escritura - }) + if 'path' in input: + path = input.get('path') + aplicacion = models.Aplicacion.objects.filter(path_app=path).first() + rol_aplicacion = models.RolAplicacion.objects.filter(id_rol=usuario.id_rol, id_aplicacion=aplicacion.id_aplicacion).first() + return JsonResponse({ + 'path_app': path, + 'nombre_app': aplicacion.nombre_app, + 'escritura': rol_aplicacion.solo_visualizar == False + }) + 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() + escritura = True + if rol_app != None: + escritura = rol_app.solo_visualizar != True + + aplicaciones.append({ + 'path_app': registro.id_aplicacion.path_app, + 'nombre_app': registro.id_aplicacion.nombre_app, + }) - return JsonResponse({ "aplicaciones": aplicaciones }) \ No newline at end of file + return JsonResponse({ "aplicaciones": aplicaciones }) \ No newline at end of file From 9d1507f445c2a635bc1b55b979a6c2a3643fb3ae Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Mon, 8 Jan 2024 21:08:31 -0300 Subject: [PATCH 4/9] se filtran lineas si usuario no es superuser --- project/api/views/linea.py | 16 +++++++++++++++- project/api/views/usuario.py | 12 +++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/project/api/views/linea.py b/project/api/views/linea.py index 0df137a..3ac71d6 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 @@ -18,6 +19,19 @@ class LineaViewSet(viewsets.ModelViewSet): filter_backends = [DjangoFilterBackend] filterset_fields = ['id_operador', 'route_short_name', 'route_long_name', 'vigente'] + def list(self, request, pk=None, *args, **kwargs): + login = request.jwt_info['login'] + usuario = models.Usuario.objects.filter(login=login).first() + + if usuario.superuser == False: + rol_lineas = models.RolLinea.objects.filter(id_rol=usuario.id_rol) + lineas = [] + for row in rol_lineas: + lineas.append(model_to_dict(row.id_linea)) + + return JsonResponse(lineas, safe=False) + else: + return super().list(request, pk, *args, **kwargs) @action(detail=False, methods=['get']) def proto(self, request, pk=None): diff --git a/project/api/views/usuario.py b/project/api/views/usuario.py index 989ca77..5e2f76b 100755 --- a/project/api/views/usuario.py +++ b/project/api/views/usuario.py @@ -160,15 +160,20 @@ class UsuarioViewSet(viewsets.ModelViewSet): login = request.jwt_info['login'] usuario = models.Usuario.objects.filter(login=login).first() + escritura = usuario.superuser if 'path' in input: path = input.get('path') aplicacion = models.Aplicacion.objects.filter(path_app=path).first() - rol_aplicacion = models.RolAplicacion.objects.filter(id_rol=usuario.id_rol, id_aplicacion=aplicacion.id_aplicacion).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': rol_aplicacion.solo_visualizar == False + 'escritura': escritura }) else: registros = models.RolAplicacion.objects.filter(id_rol=usuario.id_rol) @@ -176,9 +181,6 @@ class UsuarioViewSet(viewsets.ModelViewSet): 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() - escritura = True - if rol_app != None: - escritura = rol_app.solo_visualizar != True aplicaciones.append({ 'path_app': registro.id_aplicacion.path_app, From 6cafb320aabf929ab5cd7e084805db07ee6256cf Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Fri, 12 Jan 2024 20:11:07 -0300 Subject: [PATCH 5/9] fix crear usuario --- docs/rest/login.rest | 4 ++++ project/api/validaciones.py | 6 +++--- project/api/views/linea.py | 15 ++++++--------- project/api/views/usuario.py | 15 ++++++++++----- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/docs/rest/login.rest b/docs/rest/login.rest index 121ba80..e6cec3c 100644 --- a/docs/rest/login.rest +++ b/docs/rest/login.rest @@ -39,3 +39,7 @@ 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/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/linea.py b/project/api/views/linea.py index 3ac71d6..a58ec49 100755 --- a/project/api/views/linea.py +++ b/project/api/views/linea.py @@ -17,21 +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 == False: - rol_lineas = models.RolLinea.objects.filter(id_rol=usuario.id_rol) - lineas = [] - for row in rol_lineas: - lineas.append(model_to_dict(row.id_linea)) + 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 JsonResponse(lineas, safe=False) - else: - return super().list(request, pk, *args, **kwargs) + return super().list(request, pk, *args, **kwargs) @action(detail=False, methods=['get']) def proto(self, request, pk=None): diff --git a/project/api/views/usuario.py b/project/api/views/usuario.py index 5e2f76b..62438d6 100755 --- a/project/api/views/usuario.py +++ b/project/api/views/usuario.py @@ -48,14 +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"]}') + # logging.error(f'clave = {input["clave"]}') if input['clave']: logging.error('Modificar clave de usuario') clave = models.UsuarioClave.objects.filter(login = usuario.login).first() @@ -68,7 +73,7 @@ class UsuarioViewSet(viewsets.ModelViewSet): else: logging.error('Clave Usuario se creará') clave = models.UsuarioClave( - login = usuario.login, + login = usuario, clave = input['clave'], fecha_modificacion = datetime.datetime.now() ) @@ -153,14 +158,14 @@ class UsuarioViewSet(viewsets.ModelViewSet): return HttpResponse(str(e), status = 500) @action(detail=False, methods=['post']) - def permisos(self, request): + 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 + escritura = usuario.superuser == True if 'path' in input: path = input.get('path') @@ -187,4 +192,4 @@ class UsuarioViewSet(viewsets.ModelViewSet): 'nombre_app': registro.id_aplicacion.nombre_app, }) - return JsonResponse({ "aplicaciones": aplicaciones }) \ No newline at end of file + return JsonResponse({ "aplicaciones": aplicaciones }) From edb2e21927649df757de85ab63cea5f09b4abd44 Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sat, 13 Jan 2024 14:47:36 -0300 Subject: [PATCH 6/9] se agrega endpoint que procesa archivo zip --- docs/rest/upload.rest | 26 +++++++++ project/api/urls.py | 3 +- project/api/views/upload.py | 111 ++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 docs/rest/upload.rest create mode 100644 project/api/views/upload.py diff --git a/docs/rest/upload.rest b/docs/rest/upload.rest new file mode 100644 index 0000000..ddcbdba --- /dev/null +++ b/docs/rest/upload.rest @@ -0,0 +1,26 @@ + +@server = http://localhost:4000/api +@token = {{login.response.body.$.token}} + +### +# @name login +POST {{server}}/auth/ +Content-Type: application/json + +{ + "username": "usuario1", + "password": "usuario1" +} + +### +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/urls.py b/project/api/urls.py index 700b560..a616f3b 100755 --- a/project/api/urls.py +++ b/project/api/urls.py @@ -6,7 +6,7 @@ from api.views import mapa, linea, letrero_lur, operador from api.views import paradero_imagen, linea_paradero from api.views import dispositivo from api.views import rol_linea -# from api.views import proto +from api.views import upload router = routers.DefaultRouter() router.register('aplicaciones', aplicacion.AplicacionViewSet) @@ -36,4 +36,5 @@ urlpatterns = [ 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('upload/zip/', upload.upload_zip, name='upload_zip'), ] diff --git a/project/api/views/upload.py b/project/api/views/upload.py new file mode 100644 index 0000000..8eaf196 --- /dev/null +++ b/project/api/views/upload.py @@ -0,0 +1,111 @@ + +from django.views.decorators.csrf import csrf_exempt +from django.http import JsonResponse +from rest_framework.decorators import action +from django.db import connection +import tempfile +import threading +import time +import shutil +import logging +import zipfile +import os +import csv + + +@csrf_exempt +@action(detail=False, methods=['post']) +def upload_zip(request): + + if request.method == 'POST': + filezip = request.FILES['filezip'] + + if filezip.closed == False and hasattr(filezip,'temporary_file_path'): + 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() + # shutil.copy(filezip.temporary_file_path(), carpeta_destino) + + # 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" + ] + + # 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) + + cur.close() + connection.commit() + + # for i in range(10): + # time.sleep(1) + # print('.', end='', flush=True) + + 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);" + cursor.execute(create_table) + print(f'SQL> {create_table}', flush=True) + print('', flush=True) + + truncate_table = f"truncate table {table_name}; commit;" + cursor.execute(truncate_table) + print(f'SQL> {truncate_table}', flush=True) + print('', flush=True) + + file.seek(0) + next(reader) + + insert_query = f"COPY {table_name} ({', '.join(columns)}) FROM STDIN WITH CSV" + cursor.copy_expert(sql=insert_query, file=file) + print(f'SQL> {insert_query}', flush=True) + print('', flush=True) + + \ No newline at end of file From d35e1355656f7a0b64d42340a4ddbdac0bda4d4a Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sat, 13 Jan 2024 15:09:24 -0300 Subject: [PATCH 7/9] se notifica a redis que se inicio proceso de archivo zip --- docs/rest/upload.rest | 5 +++++ project/api/views/upload.py | 44 ++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/docs/rest/upload.rest b/docs/rest/upload.rest index ddcbdba..7427288 100644 --- a/docs/rest/upload.rest +++ b/docs/rest/upload.rest @@ -12,6 +12,11 @@ Content-Type: application/json "password": "usuario1" } + +### +GET {{server}}/upload/zip +Authorization: Bearer {{token}} + ### POST {{server}}/upload/zip/ Authorization: Bearer {{token}} diff --git a/project/api/views/upload.py b/project/api/views/upload.py index 8eaf196..20544b0 100644 --- a/project/api/views/upload.py +++ b/project/api/views/upload.py @@ -1,26 +1,46 @@ 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 time -import shutil import logging import zipfile import os import csv +import redis + @csrf_exempt -@action(detail=False, methods=['post']) +@action(detail=False, methods=['get','post']) def upload_zip(request): - if request.method == 'POST': - filezip = request.FILES['filezip'] + 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({ @@ -33,9 +53,11 @@ def upload_zip(request): 'message': 'Error en archivo zip enviado' }) + + + def procesa_zip(file_upload): carpeta_destino = tempfile.gettempdir() - # shutil.copy(filezip.temporary_file_path(), carpeta_destino) # descomprimir archivo zip archivo_zip = zipfile.ZipFile(file_upload.temporary_file_path(), "r") @@ -72,13 +94,15 @@ def procesa_zip(file_upload): cur.close() connection.commit() - # for i in range(10): - # time.sleep(1) - # print('.', end='', flush=True) - print('==============', flush=True) print(f'fin proceso archivo: {archivo_zip}', flush=True) + # 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') + # Función para crear la definición de la tabla como texto y cargar los datos From 06483aa8111d1f4741b11d945f29d6154ade4694 Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sat, 20 Jan 2024 14:18:32 -0300 Subject: [PATCH 8/9] se procesa archivo zip --- project/api/views/actualiza_GTFS.sql | 203 +++++++++++++++++++++++++++ project/api/views/upload.py | 60 +++++--- 2 files changed, 242 insertions(+), 21 deletions(-) create mode 100644 project/api/views/actualiza_GTFS.sql 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/upload.py b/project/api/views/upload.py index 20544b0..7b00d43 100644 --- a/project/api/views/upload.py +++ b/project/api/views/upload.py @@ -37,7 +37,6 @@ def upload_zip(request): 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) @@ -83,25 +82,31 @@ def procesa_zip(file_upload): "trips.txt" ] - # 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) + 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() + cur.close() + connection.commit() - print('==============', flush=True) - print(f'fin proceso archivo: {archivo_zip}', flush=True) + 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') - # 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) @@ -115,21 +120,34 @@ def create_and_load_table(filepath, file_name, cursor): 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);" - cursor.execute(create_table) print(f'SQL> {create_table}', flush=True) + cursor.execute(create_table) print('', flush=True) truncate_table = f"truncate table {table_name}; commit;" - cursor.execute(truncate_table) 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" - cursor.copy_expert(sql=insert_query, file=file) print(f'SQL> {insert_query}', flush=True) + cursor.copy_expert(sql=insert_query, file=file) print('', flush=True) - \ No newline at end of file + +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) From e374025ead0dc50fe9e0f1f2efe44165903639bb Mon Sep 17 00:00:00 2001 From: Francisco Sandoval Date: Sat, 20 Jan 2024 14:18:59 -0300 Subject: [PATCH 9/9] se corrige informacion publica de paradero --- project/api/middlewares.py | 5 +++++ project/api/urls.py | 5 ++--- project/api/views/paradero.py | 31 +++++++++++++++++++------------ 3 files changed, 26 insertions(+), 15 deletions(-) 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/urls.py b/project/api/urls.py index a616f3b..a4d0aa1 100755 --- a/project/api/urls.py +++ b/project/api/urls.py @@ -1,9 +1,9 @@ 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 rol_linea from api.views import upload @@ -35,6 +35,5 @@ urlpatterns = [ 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('upload/zip/', upload.upload_zip, name='upload_zip'), ] 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